Commit bb4d53d6 authored by NeilBrown's avatar NeilBrown Committed by Chuck Lever
Browse files

NFSD: use (un)lock_inode instead of fh_(un)lock for file operations



When locking a file to access ACLs and xattrs etc, use explicit locking
with inode_lock() instead of fh_lock().  This means that the calls to
fh_fill_pre/post_attr() are also explicit which improves readability and
allows us to place them only where they are needed.  Only the xattr
calls need pre/post information.

When locking a file we don't need I_MUTEX_PARENT as the file is not a
parent of anything, so we can use inode_lock() directly rather than the
inode_lock_nested() call that fh_lock() uses.

Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent debf16f0
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst *rqstp)
	if (error)
		goto out_errno;

	fh_lock(fh);
	inode_lock(inode);

	error = set_posix_acl(&init_user_ns, inode, ACL_TYPE_ACCESS,
			      argp->acl_access);
@@ -122,7 +122,7 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst *rqstp)
	if (error)
		goto out_drop_lock;

	fh_unlock(fh);
	inode_unlock(inode);

	fh_drop_write(fh);

@@ -136,7 +136,7 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst *rqstp)
	return rpc_success;

out_drop_lock:
	fh_unlock(fh);
	inode_unlock(inode);
	fh_drop_write(fh);
out_errno:
	resp->status = nfserrno(error);
+2 −2
Original line number Diff line number Diff line
@@ -101,7 +101,7 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst *rqstp)
	if (error)
		goto out_errno;

	fh_lock(fh);
	inode_lock(inode);

	error = set_posix_acl(&init_user_ns, inode, ACL_TYPE_ACCESS,
			      argp->acl_access);
@@ -111,7 +111,7 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst *rqstp)
			      argp->acl_default);

out_drop_lock:
	fh_unlock(fh);
	inode_unlock(inode);
	fh_drop_write(fh);
out_errno:
	resp->status = nfserrno(error);
+5 −4
Original line number Diff line number Diff line
@@ -7397,21 +7397,22 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
{
	struct nfsd_file *nf;
	struct inode *inode;
	__be32 err;

	err = nfsd_file_acquire(rqstp, fhp, NFSD_MAY_READ, &nf);
	if (err)
		return err;
	fh_lock(fhp); /* to block new leases till after test_lock: */
	err = nfserrno(nfsd_open_break_lease(fhp->fh_dentry->d_inode,
							NFSD_MAY_READ));
	inode = fhp->fh_dentry->d_inode;
	inode_lock(inode); /* to block new leases till after test_lock: */
	err = nfserrno(nfsd_open_break_lease(inode, NFSD_MAY_READ));
	if (err)
		goto out;
	lock->fl_file = nf->nf_file;
	err = nfserrno(vfs_test_lock(nf->nf_file, lock));
	lock->fl_file = NULL;
out:
	fh_unlock(fhp);
	inode_unlock(inode);
	nfsd_file_put(nf);
	return err;
}
+20 −14
Original line number Diff line number Diff line
@@ -416,7 +416,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
			return err;
	}

	fh_lock(fhp);
	inode_lock(inode);
	if (size_change) {
		/*
		 * RFC5661, Section 18.30.4:
@@ -464,7 +464,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
		attr->na_aclerr = set_posix_acl(&init_user_ns,
						inode, ACL_TYPE_DEFAULT,
						attr->na_dpacl);
	fh_unlock(fhp);
	inode_unlock(inode);
	if (size_change)
		put_write_access(inode);
out:
@@ -2155,13 +2155,16 @@ nfsd_listxattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char **bufp,
	return err;
}

/*
 * Removexattr and setxattr need to call fh_lock to both lock the inode
 * and set the change attribute. Since the top-level vfs_removexattr
 * and vfs_setxattr calls already do their own inode_lock calls, call
 * the _locked variant. Pass in a NULL pointer for delegated_inode,
 * and let the client deal with NFS4ERR_DELAY (same as with e.g.
 * setattr and remove).
/**
 * nfsd_removexattr - Remove an extended attribute
 * @rqstp: RPC transaction being executed
 * @fhp: NFS filehandle of object with xattr to remove
 * @name: name of xattr to remove (NUL-terminate)
 *
 * Pass in a NULL pointer for delegated_inode, and let the client deal
 * with NFS4ERR_DELAY (same as with e.g. setattr and remove).
 *
 * Returns nfs_ok on success, or an nfsstat in network byte order.
 */
__be32
nfsd_removexattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name)
@@ -2177,12 +2180,14 @@ nfsd_removexattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name)
	if (ret)
		return nfserrno(ret);

	fh_lock(fhp);
	inode_lock(fhp->fh_dentry->d_inode);
	fh_fill_pre_attrs(fhp);

	ret = __vfs_removexattr_locked(&init_user_ns, fhp->fh_dentry,
				       name, NULL);

	fh_unlock(fhp);
	fh_fill_post_attrs(fhp);
	inode_unlock(fhp->fh_dentry->d_inode);
	fh_drop_write(fhp);

	return nfsd_xattr_errno(ret);
@@ -2202,12 +2207,13 @@ nfsd_setxattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name,
	ret = fh_want_write(fhp);
	if (ret)
		return nfserrno(ret);
	fh_lock(fhp);
	inode_lock(fhp->fh_dentry->d_inode);
	fh_fill_pre_attrs(fhp);

	ret = __vfs_setxattr_locked(&init_user_ns, fhp->fh_dentry, name, buf,
				    len, flags, NULL);

	fh_unlock(fhp);
	fh_fill_post_attrs(fhp);
	inode_unlock(fhp->fh_dentry->d_inode);
	fh_drop_write(fhp);

	return nfsd_xattr_errno(ret);