]> git.dujemihanovic.xyz Git - linux.git/commitdiff
nfsd: Move error code mapping to per-version proc code.
authorNeilBrown <neilb@suse.de>
Mon, 29 Jul 2024 01:47:22 +0000 (11:47 +1000)
committerChuck Lever <chuck.lever@oracle.com>
Fri, 20 Sep 2024 23:31:03 +0000 (19:31 -0400)
There is code scattered around nfsd which chooses an error status based
on the particular version of nfs being used.  It is cleaner to have the
version specific choices in version specific code.

With this patch common code returns the most specific error code
possible and the version specific code maps that if necessary.

Both v2 (nfsproc.c) and v3 (nfs3proc.c) now have a "map_status()"
function which is called to map the resp->status before each non-trivial
nfsd_proc_* or nfsd3_proc_* function returns.

NFS4ERR_SYMLINK and NFS4ERR_WRONG_TYPE introduce extra complications and
are left for a later patch.

Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/export.c
fs/nfsd/nfs3proc.c
fs/nfsd/nfsfh.c
fs/nfsd/nfsproc.c
fs/nfsd/vfs.c

index 9aa5f95f18a8d1ede86b9c3043b7c7ec7f8d27e8..7bb4f2075ac5bcbb07f1f02bb8a5b62df03e04aa 100644 (file)
@@ -1121,7 +1121,7 @@ ok:
                return 0;
 
 denied:
-       return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec;
+       return nfserr_wrongsec;
 }
 
 /*
index dfcc957e460d64b9936340f27badc2ad55b59405..7581d64edfa3968e6ac3e78ee7bc17c1c1b3736b 100644 (file)
@@ -28,6 +28,22 @@ static int   nfs3_ftypes[] = {
        S_IFIFO,                /* NF3FIFO */
 };
 
+static __be32 nfsd3_map_status(__be32 status)
+{
+       switch (status) {
+       case nfs_ok:
+               break;
+       case nfserr_nofilehandle:
+               status = nfserr_badhandle;
+               break;
+       case nfserr_wrongsec:
+       case nfserr_file_open:
+               status = nfserr_acces;
+               break;
+       }
+       return status;
+}
+
 /*
  * NULL call.
  */
@@ -57,6 +73,7 @@ nfsd3_proc_getattr(struct svc_rqst *rqstp)
 
        resp->status = fh_getattr(&resp->fh, &resp->stat);
 out:
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -80,6 +97,7 @@ nfsd3_proc_setattr(struct svc_rqst *rqstp)
        if (argp->check_guard)
                guardtime = &argp->guardtime;
        resp->status = nfsd_setattr(rqstp, &resp->fh, &attrs, guardtime);
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -103,6 +121,7 @@ nfsd3_proc_lookup(struct svc_rqst *rqstp)
        resp->status = nfsd_lookup(rqstp, &resp->dirfh,
                                   argp->name, argp->len,
                                   &resp->fh);
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -122,6 +141,7 @@ nfsd3_proc_access(struct svc_rqst *rqstp)
        fh_copy(&resp->fh, &argp->fh);
        resp->access = argp->access;
        resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -142,6 +162,7 @@ nfsd3_proc_readlink(struct svc_rqst *rqstp)
        resp->pages = rqstp->rq_next_page++;
        resp->status = nfsd_readlink(rqstp, &resp->fh,
                                     page_address(*resp->pages), &resp->len);
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -179,6 +200,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp)
        fh_copy(&resp->fh, &argp->fh);
        resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
                                 &resp->count, &resp->eof);
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -212,6 +234,7 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
                                  rqstp->rq_vec, nvecs, &cnt,
                                  resp->committed, resp->verf);
        resp->count = cnt;
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -359,6 +382,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp)
        newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
 
        resp->status = nfsd3_create_file(rqstp, dirfhp, newfhp, argp);
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -384,6 +408,7 @@ 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);
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -424,6 +449,7 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp)
                                    argp->flen, argp->tname, &attrs, &resp->fh);
        kfree(argp->tname);
 out:
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -465,6 +491,7 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp)
        resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
                                   &attrs, type, rdev, &resp->fh);
 out:
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -486,6 +513,7 @@ nfsd3_proc_remove(struct svc_rqst *rqstp)
        fh_copy(&resp->fh, &argp->fh);
        resp->status = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR,
                                   argp->name, argp->len);
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -506,6 +534,7 @@ nfsd3_proc_rmdir(struct svc_rqst *rqstp)
        fh_copy(&resp->fh, &argp->fh);
        resp->status = nfsd_unlink(rqstp, &resp->fh, S_IFDIR,
                                   argp->name, argp->len);
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -528,6 +557,7 @@ nfsd3_proc_rename(struct svc_rqst *rqstp)
        fh_copy(&resp->tfh, &argp->tfh);
        resp->status = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
                                   &resp->tfh, argp->tname, argp->tlen);
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -548,6 +578,7 @@ nfsd3_proc_link(struct svc_rqst *rqstp)
        fh_copy(&resp->tfh, &argp->tfh);
        resp->status = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
                                 &resp->fh);
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -600,6 +631,7 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
        /* Recycle only pages that were part of the reply */
        rqstp->rq_next_page = resp->xdr.page_ptr + 1;
 
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -644,6 +676,7 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp)
        rqstp->rq_next_page = resp->xdr.page_ptr + 1;
 
 out:
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -661,6 +694,7 @@ nfsd3_proc_fsstat(struct svc_rqst *rqstp)
 
        resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
        fh_put(&argp->fh);
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -704,6 +738,7 @@ nfsd3_proc_fsinfo(struct svc_rqst *rqstp)
        }
 
        fh_put(&argp->fh);
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -746,6 +781,7 @@ nfsd3_proc_pathconf(struct svc_rqst *rqstp)
        }
 
        fh_put(&argp->fh);
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
@@ -773,6 +809,7 @@ nfsd3_proc_commit(struct svc_rqst *rqstp)
                                   argp->count, resp->verf);
        nfsd_file_put(nf);
 out:
+       resp->status = nfsd3_map_status(resp->status);
        return rpc_success;
 }
 
index d9039383a48ca6f7b73241a8b6059cb73ddafaa5..388c2952a0a815ec8bed3ea7d96fd353f8803c7e 100644 (file)
@@ -154,10 +154,8 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
        int len;
        __be32 error;
 
-       error = nfserr_stale;
-       if (rqstp->rq_vers > 2)
-               error = nfserr_badhandle;
-       if (rqstp->rq_vers == 4 && fh->fh_size == 0)
+       error = nfserr_badhandle;
+       if (fh->fh_size == 0)
                return nfserr_nofilehandle;
 
        if (fh->fh_version != 1)
@@ -231,9 +229,7 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
        /*
         * Look up the dentry using the NFS file handle.
         */
-       error = nfserr_stale;
-       if (rqstp->rq_vers > 2)
-               error = nfserr_badhandle;
+       error = nfserr_badhandle;
 
        fileid_type = fh->fh_fileid_type;
 
index 97aab34593ef0d59a34b09326e921091680765c7..5392f4775ee87b635644abe994a888b9b6611c50 100644 (file)
 
 #define NFSDDBG_FACILITY               NFSDDBG_PROC
 
+static __be32 nfsd_map_status(__be32 status)
+{
+       switch (status) {
+       case nfs_ok:
+               break;
+       case nfserr_nofilehandle:
+       case nfserr_badhandle:
+               status = nfserr_stale;
+               break;
+       case nfserr_wrongsec:
+       case nfserr_xdev:
+       case nfserr_file_open:
+               status = nfserr_acces;
+               break;
+       }
+       return status;
+}
+
 static __be32
 nfsd_proc_null(struct svc_rqst *rqstp)
 {
@@ -38,6 +56,7 @@ nfsd_proc_getattr(struct svc_rqst *rqstp)
                goto out;
        resp->status = fh_getattr(&resp->fh, &resp->stat);
 out:
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
@@ -109,6 +128,7 @@ nfsd_proc_setattr(struct svc_rqst *rqstp)
 
        resp->status = fh_getattr(&resp->fh, &resp->stat);
 out:
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
@@ -143,6 +163,7 @@ nfsd_proc_lookup(struct svc_rqst *rqstp)
 
        resp->status = fh_getattr(&resp->fh, &resp->stat);
 out:
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
@@ -164,6 +185,7 @@ nfsd_proc_readlink(struct svc_rqst *rqstp)
                                     page_address(resp->page), &resp->len);
 
        fh_put(&argp->fh);
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
@@ -200,6 +222,7 @@ nfsd_proc_read(struct svc_rqst *rqstp)
                resp->status = fh_getattr(&resp->fh, &resp->stat);
        else if (resp->status == nfserr_jukebox)
                set_bit(RQ_DROPME, &rqstp->rq_flags);
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
@@ -235,6 +258,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)
                resp->status = fh_getattr(&resp->fh, &resp->stat);
        else if (resp->status == nfserr_jukebox)
                set_bit(RQ_DROPME, &rqstp->rq_flags);
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
@@ -404,6 +428,7 @@ done:
                goto out;
        resp->status = fh_getattr(&resp->fh, &resp->stat);
 out:
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
@@ -420,6 +445,7 @@ nfsd_proc_remove(struct svc_rqst *rqstp)
        resp->status = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR,
                                   argp->name, argp->len);
        fh_put(&argp->fh);
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
@@ -438,6 +464,7 @@ nfsd_proc_rename(struct svc_rqst *rqstp)
                                   &argp->tfh, argp->tname, argp->tlen);
        fh_put(&argp->ffh);
        fh_put(&argp->tfh);
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
@@ -458,6 +485,7 @@ nfsd_proc_link(struct svc_rqst *rqstp)
                                 &argp->ffh);
        fh_put(&argp->ffh);
        fh_put(&argp->tfh);
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
@@ -496,6 +524,7 @@ nfsd_proc_symlink(struct svc_rqst *rqstp)
        fh_put(&argp->ffh);
        fh_put(&newfh);
 out:
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
@@ -529,6 +558,7 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp)
 
        resp->status = fh_getattr(&resp->fh, &resp->stat);
 out:
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
@@ -546,6 +576,7 @@ nfsd_proc_rmdir(struct svc_rqst *rqstp)
        resp->status = nfsd_unlink(rqstp, &argp->fh, S_IFDIR,
                                   argp->name, argp->len);
        fh_put(&argp->fh);
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
@@ -591,6 +622,7 @@ nfsd_proc_readdir(struct svc_rqst *rqstp)
        nfssvc_encode_nfscookie(resp, offset);
 
        fh_put(&argp->fh);
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
@@ -608,6 +640,7 @@ nfsd_proc_statfs(struct svc_rqst *rqstp)
        resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats,
                                   NFSD_MAY_BYPASS_GSS_ON_ROOT);
        fh_put(&argp->fh);
+       resp->status = nfsd_map_status(resp->status);
        return rpc_success;
 }
 
index bd6017510109f623c5270c9e3a7becd7ded38a13..ec99c91df173be1e374d52bca026f4fe863334b3 100644 (file)
@@ -1768,10 +1768,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
                if (!err)
                        err = nfserrno(commit_metadata(tfhp));
        } else {
-               if (host_err == -EXDEV && rqstp->rq_vers == 2)
-                       err = nfserr_acces;
-               else
-                       err = nfserrno(host_err);
+               err = nfserrno(host_err);
        }
        dput(dnew);
 out_drop_write:
@@ -1837,7 +1834,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
        if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen))
                goto out;
 
-       err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;
+       err = nfserr_xdev;
        if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt)
                goto out;
        if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry)
@@ -1852,7 +1849,7 @@ retry:
 
        trap = lock_rename(tdentry, fdentry);
        if (IS_ERR(trap)) {
-               err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;
+               err = nfserr_xdev;
                goto out_want_write;
        }
        err = fh_fill_pre_attrs(ffhp);
@@ -2021,10 +2018,7 @@ out_nfserr:
                /* name is mounted-on. There is no perfect
                 * error status.
                 */
-               if (nfsd_v4client(rqstp))
-                       err = nfserr_file_open;
-               else
-                       err = nfserr_acces;
+               err = nfserr_file_open;
        } else {
                err = nfserrno(host_err);
        }