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:
@@ -1472,6 +1472,7 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page)
|
|||||||
|
|
||||||
BUG_ON(!PageLocked(page));
|
BUG_ON(!PageLocked(page));
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
wait_on_page_writeback(page);
|
||||||
req = nfs_page_find_request(page);
|
req = nfs_page_find_request(page);
|
||||||
if (req == NULL)
|
if (req == NULL)
|
||||||
break;
|
break;
|
||||||
@@ -1506,31 +1507,19 @@ int nfs_wb_page(struct inode *inode, struct page *page)
|
|||||||
.range_start = range_start,
|
.range_start = range_start,
|
||||||
.range_end = range_end,
|
.range_end = range_end,
|
||||||
};
|
};
|
||||||
struct nfs_page *req;
|
|
||||||
int need_commit;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
while(PagePrivate(page)) {
|
while(PagePrivate(page)) {
|
||||||
|
wait_on_page_writeback(page);
|
||||||
if (clear_page_dirty_for_io(page)) {
|
if (clear_page_dirty_for_io(page)) {
|
||||||
ret = nfs_writepage_locked(page, &wbc);
|
ret = nfs_writepage_locked(page, &wbc);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_error;
|
goto out_error;
|
||||||
}
|
}
|
||||||
req = nfs_find_and_lock_request(page);
|
ret = sync_inode(inode, &wbc);
|
||||||
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);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_error;
|
goto out_error;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
out_error:
|
out_error:
|
||||||
return ret;
|
return ret;
|
||||||
|
Reference in New Issue
Block a user