aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/caching/fscache.txt4
-rw-r--r--Documentation/filesystems/caching/netfs-api.txt21
-rw-r--r--fs/9p/cache.c14
-rw-r--r--fs/afs/file.c15
-rw-r--r--fs/fscache/internal.h5
-rw-r--r--fs/fscache/page.c79
-rw-r--r--fs/fscache/stats.c11
-rw-r--r--fs/nfs/fscache.c10
-rw-r--r--include/linux/fscache-cache.h1
-rw-r--r--include/linux/fscache.h27
10 files changed, 152 insertions, 35 deletions
diff --git a/Documentation/filesystems/caching/fscache.txt b/Documentation/filesystems/caching/fscache.txt
index 057a3c71d524..7097fd29fb3d 100644
--- a/Documentation/filesystems/caching/fscache.txt
+++ b/Documentation/filesystems/caching/fscache.txt
@@ -272,6 +272,10 @@ proc files.
272 pgs=N Number of pages given store req processing time 272 pgs=N Number of pages given store req processing time
273 rxd=N Number of store reqs deleted from tracking tree 273 rxd=N Number of store reqs deleted from tracking tree
274 olm=N Number of store reqs over store limit 274 olm=N Number of store reqs over store limit
275 VmScan nos=N Number of release reqs against pages with no pending store
276 gon=N Number of release reqs against pages stored by time lock granted
277 bsy=N Number of release reqs ignored due to in-progress store
278 can=N Number of page stores cancelled due to release req
275 Ops pend=N Number of times async ops added to pending queues 279 Ops pend=N Number of times async ops added to pending queues
276 run=N Number of times async ops given CPU time 280 run=N Number of times async ops given CPU time
277 enq=N Number of times async ops queued for processing 281 enq=N Number of times async ops queued for processing
diff --git a/Documentation/filesystems/caching/netfs-api.txt b/Documentation/filesystems/caching/netfs-api.txt
index 2666b1ed5e9e..1902c57b72ef 100644
--- a/Documentation/filesystems/caching/netfs-api.txt
+++ b/Documentation/filesystems/caching/netfs-api.txt
@@ -641,7 +641,7 @@ data file must be retired (see the relinquish cookie function below).
641 641
642Furthermore, note that this does not cancel the asynchronous read or write 642Furthermore, note that this does not cancel the asynchronous read or write
643operation started by the read/alloc and write functions, so the page 643operation started by the read/alloc and write functions, so the page
644invalidation and release functions must use: 644invalidation functions must use:
645 645
646 bool fscache_check_page_write(struct fscache_cookie *cookie, 646 bool fscache_check_page_write(struct fscache_cookie *cookie,
647 struct page *page); 647 struct page *page);
@@ -654,6 +654,25 @@ to see if a page is being written to the cache, and:
654to wait for it to finish if it is. 654to wait for it to finish if it is.
655 655
656 656
657When releasepage() is being implemented, a special FS-Cache function exists to
658manage the heuristics of coping with vmscan trying to eject pages, which may
659conflict with the cache trying to write pages to the cache (which may itself
660need to allocate memory):
661
662 bool fscache_maybe_release_page(struct fscache_cookie *cookie,
663 struct page *page,
664 gfp_t gfp);
665
666This takes the netfs cookie, and the page and gfp arguments as supplied to
667releasepage(). It will return false if the page cannot be released yet for
668some reason and if it returns true, the page has been uncached and can now be
669released.
670
671To make a page available for release, this function may wait for an outstanding
672storage request to complete, or it may attempt to cancel the storage request -
673in which case the page will not be stored in the cache this time.
674
675
657========================== 676==========================
658INDEX AND DATA FILE UPDATE 677INDEX AND DATA FILE UPDATE
659========================== 678==========================
diff --git a/fs/9p/cache.c b/fs/9p/cache.c
index 51c94e26a346..bcc5357a9069 100644
--- a/fs/9p/cache.c
+++ b/fs/9p/cache.c
@@ -343,18 +343,7 @@ int __v9fs_fscache_release_page(struct page *page, gfp_t gfp)
343 343
344 BUG_ON(!vcookie->fscache); 344 BUG_ON(!vcookie->fscache);
345 345
346 if (PageFsCache(page)) { 346 return fscache_maybe_release_page(vnode->cache, page, gfp);
347 if (fscache_check_page_write(vcookie->fscache, page)) {
348 if (!(gfp & __GFP_WAIT))
349 return 0;
350 fscache_wait_on_page_write(vcookie->fscache, page);
351 }
352
353 fscache_uncache_page(vcookie->fscache, page);
354 ClearPageFsCache(page);
355 }
356
357 return 1;
358} 347}
359 348
360void __v9fs_fscache_invalidate_page(struct page *page) 349void __v9fs_fscache_invalidate_page(struct page *page)
@@ -368,7 +357,6 @@ void __v9fs_fscache_invalidate_page(struct page *page)
368 fscache_wait_on_page_write(vcookie->fscache, page); 357 fscache_wait_on_page_write(vcookie->fscache, page);
369 BUG_ON(!PageLocked(page)); 358 BUG_ON(!PageLocked(page));
370 fscache_uncache_page(vcookie->fscache, page); 359 fscache_uncache_page(vcookie->fscache, page);
371 ClearPageFsCache(page);
372 } 360 }
373} 361}
374 362
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 681c2a7b013f..39b301662f22 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -315,7 +315,6 @@ static void afs_invalidatepage(struct page *page, unsigned long offset)
315 struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 315 struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
316 fscache_wait_on_page_write(vnode->cache, page); 316 fscache_wait_on_page_write(vnode->cache, page);
317 fscache_uncache_page(vnode->cache, page); 317 fscache_uncache_page(vnode->cache, page);
318 ClearPageFsCache(page);
319 } 318 }
320#endif 319#endif
321 320
@@ -349,17 +348,9 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags)
349 /* deny if page is being written to the cache and the caller hasn't 348 /* deny if page is being written to the cache and the caller hasn't
350 * elected to wait */ 349 * elected to wait */
351#ifdef CONFIG_AFS_FSCACHE 350#ifdef CONFIG_AFS_FSCACHE
352 if (PageFsCache(page)) { 351 if (!fscache_maybe_release_page(vnode->cache, page, gfp_flags)) {
353 if (fscache_check_page_write(vnode->cache, page)) { 352 _leave(" = F [cache busy]");
354 if (!(gfp_flags & __GFP_WAIT)) { 353 return 0;
355 _leave(" = F [cache busy]");
356 return 0;
357 }
358 fscache_wait_on_page_write(vnode->cache, page);
359 }
360
361 fscache_uncache_page(vnode->cache, page);
362 ClearPageFsCache(page);
363 } 354 }
364#endif 355#endif
365 356
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h
index a0769872b19c..e5046519b153 100644
--- a/fs/fscache/internal.h
+++ b/fs/fscache/internal.h
@@ -180,6 +180,11 @@ extern atomic_t fscache_n_store_pages;
180extern atomic_t fscache_n_store_radix_deletes; 180extern atomic_t fscache_n_store_radix_deletes;
181extern atomic_t fscache_n_store_pages_over_limit; 181extern atomic_t fscache_n_store_pages_over_limit;
182 182
183extern atomic_t fscache_n_store_vmscan_not_storing;
184extern atomic_t fscache_n_store_vmscan_gone;
185extern atomic_t fscache_n_store_vmscan_busy;
186extern atomic_t fscache_n_store_vmscan_cancelled;
187
183extern atomic_t fscache_n_marks; 188extern atomic_t fscache_n_marks;
184extern atomic_t fscache_n_uncaches; 189extern atomic_t fscache_n_uncaches;
185 190
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index 022a5da8e130..fc76798bd968 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -43,6 +43,75 @@ void __fscache_wait_on_page_write(struct fscache_cookie *cookie, struct page *pa
43EXPORT_SYMBOL(__fscache_wait_on_page_write); 43EXPORT_SYMBOL(__fscache_wait_on_page_write);
44 44
45/* 45/*
46 * decide whether a page can be released, possibly by cancelling a store to it
47 * - we're allowed to sleep if __GFP_WAIT is flagged
48 */
49bool __fscache_maybe_release_page(struct fscache_cookie *cookie,
50 struct page *page,
51 gfp_t gfp)
52{
53 struct page *xpage;
54 void *val;
55
56 _enter("%p,%p,%x", cookie, page, gfp);
57
58 rcu_read_lock();
59 val = radix_tree_lookup(&cookie->stores, page->index);
60 if (!val) {
61 rcu_read_unlock();
62 fscache_stat(&fscache_n_store_vmscan_not_storing);
63 __fscache_uncache_page(cookie, page);
64 return true;
65 }
66
67 /* see if the page is actually undergoing storage - if so we can't get
68 * rid of it till the cache has finished with it */
69 if (radix_tree_tag_get(&cookie->stores, page->index,
70 FSCACHE_COOKIE_STORING_TAG)) {
71 rcu_read_unlock();
72 goto page_busy;
73 }
74
75 /* the page is pending storage, so we attempt to cancel the store and
76 * discard the store request so that the page can be reclaimed */
77 spin_lock(&cookie->stores_lock);
78 rcu_read_unlock();
79
80 if (radix_tree_tag_get(&cookie->stores, page->index,
81 FSCACHE_COOKIE_STORING_TAG)) {
82 /* the page started to undergo storage whilst we were looking,
83 * so now we can only wait or return */
84 spin_unlock(&cookie->stores_lock);
85 goto page_busy;
86 }
87
88 xpage = radix_tree_delete(&cookie->stores, page->index);
89 spin_unlock(&cookie->stores_lock);
90
91 if (xpage) {
92 fscache_stat(&fscache_n_store_vmscan_cancelled);
93 fscache_stat(&fscache_n_store_radix_deletes);
94 ASSERTCMP(xpage, ==, page);
95 } else {
96 fscache_stat(&fscache_n_store_vmscan_gone);
97 }
98
99 wake_up_bit(&cookie->flags, 0);
100 if (xpage)
101 page_cache_release(xpage);
102 __fscache_uncache_page(cookie, page);
103 return true;
104
105page_busy:
106 /* we might want to wait here, but that could deadlock the allocator as
107 * the slow-work threads writing to the cache may all end up sleeping
108 * on memory allocation */
109 fscache_stat(&fscache_n_store_vmscan_busy);
110 return false;
111}
112EXPORT_SYMBOL(__fscache_maybe_release_page);
113
114/*
46 * note that a page has finished being written to the cache 115 * note that a page has finished being written to the cache
47 */ 116 */
48static void fscache_end_page_write(struct fscache_object *object, 117static void fscache_end_page_write(struct fscache_object *object,
@@ -57,6 +126,8 @@ static void fscache_end_page_write(struct fscache_object *object,
57 /* delete the page from the tree if it is now no longer 126 /* delete the page from the tree if it is now no longer
58 * pending */ 127 * pending */
59 spin_lock(&cookie->stores_lock); 128 spin_lock(&cookie->stores_lock);
129 radix_tree_tag_clear(&cookie->stores, page->index,
130 FSCACHE_COOKIE_STORING_TAG);
60 if (!radix_tree_tag_get(&cookie->stores, page->index, 131 if (!radix_tree_tag_get(&cookie->stores, page->index,
61 FSCACHE_COOKIE_PENDING_TAG)) { 132 FSCACHE_COOKIE_PENDING_TAG)) {
62 fscache_stat(&fscache_n_store_radix_deletes); 133 fscache_stat(&fscache_n_store_radix_deletes);
@@ -640,8 +711,12 @@ static void fscache_write_op(struct fscache_operation *_op)
640 goto superseded; 711 goto superseded;
641 } 712 }
642 713
643 radix_tree_tag_clear(&cookie->stores, page->index, 714 if (page) {
644 FSCACHE_COOKIE_PENDING_TAG); 715 radix_tree_tag_set(&cookie->stores, page->index,
716 FSCACHE_COOKIE_STORING_TAG);
717 radix_tree_tag_clear(&cookie->stores, page->index,
718 FSCACHE_COOKIE_PENDING_TAG);
719 }
645 720
646 spin_unlock(&cookie->stores_lock); 721 spin_unlock(&cookie->stores_lock);
647 spin_unlock(&object->lock); 722 spin_unlock(&object->lock);
diff --git a/fs/fscache/stats.c b/fs/fscache/stats.c
index 045ba396dbf2..cda69994e06d 100644
--- a/fs/fscache/stats.c
+++ b/fs/fscache/stats.c
@@ -63,6 +63,11 @@ atomic_t fscache_n_store_pages;
63atomic_t fscache_n_store_radix_deletes; 63atomic_t fscache_n_store_radix_deletes;
64atomic_t fscache_n_store_pages_over_limit; 64atomic_t fscache_n_store_pages_over_limit;
65 65
66atomic_t fscache_n_store_vmscan_not_storing;
67atomic_t fscache_n_store_vmscan_gone;
68atomic_t fscache_n_store_vmscan_busy;
69atomic_t fscache_n_store_vmscan_cancelled;
70
66atomic_t fscache_n_marks; 71atomic_t fscache_n_marks;
67atomic_t fscache_n_uncaches; 72atomic_t fscache_n_uncaches;
68 73
@@ -211,6 +216,12 @@ static int fscache_stats_show(struct seq_file *m, void *v)
211 atomic_read(&fscache_n_store_radix_deletes), 216 atomic_read(&fscache_n_store_radix_deletes),
212 atomic_read(&fscache_n_store_pages_over_limit)); 217 atomic_read(&fscache_n_store_pages_over_limit));
213 218
219 seq_printf(m, "VmScan : nos=%u gon=%u bsy=%u can=%u\n",
220 atomic_read(&fscache_n_store_vmscan_not_storing),
221 atomic_read(&fscache_n_store_vmscan_gone),
222 atomic_read(&fscache_n_store_vmscan_busy),
223 atomic_read(&fscache_n_store_vmscan_cancelled));
224
214 seq_printf(m, "Ops : pend=%u run=%u enq=%u can=%u rej=%u\n", 225 seq_printf(m, "Ops : pend=%u run=%u enq=%u can=%u rej=%u\n",
215 atomic_read(&fscache_n_op_pend), 226 atomic_read(&fscache_n_op_pend),
216 atomic_read(&fscache_n_op_run), 227 atomic_read(&fscache_n_op_run),
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index 70fad69eb959..fa588006588d 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -359,17 +359,13 @@ int nfs_fscache_release_page(struct page *page, gfp_t gfp)
359 359
360 BUG_ON(!cookie); 360 BUG_ON(!cookie);
361 361
362 if (fscache_check_page_write(cookie, page)) {
363 if (!(gfp & __GFP_WAIT))
364 return 0;
365 fscache_wait_on_page_write(cookie, page);
366 }
367
368 if (PageFsCache(page)) { 362 if (PageFsCache(page)) {
369 dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n", 363 dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n",
370 cookie, page, nfsi); 364 cookie, page, nfsi);
371 365
372 fscache_uncache_page(cookie, page); 366 if (!fscache_maybe_release_page(cookie, page, gfp))
367 return 0;
368
373 nfs_add_fscache_stats(page->mapping->host, 369 nfs_add_fscache_stats(page->mapping->host,
374 NFSIOS_FSCACHE_PAGES_UNCACHED, 1); 370 NFSIOS_FSCACHE_PAGES_UNCACHED, 1);
375 } 371 }
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index f3aa4bdafef6..4750d5fb419f 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -317,6 +317,7 @@ struct fscache_cookie {
317 void *netfs_data; /* back pointer to netfs */ 317 void *netfs_data; /* back pointer to netfs */
318 struct radix_tree_root stores; /* pages to be stored on this cookie */ 318 struct radix_tree_root stores; /* pages to be stored on this cookie */
319#define FSCACHE_COOKIE_PENDING_TAG 0 /* pages tag: pending write to cache */ 319#define FSCACHE_COOKIE_PENDING_TAG 0 /* pages tag: pending write to cache */
320#define FSCACHE_COOKIE_STORING_TAG 1 /* pages tag: writing to cache */
320 321
321 unsigned long flags; 322 unsigned long flags;
322#define FSCACHE_COOKIE_LOOKING_UP 0 /* T if non-index cookie being looked up still */ 323#define FSCACHE_COOKIE_LOOKING_UP 0 /* T if non-index cookie being looked up still */
diff --git a/include/linux/fscache.h b/include/linux/fscache.h
index 6d8ee466e0a0..595ce49288b7 100644
--- a/include/linux/fscache.h
+++ b/include/linux/fscache.h
@@ -202,6 +202,8 @@ extern int __fscache_write_page(struct fscache_cookie *, struct page *, gfp_t);
202extern void __fscache_uncache_page(struct fscache_cookie *, struct page *); 202extern void __fscache_uncache_page(struct fscache_cookie *, struct page *);
203extern bool __fscache_check_page_write(struct fscache_cookie *, struct page *); 203extern bool __fscache_check_page_write(struct fscache_cookie *, struct page *);
204extern void __fscache_wait_on_page_write(struct fscache_cookie *, struct page *); 204extern void __fscache_wait_on_page_write(struct fscache_cookie *, struct page *);
205extern bool __fscache_maybe_release_page(struct fscache_cookie *, struct page *,
206 gfp_t);
205 207
206/** 208/**
207 * fscache_register_netfs - Register a filesystem as desiring caching services 209 * fscache_register_netfs - Register a filesystem as desiring caching services
@@ -615,4 +617,29 @@ void fscache_wait_on_page_write(struct fscache_cookie *cookie,
615 __fscache_wait_on_page_write(cookie, page); 617 __fscache_wait_on_page_write(cookie, page);
616} 618}
617 619
620/**
621 * fscache_maybe_release_page - Consider releasing a page, cancelling a store
622 * @cookie: The cookie representing the cache object
623 * @page: The netfs page that is being cached.
624 * @gfp: The gfp flags passed to releasepage()
625 *
626 * Consider releasing a page for the vmscan algorithm, on behalf of the netfs's
627 * releasepage() call. A storage request on the page may cancelled if it is
628 * not currently being processed.
629 *
630 * The function returns true if the page no longer has a storage request on it,
631 * and false if a storage request is left in place. If true is returned, the
632 * page will have been passed to fscache_uncache_page(). If false is returned
633 * the page cannot be freed yet.
634 */
635static inline
636bool fscache_maybe_release_page(struct fscache_cookie *cookie,
637 struct page *page,
638 gfp_t gfp)
639{
640 if (fscache_cookie_valid(cookie) && PageFsCache(page))
641 return __fscache_maybe_release_page(cookie, page, gfp);
642 return false;
643}
644
618#endif /* _LINUX_FSCACHE_H */ 645#endif /* _LINUX_FSCACHE_H */