diff options
Diffstat (limited to 'fs/nfsd/vfs.c')
| -rw-r--r-- | fs/nfsd/vfs.c | 23 | 
1 files changed, 9 insertions, 14 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 994d66fbb446..4212aaacbb55 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -217,10 +217,16 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,  		host_err = PTR_ERR(dentry);  		if (IS_ERR(dentry))  			goto out_nfserr; -		/* -		 * check if we have crossed a mount point ... -		 */  		if (nfsd_mountpoint(dentry, exp)) { +			/* +			 * We don't need the i_mutex after all.  It's +			 * still possible we could open this (regular +			 * files can be mountpoints too), but the +			 * i_mutex is just there to prevent renames of +			 * something that we might be about to delegate, +			 * and a mountpoint won't be renamed: +			 */ +			fh_unlock(fhp);  			if ((host_err = nfsd_cross_mnt(rqstp, &dentry, &exp))) {  				dput(dentry);  				goto out_nfserr; @@ -1809,7 +1815,6 @@ static __be32 nfsd_buffered_readdir(struct file *file, nfsd_filldir_t func,  	offset = *offsetp;  	while (1) { -		struct inode *dir_inode = file_inode(file);  		unsigned int reclen;  		cdp->err = nfserr_eof; /* will be cleared on successful read */ @@ -1828,15 +1833,6 @@ static __be32 nfsd_buffered_readdir(struct file *file, nfsd_filldir_t func,  		if (!size)  			break; -		/* -		 * Various filldir functions may end up calling back into -		 * lookup_one_len() and the file system's ->lookup() method. -		 * These expect i_mutex to be held, as it would within readdir. -		 */ -		host_err = mutex_lock_killable(&dir_inode->i_mutex); -		if (host_err) -			break; -  		de = (struct buffered_dirent *)buf.dirent;  		while (size > 0) {  			offset = de->offset; @@ -1853,7 +1849,6 @@ static __be32 nfsd_buffered_readdir(struct file *file, nfsd_filldir_t func,  			size -= reclen;  			de = (struct buffered_dirent *)((char *)de + reclen);  		} -		mutex_unlock(&dir_inode->i_mutex);  		if (size > 0) /* We bailed out early */  			break;  |