diff options
Diffstat (limited to 'fs/nfs/fscache-index.c')
-rw-r--r-- | fs/nfs/fscache-index.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/fs/nfs/fscache-index.c b/fs/nfs/fscache-index.c index a824050be807..7bc54acb7b00 100644 --- a/fs/nfs/fscache-index.c +++ b/fs/nfs/fscache-index.c | |||
@@ -146,3 +146,126 @@ const struct fscache_cookie_def nfs_fscache_super_index_def = { | |||
146 | .type = FSCACHE_COOKIE_TYPE_INDEX, | 146 | .type = FSCACHE_COOKIE_TYPE_INDEX, |
147 | .get_key = nfs_super_get_key, | 147 | .get_key = nfs_super_get_key, |
148 | }; | 148 | }; |
149 | |||
150 | /* | ||
151 | * Definition of the auxiliary data attached to NFS inode storage objects | ||
152 | * within the cache. | ||
153 | * | ||
154 | * The contents of this struct are recorded in the on-disk local cache in the | ||
155 | * auxiliary data attached to the data storage object backing an inode. This | ||
156 | * permits coherency to be managed when a new inode binds to an already extant | ||
157 | * cache object. | ||
158 | */ | ||
159 | struct nfs_fscache_inode_auxdata { | ||
160 | struct timespec mtime; | ||
161 | struct timespec ctime; | ||
162 | loff_t size; | ||
163 | u64 change_attr; | ||
164 | }; | ||
165 | |||
166 | /* | ||
167 | * Generate a key to describe an NFS inode in an NFS server's index | ||
168 | */ | ||
169 | static uint16_t nfs_fscache_inode_get_key(const void *cookie_netfs_data, | ||
170 | void *buffer, uint16_t bufmax) | ||
171 | { | ||
172 | const struct nfs_inode *nfsi = cookie_netfs_data; | ||
173 | uint16_t nsize; | ||
174 | |||
175 | /* use the inode's NFS filehandle as the key */ | ||
176 | nsize = nfsi->fh.size; | ||
177 | memcpy(buffer, nfsi->fh.data, nsize); | ||
178 | return nsize; | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * Get certain file attributes from the netfs data | ||
183 | * - This function can be absent for an index | ||
184 | * - Not permitted to return an error | ||
185 | * - The netfs data from the cookie being used as the source is presented | ||
186 | */ | ||
187 | static void nfs_fscache_inode_get_attr(const void *cookie_netfs_data, | ||
188 | uint64_t *size) | ||
189 | { | ||
190 | const struct nfs_inode *nfsi = cookie_netfs_data; | ||
191 | |||
192 | *size = nfsi->vfs_inode.i_size; | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * Get the auxiliary data from netfs data | ||
197 | * - This function can be absent if the index carries no state data | ||
198 | * - Should store the auxiliary data in the buffer | ||
199 | * - Should return the amount of amount stored | ||
200 | * - Not permitted to return an error | ||
201 | * - The netfs data from the cookie being used as the source is presented | ||
202 | */ | ||
203 | static uint16_t nfs_fscache_inode_get_aux(const void *cookie_netfs_data, | ||
204 | void *buffer, uint16_t bufmax) | ||
205 | { | ||
206 | struct nfs_fscache_inode_auxdata auxdata; | ||
207 | const struct nfs_inode *nfsi = cookie_netfs_data; | ||
208 | |||
209 | memset(&auxdata, 0, sizeof(auxdata)); | ||
210 | auxdata.size = nfsi->vfs_inode.i_size; | ||
211 | auxdata.mtime = nfsi->vfs_inode.i_mtime; | ||
212 | auxdata.ctime = nfsi->vfs_inode.i_ctime; | ||
213 | |||
214 | if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4) | ||
215 | auxdata.change_attr = nfsi->change_attr; | ||
216 | |||
217 | if (bufmax > sizeof(auxdata)) | ||
218 | bufmax = sizeof(auxdata); | ||
219 | |||
220 | memcpy(buffer, &auxdata, bufmax); | ||
221 | return bufmax; | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * Consult the netfs about the state of an object | ||
226 | * - This function can be absent if the index carries no state data | ||
227 | * - The netfs data from the cookie being used as the target is | ||
228 | * presented, as is the auxiliary data | ||
229 | */ | ||
230 | static | ||
231 | enum fscache_checkaux nfs_fscache_inode_check_aux(void *cookie_netfs_data, | ||
232 | const void *data, | ||
233 | uint16_t datalen) | ||
234 | { | ||
235 | struct nfs_fscache_inode_auxdata auxdata; | ||
236 | struct nfs_inode *nfsi = cookie_netfs_data; | ||
237 | |||
238 | if (datalen != sizeof(auxdata)) | ||
239 | return FSCACHE_CHECKAUX_OBSOLETE; | ||
240 | |||
241 | memset(&auxdata, 0, sizeof(auxdata)); | ||
242 | auxdata.size = nfsi->vfs_inode.i_size; | ||
243 | auxdata.mtime = nfsi->vfs_inode.i_mtime; | ||
244 | auxdata.ctime = nfsi->vfs_inode.i_ctime; | ||
245 | |||
246 | if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4) | ||
247 | auxdata.change_attr = nfsi->change_attr; | ||
248 | |||
249 | if (memcmp(data, &auxdata, datalen) != 0) | ||
250 | return FSCACHE_CHECKAUX_OBSOLETE; | ||
251 | |||
252 | return FSCACHE_CHECKAUX_OKAY; | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | * Define the inode object for FS-Cache. This is used to describe an inode | ||
257 | * object to fscache_acquire_cookie(). It is keyed by the NFS file handle for | ||
258 | * an inode. | ||
259 | * | ||
260 | * Coherency is managed by comparing the copies of i_size, i_mtime and i_ctime | ||
261 | * held in the cache auxiliary data for the data storage object with those in | ||
262 | * the inode struct in memory. | ||
263 | */ | ||
264 | const struct fscache_cookie_def nfs_fscache_inode_object_def = { | ||
265 | .name = "NFS.fh", | ||
266 | .type = FSCACHE_COOKIE_TYPE_DATAFILE, | ||
267 | .get_key = nfs_fscache_inode_get_key, | ||
268 | .get_attr = nfs_fscache_inode_get_attr, | ||
269 | .get_aux = nfs_fscache_inode_get_aux, | ||
270 | .check_aux = nfs_fscache_inode_check_aux, | ||
271 | }; | ||