summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-02-20 04:00:02 +0300
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-03-05 23:44:54 +0300
commit420e3646bb7d93a571734034249fbb1ae1a7a5c7 (patch)
treedc3328f6df5769e275253c23d862cb0a16ab50f1
parentff778d02bf867e1733a09b34ad6dbb723b024814 (diff)
downloadlinux-420e3646bb7d93a571734034249fbb1ae1a7a5c7.tar.xz
NFS: Reduce the number of unnecessary COMMIT calls
If the caller is doing a non-blocking flush, and there are still writebacks pending on the wire, we can usually defer the COMMIT call until those writes are done. Also ensure that we honour the wbc->nonblocking flag. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/write.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index dc08a6fbde67..fc05e35da6a9 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1415,12 +1415,30 @@ static int nfs_commit_inode(struct inode *inode, int how)
static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_control *wbc)
{
- int ret;
+ struct nfs_inode *nfsi = NFS_I(inode);
+ int flags = FLUSH_SYNC;
+ int ret = 0;
- ret = nfs_commit_inode(inode,
- wbc->sync_mode == WB_SYNC_ALL ? FLUSH_SYNC : 0);
- if (ret >= 0)
+ /* Don't commit yet if this is a non-blocking flush and there are
+ * lots of outstanding writes for this mapping.
+ */
+ if (wbc->sync_mode == WB_SYNC_NONE &&
+ nfsi->ncommit <= (nfsi->npages >> 1))
+ goto out_mark_dirty;
+
+ if (wbc->nonblocking)
+ flags = 0;
+ ret = nfs_commit_inode(inode, flags);
+ if (ret >= 0) {
+ if (wbc->sync_mode == WB_SYNC_NONE) {
+ if (ret < wbc->nr_to_write)
+ wbc->nr_to_write -= ret;
+ else
+ wbc->nr_to_write = 0;
+ }
return 0;
+ }
+out_mark_dirty:
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
return ret;
}