aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fscache/internal.h1
-rw-r--r--fs/fscache/page.c19
-rw-r--r--fs/fscache/stats.c6
-rw-r--r--fs/nfs/write.c3
4 files changed, 21 insertions, 8 deletions
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h
index dcb3e1d5dbf6..88a48ccb7d9e 100644
--- a/fs/fscache/internal.h
+++ b/fs/fscache/internal.h
@@ -200,6 +200,7 @@ extern atomic_t fscache_n_store_vmscan_not_storing;
200extern atomic_t fscache_n_store_vmscan_gone; 200extern atomic_t fscache_n_store_vmscan_gone;
201extern atomic_t fscache_n_store_vmscan_busy; 201extern atomic_t fscache_n_store_vmscan_busy;
202extern atomic_t fscache_n_store_vmscan_cancelled; 202extern atomic_t fscache_n_store_vmscan_cancelled;
203extern atomic_t fscache_n_store_vmscan_wait;
203 204
204extern atomic_t fscache_n_marks; 205extern atomic_t fscache_n_marks;
205extern atomic_t fscache_n_uncaches; 206extern atomic_t fscache_n_uncaches;
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index 4dbbca162620..f9b2fb3ae492 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -56,6 +56,7 @@ bool __fscache_maybe_release_page(struct fscache_cookie *cookie,
56 56
57 _enter("%p,%p,%x", cookie, page, gfp); 57 _enter("%p,%p,%x", cookie, page, gfp);
58 58
59try_again:
59 rcu_read_lock(); 60 rcu_read_lock();
60 val = radix_tree_lookup(&cookie->stores, page->index); 61 val = radix_tree_lookup(&cookie->stores, page->index);
61 if (!val) { 62 if (!val) {
@@ -104,11 +105,19 @@ bool __fscache_maybe_release_page(struct fscache_cookie *cookie,
104 return true; 105 return true;
105 106
106page_busy: 107page_busy:
107 /* we might want to wait here, but that could deadlock the allocator as 108 /* We will wait here if we're allowed to, but that could deadlock the
108 * the work threads writing to the cache may all end up sleeping 109 * allocator as the work threads writing to the cache may all end up
109 * on memory allocation */ 110 * sleeping on memory allocation, so we may need to impose a timeout
110 fscache_stat(&fscache_n_store_vmscan_busy); 111 * too. */
111 return false; 112 if (!(gfp & __GFP_WAIT)) {
113 fscache_stat(&fscache_n_store_vmscan_busy);
114 return false;
115 }
116
117 fscache_stat(&fscache_n_store_vmscan_wait);
118 __fscache_wait_on_page_write(cookie, page);
119 gfp &= ~__GFP_WAIT;
120 goto try_again;
112} 121}
113EXPORT_SYMBOL(__fscache_maybe_release_page); 122EXPORT_SYMBOL(__fscache_maybe_release_page);
114 123
diff --git a/fs/fscache/stats.c b/fs/fscache/stats.c
index 51cdaee14109..8179e8bc4a3d 100644
--- a/fs/fscache/stats.c
+++ b/fs/fscache/stats.c
@@ -69,6 +69,7 @@ atomic_t fscache_n_store_vmscan_not_storing;
69atomic_t fscache_n_store_vmscan_gone; 69atomic_t fscache_n_store_vmscan_gone;
70atomic_t fscache_n_store_vmscan_busy; 70atomic_t fscache_n_store_vmscan_busy;
71atomic_t fscache_n_store_vmscan_cancelled; 71atomic_t fscache_n_store_vmscan_cancelled;
72atomic_t fscache_n_store_vmscan_wait;
72 73
73atomic_t fscache_n_marks; 74atomic_t fscache_n_marks;
74atomic_t fscache_n_uncaches; 75atomic_t fscache_n_uncaches;
@@ -232,11 +233,12 @@ static int fscache_stats_show(struct seq_file *m, void *v)
232 atomic_read(&fscache_n_store_radix_deletes), 233 atomic_read(&fscache_n_store_radix_deletes),
233 atomic_read(&fscache_n_store_pages_over_limit)); 234 atomic_read(&fscache_n_store_pages_over_limit));
234 235
235 seq_printf(m, "VmScan : nos=%u gon=%u bsy=%u can=%u\n", 236 seq_printf(m, "VmScan : nos=%u gon=%u bsy=%u can=%u wt=%u\n",
236 atomic_read(&fscache_n_store_vmscan_not_storing), 237 atomic_read(&fscache_n_store_vmscan_not_storing),
237 atomic_read(&fscache_n_store_vmscan_gone), 238 atomic_read(&fscache_n_store_vmscan_gone),
238 atomic_read(&fscache_n_store_vmscan_busy), 239 atomic_read(&fscache_n_store_vmscan_busy),
239 atomic_read(&fscache_n_store_vmscan_cancelled)); 240 atomic_read(&fscache_n_store_vmscan_cancelled),
241 atomic_read(&fscache_n_store_vmscan_wait));
240 242
241 seq_printf(m, "Ops : pend=%u run=%u enq=%u can=%u rej=%u\n", 243 seq_printf(m, "Ops : pend=%u run=%u enq=%u can=%u rej=%u\n",
242 atomic_read(&fscache_n_op_pend), 244 atomic_read(&fscache_n_op_pend),
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 5209916e1222..b673be31590e 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1794,7 +1794,8 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage,
1794 if (PagePrivate(page)) 1794 if (PagePrivate(page))
1795 return -EBUSY; 1795 return -EBUSY;
1796 1796
1797 nfs_fscache_release_page(page, GFP_KERNEL); 1797 if (!nfs_fscache_release_page(page, GFP_KERNEL))
1798 return -EBUSY;
1798 1799
1799 return migrate_page(mapping, newpage, page, mode); 1800 return migrate_page(mapping, newpage, page, mode);
1800} 1801}