diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-07-30 21:31:57 +0200 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-07-30 21:38:56 +0200 |
commit | cfb506e1d330387dfaf334dd493b3773d388863d (patch) | |
tree | 4c376c8ff15082553f8f0f64a65dfe573072f7c7 /fs | |
parent | NFS: kswapd must not block in nfs_release_page (diff) | |
download | linux-cfb506e1d330387dfaf334dd493b3773d388863d.tar.xz linux-cfb506e1d330387dfaf334dd493b3773d388863d.zip |
NFS: Ensure that writepage respects the nonblock flag
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/write.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 0a6c65a1f9d7..bb72ad34d51d 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -222,7 +222,7 @@ static void nfs_end_page_writeback(struct page *page) clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); } -static struct nfs_page *nfs_find_and_lock_request(struct page *page) +static struct nfs_page *nfs_find_and_lock_request(struct page *page, bool nonblock) { struct inode *inode = page->mapping->host; struct nfs_page *req; @@ -241,7 +241,10 @@ static struct nfs_page *nfs_find_and_lock_request(struct page *page) * request as dirty (in which case we don't care). */ spin_unlock(&inode->i_lock); - ret = nfs_wait_on_request(req); + if (!nonblock) + ret = nfs_wait_on_request(req); + else + ret = -EAGAIN; nfs_release_request(req); if (ret != 0) return ERR_PTR(ret); @@ -256,12 +259,12 @@ static struct nfs_page *nfs_find_and_lock_request(struct page *page) * May return an error if the user signalled nfs_wait_on_request(). */ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, - struct page *page) + struct page *page, bool nonblock) { struct nfs_page *req; int ret = 0; - req = nfs_find_and_lock_request(page); + req = nfs_find_and_lock_request(page, nonblock); if (!req) goto out; ret = PTR_ERR(req); @@ -283,12 +286,20 @@ out: static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio) { struct inode *inode = page->mapping->host; + int ret; nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); nfs_pageio_cond_complete(pgio, page->index); - return nfs_page_async_flush(pgio, page); + ret = nfs_page_async_flush(pgio, page, + wbc->sync_mode == WB_SYNC_NONE || + wbc->nonblocking != 0); + if (ret == -EAGAIN) { + redirty_page_for_writepage(wbc, page); + ret = 0; + } + return ret; } /* @@ -1546,7 +1557,7 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage, nfs_fscache_release_page(page, GFP_KERNEL); - req = nfs_find_and_lock_request(page); + req = nfs_find_and_lock_request(page, false); ret = PTR_ERR(req); if (IS_ERR(req)) goto out; |