summaryrefslogtreecommitdiff
path: root/fs/nfsd/nfsxdr.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2020-10-02 15:52:44 -0400
committerJ. Bruce Fields <bfields@redhat.com>2020-10-12 10:29:44 -0400
commitcc028a10a48c3c555d7772d02f56eea9f86fdf79 (patch)
tree78c88ccb5662c6f189f33abbb33c636456e61d3f /fs/nfsd/nfsxdr.c
parent4b74fd793a77f6149d68dbf95574311af9506e39 (diff)
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/nfsxdr.c')
-rw-r--r--fs/nfsd/nfsxdr.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 952e71c95d4e..8a288c8fcd57 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -430,14 +430,24 @@ nfssvc_encode_void(struct svc_rqst *rqstp, __be32 *p)
}
int
+nfssvc_encode_stat(struct svc_rqst *rqstp, __be32 *p)
+{
+ struct nfsd_stat *resp = rqstp->rq_resp;
+
+ *p++ = resp->status;
+ return xdr_ressize_check(rqstp, p);
+}
+
+int
nfssvc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p)
{
struct nfsd_attrstat *resp = rqstp->rq_resp;
+ *p++ = resp->status;
if (resp->status != nfs_ok)
- return xdr_ressize_check(rqstp, p);
-
+ goto out;
p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
+out:
return xdr_ressize_check(rqstp, p);
}
@@ -446,11 +456,12 @@ nfssvc_encode_diropres(struct svc_rqst *rqstp, __be32 *p)
{
struct nfsd_diropres *resp = rqstp->rq_resp;
+ *p++ = resp->status;
if (resp->status != nfs_ok)
- return xdr_ressize_check(rqstp, p);
-
+ goto out;
p = encode_fh(p, &resp->fh);
p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
+out:
return xdr_ressize_check(rqstp, p);
}
@@ -459,6 +470,7 @@ nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p)
{
struct nfsd_readlinkres *resp = rqstp->rq_resp;
+ *p++ = resp->status;
if (resp->status != nfs_ok)
return xdr_ressize_check(rqstp, p);
@@ -479,6 +491,7 @@ nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p)
{
struct nfsd_readres *resp = rqstp->rq_resp;
+ *p++ = resp->status;
if (resp->status != nfs_ok)
return xdr_ressize_check(rqstp, p);
@@ -502,6 +515,7 @@ nfssvc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p)
{
struct nfsd_readdirres *resp = rqstp->rq_resp;
+ *p++ = resp->status;
if (resp->status != nfs_ok)
return xdr_ressize_check(rqstp, p);
@@ -520,6 +534,7 @@ nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p)
struct nfsd_statfsres *resp = rqstp->rq_resp;
struct kstatfs *stat = &resp->stats;
+ *p++ = resp->status;
if (resp->status != nfs_ok)
return xdr_ressize_check(rqstp, p);