aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-04-11 16:03:54 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-04-19 16:52:58 -0400
commit73e3302f60c0e11a0db0b34b903f591139c4f937 (patch)
tree7f1a4be9e1b534bf9eb87fabaa1a15e468221a9e
parent080a1f148df0615f7a610e4776dd8f3fb706f54f (diff)
NFS: Fix nfs_wb_page() to always exit with an error or a clean page
It is possible for nfs_wb_page() to sometimes exit with 0 return value, yet the page is left in a dirty state. For instance in the case where the server rebooted, and the COMMIT request failed, then all the previously "clean" pages which were cached by the server, but were not guaranteed to have been writted out to disk, have to be redirtied and resent to the server. The fix is to have nfs_wb_page_priority() check that the page is clean before it exits... This fixes a condition that triggers the BUG_ON(PagePrivate(page)) in nfs_create_request() when we're in the nfs_readpage() path. Also eliminate a redundant BUG_ON(!PageLocked(page)) while we're at it. It turns out that clear_page_dirty_for_io() has the exact same test. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/write.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index ce40cadb15db..997b42aa3702 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1493,18 +1493,19 @@ static int nfs_wb_page_priority(struct inode *inode, struct page *page,
1493 }; 1493 };
1494 int ret; 1494 int ret;
1495 1495
1496 BUG_ON(!PageLocked(page)); 1496 do {
1497 if (clear_page_dirty_for_io(page)) { 1497 if (clear_page_dirty_for_io(page)) {
1498 ret = nfs_writepage_locked(page, &wbc); 1498 ret = nfs_writepage_locked(page, &wbc);
1499 if (ret < 0)
1500 goto out_error;
1501 } else if (!PagePrivate(page))
1502 break;
1503 ret = nfs_sync_mapping_wait(page->mapping, &wbc, how);
1499 if (ret < 0) 1504 if (ret < 0)
1500 goto out; 1505 goto out_error;
1501 } 1506 } while (PagePrivate(page));
1502 if (!PagePrivate(page)) 1507 return 0;
1503 return 0; 1508out_error:
1504 ret = nfs_sync_mapping_wait(page->mapping, &wbc, how);
1505 if (ret >= 0)
1506 return 0;
1507out:
1508 __mark_inode_dirty(inode, I_DIRTY_PAGES); 1509 __mark_inode_dirty(inode, I_DIRTY_PAGES);
1509 return ret; 1510 return ret;
1510} 1511}