aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2011-10-11 09:49:21 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-10-18 12:08:10 -0400
commit3236c3e1adc0c7ec83eaff1de2d06746b7c5bb28 (patch)
tree56f360348d301c7f238a7bac464440f84930e293 /fs/nfs/write.c
parent59b7c05fffba030e5d9e72324691e2f99aa69b79 (diff)
nfs: don't redirty inode when ncommit == 0 in nfs_commit_unstable_pages
commit 420e3646 allowed the kernel to reduce the number of unnecessary commit calls by skipping the commit when there are a large number of outstanding pages. However, the current test in nfs_commit_unstable_pages does not handle the edge condition properly. When ncommit == 0, then that means that the kernel doesn't need to do anything more for the inode. The current test though in the WB_SYNC_NONE case will return true, and the inode will end up being marked dirty. Once that happens the inode will never be clean until there's a WB_SYNC_ALL flush. Fix this by immediately returning from nfs_commit_unstable_pages when ncommit == 0. Mike noticed this problem initially in RHEL5 (2.6.18-based kernel) which has a backported version of 420e3646. The inode cache there was growing very large. The inode cache was unable to be shrunk since the inodes were all marked dirty. Calling sync() would essentially "fix" the problem -- the WB_SYNC_ALL flush would result in the inodes all being marked clean. What I'm not clear on is how big a problem this is in mainline kernels as the writeback code there is very different. Either way, it seems incorrect to re-mark the inode dirty in this case. Reported-by: Mike McLean <mikem@redhat.com> Signed-off-by: Jeff Layton <jlayton@redhat.com> Cc: stable@kernel.org [2.6.34+] Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 71296cc97f98..46aa4389ce13 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1554,6 +1554,10 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr
1554 int flags = FLUSH_SYNC; 1554 int flags = FLUSH_SYNC;
1555 int ret = 0; 1555 int ret = 0;
1556 1556
1557 /* no commits means nothing needs to be done */
1558 if (!nfsi->ncommit)
1559 return ret;
1560
1557 if (wbc->sync_mode == WB_SYNC_NONE) { 1561 if (wbc->sync_mode == WB_SYNC_NONE) {
1558 /* Don't commit yet if this is a non-blocking flush and there 1562 /* Don't commit yet if this is a non-blocking flush and there
1559 * are a lot of outstanding writes for this mapping. 1563 * are a lot of outstanding writes for this mapping.