The heuristics introduced by commit 420e3646 ("NFS: Reduce the number of unnecessary COMMIT calls") do not work well for large inodes being actively written to. Refine the criterion to - it has gone quiet (all data transfered to server) - has accumulated >= 4MB data to commit (so it will be large IO) - too few active commits (hence active IO) in the server Signed-off-by: Wu Fengguang <fengguang.wu@xxxxxxxxx> --- fs/nfs/write.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) --- linux-next.orig/fs/nfs/write.c 2010-12-13 21:46:21.000000000 +0800 +++ linux-next/fs/nfs/write.c 2010-12-13 21:46:21.000000000 +0800 @@ -1518,17 +1518,38 @@ out_mark_dirty: return res; } -static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_control *wbc) +static bool nfs_should_commit(struct inode *inode, + struct writeback_control *wbc) { + struct nfs_server *nfss = NFS_SERVER(inode); struct nfs_inode *nfsi = NFS_I(inode); + unsigned long npages = nfsi->npages; + unsigned long to_commit = nfsi->ncommit; + unsigned long in_commit = atomic_long_read(&nfss->in_commit); + + /* no more active writes */ + if (to_commit == npages) + return true; + + /* big enough */ + if (to_commit >= MIN_WRITEBACK_PAGES) + return true; + + /* active commits drop low: kick more IO for the server disk */ + if (to_commit > in_commit / 2) + return true; + + return false; +} + +static int nfs_commit_unstable_pages(struct inode *inode, + struct writeback_control *wbc) +{ int flags = FLUSH_SYNC; int ret = 0; if (wbc->sync_mode == WB_SYNC_NONE) { - /* Don't commit yet if this is a non-blocking flush and there - * are a lot of outstanding writes for this mapping. - */ - if (nfsi->ncommit <= (nfsi->npages >> 1)) + if (!nfs_should_commit(inode, wbc)) goto out_mark_dirty; /* don't wait for the COMMIT response */ -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html