NFS: Ensure that nfs_wb_page() waits for Pg_writeback to clear

Neil Brown reports that he is seeing the BUG_ON(ret == 0) trigger in
nfs_page_async_flush. According to the trace in
     https://bugzilla.novell.com/show_bug.cgi?id=599628
the problem appears to be due to nfs_wb_page() not waiting for the
PG_writeback flag to clear.

There is a ditto problem in nfs_wb_page_cancel()

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
Trond Myklebust 2010-04-27 18:33:54 -04:00
parent 71d0a6112a
commit ba8b06e67e

View File

@ -1472,6 +1472,7 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page)
BUG_ON(!PageLocked(page));
for (;;) {
wait_on_page_writeback(page);
req = nfs_page_find_request(page);
if (req == NULL)
break;
@ -1506,31 +1507,19 @@ int nfs_wb_page(struct inode *inode, struct page *page)
.range_start = range_start,
.range_end = range_end,
};
struct nfs_page *req;
int need_commit;
int ret;
while(PagePrivate(page)) {
wait_on_page_writeback(page);
if (clear_page_dirty_for_io(page)) {
ret = nfs_writepage_locked(page, &wbc);
if (ret < 0)
goto out_error;
}
req = nfs_find_and_lock_request(page);
if (!req)
break;
if (IS_ERR(req)) {
ret = PTR_ERR(req);
goto out_error;
}
need_commit = test_bit(PG_CLEAN, &req->wb_flags);
nfs_clear_page_tag_locked(req);
if (need_commit) {
ret = nfs_commit_inode(inode, FLUSH_SYNC);
ret = sync_inode(inode, &wbc);
if (ret < 0)
goto out_error;
}
}
return 0;
out_error:
return ret;