diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2007-10-26 13:32:13 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-01-30 02:05:45 -0500 |
commit | 28c494c5c8d425e15b7b82571e4df6d6bc34594d (patch) | |
tree | cbd7902da8f467182b1d5faed90349329cb8d042 /fs/nfs | |
parent | 464ad6b1ade186b53a1dae863361853326b85694 (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>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/inode.c | 13 |
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. |