]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
SUNRPC: Prepare for xdr_stream-style decoding on the server-side
authorChuck Lever <chuck.lever@oracle.com>
Thu, 5 Nov 2020 16:19:42 +0000 (11:19 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 21 Jun 2024 12:52:34 +0000 (14:52 +0200)
[ Upstream commit 5191955d6fc65e6d4efe8f4f10a6028298f57281 ]

A "permanent" struct xdr_stream is allocated in struct svc_rqst so
that it is usable by all server-side decoders. A per-rqst scratch
buffer is also allocated to handle decoding XDR data items that
cross page boundaries.

To demonstrate how it will be used, add the first call site for the
new svcxdr_init_decode() API.

As an additional part of the overall conversion, add symbolic
constants for successful and failed XDR operations. Returning "0" is
overloaded. Sometimes it means something failed, but sometimes it
means success. To make it more clear when XDR decoding functions
succeed or fail, introduce symbolic constants.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/nfsd/nfssvc.c
include/linux/sunrpc/svc.h
net/sunrpc/svc.c

index 2e61a565cdbd8c81a4651edc0a3cfdf2f1feb2df..311b287c5024fc23d4244781a0ef49a3cad90ecf 100644 (file)
@@ -1052,6 +1052,8 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
         * (necessary in the NFSv4.0 compound case)
         */
        rqstp->rq_cachetype = proc->pc_cachetype;
+
+       svcxdr_init_decode(rqstp);
        if (!proc->pc_decode(rqstp, argv->iov_base))
                goto out_decode_err;
 
index c220b734fa69e857151f5d0552a935d1660a16c5..34c2a69820e930d8b30693d1790ebbae1422b602 100644 (file)
@@ -247,6 +247,8 @@ struct svc_rqst {
 
        size_t                  rq_xprt_hlen;   /* xprt header len */
        struct xdr_buf          rq_arg;
+       struct xdr_stream       rq_arg_stream;
+       struct page             *rq_scratch_page;
        struct xdr_buf          rq_res;
        struct page             *rq_pages[RPCSVC_MAXPAGES + 1];
        struct page *           *rq_respages;   /* points into rq_pages */
@@ -557,4 +559,18 @@ static inline void svc_reserve_auth(struct svc_rqst *rqstp, int space)
        svc_reserve(rqstp, space + rqstp->rq_auth_slack);
 }
 
+/**
+ * svcxdr_init_decode - Prepare an xdr_stream for svc Call decoding
+ * @rqstp: controlling server RPC transaction context
+ *
+ */
+static inline void svcxdr_init_decode(struct svc_rqst *rqstp)
+{
+       struct xdr_stream *xdr = &rqstp->rq_arg_stream;
+       struct kvec *argv = rqstp->rq_arg.head;
+
+       xdr_init_decode(xdr, &rqstp->rq_arg, argv->iov_base, NULL);
+       xdr_set_scratch_page(xdr, rqstp->rq_scratch_page);
+}
+
 #endif /* SUNRPC_SVC_H */
index e4e4e203ecdadfa8528f393da476a6a7d07513f4..73e02ba4ed53a706472472862de1ce2c1dcef2a4 100644 (file)
@@ -614,6 +614,10 @@ svc_rqst_alloc(struct svc_serv *serv, struct svc_pool *pool, int node)
        rqstp->rq_server = serv;
        rqstp->rq_pool = pool;
 
+       rqstp->rq_scratch_page = alloc_pages_node(node, GFP_KERNEL, 0);
+       if (!rqstp->rq_scratch_page)
+               goto out_enomem;
+
        rqstp->rq_argp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node);
        if (!rqstp->rq_argp)
                goto out_enomem;
@@ -846,6 +850,7 @@ void
 svc_rqst_free(struct svc_rqst *rqstp)
 {
        svc_release_buffer(rqstp);
+       put_page(rqstp->rq_scratch_page);
        kfree(rqstp->rq_resp);
        kfree(rqstp->rq_argp);
        kfree(rqstp->rq_auth_data);