diff options
author | J. Bruce Fields <bfields@citi.umich.edu> | 2009-08-21 11:27:29 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-08-21 11:27:29 -0400 |
commit | e9dc122166b8d863d3057a66ada04838e5548e52 (patch) | |
tree | 749e15bf719b64bf9113db7acd8e043d9742cb26 /fs/nfs/write.c | |
parent | 560ab42ef923aaf2e4347315bdfcc74b2708972c (diff) | |
parent | 405d8f8b1d936414da2093d4149ff790ff3f84a5 (diff) |
Merge branch 'nfs-for-2.6.32' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6 into for-2.6.32-incoming
Conflicts:
net/sunrpc/cache.c
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 105 |
1 files changed, 76 insertions, 29 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index ce728829f79a..120acadc6a84 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/file.h> | 13 | #include <linux/file.h> |
14 | #include <linux/writeback.h> | 14 | #include <linux/writeback.h> |
15 | #include <linux/swap.h> | 15 | #include <linux/swap.h> |
16 | #include <linux/migrate.h> | ||
16 | 17 | ||
17 | #include <linux/sunrpc/clnt.h> | 18 | #include <linux/sunrpc/clnt.h> |
18 | #include <linux/nfs_fs.h> | 19 | #include <linux/nfs_fs.h> |
@@ -26,6 +27,7 @@ | |||
26 | #include "internal.h" | 27 | #include "internal.h" |
27 | #include "iostat.h" | 28 | #include "iostat.h" |
28 | #include "nfs4_fs.h" | 29 | #include "nfs4_fs.h" |
30 | #include "fscache.h" | ||
29 | 31 | ||
30 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE | 32 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE |
31 | 33 | ||
@@ -87,17 +89,15 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) | |||
87 | return p; | 89 | return p; |
88 | } | 90 | } |
89 | 91 | ||
90 | static void nfs_writedata_free(struct nfs_write_data *p) | 92 | void nfs_writedata_free(struct nfs_write_data *p) |
91 | { | 93 | { |
92 | if (p && (p->pagevec != &p->page_array[0])) | 94 | if (p && (p->pagevec != &p->page_array[0])) |
93 | kfree(p->pagevec); | 95 | kfree(p->pagevec); |
94 | mempool_free(p, nfs_wdata_mempool); | 96 | mempool_free(p, nfs_wdata_mempool); |
95 | } | 97 | } |
96 | 98 | ||
97 | void nfs_writedata_release(void *data) | 99 | static void nfs_writedata_release(struct nfs_write_data *wdata) |
98 | { | 100 | { |
99 | struct nfs_write_data *wdata = data; | ||
100 | |||
101 | put_nfs_open_context(wdata->args.context); | 101 | put_nfs_open_context(wdata->args.context); |
102 | nfs_writedata_free(wdata); | 102 | nfs_writedata_free(wdata); |
103 | } | 103 | } |
@@ -202,8 +202,10 @@ static int nfs_set_page_writeback(struct page *page) | |||
202 | struct nfs_server *nfss = NFS_SERVER(inode); | 202 | struct nfs_server *nfss = NFS_SERVER(inode); |
203 | 203 | ||
204 | if (atomic_long_inc_return(&nfss->writeback) > | 204 | if (atomic_long_inc_return(&nfss->writeback) > |
205 | NFS_CONGESTION_ON_THRESH) | 205 | NFS_CONGESTION_ON_THRESH) { |
206 | set_bdi_congested(&nfss->backing_dev_info, WRITE); | 206 | set_bdi_congested(&nfss->backing_dev_info, |
207 | BLK_RW_ASYNC); | ||
208 | } | ||
207 | } | 209 | } |
208 | return ret; | 210 | return ret; |
209 | } | 211 | } |
@@ -215,27 +217,20 @@ static void nfs_end_page_writeback(struct page *page) | |||
215 | 217 | ||
216 | end_page_writeback(page); | 218 | end_page_writeback(page); |
217 | if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) | 219 | if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) |
218 | clear_bdi_congested(&nfss->backing_dev_info, WRITE); | 220 | clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); |
219 | } | 221 | } |
220 | 222 | ||
221 | /* | 223 | static struct nfs_page *nfs_find_and_lock_request(struct page *page) |
222 | * Find an associated nfs write request, and prepare to flush it out | ||
223 | * May return an error if the user signalled nfs_wait_on_request(). | ||
224 | */ | ||
225 | static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | ||
226 | struct page *page) | ||
227 | { | 224 | { |
228 | struct inode *inode = page->mapping->host; | 225 | struct inode *inode = page->mapping->host; |
229 | struct nfs_page *req; | 226 | struct nfs_page *req; |
230 | int ret; | 227 | int ret; |
231 | 228 | ||
232 | spin_lock(&inode->i_lock); | 229 | spin_lock(&inode->i_lock); |
233 | for(;;) { | 230 | for (;;) { |
234 | req = nfs_page_find_request_locked(page); | 231 | req = nfs_page_find_request_locked(page); |
235 | if (req == NULL) { | 232 | if (req == NULL) |
236 | spin_unlock(&inode->i_lock); | 233 | break; |
237 | return 0; | ||
238 | } | ||
239 | if (nfs_set_page_tag_locked(req)) | 234 | if (nfs_set_page_tag_locked(req)) |
240 | break; | 235 | break; |
241 | /* Note: If we hold the page lock, as is the case in nfs_writepage, | 236 | /* Note: If we hold the page lock, as is the case in nfs_writepage, |
@@ -247,23 +242,40 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
247 | ret = nfs_wait_on_request(req); | 242 | ret = nfs_wait_on_request(req); |
248 | nfs_release_request(req); | 243 | nfs_release_request(req); |
249 | if (ret != 0) | 244 | if (ret != 0) |
250 | return ret; | 245 | return ERR_PTR(ret); |
251 | spin_lock(&inode->i_lock); | 246 | spin_lock(&inode->i_lock); |
252 | } | 247 | } |
253 | if (test_bit(PG_CLEAN, &req->wb_flags)) { | ||
254 | spin_unlock(&inode->i_lock); | ||
255 | BUG(); | ||
256 | } | ||
257 | if (nfs_set_page_writeback(page) != 0) { | ||
258 | spin_unlock(&inode->i_lock); | ||
259 | BUG(); | ||
260 | } | ||
261 | spin_unlock(&inode->i_lock); | 248 | spin_unlock(&inode->i_lock); |
249 | return req; | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * Find an associated nfs write request, and prepare to flush it out | ||
254 | * May return an error if the user signalled nfs_wait_on_request(). | ||
255 | */ | ||
256 | static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | ||
257 | struct page *page) | ||
258 | { | ||
259 | struct nfs_page *req; | ||
260 | int ret = 0; | ||
261 | |||
262 | req = nfs_find_and_lock_request(page); | ||
263 | if (!req) | ||
264 | goto out; | ||
265 | ret = PTR_ERR(req); | ||
266 | if (IS_ERR(req)) | ||
267 | goto out; | ||
268 | |||
269 | ret = nfs_set_page_writeback(page); | ||
270 | BUG_ON(ret != 0); | ||
271 | BUG_ON(test_bit(PG_CLEAN, &req->wb_flags)); | ||
272 | |||
262 | if (!nfs_pageio_add_request(pgio, req)) { | 273 | if (!nfs_pageio_add_request(pgio, req)) { |
263 | nfs_redirty_request(req); | 274 | nfs_redirty_request(req); |
264 | return pgio->pg_error; | 275 | ret = pgio->pg_error; |
265 | } | 276 | } |
266 | return 0; | 277 | out: |
278 | return ret; | ||
267 | } | 279 | } |
268 | 280 | ||
269 | static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio) | 281 | static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio) |
@@ -1580,6 +1592,41 @@ int nfs_wb_page(struct inode *inode, struct page* page) | |||
1580 | return nfs_wb_page_priority(inode, page, FLUSH_STABLE); | 1592 | return nfs_wb_page_priority(inode, page, FLUSH_STABLE); |
1581 | } | 1593 | } |
1582 | 1594 | ||
1595 | #ifdef CONFIG_MIGRATION | ||
1596 | int nfs_migrate_page(struct address_space *mapping, struct page *newpage, | ||
1597 | struct page *page) | ||
1598 | { | ||
1599 | struct nfs_page *req; | ||
1600 | int ret; | ||
1601 | |||
1602 | if (PageFsCache(page)) | ||
1603 | nfs_fscache_release_page(page, GFP_KERNEL); | ||
1604 | |||
1605 | req = nfs_find_and_lock_request(page); | ||
1606 | ret = PTR_ERR(req); | ||
1607 | if (IS_ERR(req)) | ||
1608 | goto out; | ||
1609 | |||
1610 | ret = migrate_page(mapping, newpage, page); | ||
1611 | if (!req) | ||
1612 | goto out; | ||
1613 | if (ret) | ||
1614 | goto out_unlock; | ||
1615 | page_cache_get(newpage); | ||
1616 | req->wb_page = newpage; | ||
1617 | SetPagePrivate(newpage); | ||
1618 | set_page_private(newpage, page_private(page)); | ||
1619 | ClearPagePrivate(page); | ||
1620 | set_page_private(page, 0); | ||
1621 | page_cache_release(page); | ||
1622 | out_unlock: | ||
1623 | nfs_clear_page_tag_locked(req); | ||
1624 | nfs_release_request(req); | ||
1625 | out: | ||
1626 | return ret; | ||
1627 | } | ||
1628 | #endif | ||
1629 | |||
1583 | int __init nfs_init_writepagecache(void) | 1630 | int __init nfs_init_writepagecache(void) |
1584 | { | 1631 | { |
1585 | nfs_wdata_cachep = kmem_cache_create("nfs_write_data", | 1632 | nfs_wdata_cachep = kmem_cache_create("nfs_write_data", |