aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-07-30 15:31:57 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-07-30 15:38:56 -0400
commitcfb506e1d330387dfaf334dd493b3773d388863d (patch)
tree4c376c8ff15082553f8f0f64a65dfe573072f7c7
parentb608b283a962caaa280756bc8563016a71712acf (diff)
NFS: Ensure that writepage respects the nonblock flag
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/write.c23
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)
222 clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); 222 clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC);
223} 223}
224 224
225static struct nfs_page *nfs_find_and_lock_request(struct page *page) 225static struct nfs_page *nfs_find_and_lock_request(struct page *page, bool nonblock)
226{ 226{
227 struct inode *inode = page->mapping->host; 227 struct inode *inode = page->mapping->host;
228 struct nfs_page *req; 228 struct nfs_page *req;
@@ -241,7 +241,10 @@ static struct nfs_page *nfs_find_and_lock_request(struct page *page)
241 * request as dirty (in which case we don't care). 241 * request as dirty (in which case we don't care).
242 */ 242 */
243 spin_unlock(&inode->i_lock); 243 spin_unlock(&inode->i_lock);
244 ret = nfs_wait_on_request(req); 244 if (!nonblock)
245 ret = nfs_wait_on_request(req);
246 else
247 ret = -EAGAIN;
245 nfs_release_request(req); 248 nfs_release_request(req);
246 if (ret != 0) 249 if (ret != 0)
247 return ERR_PTR(ret); 250 return ERR_PTR(ret);
@@ -256,12 +259,12 @@ static struct nfs_page *nfs_find_and_lock_request(struct page *page)
256 * May return an error if the user signalled nfs_wait_on_request(). 259 * May return an error if the user signalled nfs_wait_on_request().
257 */ 260 */
258static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, 261static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
259 struct page *page) 262 struct page *page, bool nonblock)
260{ 263{
261 struct nfs_page *req; 264 struct nfs_page *req;
262 int ret = 0; 265 int ret = 0;
263 266
264 req = nfs_find_and_lock_request(page); 267 req = nfs_find_and_lock_request(page, nonblock);
265 if (!req) 268 if (!req)
266 goto out; 269 goto out;
267 ret = PTR_ERR(req); 270 ret = PTR_ERR(req);
@@ -283,12 +286,20 @@ out:
283static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio) 286static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio)
284{ 287{
285 struct inode *inode = page->mapping->host; 288 struct inode *inode = page->mapping->host;
289 int ret;
286 290
287 nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); 291 nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE);
288 nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); 292 nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1);
289 293
290 nfs_pageio_cond_complete(pgio, page->index); 294 nfs_pageio_cond_complete(pgio, page->index);
291 return nfs_page_async_flush(pgio, page); 295 ret = nfs_page_async_flush(pgio, page,
296 wbc->sync_mode == WB_SYNC_NONE ||
297 wbc->nonblocking != 0);
298 if (ret == -EAGAIN) {
299 redirty_page_for_writepage(wbc, page);
300 ret = 0;
301 }
302 return ret;
292} 303}
293 304
294/* 305/*
@@ -1546,7 +1557,7 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage,
1546 1557
1547 nfs_fscache_release_page(page, GFP_KERNEL); 1558 nfs_fscache_release_page(page, GFP_KERNEL);
1548 1559
1549 req = nfs_find_and_lock_request(page); 1560 req = nfs_find_and_lock_request(page, false);
1550 ret = PTR_ERR(req); 1561 ret = PTR_ERR(req);
1551 if (IS_ERR(req)) 1562 if (IS_ERR(req))
1552 goto out; 1563 goto out;