forked from Minki/linux
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>
This commit is contained in:
parent
464ad6b1ad
commit
28c494c5c8
@ -461,9 +461,18 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
|
||||
int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
|
||||
int err;
|
||||
|
||||
/* Flush out writes to the server in order to update c/mtime */
|
||||
if (S_ISREG(inode->i_mode))
|
||||
/*
|
||||
* Flush out writes to the server in order to update c/mtime.
|
||||
*
|
||||
* Hold the i_mutex to suspend application writes temporarily;
|
||||
* this prevents long-running writing applications from blocking
|
||||
* nfs_wb_nocommit.
|
||||
*/
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
mutex_lock(&inode->i_mutex);
|
||||
nfs_wb_nocommit(inode);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* We may force a getattr if the user cares about atime.
|
||||
|
Loading…
Reference in New Issue
Block a user