diff options
-rw-r--r-- | fs/fscache/internal.h | 1 | ||||
-rw-r--r-- | fs/fscache/page.c | 19 | ||||
-rw-r--r-- | fs/fscache/stats.c | 6 | ||||
-rw-r--r-- | fs/nfs/write.c | 3 |
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; | |||
200 | extern atomic_t fscache_n_store_vmscan_gone; | 200 | extern atomic_t fscache_n_store_vmscan_gone; |
201 | extern atomic_t fscache_n_store_vmscan_busy; | 201 | extern atomic_t fscache_n_store_vmscan_busy; |
202 | extern atomic_t fscache_n_store_vmscan_cancelled; | 202 | extern atomic_t fscache_n_store_vmscan_cancelled; |
203 | extern atomic_t fscache_n_store_vmscan_wait; | ||
203 | 204 | ||
204 | extern atomic_t fscache_n_marks; | 205 | extern atomic_t fscache_n_marks; |
205 | extern atomic_t fscache_n_uncaches; | 206 | extern 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 | ||
59 | try_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 | ||
106 | page_busy: | 107 | page_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 | } |
113 | EXPORT_SYMBOL(__fscache_maybe_release_page); | 122 | EXPORT_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; | |||
69 | atomic_t fscache_n_store_vmscan_gone; | 69 | atomic_t fscache_n_store_vmscan_gone; |
70 | atomic_t fscache_n_store_vmscan_busy; | 70 | atomic_t fscache_n_store_vmscan_busy; |
71 | atomic_t fscache_n_store_vmscan_cancelled; | 71 | atomic_t fscache_n_store_vmscan_cancelled; |
72 | atomic_t fscache_n_store_vmscan_wait; | ||
72 | 73 | ||
73 | atomic_t fscache_n_marks; | 74 | atomic_t fscache_n_marks; |
74 | atomic_t fscache_n_uncaches; | 75 | atomic_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 | } |