diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2009-12-07 01:28:35 -0500 |
---|---|---|
committer | Frederic Weisbecker <fweisbec@gmail.com> | 2009-12-07 01:29:22 -0500 |
commit | 6548698f929814375fa5d62ae1db96959b0418c1 (patch) | |
tree | 340924ae82cb0946aa15045b2b72186de52a8146 /fs/nfs/write.c | |
parent | 1d2c6cfd40b2dece3bb958cbbc405a2c1536ab75 (diff) | |
parent | 22763c5cf3690a681551162c15d34d935308c8d7 (diff) |
Merge commit 'v2.6.32' into reiserfs/kill-bkl
Merge-reason: The tree was based 2.6.31. It's better to be up to date
with 2.6.32. Although no conflicting changes were made in between,
it gives benchmarking results closer to the lastest kernel behaviour.
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 92 |
1 files changed, 69 insertions, 23 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index a34fae21fe10..53eb26c16b50 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 | ||
@@ -218,24 +220,17 @@ static void nfs_end_page_writeback(struct page *page) | |||
218 | clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); | 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) |
@@ -1478,7 +1490,6 @@ static int nfs_write_mapping(struct address_space *mapping, int how) | |||
1478 | .nr_to_write = LONG_MAX, | 1490 | .nr_to_write = LONG_MAX, |
1479 | .range_start = 0, | 1491 | .range_start = 0, |
1480 | .range_end = LLONG_MAX, | 1492 | .range_end = LLONG_MAX, |
1481 | .for_writepages = 1, | ||
1482 | }; | 1493 | }; |
1483 | 1494 | ||
1484 | return __nfs_write_mapping(mapping, &wbc, how); | 1495 | return __nfs_write_mapping(mapping, &wbc, how); |
@@ -1580,6 +1591,41 @@ int nfs_wb_page(struct inode *inode, struct page* page) | |||
1580 | return nfs_wb_page_priority(inode, page, FLUSH_STABLE); | 1591 | return nfs_wb_page_priority(inode, page, FLUSH_STABLE); |
1581 | } | 1592 | } |
1582 | 1593 | ||
1594 | #ifdef CONFIG_MIGRATION | ||
1595 | int nfs_migrate_page(struct address_space *mapping, struct page *newpage, | ||
1596 | struct page *page) | ||
1597 | { | ||
1598 | struct nfs_page *req; | ||
1599 | int ret; | ||
1600 | |||
1601 | if (PageFsCache(page)) | ||
1602 | nfs_fscache_release_page(page, GFP_KERNEL); | ||
1603 | |||
1604 | req = nfs_find_and_lock_request(page); | ||
1605 | ret = PTR_ERR(req); | ||
1606 | if (IS_ERR(req)) | ||
1607 | goto out; | ||
1608 | |||
1609 | ret = migrate_page(mapping, newpage, page); | ||
1610 | if (!req) | ||
1611 | goto out; | ||
1612 | if (ret) | ||
1613 | goto out_unlock; | ||
1614 | page_cache_get(newpage); | ||
1615 | req->wb_page = newpage; | ||
1616 | SetPagePrivate(newpage); | ||
1617 | set_page_private(newpage, page_private(page)); | ||
1618 | ClearPagePrivate(page); | ||
1619 | set_page_private(page, 0); | ||
1620 | page_cache_release(page); | ||
1621 | out_unlock: | ||
1622 | nfs_clear_page_tag_locked(req); | ||
1623 | nfs_release_request(req); | ||
1624 | out: | ||
1625 | return ret; | ||
1626 | } | ||
1627 | #endif | ||
1628 | |||
1583 | int __init nfs_init_writepagecache(void) | 1629 | int __init nfs_init_writepagecache(void) |
1584 | { | 1630 | { |
1585 | nfs_wdata_cachep = kmem_cache_create("nfs_write_data", | 1631 | nfs_wdata_cachep = kmem_cache_create("nfs_write_data", |