1/* Filesystem index definition 2 * 3 * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12#define FSCACHE_DEBUG_LEVEL CACHE 13#include <linux/module.h> 14#include "internal.h" 15 16static uint16_t fscache_fsdef_netfs_get_key(const void *cookie_netfs_data, 17 void *buffer, uint16_t bufmax); 18 19static uint16_t fscache_fsdef_netfs_get_aux(const void *cookie_netfs_data, 20 void *buffer, uint16_t bufmax); 21 22static 23enum fscache_checkaux fscache_fsdef_netfs_check_aux(void *cookie_netfs_data, 24 const void *data, 25 uint16_t datalen); 26 27/* 28 * The root index is owned by FS-Cache itself. 29 * 30 * When a netfs requests caching facilities, FS-Cache will, if one doesn't 31 * already exist, create an entry in the root index with the key being the name 32 * of the netfs ("AFS" for example), and the auxiliary data holding the index 33 * structure version supplied by the netfs: 34 * 35 * FSDEF 36 * | 37 * +-----------+ 38 * | | 39 * NFS AFS 40 * [v=1] [v=1] 41 * 42 * If an entry with the appropriate name does already exist, the version is 43 * compared. If the version is different, the entire subtree from that entry 44 * will be discarded and a new entry created. 45 * 46 * The new entry will be an index, and a cookie referring to it will be passed 47 * to the netfs. This is then the root handle by which the netfs accesses the 48 * cache. It can create whatever objects it likes in that index, including 49 * further indices. 50 */ 51static struct fscache_cookie_def fscache_fsdef_index_def = { 52 .name = ".FS-Cache", 53 .type = FSCACHE_COOKIE_TYPE_INDEX, 54}; 55 56struct fscache_cookie fscache_fsdef_index = { 57 .usage = ATOMIC_INIT(1), 58 .lock = __SPIN_LOCK_UNLOCKED(fscache_fsdef_index.lock), 59 .backing_objects = HLIST_HEAD_INIT, 60 .def = &fscache_fsdef_index_def, 61}; 62EXPORT_SYMBOL(fscache_fsdef_index); 63 64/* 65 * Definition of an entry in the root index. Each entry is an index, keyed to 66 * a specific netfs and only applicable to a particular version of the index 67 * structure used by that netfs. 68 */ 69struct fscache_cookie_def fscache_fsdef_netfs_def = { 70 .name = "FSDEF.netfs", 71 .type = FSCACHE_COOKIE_TYPE_INDEX, 72 .get_key = fscache_fsdef_netfs_get_key, 73 .get_aux = fscache_fsdef_netfs_get_aux, 74 .check_aux = fscache_fsdef_netfs_check_aux, 75}; 76 77/* 78 * get the key data for an FSDEF index record - this is the name of the netfs 79 * for which this entry is created 80 */ 81static uint16_t fscache_fsdef_netfs_get_key(const void *cookie_netfs_data, 82 void *buffer, uint16_t bufmax) 83{ 84 const struct fscache_netfs *netfs = cookie_netfs_data; 85 unsigned klen; 86 87 _enter("{%s.%u},", netfs->name, netfs->version); 88 89 klen = strlen(netfs->name); 90 if (klen > bufmax) 91 return 0; 92 93 memcpy(buffer, netfs->name, klen); 94 return klen; 95} 96 97/* 98 * get the auxiliary data for an FSDEF index record - this is the index 99 * structure version number of the netfs for which this version is created 100 */ 101static uint16_t fscache_fsdef_netfs_get_aux(const void *cookie_netfs_data, 102 void *buffer, uint16_t bufmax) 103{ 104 const struct fscache_netfs *netfs = cookie_netfs_data; 105 unsigned dlen; 106 107 _enter("{%s.%u},", netfs->name, netfs->version); 108 109 dlen = sizeof(uint32_t); 110 if (dlen > bufmax) 111 return 0; 112 113 memcpy(buffer, &netfs->version, dlen); 114 return dlen; 115} 116 117/* 118 * check that the index structure version number stored in the auxiliary data 119 * matches the one the netfs gave us 120 */ 121static enum fscache_checkaux fscache_fsdef_netfs_check_aux( 122 void *cookie_netfs_data, 123 const void *data, 124 uint16_t datalen) 125{ 126 struct fscache_netfs *netfs = cookie_netfs_data; 127 uint32_t version; 128 129 _enter("{%s},,%hu", netfs->name, datalen); 130 131 if (datalen != sizeof(version)) { 132 _leave(" = OBSOLETE [dl=%d v=%zu]", datalen, sizeof(version)); 133 return FSCACHE_CHECKAUX_OBSOLETE; 134 } 135 136 memcpy(&version, data, sizeof(version)); 137 if (version != netfs->version) { 138 _leave(" = OBSOLETE [ver=%x net=%x]", version, netfs->version); 139 return FSCACHE_CHECKAUX_OBSOLETE; 140 } 141 142 _leave(" = OKAY"); 143 return FSCACHE_CHECKAUX_OKAY; 144} 145