aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/dir.c2
-rw-r--r--fs/nfs/fscache.c198
-rw-r--r--fs/nfs/fscache.h18
-rw-r--r--fs/nfs/inode.c6
-rw-r--r--fs/nfs/nfs4file.c2
-rw-r--r--include/linux/fs.h5
-rw-r--r--include/linux/nfs_fs.h8
7 files changed, 79 insertions, 160 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 854a8f05a610..4c5edcc8b6e9 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1381,7 +1381,7 @@ static struct nfs_open_context *create_nfs_open_context(struct dentry *dentry, i
1381 1381
1382static int do_open(struct inode *inode, struct file *filp) 1382static int do_open(struct inode *inode, struct file *filp)
1383{ 1383{
1384 nfs_fscache_set_inode_cookie(inode, filp); 1384 nfs_fscache_open_file(inode, filp);
1385 return 0; 1385 return 0;
1386} 1386}
1387 1387
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index cd6e7efd4305..3ef01f0ba0bc 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -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 */
181void nfs_fscache_init_inode_cookie(struct inode *inode) 181void 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 */
191static 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, true);
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 */
213void nfs_fscache_release_inode_cookie(struct inode *inode) 196void 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/* 207static bool nfs_fscache_can_enable(void *data)
225 * Retire a per-inode cookie, destroying the data attached to it.
226 */
227void 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.
243static 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 */
262static 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 */
271static 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 */
283static 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 */
299void 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}
310EXPORT_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 */
316void nfs_fscache_reset_inode_cookie(struct inode *inode) 233void 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, true);
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}
253EXPORT_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)
344int nfs_fscache_release_page(struct page *page, gfp_t gfp) 260int 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 */
368void __nfs_fscache_invalidate_page(struct page *page, struct inode *inode) 283void __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);
diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h
index 4ecb76652eba..d7fe3e799f2f 100644
--- a/fs/nfs/fscache.h
+++ b/fs/nfs/fscache.h
@@ -76,11 +76,9 @@ extern void nfs_fscache_release_client_cookie(struct nfs_client *);
76extern void nfs_fscache_get_super_cookie(struct super_block *, const char *, int); 76extern void nfs_fscache_get_super_cookie(struct super_block *, const char *, int);
77extern void nfs_fscache_release_super_cookie(struct super_block *); 77extern void nfs_fscache_release_super_cookie(struct super_block *);
78 78
79extern void nfs_fscache_init_inode_cookie(struct inode *); 79extern void nfs_fscache_init_inode(struct inode *);
80extern void nfs_fscache_release_inode_cookie(struct inode *); 80extern void nfs_fscache_clear_inode(struct inode *);
81extern void nfs_fscache_zap_inode_cookie(struct inode *); 81extern void nfs_fscache_open_file(struct inode *, struct file *);
82extern void nfs_fscache_set_inode_cookie(struct inode *, struct file *);
83extern void nfs_fscache_reset_inode_cookie(struct inode *);
84 82
85extern void __nfs_fscache_invalidate_page(struct page *, struct inode *); 83extern void __nfs_fscache_invalidate_page(struct page *, struct inode *);
86extern int nfs_fscache_release_page(struct page *, gfp_t); 84extern int nfs_fscache_release_page(struct page *, gfp_t);
@@ -187,12 +185,10 @@ static inline void nfs_fscache_release_client_cookie(struct nfs_client *clp) {}
187 185
188static inline void nfs_fscache_release_super_cookie(struct super_block *sb) {} 186static inline void nfs_fscache_release_super_cookie(struct super_block *sb) {}
189 187
190static inline void nfs_fscache_init_inode_cookie(struct inode *inode) {} 188static inline void nfs_fscache_init_inode(struct inode *inode) {}
191static inline void nfs_fscache_release_inode_cookie(struct inode *inode) {} 189static inline void nfs_fscache_clear_inode(struct inode *inode) {}
192static inline void nfs_fscache_zap_inode_cookie(struct inode *inode) {} 190static inline void nfs_fscache_open_file(struct inode *inode,
193static inline void nfs_fscache_set_inode_cookie(struct inode *inode, 191 struct file *filp) {}
194 struct file *filp) {}
195static inline void nfs_fscache_reset_inode_cookie(struct inode *inode) {}
196 192
197static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp) 193static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp)
198{ 194{
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index eda8879171c4..bb90bff0cb7a 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -122,7 +122,7 @@ void nfs_clear_inode(struct inode *inode)
122 WARN_ON_ONCE(!list_empty(&NFS_I(inode)->open_files)); 122 WARN_ON_ONCE(!list_empty(&NFS_I(inode)->open_files));
123 nfs_zap_acl_cache(inode); 123 nfs_zap_acl_cache(inode);
124 nfs_access_zap_cache(inode); 124 nfs_access_zap_cache(inode);
125 nfs_fscache_release_inode_cookie(inode); 125 nfs_fscache_clear_inode(inode);
126} 126}
127EXPORT_SYMBOL_GPL(nfs_clear_inode); 127EXPORT_SYMBOL_GPL(nfs_clear_inode);
128 128
@@ -459,7 +459,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
459 nfsi->attrtimeo_timestamp = now; 459 nfsi->attrtimeo_timestamp = now;
460 nfsi->access_cache = RB_ROOT; 460 nfsi->access_cache = RB_ROOT;
461 461
462 nfs_fscache_init_inode_cookie(inode); 462 nfs_fscache_init_inode(inode);
463 463
464 unlock_new_inode(inode); 464 unlock_new_inode(inode);
465 } else 465 } else
@@ -854,7 +854,7 @@ int nfs_open(struct inode *inode, struct file *filp)
854 return PTR_ERR(ctx); 854 return PTR_ERR(ctx);
855 nfs_file_set_open_context(filp, ctx); 855 nfs_file_set_open_context(filp, ctx);
856 put_nfs_open_context(ctx); 856 put_nfs_open_context(ctx);
857 nfs_fscache_set_inode_cookie(inode, filp); 857 nfs_fscache_open_file(inode, filp);
858 return 0; 858 return 0;
859} 859}
860 860
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index e5b804dd944c..5b8a618a0f7a 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -74,7 +74,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
74 74
75 nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 75 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
76 nfs_file_set_open_context(filp, ctx); 76 nfs_file_set_open_context(filp, ctx);
77 nfs_fscache_set_inode_cookie(inode, filp); 77 nfs_fscache_open_file(inode, filp);
78 err = 0; 78 err = 0;
79 79
80out_put_ctx: 80out_put_ctx:
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 3f40547ba191..955dff5da56a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2292,6 +2292,11 @@ static inline void allow_write_access(struct file *file)
2292 if (file) 2292 if (file)
2293 atomic_inc(&file_inode(file)->i_writecount); 2293 atomic_inc(&file_inode(file)->i_writecount);
2294} 2294}
2295static inline bool inode_is_open_for_write(const struct inode *inode)
2296{
2297 return atomic_read(&inode->i_writecount) > 0;
2298}
2299
2295#ifdef CONFIG_IMA 2300#ifdef CONFIG_IMA
2296static inline void i_readcount_dec(struct inode *inode) 2301static inline void i_readcount_dec(struct inode *inode)
2297{ 2302{
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 3ea4cde8701c..14a48207a304 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -269,9 +269,13 @@ static inline int NFS_STALE(const struct inode *inode)
269 return test_bit(NFS_INO_STALE, &NFS_I(inode)->flags); 269 return test_bit(NFS_INO_STALE, &NFS_I(inode)->flags);
270} 270}
271 271
272static inline int NFS_FSCACHE(const struct inode *inode) 272static inline struct fscache_cookie *nfs_i_fscache(struct inode *inode)
273{ 273{
274 return test_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags); 274#ifdef CONFIG_NFS_FSCACHE
275 return NFS_I(inode)->fscache;
276#else
277 return NULL;
278#endif
275} 279}
276 280
277static inline __u64 NFS_FILEID(const struct inode *inode) 281static inline __u64 NFS_FILEID(const struct inode *inode)