diff options
Diffstat (limited to 'fs/nfs/fscache.c')
-rw-r--r-- | fs/nfs/fscache.c | 202 |
1 files changed, 58 insertions, 144 deletions
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c index 24d1d1c5fcaf..3ef01f0ba0bc 100644 --- a/fs/nfs/fscache.c +++ b/fs/nfs/fscache.c | |||
@@ -39,7 +39,7 @@ void nfs_fscache_get_client_cookie(struct nfs_client *clp) | |||
39 | /* create a cache index for looking up filehandles */ | 39 | /* create a cache index for looking up filehandles */ |
40 | clp->fscache = fscache_acquire_cookie(nfs_fscache_netfs.primary_index, | 40 | clp->fscache = fscache_acquire_cookie(nfs_fscache_netfs.primary_index, |
41 | &nfs_fscache_server_index_def, | 41 | &nfs_fscache_server_index_def, |
42 | clp); | 42 | clp, true); |
43 | dfprintk(FSCACHE, "NFS: get client cookie (0x%p/0x%p)\n", | 43 | dfprintk(FSCACHE, "NFS: get client cookie (0x%p/0x%p)\n", |
44 | clp, clp->fscache); | 44 | clp, clp->fscache); |
45 | } | 45 | } |
@@ -139,7 +139,7 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int | |||
139 | /* create a cache index for looking up filehandles */ | 139 | /* create a cache index for looking up filehandles */ |
140 | nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache, | 140 | nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache, |
141 | &nfs_fscache_super_index_def, | 141 | &nfs_fscache_super_index_def, |
142 | nfss); | 142 | nfss, true); |
143 | dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n", | 143 | dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n", |
144 | nfss, nfss->fscache); | 144 | nfss, nfss->fscache); |
145 | return; | 145 | return; |
@@ -178,163 +178,79 @@ void nfs_fscache_release_super_cookie(struct super_block *sb) | |||
178 | /* | 178 | /* |
179 | * Initialise the per-inode cache cookie pointer for an NFS inode. | 179 | * Initialise the per-inode cache cookie pointer for an NFS inode. |
180 | */ | 180 | */ |
181 | void nfs_fscache_init_inode_cookie(struct inode *inode) | 181 | void nfs_fscache_init_inode(struct inode *inode) |
182 | { | 182 | { |
183 | NFS_I(inode)->fscache = NULL; | ||
184 | if (S_ISREG(inode->i_mode)) | ||
185 | set_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags); | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | * Get the per-inode cache cookie for an NFS inode. | ||
190 | */ | ||
191 | static void nfs_fscache_enable_inode_cookie(struct inode *inode) | ||
192 | { | ||
193 | struct super_block *sb = inode->i_sb; | ||
194 | struct nfs_inode *nfsi = NFS_I(inode); | 183 | struct nfs_inode *nfsi = NFS_I(inode); |
195 | 184 | ||
196 | if (nfsi->fscache || !NFS_FSCACHE(inode)) | 185 | nfsi->fscache = NULL; |
186 | if (!S_ISREG(inode->i_mode)) | ||
197 | return; | 187 | return; |
198 | 188 | nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache, | |
199 | if ((NFS_SB(sb)->options & NFS_OPTION_FSCACHE)) { | 189 | &nfs_fscache_inode_object_def, |
200 | nfsi->fscache = fscache_acquire_cookie( | 190 | nfsi, false); |
201 | NFS_SB(sb)->fscache, | ||
202 | &nfs_fscache_inode_object_def, | ||
203 | nfsi); | ||
204 | |||
205 | dfprintk(FSCACHE, "NFS: get FH cookie (0x%p/0x%p/0x%p)\n", | ||
206 | sb, nfsi, nfsi->fscache); | ||
207 | } | ||
208 | } | 191 | } |
209 | 192 | ||
210 | /* | 193 | /* |
211 | * Release a per-inode cookie. | 194 | * Release a per-inode cookie. |
212 | */ | 195 | */ |
213 | void nfs_fscache_release_inode_cookie(struct inode *inode) | 196 | void nfs_fscache_clear_inode(struct inode *inode) |
214 | { | 197 | { |
215 | struct nfs_inode *nfsi = NFS_I(inode); | 198 | struct nfs_inode *nfsi = NFS_I(inode); |
199 | struct fscache_cookie *cookie = nfs_i_fscache(inode); | ||
216 | 200 | ||
217 | dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", | 201 | dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie); |
218 | nfsi, nfsi->fscache); | ||
219 | 202 | ||
220 | fscache_relinquish_cookie(nfsi->fscache, 0); | 203 | fscache_relinquish_cookie(cookie, false); |
221 | nfsi->fscache = NULL; | 204 | nfsi->fscache = NULL; |
222 | } | 205 | } |
223 | 206 | ||
224 | /* | 207 | static bool nfs_fscache_can_enable(void *data) |
225 | * Retire a per-inode cookie, destroying the data attached to it. | ||
226 | */ | ||
227 | void nfs_fscache_zap_inode_cookie(struct inode *inode) | ||
228 | { | 208 | { |
229 | struct nfs_inode *nfsi = NFS_I(inode); | 209 | struct inode *inode = data; |
230 | 210 | ||
231 | dfprintk(FSCACHE, "NFS: zapping cookie (0x%p/0x%p)\n", | 211 | return !inode_is_open_for_write(inode); |
232 | nfsi, nfsi->fscache); | ||
233 | |||
234 | fscache_relinquish_cookie(nfsi->fscache, 1); | ||
235 | nfsi->fscache = NULL; | ||
236 | } | 212 | } |
237 | 213 | ||
238 | /* | 214 | /* |
239 | * Turn off the cache with regard to a per-inode cookie if opened for writing, | 215 | * Enable or disable caching for a file that is being opened as appropriate. |
240 | * invalidating all the pages in the page cache relating to the associated | 216 | * The cookie is allocated when the inode is initialised, but is not enabled at |
241 | * inode to clear the per-page caching. | 217 | * that time. Enablement is deferred to file-open time to avoid stat() and |
242 | */ | 218 | * access() thrashing the cache. |
243 | static void nfs_fscache_disable_inode_cookie(struct inode *inode) | 219 | * |
244 | { | 220 | * For now, with NFS, only regular files that are open read-only will be able |
245 | clear_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags); | 221 | * to use the cache. |
246 | 222 | * | |
247 | if (NFS_I(inode)->fscache) { | 223 | * We enable the cache for an inode if we open it read-only and it isn't |
248 | dfprintk(FSCACHE, | 224 | * currently open for writing. We disable the cache if the inode is open |
249 | "NFS: nfsi 0x%p turning cache off\n", NFS_I(inode)); | 225 | * write-only. |
250 | 226 | * | |
251 | /* Need to uncache any pages attached to this inode that | 227 | * The caller uses the file struct to pin i_writecount on the inode before |
252 | * fscache knows about before turning off the cache. | 228 | * calling us when a file is opened for writing, so we can make use of that. |
253 | */ | 229 | * |
254 | fscache_uncache_all_inode_pages(NFS_I(inode)->fscache, inode); | 230 | * Note that this may be invoked multiple times in parallel by parallel |
255 | nfs_fscache_zap_inode_cookie(inode); | 231 | * nfs_open() functions. |
256 | } | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * wait_on_bit() sleep function for uninterruptible waiting | ||
261 | */ | ||
262 | static int nfs_fscache_wait_bit(void *flags) | ||
263 | { | ||
264 | schedule(); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | * Lock against someone else trying to also acquire or relinquish a cookie | ||
270 | */ | ||
271 | static inline void nfs_fscache_inode_lock(struct inode *inode) | ||
272 | { | ||
273 | struct nfs_inode *nfsi = NFS_I(inode); | ||
274 | |||
275 | while (test_and_set_bit(NFS_INO_FSCACHE_LOCK, &nfsi->flags)) | ||
276 | wait_on_bit(&nfsi->flags, NFS_INO_FSCACHE_LOCK, | ||
277 | nfs_fscache_wait_bit, TASK_UNINTERRUPTIBLE); | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * Unlock cookie management lock | ||
282 | */ | ||
283 | static inline void nfs_fscache_inode_unlock(struct inode *inode) | ||
284 | { | ||
285 | struct nfs_inode *nfsi = NFS_I(inode); | ||
286 | |||
287 | smp_mb__before_clear_bit(); | ||
288 | clear_bit(NFS_INO_FSCACHE_LOCK, &nfsi->flags); | ||
289 | smp_mb__after_clear_bit(); | ||
290 | wake_up_bit(&nfsi->flags, NFS_INO_FSCACHE_LOCK); | ||
291 | } | ||
292 | |||
293 | /* | ||
294 | * Decide if we should enable or disable local caching for this inode. | ||
295 | * - For now, with NFS, only regular files that are open read-only will be able | ||
296 | * to use the cache. | ||
297 | * - May be invoked multiple times in parallel by parallel nfs_open() functions. | ||
298 | */ | ||
299 | void nfs_fscache_set_inode_cookie(struct inode *inode, struct file *filp) | ||
300 | { | ||
301 | if (NFS_FSCACHE(inode)) { | ||
302 | nfs_fscache_inode_lock(inode); | ||
303 | if ((filp->f_flags & O_ACCMODE) != O_RDONLY) | ||
304 | nfs_fscache_disable_inode_cookie(inode); | ||
305 | else | ||
306 | nfs_fscache_enable_inode_cookie(inode); | ||
307 | nfs_fscache_inode_unlock(inode); | ||
308 | } | ||
309 | } | ||
310 | EXPORT_SYMBOL_GPL(nfs_fscache_set_inode_cookie); | ||
311 | |||
312 | /* | ||
313 | * Replace a per-inode cookie due to revalidation detecting a file having | ||
314 | * changed on the server. | ||
315 | */ | 232 | */ |
316 | void nfs_fscache_reset_inode_cookie(struct inode *inode) | 233 | void nfs_fscache_open_file(struct inode *inode, struct file *filp) |
317 | { | 234 | { |
318 | struct nfs_inode *nfsi = NFS_I(inode); | 235 | struct nfs_inode *nfsi = NFS_I(inode); |
319 | struct nfs_server *nfss = NFS_SERVER(inode); | 236 | struct fscache_cookie *cookie = nfs_i_fscache(inode); |
320 | NFS_IFDEBUG(struct fscache_cookie *old = nfsi->fscache); | ||
321 | 237 | ||
322 | nfs_fscache_inode_lock(inode); | 238 | if (!fscache_cookie_valid(cookie)) |
323 | if (nfsi->fscache) { | 239 | return; |
324 | /* retire the current fscache cache and get a new one */ | ||
325 | fscache_relinquish_cookie(nfsi->fscache, 1); | ||
326 | |||
327 | nfsi->fscache = fscache_acquire_cookie( | ||
328 | nfss->nfs_client->fscache, | ||
329 | &nfs_fscache_inode_object_def, | ||
330 | nfsi); | ||
331 | 240 | ||
332 | dfprintk(FSCACHE, | 241 | if (inode_is_open_for_write(inode)) { |
333 | "NFS: revalidation new cookie (0x%p/0x%p/0x%p/0x%p)\n", | 242 | dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi); |
334 | nfss, nfsi, old, nfsi->fscache); | 243 | clear_bit(NFS_INO_FSCACHE, &nfsi->flags); |
244 | fscache_disable_cookie(cookie, true); | ||
245 | fscache_uncache_all_inode_pages(cookie, inode); | ||
246 | } else { | ||
247 | dfprintk(FSCACHE, "NFS: nfsi 0x%p enabling cache\n", nfsi); | ||
248 | fscache_enable_cookie(cookie, nfs_fscache_can_enable, inode); | ||
249 | if (fscache_cookie_enabled(cookie)) | ||
250 | set_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags); | ||
335 | } | 251 | } |
336 | nfs_fscache_inode_unlock(inode); | ||
337 | } | 252 | } |
253 | EXPORT_SYMBOL_GPL(nfs_fscache_open_file); | ||
338 | 254 | ||
339 | /* | 255 | /* |
340 | * Release the caching state associated with a page, if the page isn't busy | 256 | * Release the caching state associated with a page, if the page isn't busy |
@@ -344,12 +260,11 @@ void nfs_fscache_reset_inode_cookie(struct inode *inode) | |||
344 | int nfs_fscache_release_page(struct page *page, gfp_t gfp) | 260 | int nfs_fscache_release_page(struct page *page, gfp_t gfp) |
345 | { | 261 | { |
346 | if (PageFsCache(page)) { | 262 | if (PageFsCache(page)) { |
347 | struct nfs_inode *nfsi = NFS_I(page->mapping->host); | 263 | struct fscache_cookie *cookie = nfs_i_fscache(page->mapping->host); |
348 | struct fscache_cookie *cookie = nfsi->fscache; | ||
349 | 264 | ||
350 | BUG_ON(!cookie); | 265 | BUG_ON(!cookie); |
351 | dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n", | 266 | dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n", |
352 | cookie, page, nfsi); | 267 | cookie, page, NFS_I(page->mapping->host)); |
353 | 268 | ||
354 | if (!fscache_maybe_release_page(cookie, page, gfp)) | 269 | if (!fscache_maybe_release_page(cookie, page, gfp)) |
355 | return 0; | 270 | return 0; |
@@ -367,13 +282,12 @@ int nfs_fscache_release_page(struct page *page, gfp_t gfp) | |||
367 | */ | 282 | */ |
368 | void __nfs_fscache_invalidate_page(struct page *page, struct inode *inode) | 283 | void __nfs_fscache_invalidate_page(struct page *page, struct inode *inode) |
369 | { | 284 | { |
370 | struct nfs_inode *nfsi = NFS_I(inode); | 285 | struct fscache_cookie *cookie = nfs_i_fscache(inode); |
371 | struct fscache_cookie *cookie = nfsi->fscache; | ||
372 | 286 | ||
373 | BUG_ON(!cookie); | 287 | BUG_ON(!cookie); |
374 | 288 | ||
375 | dfprintk(FSCACHE, "NFS: fscache invalidatepage (0x%p/0x%p/0x%p)\n", | 289 | dfprintk(FSCACHE, "NFS: fscache invalidatepage (0x%p/0x%p/0x%p)\n", |
376 | cookie, page, nfsi); | 290 | cookie, page, NFS_I(inode)); |
377 | 291 | ||
378 | fscache_wait_on_page_write(cookie, page); | 292 | fscache_wait_on_page_write(cookie, page); |
379 | 293 | ||
@@ -417,9 +331,9 @@ int __nfs_readpage_from_fscache(struct nfs_open_context *ctx, | |||
417 | 331 | ||
418 | dfprintk(FSCACHE, | 332 | dfprintk(FSCACHE, |
419 | "NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n", | 333 | "NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n", |
420 | NFS_I(inode)->fscache, page, page->index, page->flags, inode); | 334 | nfs_i_fscache(inode), page, page->index, page->flags, inode); |
421 | 335 | ||
422 | ret = fscache_read_or_alloc_page(NFS_I(inode)->fscache, | 336 | ret = fscache_read_or_alloc_page(nfs_i_fscache(inode), |
423 | page, | 337 | page, |
424 | nfs_readpage_from_fscache_complete, | 338 | nfs_readpage_from_fscache_complete, |
425 | ctx, | 339 | ctx, |
@@ -459,9 +373,9 @@ int __nfs_readpages_from_fscache(struct nfs_open_context *ctx, | |||
459 | int ret; | 373 | int ret; |
460 | 374 | ||
461 | dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n", | 375 | dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n", |
462 | NFS_I(inode)->fscache, npages, inode); | 376 | nfs_i_fscache(inode), npages, inode); |
463 | 377 | ||
464 | ret = fscache_read_or_alloc_pages(NFS_I(inode)->fscache, | 378 | ret = fscache_read_or_alloc_pages(nfs_i_fscache(inode), |
465 | mapping, pages, nr_pages, | 379 | mapping, pages, nr_pages, |
466 | nfs_readpage_from_fscache_complete, | 380 | nfs_readpage_from_fscache_complete, |
467 | ctx, | 381 | ctx, |
@@ -506,15 +420,15 @@ void __nfs_readpage_to_fscache(struct inode *inode, struct page *page, int sync) | |||
506 | 420 | ||
507 | dfprintk(FSCACHE, | 421 | dfprintk(FSCACHE, |
508 | "NFS: readpage_to_fscache(fsc:%p/p:%p(i:%lx f:%lx)/%d)\n", | 422 | "NFS: readpage_to_fscache(fsc:%p/p:%p(i:%lx f:%lx)/%d)\n", |
509 | NFS_I(inode)->fscache, page, page->index, page->flags, sync); | 423 | nfs_i_fscache(inode), page, page->index, page->flags, sync); |
510 | 424 | ||
511 | ret = fscache_write_page(NFS_I(inode)->fscache, page, GFP_KERNEL); | 425 | ret = fscache_write_page(nfs_i_fscache(inode), page, GFP_KERNEL); |
512 | dfprintk(FSCACHE, | 426 | dfprintk(FSCACHE, |
513 | "NFS: readpage_to_fscache: p:%p(i:%lu f:%lx) ret %d\n", | 427 | "NFS: readpage_to_fscache: p:%p(i:%lu f:%lx) ret %d\n", |
514 | page, page->index, page->flags, ret); | 428 | page, page->index, page->flags, ret); |
515 | 429 | ||
516 | if (ret != 0) { | 430 | if (ret != 0) { |
517 | fscache_uncache_page(NFS_I(inode)->fscache, page); | 431 | fscache_uncache_page(nfs_i_fscache(inode), page); |
518 | nfs_add_fscache_stats(inode, | 432 | nfs_add_fscache_stats(inode, |
519 | NFSIOS_FSCACHE_PAGES_WRITTEN_FAIL, 1); | 433 | NFSIOS_FSCACHE_PAGES_WRITTEN_FAIL, 1); |
520 | nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_UNCACHED, 1); | 434 | nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_UNCACHED, 1); |