diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-12-05 00:35:41 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-12-06 10:46:39 -0500 |
commit | 4d770ccf4257b23a7ca2a85de1b1c22657b581d8 (patch) | |
tree | 6d4002f6a9497e3eb3dd5dee6b27e9c5dc28e46e /fs/nfs/write.c | |
parent | 1a54533ec8d92a5edae97ec6ae10023ee71c4b46 (diff) | |
download | lwn-4d770ccf4257b23a7ca2a85de1b1c22657b581d8.tar.gz lwn-4d770ccf4257b23a7ca2a85de1b1c22657b581d8.zip |
NFS: Ensure that nfs_wb_page() calls writepage when necessary.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 266fea71cfc0..0eca6a542106 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -247,7 +247,7 @@ static int wb_priority(struct writeback_control *wbc) /* * Write an mmapped page to the server. */ -int nfs_writepage(struct page *page, struct writeback_control *wbc) +static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc) { struct nfs_open_context *ctx; struct inode *inode = page->mapping->host; @@ -265,7 +265,7 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc) if (!flushme) goto out; /* Ensure we've flushed out the invalid write */ - nfs_wb_page_priority(inode, page, wb_priority(wbc)); + nfs_wb_page_priority(inode, page, wb_priority(wbc) | FLUSH_STABLE | FLUSH_NOWRITEPAGE); } offset = nfs_page_length(page); @@ -283,6 +283,14 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc) out: if (!wbc->for_writepages) nfs_flush_mapping(page->mapping, wbc, wb_priority(wbc)); + return err; +} + +int nfs_writepage(struct page *page, struct writeback_control *wbc) +{ + int err; + + err = nfs_writepage_locked(page, wbc); unlock_page(page); return err; } @@ -1435,8 +1443,26 @@ static int nfs_wb_page_priority(struct inode *inode, struct page *page, int how) { loff_t range_start = page_offset(page); loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); + struct writeback_control wbc = { + .bdi = page->mapping->backing_dev_info, + .sync_mode = WB_SYNC_ALL, + .nr_to_write = LONG_MAX, + .range_start = range_start, + .range_end = range_end, + }; + int ret; - return nfs_sync_mapping_range(inode->i_mapping, range_start, range_end, how | FLUSH_STABLE); + BUG_ON(!PageLocked(page)); + if (!(how & FLUSH_NOWRITEPAGE) && clear_page_dirty_for_io(page)) { + ret = nfs_writepage_locked(page, &wbc); + if (ret < 0) + goto out; + } + ret = nfs_sync_mapping_wait(page->mapping, &wbc, how); + if (ret >= 0) + return 0; +out: + return ret; } /* @@ -1444,7 +1470,7 @@ static int nfs_wb_page_priority(struct inode *inode, struct page *page, int how) */ int nfs_wb_page(struct inode *inode, struct page* page) { - return nfs_wb_page_priority(inode, page, 0); + return nfs_wb_page_priority(inode, page, FLUSH_STABLE); } int nfs_set_page_dirty(struct page *page) |