aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2007-10-26 13:32:13 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-01-30 02:05:45 -0500
commit28c494c5c8d425e15b7b82571e4df6d6bc34594d (patch)
treecbd7902da8f467182b1d5faed90349329cb8d042
parent464ad6b1ade186b53a1dae863361853326b85694 (diff)
NFS: Prevent nfs_getattr() hang during heavy write workloads
POSIX requires that ctime and mtime, as reported by the stat(2) call, reflect the activity of the most recent write(2). To that end, nfs_getattr() flushes pending dirty writes to a file before doing a GETATTR to allow the NFS server to set the file's size, ctime, and mtime properly. However, nfs_getattr() can be starved when a constant stream of application writes to a file prevents nfs_wb_nocommit() from completing. This usually results in hangs of programs doing a stat against an NFS file that is being written. "ls -l" is a common victim of this behavior. To prevent starvation, hold the file's i_mutex in nfs_getattr() to freeze applications writes temporarily so the client can more quickly obtain clean values for a file's size, mtime, and ctime. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/inode.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index cd0e57f3a00f..cc3a09db41a9 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -461,9 +461,18 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
461 int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; 461 int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
462 int err; 462 int err;
463 463
464 /* Flush out writes to the server in order to update c/mtime */ 464 /*
465 if (S_ISREG(inode->i_mode)) 465 * Flush out writes to the server in order to update c/mtime.
466 *
467 * Hold the i_mutex to suspend application writes temporarily;
468 * this prevents long-running writing applications from blocking
469 * nfs_wb_nocommit.
470 */
471 if (S_ISREG(inode->i_mode)) {
472 mutex_lock(&inode->i_mutex);
466 nfs_wb_nocommit(inode); 473 nfs_wb_nocommit(inode);
474 mutex_unlock(&inode->i_mutex);
475 }
467 476
468 /* 477 /*
469 * We may force a getattr if the user cares about atime. 478 * We may force a getattr if the user cares about atime.