summaryrefslogtreecommitdiff
path: root/fs/nfsd/nfssvc.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2020-10-02 22:52:44 +0300
committerJ. Bruce Fields <bfields@redhat.com>2020-10-12 17:29:44 +0300
commitcc028a10a48c3c555d7772d02f56eea9f86fdf79 (patch)
tree78c88ccb5662c6f189f33abbb33c636456e61d3f /fs/nfsd/nfssvc.c
parent4b74fd793a77f6149d68dbf95574311af9506e39 (diff)
downloadlinux-cc028a10a48c3c555d7772d02f56eea9f86fdf79.tar.xz
NFSD: Hoist status code encoding into XDR encoder functions
The original intent was presumably to reduce code duplication. The trade-off was: - No support for an NFSD proc function returning a non-success RPC accept_stat value. - No support for void NFS replies to non-NULL procedures. - Everyone pays for the deduplication with a few extra conditional branches in a hot path. In addition, nfsd_dispatch() leaves *statp uninitialized in the success path, unlike svc_generic_dispatch(). Address all of these problems by moving the logic for encoding the NFS status code into the NFS XDR encoders themselves. Then update the NFS .pc_func methods to return an RPC accept_stat value. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfssvc.c')
-rw-r--r--fs/nfsd/nfssvc.c21
1 files changed, 5 insertions, 16 deletions
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index beb3875241cb..27b1ad136150 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -960,13 +960,6 @@ out:
return 0;
}
-static __be32 map_new_errors(u32 vers, __be32 nfserr)
-{
- if (nfserr == nfserr_jukebox && vers == 2)
- return nfserr_dropit;
- return nfserr;
-}
-
/*
* A write procedure can have a large argument, and a read procedure can
* have a large reply, but no NFSv2 or NFSv3 procedure has argument and
@@ -1014,7 +1007,7 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
const struct svc_procedure *proc = rqstp->rq_procinfo;
struct kvec *argv = &rqstp->rq_arg.head[0];
struct kvec *resv = &rqstp->rq_res.head[0];
- __be32 nfserr, *nfserrp;
+ __be32 *p;
dprintk("nfsd_dispatch: vers %d proc %d\n",
rqstp->rq_vers, rqstp->rq_proc);
@@ -1043,18 +1036,14 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
* Need to grab the location to store the status, as
* NFSv4 does some encoding while processing
*/
- nfserrp = resv->iov_base + resv->iov_len;
+ p = resv->iov_base + resv->iov_len;
resv->iov_len += sizeof(__be32);
- nfserr = proc->pc_func(rqstp);
- nfserr = map_new_errors(rqstp->rq_vers, nfserr);
- if (nfserr == nfserr_dropit || test_bit(RQ_DROPME, &rqstp->rq_flags))
+ *statp = proc->pc_func(rqstp);
+ if (*statp == rpc_drop_reply || test_bit(RQ_DROPME, &rqstp->rq_flags))
goto out_update_drop;
- if (rqstp->rq_proc != 0)
- *nfserrp++ = nfserr;
-
- if (!proc->pc_encode(rqstp, nfserrp))
+ if (!proc->pc_encode(rqstp, p))
goto out_encode_err;
nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);