nfsd: Move error code mapping to per-version proc code.

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>
This commit is contained in:
NeilBrown 2024-07-29 11:47:22 +10:00 committed by Chuck Lever
parent ef7f6c4904
commit 1459ad5767
5 changed files with 78 additions and 18 deletions

View file

@ -1121,7 +1121,7 @@ ok:
return 0;
denied:
return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec;
return nfserr_wrongsec;
}
/*

View 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;
}

View 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;

View file

@ -13,6 +13,24 @@
#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;
}

View 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);
}