]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
NFSD: change nfsd_create()/nfsd_symlink() to unlock directory before returning.
authorNeilBrown <neilb@suse.de>
Tue, 26 Jul 2022 06:45:30 +0000 (16:45 +1000)
committerChuck Lever <chuck.lever@oracle.com>
Thu, 4 Aug 2022 14:28:19 +0000 (10:28 -0400)
nfsd_create() usually returns with the directory still locked.
nfsd_symlink() usually returns with it unlocked.  This is clumsy.

Until recently nfsd_create() needed to keep the directory locked until
ACLs and security label had been set.  These are now set inside
nfsd_create() (in nfsd_setattr()) so this need is gone.

So change nfsd_create() and nfsd_symlink() to always unlock, and remove
any fh_unlock() calls that follow calls to these functions.

Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/nfs3proc.c
fs/nfsd/nfs4proc.c
fs/nfsd/vfs.c

index 0078e73009fa4dcca417792ad8dd080dde94713e..1fb75a68b8e54777e8de6c91b83a2bd9c6219ba9 100644 (file)
@@ -388,7 +388,6 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp)
        fh_init(&resp->fh, NFS3_FHSIZE);
        resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
                                   &attrs, S_IFDIR, 0, &resp->fh);
-       fh_unlock(&resp->dirfh);
        return rpc_success;
 }
 
@@ -469,7 +468,6 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp)
        type = nfs3_ftypes[argp->ftype];
        resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
                                   &attrs, type, rdev, &resp->fh);
-       fh_unlock(&resp->dirfh);
 out:
        return rpc_success;
 }
index ade2ea29feb06fd9288640f4fb2746dfaf6cb17c..d585c01d8da6109bbee3eda8d74c950cb8f65823 100644 (file)
@@ -823,8 +823,6 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                create->cr_bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
        if (attrs.na_aclerr)
                create->cr_bmval[0] &= ~FATTR4_WORD0_ACL;
-
-       fh_unlock(&cstate->current_fh);
        set_change_info(&create->cr_cinfo, &cstate->current_fh);
        fh_dup2(&cstate->current_fh, &resfh);
 out:
index fdea5cce2b228221abad64d188b04689d3ca7788..e726495f20759eeeb0118e6d034180bb3869fa4a 100644 (file)
@@ -1379,8 +1379,10 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
        fh_lock_nested(fhp, I_MUTEX_PARENT);
        dchild = lookup_one_len(fname, dentry, flen);
        host_err = PTR_ERR(dchild);
-       if (IS_ERR(dchild))
-               return nfserrno(host_err);
+       if (IS_ERR(dchild)) {
+               err = nfserrno(host_err);
+               goto out_unlock;
+       }
        err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
        /*
         * We unconditionally drop our ref to dchild as fh_compose will have
@@ -1388,9 +1390,12 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
         */
        dput(dchild);
        if (err)
-               return err;
-       return nfsd_create_locked(rqstp, fhp, fname, flen, attrs, type,
-                                       rdev, resfhp);
+               goto out_unlock;
+       err = nfsd_create_locked(rqstp, fhp, fname, flen, attrs, type,
+                                rdev, resfhp);
+out_unlock:
+       fh_unlock(fhp);
+       return err;
 }
 
 /*
@@ -1467,16 +1472,19 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
                goto out;
 
        host_err = fh_want_write(fhp);
-       if (host_err)
-               goto out_nfserr;
+       if (host_err) {
+               err = nfserrno(host_err);
+               goto out;
+       }
 
        fh_lock(fhp);
        dentry = fhp->fh_dentry;
        dnew = lookup_one_len(fname, dentry, flen);
-       host_err = PTR_ERR(dnew);
-       if (IS_ERR(dnew))
-               goto out_nfserr;
-
+       if (IS_ERR(dnew)) {
+               err = nfserrno(PTR_ERR(dnew));
+               fh_unlock(fhp);
+               goto out_drop_write;
+       }
        host_err = vfs_symlink(&init_user_ns, d_inode(dentry), dnew, path);
        err = nfserrno(host_err);
        cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
@@ -1485,16 +1493,12 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
        fh_unlock(fhp);
        if (!err)
                err = nfserrno(commit_metadata(fhp));
-       fh_drop_write(fhp);
-
        dput(dnew);
        if (err==0) err = cerr;
+out_drop_write:
+       fh_drop_write(fhp);
 out:
        return err;
-
-out_nfserr:
-       err = nfserrno(host_err);
-       goto out;
 }
 
 /*