Should be reviewed on the list.
Stable-dep-of: 26696d465716 ("dmaengine: mxs: use platform_driver_register")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
- drivers/dma/mxs-dma.c | 37 +++++--------------------------------
+ drivers/dma/mxs-dma.c | 37 +++++--------------------------------
1 file changed, 5 insertions(+), 32 deletions(-)
-diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
-index 65f816b40c32..994fc4d2aca4 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
-@@ -167,29 +167,11 @@ static struct mxs_dma_type mxs_dma_types[] = {
+@@ -167,29 +167,11 @@ static struct mxs_dma_type mxs_dma_types
}
};
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mxs_dma_dt_ids);
-@@ -762,8 +744,6 @@ static struct dma_chan *mxs_dma_xlate(struct of_phandle_args *dma_spec,
+@@ -762,8 +744,6 @@ static struct dma_chan *mxs_dma_xlate(st
static int __init mxs_dma_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
const struct mxs_dma_type *dma_type;
struct mxs_dma_engine *mxs_dma;
struct resource *iores;
-@@ -779,13 +759,7 @@ static int __init mxs_dma_probe(struct platform_device *pdev)
+@@ -779,13 +759,7 @@ static int __init mxs_dma_probe(struct p
return ret;
}
mxs_dma->type = dma_type->type;
mxs_dma->dev_id = dma_type->id;
-@@ -865,7 +839,6 @@ static struct platform_driver mxs_dma_driver = {
+@@ -865,7 +839,6 @@ static struct platform_driver mxs_dma_dr
.name = "mxs-dma",
.of_match_table = mxs_dma_dt_ids,
},
};
static int __init mxs_dma_module_init(void)
---
-2.35.1
-
+++ /dev/null
-From 34e09e5c9a1611aa6be5e62844ff84e408ee3701 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 5 Nov 2020 14:48:29 -0500
-Subject: NFSD: Add common helpers to decode void args and encode void results
-
-From: Chuck Lever <chuck.lever@oracle.com>
-
-[ Upstream commit 788f7183fba86b46074c16e7d57ea09302badff4 ]
-
-Start off the conversion to xdr_stream by de-duplicating the functions
-that decode void arguments and encode void results.
-
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Stable-dep-of: 401bc1f90874 ("NFSD: Protect against send buffer overflow in NFSv2 READ")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nfsd/nfs2acl.c | 21 ++++-----------------
- fs/nfsd/nfs3acl.c | 8 ++++----
- fs/nfsd/nfs3proc.c | 10 ++++------
- fs/nfsd/nfs3xdr.c | 11 -----------
- fs/nfsd/nfs4proc.c | 11 ++++-------
- fs/nfsd/nfs4xdr.c | 12 ------------
- fs/nfsd/nfsd.h | 8 ++++++++
- fs/nfsd/nfsproc.c | 25 ++++++++++++-------------
- fs/nfsd/nfssvc.c | 28 ++++++++++++++++++++++++++++
- fs/nfsd/nfsxdr.c | 10 ----------
- fs/nfsd/xdr.h | 2 --
- fs/nfsd/xdr3.h | 2 --
- fs/nfsd/xdr4.h | 2 --
- 13 files changed, 64 insertions(+), 86 deletions(-)
-
-diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
-index 6a900f770dd2..b0f66604532a 100644
---- a/fs/nfsd/nfs2acl.c
-+++ b/fs/nfsd/nfs2acl.c
-@@ -185,10 +185,6 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp)
- /*
- * XDR decode functions
- */
--static int nfsaclsvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
--{
-- return 1;
--}
-
- static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
- {
-@@ -255,15 +251,6 @@ static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p)
- * XDR encode functions
- */
-
--/*
-- * There must be an encoding function for void results so svc_process
-- * will work properly.
-- */
--static int nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p)
--{
-- return xdr_ressize_check(rqstp, p);
--}
--
- /* GETACL */
- static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
- {
-@@ -378,10 +365,10 @@ struct nfsd3_voidargs { int dummy; };
- static const struct svc_procedure nfsd_acl_procedures2[5] = {
- [ACLPROC2_NULL] = {
- .pc_func = nfsacld_proc_null,
-- .pc_decode = nfsaclsvc_decode_voidarg,
-- .pc_encode = nfsaclsvc_encode_voidres,
-- .pc_argsize = sizeof(struct nfsd3_voidargs),
-- .pc_ressize = sizeof(struct nfsd3_voidargs),
-+ .pc_decode = nfssvc_decode_voidarg,
-+ .pc_encode = nfssvc_encode_voidres,
-+ .pc_argsize = sizeof(struct nfsd_voidargs),
-+ .pc_ressize = sizeof(struct nfsd_voidres),
- .pc_cachetype = RC_NOCACHE,
- .pc_xdrressize = ST,
- },
-diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
-index 34a394e50e1d..7c30876a31a1 100644
---- a/fs/nfsd/nfs3acl.c
-+++ b/fs/nfsd/nfs3acl.c
-@@ -245,10 +245,10 @@ struct nfsd3_voidargs { int dummy; };
- static const struct svc_procedure nfsd_acl_procedures3[3] = {
- [ACLPROC3_NULL] = {
- .pc_func = nfsd3_proc_null,
-- .pc_decode = nfs3svc_decode_voidarg,
-- .pc_encode = nfs3svc_encode_voidres,
-- .pc_argsize = sizeof(struct nfsd3_voidargs),
-- .pc_ressize = sizeof(struct nfsd3_voidargs),
-+ .pc_decode = nfssvc_decode_voidarg,
-+ .pc_encode = nfssvc_encode_voidres,
-+ .pc_argsize = sizeof(struct nfsd_voidargs),
-+ .pc_ressize = sizeof(struct nfsd_voidres),
- .pc_cachetype = RC_NOCACHE,
- .pc_xdrressize = ST,
- },
-diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
-index 981a4e4c9a3c..a4dfe8160d55 100644
---- a/fs/nfsd/nfs3proc.c
-+++ b/fs/nfsd/nfs3proc.c
-@@ -698,8 +698,6 @@ nfsd3_proc_commit(struct svc_rqst *rqstp)
- #define nfsd3_attrstatres nfsd3_attrstat
- #define nfsd3_wccstatres nfsd3_attrstat
- #define nfsd3_createres nfsd3_diropres
--#define nfsd3_voidres nfsd3_voidargs
--struct nfsd3_voidargs { int dummy; };
-
- #define ST 1 /* status*/
- #define FH 17 /* filehandle with length */
-@@ -710,10 +708,10 @@ struct nfsd3_voidargs { int dummy; };
- static const struct svc_procedure nfsd_procedures3[22] = {
- [NFS3PROC_NULL] = {
- .pc_func = nfsd3_proc_null,
-- .pc_decode = nfs3svc_decode_voidarg,
-- .pc_encode = nfs3svc_encode_voidres,
-- .pc_argsize = sizeof(struct nfsd3_voidargs),
-- .pc_ressize = sizeof(struct nfsd3_voidres),
-+ .pc_decode = nfssvc_decode_voidarg,
-+ .pc_encode = nfssvc_encode_voidres,
-+ .pc_argsize = sizeof(struct nfsd_voidargs),
-+ .pc_ressize = sizeof(struct nfsd_voidres),
- .pc_cachetype = RC_NOCACHE,
- .pc_xdrressize = ST,
- },
-diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
-index 716566da400e..9dc22d917bd2 100644
---- a/fs/nfsd/nfs3xdr.c
-+++ b/fs/nfsd/nfs3xdr.c
-@@ -304,11 +304,6 @@ void fill_post_wcc(struct svc_fh *fhp)
- /*
- * XDR decode functions
- */
--int
--nfs3svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
--{
-- return 1;
--}
-
- int
- nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p)
-@@ -642,12 +637,6 @@ nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p)
- * XDR encode functions
- */
-
--int
--nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p)
--{
-- return xdr_ressize_check(rqstp, p);
--}
--
- /* GETATTR */
- int
- nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p)
-diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
-index 9aeeb51e8c61..1acafc39f008 100644
---- a/fs/nfsd/nfs4proc.c
-+++ b/fs/nfsd/nfs4proc.c
-@@ -3293,16 +3293,13 @@ static const char *nfsd4_op_name(unsigned opnum)
- return "unknown_operation";
- }
-
--#define nfsd4_voidres nfsd4_voidargs
--struct nfsd4_voidargs { int dummy; };
--
- static const struct svc_procedure nfsd_procedures4[2] = {
- [NFSPROC4_NULL] = {
- .pc_func = nfsd4_proc_null,
-- .pc_decode = nfs4svc_decode_voidarg,
-- .pc_encode = nfs4svc_encode_voidres,
-- .pc_argsize = sizeof(struct nfsd4_voidargs),
-- .pc_ressize = sizeof(struct nfsd4_voidres),
-+ .pc_decode = nfssvc_decode_voidarg,
-+ .pc_encode = nfssvc_encode_voidres,
-+ .pc_argsize = sizeof(struct nfsd_voidargs),
-+ .pc_ressize = sizeof(struct nfsd_voidres),
- .pc_cachetype = RC_NOCACHE,
- .pc_xdrressize = 1,
- },
-diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
-index cc605ee0b2fa..e7b891a19bf8 100644
---- a/fs/nfsd/nfs4xdr.c
-+++ b/fs/nfsd/nfs4xdr.c
-@@ -5263,12 +5263,6 @@ nfsd4_encode_replay(struct xdr_stream *xdr, struct nfsd4_op *op)
- p = xdr_encode_opaque_fixed(p, rp->rp_buf, rp->rp_buflen);
- }
-
--int
--nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p)
--{
-- return xdr_ressize_check(rqstp, p);
--}
--
- void nfsd4_release_compoundargs(struct svc_rqst *rqstp)
- {
- struct nfsd4_compoundargs *args = rqstp->rq_argp;
-@@ -5286,12 +5280,6 @@ void nfsd4_release_compoundargs(struct svc_rqst *rqstp)
- }
- }
-
--int
--nfs4svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
--{
-- return 1;
--}
--
- int
- nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p)
- {
-diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
-index cb742e17e04a..7907de3f2ee6 100644
---- a/fs/nfsd/nfsd.h
-+++ b/fs/nfsd/nfsd.h
-@@ -73,6 +73,14 @@ extern unsigned long nfsd_drc_mem_used;
-
- extern const struct seq_operations nfs_exports_op;
-
-+/*
-+ * Common void argument and result helpers
-+ */
-+struct nfsd_voidargs { };
-+struct nfsd_voidres { };
-+int nfssvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p);
-+int nfssvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p);
-+
- /*
- * Function prototypes.
- */
-diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
-index bbd01e8397f6..dbd8d3604653 100644
---- a/fs/nfsd/nfsproc.c
-+++ b/fs/nfsd/nfsproc.c
-@@ -609,7 +609,6 @@ nfsd_proc_statfs(struct svc_rqst *rqstp)
- * NFSv2 Server procedures.
- * Only the results of non-idempotent operations are cached.
- */
--struct nfsd_void { int dummy; };
-
- #define ST 1 /* status */
- #define FH 8 /* filehandle */
-@@ -618,10 +617,10 @@ struct nfsd_void { int dummy; };
- static const struct svc_procedure nfsd_procedures2[18] = {
- [NFSPROC_NULL] = {
- .pc_func = nfsd_proc_null,
-- .pc_decode = nfssvc_decode_void,
-- .pc_encode = nfssvc_encode_void,
-- .pc_argsize = sizeof(struct nfsd_void),
-- .pc_ressize = sizeof(struct nfsd_void),
-+ .pc_decode = nfssvc_decode_voidarg,
-+ .pc_encode = nfssvc_encode_voidres,
-+ .pc_argsize = sizeof(struct nfsd_voidargs),
-+ .pc_ressize = sizeof(struct nfsd_voidres),
- .pc_cachetype = RC_NOCACHE,
- .pc_xdrressize = 0,
- },
-@@ -647,10 +646,10 @@ static const struct svc_procedure nfsd_procedures2[18] = {
- },
- [NFSPROC_ROOT] = {
- .pc_func = nfsd_proc_root,
-- .pc_decode = nfssvc_decode_void,
-- .pc_encode = nfssvc_encode_void,
-- .pc_argsize = sizeof(struct nfsd_void),
-- .pc_ressize = sizeof(struct nfsd_void),
-+ .pc_decode = nfssvc_decode_voidarg,
-+ .pc_encode = nfssvc_encode_voidres,
-+ .pc_argsize = sizeof(struct nfsd_voidargs),
-+ .pc_ressize = sizeof(struct nfsd_voidres),
- .pc_cachetype = RC_NOCACHE,
- .pc_xdrressize = 0,
- },
-@@ -685,10 +684,10 @@ static const struct svc_procedure nfsd_procedures2[18] = {
- },
- [NFSPROC_WRITECACHE] = {
- .pc_func = nfsd_proc_writecache,
-- .pc_decode = nfssvc_decode_void,
-- .pc_encode = nfssvc_encode_void,
-- .pc_argsize = sizeof(struct nfsd_void),
-- .pc_ressize = sizeof(struct nfsd_void),
-+ .pc_decode = nfssvc_decode_voidarg,
-+ .pc_encode = nfssvc_encode_voidres,
-+ .pc_argsize = sizeof(struct nfsd_voidargs),
-+ .pc_ressize = sizeof(struct nfsd_voidres),
- .pc_cachetype = RC_NOCACHE,
- .pc_xdrressize = 0,
- },
-diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
-index ad6fedf37a40..8b675e8e6a6e 100644
---- a/fs/nfsd/nfssvc.c
-+++ b/fs/nfsd/nfssvc.c
-@@ -1074,6 +1074,34 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
- return 1;
- }
-
-+/**
-+ * nfssvc_decode_voidarg - Decode void arguments
-+ * @rqstp: Server RPC transaction context
-+ * @p: buffer containing arguments to decode
-+ *
-+ * Return values:
-+ * %0: Arguments were not valid
-+ * %1: Decoding was successful
-+ */
-+int nfssvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
-+{
-+ return 1;
-+}
-+
-+/**
-+ * nfssvc_encode_voidres - Encode void results
-+ * @rqstp: Server RPC transaction context
-+ * @p: buffer in which to encode results
-+ *
-+ * Return values:
-+ * %0: Local error while encoding
-+ * %1: Encoding was successful
-+ */
-+int nfssvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p)
-+{
-+ return xdr_ressize_check(rqstp, p);
-+}
-+
- int nfsd_pool_stats_open(struct inode *inode, struct file *file)
- {
- int ret;
-diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
-index 8a288c8fcd57..13df5464a087 100644
---- a/fs/nfsd/nfsxdr.c
-+++ b/fs/nfsd/nfsxdr.c
-@@ -192,11 +192,6 @@ __be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *f
- /*
- * XDR decode functions
- */
--int
--nfssvc_decode_void(struct svc_rqst *rqstp, __be32 *p)
--{
-- return xdr_argsize_check(rqstp, p);
--}
-
- int
- nfssvc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p)
-@@ -423,11 +418,6 @@ nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p)
- /*
- * XDR encode functions
- */
--int
--nfssvc_encode_void(struct svc_rqst *rqstp, __be32 *p)
--{
-- return xdr_ressize_check(rqstp, p);
--}
-
- int
- nfssvc_encode_stat(struct svc_rqst *rqstp, __be32 *p)
-diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
-index b8cc6a4b2e0e..edd87688ff86 100644
---- a/fs/nfsd/xdr.h
-+++ b/fs/nfsd/xdr.h
-@@ -144,7 +144,6 @@ union nfsd_xdrstore {
- #define NFS2_SVC_XDRSIZE sizeof(union nfsd_xdrstore)
-
-
--int nfssvc_decode_void(struct svc_rqst *, __be32 *);
- int nfssvc_decode_fhandle(struct svc_rqst *, __be32 *);
- int nfssvc_decode_sattrargs(struct svc_rqst *, __be32 *);
- int nfssvc_decode_diropargs(struct svc_rqst *, __be32 *);
-@@ -156,7 +155,6 @@ int nfssvc_decode_readlinkargs(struct svc_rqst *, __be32 *);
- int nfssvc_decode_linkargs(struct svc_rqst *, __be32 *);
- int nfssvc_decode_symlinkargs(struct svc_rqst *, __be32 *);
- int nfssvc_decode_readdirargs(struct svc_rqst *, __be32 *);
--int nfssvc_encode_void(struct svc_rqst *, __be32 *);
- int nfssvc_encode_stat(struct svc_rqst *, __be32 *);
- int nfssvc_encode_attrstat(struct svc_rqst *, __be32 *);
- int nfssvc_encode_diropres(struct svc_rqst *, __be32 *);
-diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
-index ae6fa6c9cb46..456fcd7a1038 100644
---- a/fs/nfsd/xdr3.h
-+++ b/fs/nfsd/xdr3.h
-@@ -273,7 +273,6 @@ union nfsd3_xdrstore {
-
- #define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore)
-
--int nfs3svc_decode_voidarg(struct svc_rqst *, __be32 *);
- int nfs3svc_decode_fhandle(struct svc_rqst *, __be32 *);
- int nfs3svc_decode_sattrargs(struct svc_rqst *, __be32 *);
- int nfs3svc_decode_diropargs(struct svc_rqst *, __be32 *);
-@@ -290,7 +289,6 @@ int nfs3svc_decode_symlinkargs(struct svc_rqst *, __be32 *);
- int nfs3svc_decode_readdirargs(struct svc_rqst *, __be32 *);
- int nfs3svc_decode_readdirplusargs(struct svc_rqst *, __be32 *);
- int nfs3svc_decode_commitargs(struct svc_rqst *, __be32 *);
--int nfs3svc_encode_voidres(struct svc_rqst *, __be32 *);
- int nfs3svc_encode_attrstat(struct svc_rqst *, __be32 *);
- int nfs3svc_encode_wccstat(struct svc_rqst *, __be32 *);
- int nfs3svc_encode_diropres(struct svc_rqst *, __be32 *);
-diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
-index 679d40af1bbb..37f89ad5e992 100644
---- a/fs/nfsd/xdr4.h
-+++ b/fs/nfsd/xdr4.h
-@@ -781,8 +781,6 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
-
-
- bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp);
--int nfs4svc_decode_voidarg(struct svc_rqst *, __be32 *);
--int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *);
- int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *);
- int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *);
- __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *, u32);
---
-2.35.1
-
+++ /dev/null
-From 3d69c488be74d18b9be2d42a67f4f2326a499362 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 4 Feb 2022 15:19:34 -0500
-Subject: NFSD: Fix the behavior of READ near OFFSET_MAX
-
-From: Chuck Lever <chuck.lever@oracle.com>
-
-[ Upstream commit 0cb4d23ae08c48f6bf3c29a8e5c4a74b8388b960 ]
-
-Dan Aloni reports:
-> Due to commit 8cfb9015280d ("NFS: Always provide aligned buffers to
-> the RPC read layers") on the client, a read of 0xfff is aligned up
-> to server rsize of 0x1000.
->
-> As a result, in a test where the server has a file of size
-> 0x7fffffffffffffff, and the client tries to read from the offset
-> 0x7ffffffffffff000, the read causes loff_t overflow in the server
-> and it returns an NFS code of EINVAL to the client. The client as
-> a result indefinitely retries the request.
-
-The Linux NFS client does not handle NFS?ERR_INVAL, even though all
-NFS specifications permit servers to return that status code for a
-READ.
-
-Instead of NFS?ERR_INVAL, have out-of-range READ requests succeed
-and return a short result. Set the EOF flag in the result to prevent
-the client from retrying the READ request. This behavior appears to
-be consistent with Solaris NFS servers.
-
-Note that NFSv3 and NFSv4 use u64 offset values on the wire. These
-must be converted to loff_t internally before use -- an implicit
-type cast is not adequate for this purpose. Otherwise VFS checks
-against sb->s_maxbytes do not work properly.
-
-Reported-by: Dan Aloni <dan.aloni@vastdata.com>
-Cc: stable@vger.kernel.org
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Stable-dep-of: fa6be9cc6e80 ("NFSD: Protect against send buffer overflow in NFSv3 READ")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nfsd/nfs3proc.c | 8 ++++++--
- fs/nfsd/nfs4proc.c | 8 ++++++--
- fs/nfsd/nfs4xdr.c | 8 ++------
- 3 files changed, 14 insertions(+), 10 deletions(-)
-
-diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
-index 104e7d705ea8..60faa5b8eccf 100644
---- a/fs/nfsd/nfs3proc.c
-+++ b/fs/nfsd/nfs3proc.c
-@@ -148,13 +148,17 @@ nfsd3_proc_read(struct svc_rqst *rqstp)
- unsigned int len;
- int v;
-
-- argp->count = min_t(u32, argp->count, max_blocksize);
--
- dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n",
- SVCFH_fmt(&argp->fh),
- (unsigned long) argp->count,
- (unsigned long long) argp->offset);
-
-+ argp->count = min_t(u32, argp->count, max_blocksize);
-+ if (argp->offset > (u64)OFFSET_MAX)
-+ argp->offset = (u64)OFFSET_MAX;
-+ if (argp->offset + argp->count > (u64)OFFSET_MAX)
-+ argp->count = (u64)OFFSET_MAX - argp->offset;
-+
- v = 0;
- len = argp->count;
- while (len > 0) {
-diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
-index 5054dc66cbf9..363df0a795bc 100644
---- a/fs/nfsd/nfs4proc.c
-+++ b/fs/nfsd/nfs4proc.c
-@@ -772,12 +772,16 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
- __be32 status;
-
- read->rd_nf = NULL;
-- if (read->rd_offset >= OFFSET_MAX)
-- return nfserr_inval;
-
- trace_nfsd_read_start(rqstp, &cstate->current_fh,
- read->rd_offset, read->rd_length);
-
-+ read->rd_length = min_t(u32, read->rd_length, svc_max_payload(rqstp));
-+ if (read->rd_offset > (u64)OFFSET_MAX)
-+ read->rd_offset = (u64)OFFSET_MAX;
-+ if (read->rd_offset + read->rd_length > (u64)OFFSET_MAX)
-+ read->rd_length = (u64)OFFSET_MAX - read->rd_offset;
-+
- /*
- * If we do a zero copy read, then a client will see read data
- * that reflects the state of the file *after* performing the
-diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
-index d0af93a0558f..930bed3e40a4 100644
---- a/fs/nfsd/nfs4xdr.c
-+++ b/fs/nfsd/nfs4xdr.c
-@@ -3754,10 +3754,8 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
- }
- xdr_commit_encode(xdr);
-
-- maxcount = svc_max_payload(resp->rqstp);
-- maxcount = min_t(unsigned long, maxcount,
-+ maxcount = min_t(unsigned long, read->rd_length,
- (xdr->buf->buflen - xdr->buf->len));
-- maxcount = min_t(unsigned long, maxcount, read->rd_length);
-
- if (file->f_op->splice_read &&
- test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags))
-@@ -4585,10 +4583,8 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr,
- return nfserr_resource;
- xdr_commit_encode(xdr);
-
-- maxcount = svc_max_payload(resp->rqstp);
-- maxcount = min_t(unsigned long, maxcount,
-+ maxcount = min_t(unsigned long, read->rd_length,
- (xdr->buf->buflen - xdr->buf->len));
-- maxcount = min_t(unsigned long, maxcount, read->rd_length);
- count = maxcount;
-
- eof = read->rd_offset >= i_size_read(file_inode(file));
---
-2.35.1
-
+++ /dev/null
-From 371805ae7d57acb15b4ae15945abde5c27336ac4 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 1 Sep 2022 15:10:18 -0400
-Subject: NFSD: Protect against send buffer overflow in NFSv2 READ
-
-From: Chuck Lever <chuck.lever@oracle.com>
-
-[ Upstream commit 401bc1f90874280a80b93f23be33a0e7e2d1f912 ]
-
-Since before the git era, NFSD has conserved the number of pages
-held by each nfsd thread by combining the RPC receive and send
-buffers into a single array of pages. This works because there are
-no cases where an operation needs a large RPC Call message and a
-large RPC Reply at the same time.
-
-Once an RPC Call has been received, svc_process() updates
-svc_rqst::rq_res to describe the part of rq_pages that can be
-used for constructing the Reply. This means that the send buffer
-(rq_res) shrinks when the received RPC record containing the RPC
-Call is large.
-
-A client can force this shrinkage on TCP by sending a correctly-
-formed RPC Call header contained in an RPC record that is
-excessively large. The full maximum payload size cannot be
-constructed in that case.
-
-Cc: <stable@vger.kernel.org>
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Reviewed-by: Jeff Layton <jlayton@kernel.org>
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nfsd/nfsproc.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
-index deaa34b89251..c540326c8e00 100644
---- a/fs/nfsd/nfsproc.c
-+++ b/fs/nfsd/nfsproc.c
-@@ -180,6 +180,7 @@ nfsd_proc_read(struct svc_rqst *rqstp)
- argp->count, argp->offset);
-
- argp->count = min_t(u32, argp->count, NFSSVC_MAXBLKSIZE_V2);
-+ argp->count = min_t(u32, argp->count, rqstp->rq_res.buflen);
-
- v = 0;
- len = argp->count;
---
-2.35.1
-
+++ /dev/null
-From 4d327c12bb49db2ecc125a939bbc32a273a6607a Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 1 Sep 2022 15:10:24 -0400
-Subject: NFSD: Protect against send buffer overflow in NFSv3 READ
-
-From: Chuck Lever <chuck.lever@oracle.com>
-
-[ Upstream commit fa6be9cc6e80ec79892ddf08a8c10cabab9baf38 ]
-
-Since before the git era, NFSD has conserved the number of pages
-held by each nfsd thread by combining the RPC receive and send
-buffers into a single array of pages. This works because there are
-no cases where an operation needs a large RPC Call message and a
-large RPC Reply at the same time.
-
-Once an RPC Call has been received, svc_process() updates
-svc_rqst::rq_res to describe the part of rq_pages that can be
-used for constructing the Reply. This means that the send buffer
-(rq_res) shrinks when the received RPC record containing the RPC
-Call is large.
-
-A client can force this shrinkage on TCP by sending a correctly-
-formed RPC Call header contained in an RPC record that is
-excessively large. The full maximum payload size cannot be
-constructed in that case.
-
-Cc: <stable@vger.kernel.org>
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Reviewed-by: Jeff Layton <jlayton@kernel.org>
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nfsd/nfs3proc.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
-index 60faa5b8eccf..84e700a54d01 100644
---- a/fs/nfsd/nfs3proc.c
-+++ b/fs/nfsd/nfs3proc.c
-@@ -144,7 +144,6 @@ nfsd3_proc_read(struct svc_rqst *rqstp)
- {
- struct nfsd3_readargs *argp = rqstp->rq_argp;
- struct nfsd3_readres *resp = rqstp->rq_resp;
-- u32 max_blocksize = svc_max_payload(rqstp);
- unsigned int len;
- int v;
-
-@@ -153,7 +152,8 @@ nfsd3_proc_read(struct svc_rqst *rqstp)
- (unsigned long) argp->count,
- (unsigned long long) argp->offset);
-
-- argp->count = min_t(u32, argp->count, max_blocksize);
-+ argp->count = min_t(u32, argp->count, svc_max_payload(rqstp));
-+ argp->count = min_t(u32, argp->count, rqstp->rq_res.buflen);
- if (argp->offset > (u64)OFFSET_MAX)
- argp->offset = (u64)OFFSET_MAX;
- if (argp->offset + argp->count > (u64)OFFSET_MAX)
---
-2.35.1
-
+++ /dev/null
-From add4e4ab8734bc7519f9c446cb6b5a4aa1bb5b63 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 3 Nov 2020 13:19:51 -0500
-Subject: NFSD: Replace READ* macros in nfsd4_decode_commit()
-
-From: Chuck Lever <chuck.lever@oracle.com>
-
-[ Upstream commit cbd9abb3706e96563b36af67595707a7054ab693 ]
-
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Stable-dep-of: fa6be9cc6e80 ("NFSD: Protect against send buffer overflow in NFSv3 READ")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nfsd/nfs4xdr.c | 12 +++++-------
- include/linux/sunrpc/xdr.h | 21 +++++++++++++++++++++
- 2 files changed, 26 insertions(+), 7 deletions(-)
-
-diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
-index 69233350b061..d0af93a0558f 100644
---- a/fs/nfsd/nfs4xdr.c
-+++ b/fs/nfsd/nfs4xdr.c
-@@ -568,13 +568,11 @@ nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
- static __be32
- nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit)
- {
-- DECODE_HEAD;
--
-- READ_BUF(12);
-- p = xdr_decode_hyper(p, &commit->co_offset);
-- commit->co_count = be32_to_cpup(p++);
--
-- DECODE_TAIL;
-+ if (xdr_stream_decode_u64(argp->xdr, &commit->co_offset) < 0)
-+ return nfserr_bad_xdr;
-+ if (xdr_stream_decode_u32(argp->xdr, &commit->co_count) < 0)
-+ return nfserr_bad_xdr;
-+ return nfs_ok;
- }
-
- static __be32
-diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
-index c03f7bf585c9..6b1757543747 100644
---- a/include/linux/sunrpc/xdr.h
-+++ b/include/linux/sunrpc/xdr.h
-@@ -569,6 +569,27 @@ xdr_stream_decode_u32(struct xdr_stream *xdr, __u32 *ptr)
- return 0;
- }
-
-+/**
-+ * xdr_stream_decode_u64 - Decode a 64-bit integer
-+ * @xdr: pointer to xdr_stream
-+ * @ptr: location to store 64-bit integer
-+ *
-+ * Return values:
-+ * %0 on success
-+ * %-EBADMSG on XDR buffer overflow
-+ */
-+static inline ssize_t
-+xdr_stream_decode_u64(struct xdr_stream *xdr, __u64 *ptr)
-+{
-+ const size_t count = sizeof(*ptr);
-+ __be32 *p = xdr_inline_decode(xdr, count);
-+
-+ if (unlikely(!p))
-+ return -EBADMSG;
-+ xdr_decode_hyper(p, ptr);
-+ return 0;
-+}
-+
- /**
- * xdr_stream_decode_opaque_fixed - Decode fixed length opaque xdr data
- * @xdr: pointer to xdr_stream
---
-2.35.1
-
+++ /dev/null
-From fbbbdfeb61de7dfbaa5e5498af2254b49f0cb417 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 3 Nov 2020 11:54:23 -0500
-Subject: NFSD: Replace the internals of the READ_BUF() macro
-
-From: Chuck Lever <chuck.lever@oracle.com>
-
-[ Upstream commit c1346a1216ab5cb04a265380ac9035d91b16b6d5 ]
-
-Convert the READ_BUF macro in nfs4xdr.c from open code to instead
-use the new xdr_stream-style decoders already in use by the encode
-side (and by the in-kernel NFS client implementation). Once this
-conversion is done, each individual NFSv4 argument decoder can be
-independently cleaned up to replace these macros with C code.
-
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Stable-dep-of: fa6be9cc6e80 ("NFSD: Protect against send buffer overflow in NFSv3 READ")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nfsd/nfs4proc.c | 4 +-
- fs/nfsd/nfs4xdr.c | 181 ++++++-------------------------------
- fs/nfsd/xdr4.h | 10 +-
- include/linux/sunrpc/xdr.h | 2 +
- net/sunrpc/xdr.c | 45 +++++++++
- 5 files changed, 77 insertions(+), 165 deletions(-)
-
-diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
-index 1acafc39f008..5054dc66cbf9 100644
---- a/fs/nfsd/nfs4proc.c
-+++ b/fs/nfsd/nfs4proc.c
-@@ -1024,8 +1024,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
-
- write->wr_how_written = write->wr_stable_how;
-
-- nvecs = svc_fill_write_vector(rqstp, write->wr_pagelist,
-- &write->wr_head, write->wr_buflen);
-+ nvecs = svc_fill_write_vector(rqstp, write->wr_payload.pages,
-+ write->wr_payload.head, write->wr_buflen);
- WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));
-
- status = nfsd_vfs_write(rqstp, &cstate->current_fh, nf,
-diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
-index e7b891a19bf8..69233350b061 100644
---- a/fs/nfsd/nfs4xdr.c
-+++ b/fs/nfsd/nfs4xdr.c
-@@ -129,90 +129,13 @@ xdr_error: \
- memcpy((x), p, nbytes); \
- p += XDR_QUADLEN(nbytes); \
- } while (0)
--
--/* READ_BUF, read_buf(): nbytes must be <= PAGE_SIZE */
--#define READ_BUF(nbytes) do { \
-- if (nbytes <= (u32)((char *)argp->end - (char *)argp->p)) { \
-- p = argp->p; \
-- argp->p += XDR_QUADLEN(nbytes); \
-- } else if (!(p = read_buf(argp, nbytes))) { \
-- dprintk("NFSD: xdr error (%s:%d)\n", \
-- __FILE__, __LINE__); \
-- goto xdr_error; \
-- } \
--} while (0)
--
--static void next_decode_page(struct nfsd4_compoundargs *argp)
--{
-- argp->p = page_address(argp->pagelist[0]);
-- argp->pagelist++;
-- if (argp->pagelen < PAGE_SIZE) {
-- argp->end = argp->p + XDR_QUADLEN(argp->pagelen);
-- argp->pagelen = 0;
-- } else {
-- argp->end = argp->p + (PAGE_SIZE>>2);
-- argp->pagelen -= PAGE_SIZE;
-- }
--}
--
--static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
--{
-- /* We want more bytes than seem to be available.
-- * Maybe we need a new page, maybe we have just run out
-- */
-- unsigned int avail = (char *)argp->end - (char *)argp->p;
-- __be32 *p;
--
-- if (argp->pagelen == 0) {
-- struct kvec *vec = &argp->rqstp->rq_arg.tail[0];
--
-- if (!argp->tail) {
-- argp->tail = true;
-- avail = vec->iov_len;
-- argp->p = vec->iov_base;
-- argp->end = vec->iov_base + avail;
-- }
--
-- if (avail < nbytes)
-- return NULL;
--
-- p = argp->p;
-- argp->p += XDR_QUADLEN(nbytes);
-- return p;
-- }
--
-- if (avail + argp->pagelen < nbytes)
-- return NULL;
-- if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */
-- return NULL;
-- /* ok, we can do it with the current plus the next page */
-- if (nbytes <= sizeof(argp->tmp))
-- p = argp->tmp;
-- else {
-- kfree(argp->tmpp);
-- p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL);
-- if (!p)
-- return NULL;
--
-- }
-- /*
-- * The following memcpy is safe because read_buf is always
-- * called with nbytes > avail, and the two cases above both
-- * guarantee p points to at least nbytes bytes.
-- */
-- memcpy(p, argp->p, avail);
-- next_decode_page(argp);
-- memcpy(((char*)p)+avail, argp->p, (nbytes - avail));
-- argp->p += XDR_QUADLEN(nbytes - avail);
-- return p;
--}
--
--static unsigned int compoundargs_bytes_left(struct nfsd4_compoundargs *argp)
--{
-- unsigned int this = (char *)argp->end - (char *)argp->p;
--
-- return this + argp->pagelen;
--}
-+#define READ_BUF(nbytes) \
-+ do { \
-+ p = xdr_inline_decode(argp->xdr,\
-+ nbytes); \
-+ if (!p) \
-+ goto xdr_error; \
-+ } while (0)
-
- static int zero_clientid(clientid_t *clid)
- {
-@@ -259,44 +182,6 @@ svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, u32 len)
- return p;
- }
-
--static __be32
--svcxdr_construct_vector(struct nfsd4_compoundargs *argp, struct kvec *head,
-- struct page ***pagelist, u32 buflen)
--{
-- int avail;
-- int len;
-- int pages;
--
-- /* Sorry .. no magic macros for this.. *
-- * READ_BUF(write->wr_buflen);
-- * SAVEMEM(write->wr_buf, write->wr_buflen);
-- */
-- avail = (char *)argp->end - (char *)argp->p;
-- if (avail + argp->pagelen < buflen) {
-- dprintk("NFSD: xdr error (%s:%d)\n",
-- __FILE__, __LINE__);
-- return nfserr_bad_xdr;
-- }
-- head->iov_base = argp->p;
-- head->iov_len = avail;
-- *pagelist = argp->pagelist;
--
-- len = XDR_QUADLEN(buflen) << 2;
-- if (len >= avail) {
-- len -= avail;
--
-- pages = len >> PAGE_SHIFT;
-- argp->pagelist += pages;
-- argp->pagelen -= pages * PAGE_SIZE;
-- len -= pages * PAGE_SIZE;
--
-- next_decode_page(argp);
-- }
-- argp->p += XDR_QUADLEN(len);
--
-- return 0;
--}
--
- /**
- * savemem - duplicate a chunk of memory for later processing
- * @argp: NFSv4 compound argument structure to be freed with
-@@ -396,7 +281,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
- READ_BUF(4); len += 4;
- nace = be32_to_cpup(p++);
-
-- if (nace > compoundargs_bytes_left(argp)/20)
-+ if (nace > xdr_stream_remaining(argp->xdr) / sizeof(struct nfs4_ace))
- /*
- * Even with 4-byte names there wouldn't be
- * space for that many aces; something fishy is
-@@ -927,7 +812,7 @@ static __be32 nfsd4_decode_share_deny(struct nfsd4_compoundargs *argp, u32 *x)
-
- static __be32 nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o)
- {
-- __be32 *p;
-+ DECODE_HEAD;
-
- READ_BUF(4);
- o->len = be32_to_cpup(p++);
-@@ -937,9 +822,8 @@ static __be32 nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_ne
-
- READ_BUF(o->len);
- SAVEMEM(o->data, o->len);
-- return nfs_ok;
--xdr_error:
-- return nfserr_bad_xdr;
-+
-+ DECODE_TAIL;
- }
-
- static __be32
-@@ -1317,10 +1201,8 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
- goto xdr_error;
- write->wr_buflen = be32_to_cpup(p++);
-
-- status = svcxdr_construct_vector(argp, &write->wr_head,
-- &write->wr_pagelist, write->wr_buflen);
-- if (status)
-- return status;
-+ if (!xdr_stream_subsegment(argp->xdr, &write->wr_payload, write->wr_buflen))
-+ goto xdr_error;
-
- DECODE_TAIL;
- }
-@@ -1889,13 +1771,14 @@ nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek)
- */
-
- /*
-- * Decode data into buffer. Uses head and pages constructed by
-- * svcxdr_construct_vector.
-+ * Decode data into buffer.
- */
- static __be32
--nfsd4_vbuf_from_vector(struct nfsd4_compoundargs *argp, struct kvec *head,
-- struct page **pages, char **bufp, u32 buflen)
-+nfsd4_vbuf_from_vector(struct nfsd4_compoundargs *argp, struct xdr_buf *xdr,
-+ char **bufp, u32 buflen)
- {
-+ struct page **pages = xdr->pages;
-+ struct kvec *head = xdr->head;
- char *tmp, *dp;
- u32 len;
-
-@@ -2010,8 +1893,6 @@ nfsd4_decode_setxattr(struct nfsd4_compoundargs *argp,
- {
- DECODE_HEAD;
- u32 flags, maxcount, size;
-- struct kvec head;
-- struct page **pagelist;
-
- READ_BUF(4);
- flags = be32_to_cpup(p++);
-@@ -2034,12 +1915,12 @@ nfsd4_decode_setxattr(struct nfsd4_compoundargs *argp,
-
- setxattr->setxa_len = size;
- if (size > 0) {
-- status = svcxdr_construct_vector(argp, &head, &pagelist, size);
-- if (status)
-- return status;
-+ struct xdr_buf payload;
-
-- status = nfsd4_vbuf_from_vector(argp, &head, pagelist,
-- &setxattr->setxa_buf, size);
-+ if (!xdr_stream_subsegment(argp->xdr, &payload, size))
-+ goto xdr_error;
-+ status = nfsd4_vbuf_from_vector(argp, &payload,
-+ &setxattr->setxa_buf, size);
- }
-
- DECODE_TAIL;
-@@ -5271,8 +5152,6 @@ void nfsd4_release_compoundargs(struct svc_rqst *rqstp)
- kfree(args->ops);
- args->ops = args->iops;
- }
-- kfree(args->tmpp);
-- args->tmpp = NULL;
- while (args->to_free) {
- struct svcxdr_tmpbuf *tb = args->to_free;
- args->to_free = tb->next;
-@@ -5285,19 +5164,11 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p)
- {
- struct nfsd4_compoundargs *args = rqstp->rq_argp;
-
-- if (rqstp->rq_arg.head[0].iov_len % 4) {
-- /* client is nuts */
-- dprintk("%s: compound not properly padded! (peeraddr=%pISc xid=0x%x)",
-- __func__, svc_addr(rqstp), be32_to_cpu(rqstp->rq_xid));
-- return 0;
-- }
-- args->p = p;
-- args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
-- args->pagelist = rqstp->rq_arg.pages;
-- args->pagelen = rqstp->rq_arg.page_len;
-- args->tail = false;
-+ /* svcxdr_tmp_alloc */
- args->tmpp = NULL;
- args->to_free = NULL;
-+
-+ args->xdr = &rqstp->rq_arg_stream;
- args->ops = args->iops;
- args->rqstp = rqstp;
-
-diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
-index 37f89ad5e992..0eb13bd603ea 100644
---- a/fs/nfsd/xdr4.h
-+++ b/fs/nfsd/xdr4.h
-@@ -419,8 +419,7 @@ struct nfsd4_write {
- u64 wr_offset; /* request */
- u32 wr_stable_how; /* request */
- u32 wr_buflen; /* request */
-- struct kvec wr_head;
-- struct page ** wr_pagelist; /* request */
-+ struct xdr_buf wr_payload; /* request */
-
- u32 wr_bytes_written; /* response */
- u32 wr_how_written; /* response */
-@@ -696,15 +695,10 @@ struct svcxdr_tmpbuf {
-
- struct nfsd4_compoundargs {
- /* scratch variables for XDR decode */
-- __be32 * p;
-- __be32 * end;
-- struct page ** pagelist;
-- int pagelen;
-- bool tail;
- __be32 tmp[8];
- __be32 * tmpp;
-+ struct xdr_stream *xdr;
- struct svcxdr_tmpbuf *to_free;
--
- struct svc_rqst *rqstp;
-
- u32 taglen;
-diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
-index 0c8cab6210b3..c03f7bf585c9 100644
---- a/include/linux/sunrpc/xdr.h
-+++ b/include/linux/sunrpc/xdr.h
-@@ -252,6 +252,8 @@ extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
- extern int xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data);
- extern uint64_t xdr_align_data(struct xdr_stream *, uint64_t, uint32_t);
- extern uint64_t xdr_expand_hole(struct xdr_stream *, uint64_t, uint64_t);
-+extern bool xdr_stream_subsegment(struct xdr_stream *xdr, struct xdr_buf *subbuf,
-+ unsigned int len);
-
- /**
- * xdr_set_scratch_buffer - Attach a scratch buffer for decoding data.
-diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
-index 02adc5c7f034..722586696fad 100644
---- a/net/sunrpc/xdr.c
-+++ b/net/sunrpc/xdr.c
-@@ -1412,6 +1412,51 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf,
- }
- EXPORT_SYMBOL_GPL(xdr_buf_subsegment);
-
-+/**
-+ * xdr_stream_subsegment - set @subbuf to a portion of @xdr
-+ * @xdr: an xdr_stream set up for decoding
-+ * @subbuf: the result buffer
-+ * @nbytes: length of @xdr to extract, in bytes
-+ *
-+ * Sets up @subbuf to represent a portion of @xdr. The portion
-+ * starts at the current offset in @xdr, and extends for a length
-+ * of @nbytes. If this is successful, @xdr is advanced to the next
-+ * position following that portion.
-+ *
-+ * Return values:
-+ * %true: @subbuf has been initialized, and @xdr has been advanced.
-+ * %false: a bounds error has occurred
-+ */
-+bool xdr_stream_subsegment(struct xdr_stream *xdr, struct xdr_buf *subbuf,
-+ unsigned int nbytes)
-+{
-+ unsigned int remaining, offset, len;
-+
-+ if (xdr_buf_subsegment(xdr->buf, subbuf, xdr_stream_pos(xdr), nbytes))
-+ return false;
-+
-+ if (subbuf->head[0].iov_len)
-+ if (!__xdr_inline_decode(xdr, subbuf->head[0].iov_len))
-+ return false;
-+
-+ remaining = subbuf->page_len;
-+ offset = subbuf->page_base;
-+ while (remaining) {
-+ len = min_t(unsigned int, remaining, PAGE_SIZE) - offset;
-+
-+ if (xdr->p == xdr->end && !xdr_set_next_buffer(xdr))
-+ return false;
-+ if (!__xdr_inline_decode(xdr, len))
-+ return false;
-+
-+ remaining -= len;
-+ offset = 0;
-+ }
-+
-+ return true;
-+}
-+EXPORT_SYMBOL_GPL(xdr_stream_subsegment);
-+
- /**
- * xdr_buf_trim - lop at most "len" bytes off the end of "buf"
- * @buf: buf to be trimmed
---
-2.35.1
-
+++ /dev/null
-From f846eda22099bbc03b9706b9a0e4318b753d8077 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 20 Oct 2020 14:30:02 -0400
-Subject: NFSD: Update GETATTR3args decoder to use struct xdr_stream
-
-From: Chuck Lever <chuck.lever@oracle.com>
-
-[ Upstream commit 9575363a9e4c8d7e2f9ba5e79884d623fff0be6f ]
-
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Stable-dep-of: fa6be9cc6e80 ("NFSD: Protect against send buffer overflow in NFSv3 READ")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nfsd/nfs3proc.c | 3 +--
- fs/nfsd/nfs3xdr.c | 31 +++++++++++++++++++++++++------
- fs/nfsd/xdr3.h | 2 +-
- 3 files changed, 27 insertions(+), 9 deletions(-)
-
-diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
-index a4dfe8160d55..3d741ea482f4 100644
---- a/fs/nfsd/nfs3proc.c
-+++ b/fs/nfsd/nfs3proc.c
-@@ -688,7 +688,6 @@ nfsd3_proc_commit(struct svc_rqst *rqstp)
- * NFSv3 Server procedures.
- * Only the results of non-idempotent operations are cached.
- */
--#define nfs3svc_decode_fhandleargs nfs3svc_decode_fhandle
- #define nfs3svc_encode_attrstatres nfs3svc_encode_attrstat
- #define nfs3svc_encode_wccstatres nfs3svc_encode_wccstat
- #define nfsd3_mkdirargs nfsd3_createargs
-@@ -720,7 +719,7 @@ static const struct svc_procedure nfsd_procedures3[22] = {
- .pc_decode = nfs3svc_decode_fhandleargs,
- .pc_encode = nfs3svc_encode_attrstatres,
- .pc_release = nfs3svc_release_fhandle,
-- .pc_argsize = sizeof(struct nfsd3_fhandleargs),
-+ .pc_argsize = sizeof(struct nfsd_fhandle),
- .pc_ressize = sizeof(struct nfsd3_attrstatres),
- .pc_cachetype = RC_NOCACHE,
- .pc_xdrressize = ST+AT,
-diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
-index 9dc22d917bd2..ed500f254337 100644
---- a/fs/nfsd/nfs3xdr.c
-+++ b/fs/nfsd/nfs3xdr.c
-@@ -29,8 +29,9 @@ static u32 nfs3_ftypes[] = {
-
-
- /*
-- * XDR functions for basic NFS types
-+ * Basic NFSv3 data types (RFC 1813 Sections 2.5 and 2.6)
- */
-+
- static __be32 *
- encode_time3(__be32 *p, struct timespec64 *time)
- {
-@@ -46,6 +47,26 @@ decode_time3(__be32 *p, struct timespec64 *time)
- return p;
- }
-
-+static bool
-+svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp)
-+{
-+ __be32 *p;
-+ u32 size;
-+
-+ if (xdr_stream_decode_u32(xdr, &size) < 0)
-+ return false;
-+ if (size == 0 || size > NFS3_FHSIZE)
-+ return false;
-+ p = xdr_inline_decode(xdr, size);
-+ if (!p)
-+ return false;
-+ fh_init(fhp, NFS3_FHSIZE);
-+ fhp->fh_handle.fh_size = size;
-+ memcpy(&fhp->fh_handle.fh_base, p, size);
-+
-+ return true;
-+}
-+
- static __be32 *
- decode_fh(__be32 *p, struct svc_fh *fhp)
- {
-@@ -306,14 +327,12 @@ void fill_post_wcc(struct svc_fh *fhp)
- */
-
- int
--nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p)
-+nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p)
- {
-+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
- struct nfsd_fhandle *args = rqstp->rq_argp;
-
-- p = decode_fh(p, &args->fh);
-- if (!p)
-- return 0;
-- return xdr_argsize_check(rqstp, p);
-+ return svcxdr_decode_nfs_fh3(xdr, &args->fh);
- }
-
- int
-diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
-index 456fcd7a1038..62ea669768cf 100644
---- a/fs/nfsd/xdr3.h
-+++ b/fs/nfsd/xdr3.h
-@@ -273,7 +273,7 @@ union nfsd3_xdrstore {
-
- #define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore)
-
--int nfs3svc_decode_fhandle(struct svc_rqst *, __be32 *);
-+int nfs3svc_decode_fhandleargs(struct svc_rqst *, __be32 *);
- int nfs3svc_decode_sattrargs(struct svc_rqst *, __be32 *);
- int nfs3svc_decode_diropargs(struct svc_rqst *, __be32 *);
- int nfs3svc_decode_accessargs(struct svc_rqst *, __be32 *);
---
-2.35.1
-
+++ /dev/null
-From ec8c3337fcceb6bc1f0cbbd1ae44d5e419cbf171 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 20 Oct 2020 14:34:40 -0400
-Subject: NFSD: Update READ3arg decoder to use struct xdr_stream
-
-From: Chuck Lever <chuck.lever@oracle.com>
-
-[ Upstream commit be63bd2ac6bbf8c065a0ef6dfbea76934326c352 ]
-
-The code that sets up rq_vec is refactored so that it is now
-adjacent to the nfsd_read() call site where it is used.
-
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Stable-dep-of: fa6be9cc6e80 ("NFSD: Protect against send buffer overflow in NFSv3 READ")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nfsd/nfs3proc.c | 23 ++++++++++++++++++-----
- fs/nfsd/nfs3xdr.c | 28 +++++++---------------------
- fs/nfsd/xdr3.h | 1 -
- 3 files changed, 25 insertions(+), 27 deletions(-)
-
-diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
-index 3d741ea482f4..104e7d705ea8 100644
---- a/fs/nfsd/nfs3proc.c
-+++ b/fs/nfsd/nfs3proc.c
-@@ -144,25 +144,38 @@ nfsd3_proc_read(struct svc_rqst *rqstp)
- {
- struct nfsd3_readargs *argp = rqstp->rq_argp;
- struct nfsd3_readres *resp = rqstp->rq_resp;
-- u32 max_blocksize = svc_max_payload(rqstp);
-- unsigned long cnt = min(argp->count, max_blocksize);
-+ u32 max_blocksize = svc_max_payload(rqstp);
-+ unsigned int len;
-+ int v;
-+
-+ argp->count = min_t(u32, argp->count, max_blocksize);
-
- dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n",
- SVCFH_fmt(&argp->fh),
- (unsigned long) argp->count,
- (unsigned long long) argp->offset);
-
-+ v = 0;
-+ len = argp->count;
-+ while (len > 0) {
-+ struct page *page = *(rqstp->rq_next_page++);
-+
-+ rqstp->rq_vec[v].iov_base = page_address(page);
-+ rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE);
-+ len -= rqstp->rq_vec[v].iov_len;
-+ v++;
-+ }
-+
- /* Obtain buffer pointer for payload.
- * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
- * + 1 (xdr opaque byte count) = 26
- */
-- resp->count = cnt;
-+ resp->count = argp->count;
- svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
-
- fh_copy(&resp->fh, &argp->fh);
- resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
-- rqstp->rq_vec, argp->vlen, &resp->count,
-- &resp->eof);
-+ rqstp->rq_vec, v, &resp->count, &resp->eof);
- return rpc_success;
- }
-
-diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
-index ed500f254337..0c51f241c047 100644
---- a/fs/nfsd/nfs3xdr.c
-+++ b/fs/nfsd/nfs3xdr.c
-@@ -382,31 +382,17 @@ nfs3svc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p)
- int
- nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p)
- {
-+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
- struct nfsd3_readargs *args = rqstp->rq_argp;
-- unsigned int len;
-- int v;
-- u32 max_blocksize = svc_max_payload(rqstp);
-
-- p = decode_fh(p, &args->fh);
-- if (!p)
-+ if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
-+ return 0;
-+ if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
-+ return 0;
-+ if (xdr_stream_decode_u32(xdr, &args->count) < 0)
- return 0;
-- p = xdr_decode_hyper(p, &args->offset);
--
-- args->count = ntohl(*p++);
-- len = min(args->count, max_blocksize);
--
-- /* set up the kvec */
-- v=0;
-- while (len > 0) {
-- struct page *p = *(rqstp->rq_next_page++);
-
-- rqstp->rq_vec[v].iov_base = page_address(p);
-- rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE);
-- len -= rqstp->rq_vec[v].iov_len;
-- v++;
-- }
-- args->vlen = v;
-- return xdr_argsize_check(rqstp, p);
-+ return 1;
- }
-
- int
-diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
-index 62ea669768cf..68cbb9e24afa 100644
---- a/fs/nfsd/xdr3.h
-+++ b/fs/nfsd/xdr3.h
-@@ -32,7 +32,6 @@ struct nfsd3_readargs {
- struct svc_fh fh;
- __u64 offset;
- __u32 count;
-- int vlen;
- };
-
- struct nfsd3_writeargs {
---
-2.35.1
-
+++ /dev/null
-From 1e265741e8e5554e2fd1e4a42aa49e827a518da2 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 21 Oct 2020 12:14:23 -0400
-Subject: NFSD: Update the NFSv2 GETATTR argument decoder to use struct
- xdr_stream
-
-From: Chuck Lever <chuck.lever@oracle.com>
-
-[ Upstream commit ebcd8e8b28535b643a4c06685bd363b3b73a96af ]
-
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Stable-dep-of: 401bc1f90874 ("NFSD: Protect against send buffer overflow in NFSv2 READ")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nfsd/nfsproc.c | 4 ++--
- fs/nfsd/nfsxdr.c | 26 ++++++++++++++++++++------
- fs/nfsd/xdr.h | 2 +-
- 3 files changed, 23 insertions(+), 9 deletions(-)
-
-diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
-index dbd8d3604653..5c187d3bcb57 100644
---- a/fs/nfsd/nfsproc.c
-+++ b/fs/nfsd/nfsproc.c
-@@ -626,7 +626,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
- },
- [NFSPROC_GETATTR] = {
- .pc_func = nfsd_proc_getattr,
-- .pc_decode = nfssvc_decode_fhandle,
-+ .pc_decode = nfssvc_decode_fhandleargs,
- .pc_encode = nfssvc_encode_attrstat,
- .pc_release = nfssvc_release_attrstat,
- .pc_argsize = sizeof(struct nfsd_fhandle),
-@@ -776,7 +776,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
- },
- [NFSPROC_STATFS] = {
- .pc_func = nfsd_proc_statfs,
-- .pc_decode = nfssvc_decode_fhandle,
-+ .pc_decode = nfssvc_decode_fhandleargs,
- .pc_encode = nfssvc_encode_statfsres,
- .pc_argsize = sizeof(struct nfsd_fhandle),
- .pc_ressize = sizeof(struct nfsd_statfsres),
-diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
-index 13df5464a087..45d980d624f4 100644
---- a/fs/nfsd/nfsxdr.c
-+++ b/fs/nfsd/nfsxdr.c
-@@ -23,8 +23,9 @@ static u32 nfs_ftypes[] = {
-
-
- /*
-- * XDR functions for basic NFS types
-+ * Basic NFSv2 data types (RFC 1094 Section 2.3)
- */
-+
- static __be32 *
- decode_fh(__be32 *p, struct svc_fh *fhp)
- {
-@@ -37,6 +38,21 @@ decode_fh(__be32 *p, struct svc_fh *fhp)
- return p + (NFS_FHSIZE >> 2);
- }
-
-+static bool
-+svcxdr_decode_fhandle(struct xdr_stream *xdr, struct svc_fh *fhp)
-+{
-+ __be32 *p;
-+
-+ p = xdr_inline_decode(xdr, NFS_FHSIZE);
-+ if (!p)
-+ return false;
-+ fh_init(fhp, NFS_FHSIZE);
-+ memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
-+ fhp->fh_handle.fh_size = NFS_FHSIZE;
-+
-+ return true;
-+}
-+
- /* Helper function for NFSv2 ACL code */
- __be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp)
- {
-@@ -194,14 +210,12 @@ __be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *f
- */
-
- int
--nfssvc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p)
-+nfssvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p)
- {
-+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
- struct nfsd_fhandle *args = rqstp->rq_argp;
-
-- p = decode_fh(p, &args->fh);
-- if (!p)
-- return 0;
-- return xdr_argsize_check(rqstp, p);
-+ return svcxdr_decode_fhandle(xdr, &args->fh);
- }
-
- int
-diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
-index edd87688ff86..50466ac6200c 100644
---- a/fs/nfsd/xdr.h
-+++ b/fs/nfsd/xdr.h
-@@ -144,7 +144,7 @@ union nfsd_xdrstore {
- #define NFS2_SVC_XDRSIZE sizeof(union nfsd_xdrstore)
-
-
--int nfssvc_decode_fhandle(struct svc_rqst *, __be32 *);
-+int nfssvc_decode_fhandleargs(struct svc_rqst *, __be32 *);
- int nfssvc_decode_sattrargs(struct svc_rqst *, __be32 *);
- int nfssvc_decode_diropargs(struct svc_rqst *, __be32 *);
- int nfssvc_decode_readargs(struct svc_rqst *, __be32 *);
---
-2.35.1
-
+++ /dev/null
-From 8085ba35427e0fa7b6378cddbd1d5cc0e89c8b09 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 21 Oct 2020 12:15:51 -0400
-Subject: NFSD: Update the NFSv2 READ argument decoder to use struct xdr_stream
-
-From: Chuck Lever <chuck.lever@oracle.com>
-
-[ Upstream commit 8c293ef993c8df0b1bea9ecb0de6eb96dec3ac9d ]
-
-The code that sets up rq_vec is refactored so that it is now
-adjacent to the nfsd_read() call site where it is used.
-
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Stable-dep-of: 401bc1f90874 ("NFSD: Protect against send buffer overflow in NFSv2 READ")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nfsd/nfsproc.c | 32 ++++++++++++++++++--------------
- fs/nfsd/nfsxdr.c | 36 ++++++++++++------------------------
- fs/nfsd/xdr.h | 1 -
- 3 files changed, 30 insertions(+), 39 deletions(-)
-
-diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
-index 5c187d3bcb57..deaa34b89251 100644
---- a/fs/nfsd/nfsproc.c
-+++ b/fs/nfsd/nfsproc.c
-@@ -171,32 +171,36 @@ nfsd_proc_read(struct svc_rqst *rqstp)
- {
- struct nfsd_readargs *argp = rqstp->rq_argp;
- struct nfsd_readres *resp = rqstp->rq_resp;
-+ unsigned int len;
- u32 eof;
-+ int v;
-
- dprintk("nfsd: READ %s %d bytes at %d\n",
- SVCFH_fmt(&argp->fh),
- argp->count, argp->offset);
-
-+ argp->count = min_t(u32, argp->count, NFSSVC_MAXBLKSIZE_V2);
-+
-+ v = 0;
-+ len = argp->count;
-+ while (len > 0) {
-+ struct page *page = *(rqstp->rq_next_page++);
-+
-+ rqstp->rq_vec[v].iov_base = page_address(page);
-+ rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE);
-+ len -= rqstp->rq_vec[v].iov_len;
-+ v++;
-+ }
-+
- /* Obtain buffer pointer for payload. 19 is 1 word for
- * status, 17 words for fattr, and 1 word for the byte count.
- */
--
-- if (NFSSVC_MAXBLKSIZE_V2 < argp->count) {
-- char buf[RPC_MAX_ADDRBUFLEN];
-- printk(KERN_NOTICE
-- "oversized read request from %s (%d bytes)\n",
-- svc_print_addr(rqstp, buf, sizeof(buf)),
-- argp->count);
-- argp->count = NFSSVC_MAXBLKSIZE_V2;
-- }
- svc_reserve_auth(rqstp, (19<<2) + argp->count + 4);
-
- resp->count = argp->count;
-- resp->status = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
-- argp->offset,
-- rqstp->rq_vec, argp->vlen,
-- &resp->count,
-- &eof);
-+ fh_copy(&resp->fh, &argp->fh);
-+ resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
-+ rqstp->rq_vec, v, &resp->count, &eof);
- if (resp->status == nfs_ok)
- resp->status = fh_getattr(&resp->fh, &resp->stat);
- else if (resp->status == nfserr_jukebox)
-diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
-index 45d980d624f4..a44c42d35351 100644
---- a/fs/nfsd/nfsxdr.c
-+++ b/fs/nfsd/nfsxdr.c
-@@ -246,33 +246,21 @@ nfssvc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p)
- int
- nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p)
- {
-+ struct xdr_stream *xdr = &rqstp->rq_arg_stream;
- struct nfsd_readargs *args = rqstp->rq_argp;
-- unsigned int len;
-- int v;
-- p = decode_fh(p, &args->fh);
-- if (!p)
-- return 0;
-+ u32 totalcount;
-
-- args->offset = ntohl(*p++);
-- len = args->count = ntohl(*p++);
-- p++; /* totalcount - unused */
--
-- len = min_t(unsigned int, len, NFSSVC_MAXBLKSIZE_V2);
-+ if (!svcxdr_decode_fhandle(xdr, &args->fh))
-+ return 0;
-+ if (xdr_stream_decode_u32(xdr, &args->offset) < 0)
-+ return 0;
-+ if (xdr_stream_decode_u32(xdr, &args->count) < 0)
-+ return 0;
-+ /* totalcount is ignored */
-+ if (xdr_stream_decode_u32(xdr, &totalcount) < 0)
-+ return 0;
-
-- /* set up somewhere to store response.
-- * We take pages, put them on reslist and include in iovec
-- */
-- v=0;
-- while (len > 0) {
-- struct page *p = *(rqstp->rq_next_page++);
--
-- rqstp->rq_vec[v].iov_base = page_address(p);
-- rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE);
-- len -= rqstp->rq_vec[v].iov_len;
-- v++;
-- }
-- args->vlen = v;
-- return xdr_argsize_check(rqstp, p);
-+ return 1;
- }
-
- int
-diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
-index 50466ac6200c..7c704fa3215e 100644
---- a/fs/nfsd/xdr.h
-+++ b/fs/nfsd/xdr.h
-@@ -27,7 +27,6 @@ struct nfsd_readargs {
- struct svc_fh fh;
- __u32 offset;
- __u32 count;
-- int vlen;
- };
-
- struct nfsd_writeargs {
---
-2.35.1
-
iommu-vt-d-allow-nvs-regions-in-arch_rmrr_sanity_che.patch
iommu-vt-d-clean-up-si_domain-in-the-init_dmars-erro.patch
drm-virtio-use-appropriate-atomic-state-in-virtio_gp.patch
-sunrpc-add-xdr_set_scratch_page-and-xdr_reset_scratc.patch
-sunrpc-prepare-for-xdr_stream-style-decoding-on-the-.patch
-nfsd-add-common-helpers-to-decode-void-args-and-enco.patch
-nfsd-update-the-nfsv2-getattr-argument-decoder-to-us.patch
-nfsd-update-the-nfsv2-read-argument-decoder-to-use-s.patch
-nfsd-protect-against-send-buffer-overflow-in-nfsv2-r.patch
-nfsd-replace-the-internals-of-the-read_buf-macro.patch
-nfsd-replace-read-macros-in-nfsd4_decode_commit.patch
-nfsd-update-getattr3args-decoder-to-use-struct-xdr_s.patch
-nfsd-update-read3arg-decoder-to-use-struct-xdr_strea.patch
-nfsd-fix-the-behavior-of-read-near-offset_max.patch
-nfsd-protect-against-send-buffer-overflow-in-nfsv3-r.patch
dmaengine-mxs-dma-remove-the-unused-.id_table.patch
dmaengine-mxs-use-platform_driver_register.patch
writeback-don-t-warn-on-an-unregistered-bdi-in-__mar.patch
+++ /dev/null
-From 520c12fe7527e8c6fa85982c46d0d079fa704a08 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 11 Nov 2020 15:52:47 -0500
-Subject: SUNRPC: Add xdr_set_scratch_page() and xdr_reset_scratch_buffer()
-
-From: Chuck Lever <chuck.lever@oracle.com>
-
-[ Upstream commit 0ae4c3e8a64ace1b8d7de033b0751afe43024416 ]
-
-Clean up: De-duplicate some frequently-used code.
-
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Stable-dep-of: 401bc1f90874 ("NFSD: Protect against send buffer overflow in NFSv2 READ")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nfs/blocklayout/blocklayout.c | 2 +-
- fs/nfs/blocklayout/dev.c | 2 +-
- fs/nfs/dir.c | 2 +-
- fs/nfs/filelayout/filelayout.c | 2 +-
- fs/nfs/filelayout/filelayoutdev.c | 2 +-
- fs/nfs/flexfilelayout/flexfilelayout.c | 2 +-
- fs/nfs/flexfilelayout/flexfilelayoutdev.c | 2 +-
- fs/nfs/nfs42xdr.c | 2 +-
- fs/nfs/nfs4xdr.c | 6 ++--
- fs/nfsd/nfs4proc.c | 2 +-
- include/linux/sunrpc/xdr.h | 44 ++++++++++++++++++++++-
- net/sunrpc/auth_gss/gss_rpc_xdr.c | 2 +-
- net/sunrpc/xdr.c | 28 +++------------
- 13 files changed, 59 insertions(+), 39 deletions(-)
-
-diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
-index 08108b6d2fa1..3be6836074ae 100644
---- a/fs/nfs/blocklayout/blocklayout.c
-+++ b/fs/nfs/blocklayout/blocklayout.c
-@@ -697,7 +697,7 @@ bl_alloc_lseg(struct pnfs_layout_hdr *lo, struct nfs4_layoutget_res *lgr,
-
- xdr_init_decode_pages(&xdr, &buf,
- lgr->layoutp->pages, lgr->layoutp->len);
-- xdr_set_scratch_buffer(&xdr, page_address(scratch), PAGE_SIZE);
-+ xdr_set_scratch_page(&xdr, scratch);
-
- status = -EIO;
- p = xdr_inline_decode(&xdr, 4);
-diff --git a/fs/nfs/blocklayout/dev.c b/fs/nfs/blocklayout/dev.c
-index dec5880ac6de..acb1d22907da 100644
---- a/fs/nfs/blocklayout/dev.c
-+++ b/fs/nfs/blocklayout/dev.c
-@@ -510,7 +510,7 @@ bl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
- goto out;
-
- xdr_init_decode_pages(&xdr, &buf, pdev->pages, pdev->pglen);
-- xdr_set_scratch_buffer(&xdr, page_address(scratch), PAGE_SIZE);
-+ xdr_set_scratch_page(&xdr, scratch);
-
- p = xdr_inline_decode(&xdr, sizeof(__be32));
- if (!p)
-diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
-index 9f88ca7b2001..935029632d5f 100644
---- a/fs/nfs/dir.c
-+++ b/fs/nfs/dir.c
-@@ -576,7 +576,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
- goto out_nopages;
-
- xdr_init_decode_pages(&stream, &buf, xdr_pages, buflen);
-- xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
-+ xdr_set_scratch_page(&stream, scratch);
-
- do {
- if (entry->label)
-diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c
-index ae5ed3a07494..d2103852475f 100644
---- a/fs/nfs/filelayout/filelayout.c
-+++ b/fs/nfs/filelayout/filelayout.c
-@@ -666,7 +666,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
- return -ENOMEM;
-
- xdr_init_decode_pages(&stream, &buf, lgr->layoutp->pages, lgr->layoutp->len);
-- xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
-+ xdr_set_scratch_page(&stream, scratch);
-
- /* 20 = ufl_util (4), first_stripe_index (4), pattern_offset (8),
- * num_fh (4) */
-diff --git a/fs/nfs/filelayout/filelayoutdev.c b/fs/nfs/filelayout/filelayoutdev.c
-index d913e818858f..86c3f7e69ec4 100644
---- a/fs/nfs/filelayout/filelayoutdev.c
-+++ b/fs/nfs/filelayout/filelayoutdev.c
-@@ -82,7 +82,7 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
- goto out_err;
-
- xdr_init_decode_pages(&stream, &buf, pdev->pages, pdev->pglen);
-- xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
-+ xdr_set_scratch_page(&stream, scratch);
-
- /* Get the stripe count (number of stripe index) */
- p = xdr_inline_decode(&stream, 4);
-diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
-index a8a02081942d..0200d96b8d5b 100644
---- a/fs/nfs/flexfilelayout/flexfilelayout.c
-+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
-@@ -378,7 +378,7 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
-
- xdr_init_decode_pages(&stream, &buf, lgr->layoutp->pages,
- lgr->layoutp->len);
-- xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
-+ xdr_set_scratch_page(&stream, scratch);
-
- /* stripe unit and mirror_array_cnt */
- rc = -EIO;
-diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
-index 1f12297109b4..bfa7202ca7be 100644
---- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c
-+++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
-@@ -69,7 +69,7 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
- INIT_LIST_HEAD(&dsaddrs);
-
- xdr_init_decode_pages(&stream, &buf, pdev->pages, pdev->pglen);
-- xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
-+ xdr_set_scratch_page(&stream, scratch);
-
- /* multipath count */
- p = xdr_inline_decode(&stream, 4);
-diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c
-index f2248d9d4db5..df5bee2f505c 100644
---- a/fs/nfs/nfs42xdr.c
-+++ b/fs/nfs/nfs42xdr.c
-@@ -1536,7 +1536,7 @@ static int nfs4_xdr_dec_listxattrs(struct rpc_rqst *rqstp,
- struct compound_hdr hdr;
- int status;
-
-- xdr_set_scratch_buffer(xdr, page_address(res->scratch), PAGE_SIZE);
-+ xdr_set_scratch_page(xdr, res->scratch);
-
- status = decode_compound_hdr(xdr, &hdr);
- if (status)
-diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
-index e2f0e3446e22..f21dc4284468 100644
---- a/fs/nfs/nfs4xdr.c
-+++ b/fs/nfs/nfs4xdr.c
-@@ -6406,10 +6406,8 @@ nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
- struct compound_hdr hdr;
- int status;
-
-- if (res->acl_scratch != NULL) {
-- void *p = page_address(res->acl_scratch);
-- xdr_set_scratch_buffer(xdr, p, PAGE_SIZE);
-- }
-+ if (res->acl_scratch != NULL)
-+ xdr_set_scratch_page(xdr, res->acl_scratch);
- status = decode_compound_hdr(xdr, &hdr);
- if (status)
- goto out;
-diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
-index 735ee8a79870..9aeeb51e8c61 100644
---- a/fs/nfsd/nfs4proc.c
-+++ b/fs/nfsd/nfs4proc.c
-@@ -2274,7 +2274,7 @@ static void svcxdr_init_encode(struct svc_rqst *rqstp,
- xdr->end = head->iov_base + PAGE_SIZE - rqstp->rq_auth_slack;
- /* Tail and page_len should be zero at this point: */
- buf->len = buf->head[0].iov_len;
-- xdr->scratch.iov_len = 0;
-+ xdr_reset_scratch_buffer(xdr);
- xdr->page_ptr = buf->pages - 1;
- buf->buflen = PAGE_SIZE * (1 + rqstp->rq_page_end - buf->pages)
- - rqstp->rq_auth_slack;
-diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
-index 6d9d1520612b..0c8cab6210b3 100644
---- a/include/linux/sunrpc/xdr.h
-+++ b/include/linux/sunrpc/xdr.h
-@@ -246,7 +246,6 @@ extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf,
- __be32 *p, struct rpc_rqst *rqst);
- extern void xdr_init_decode_pages(struct xdr_stream *xdr, struct xdr_buf *buf,
- struct page **pages, unsigned int len);
--extern void xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen);
- extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
- extern unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
- extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
-@@ -254,6 +253,49 @@ extern int xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned in
- extern uint64_t xdr_align_data(struct xdr_stream *, uint64_t, uint32_t);
- extern uint64_t xdr_expand_hole(struct xdr_stream *, uint64_t, uint64_t);
-
-+/**
-+ * xdr_set_scratch_buffer - Attach a scratch buffer for decoding data.
-+ * @xdr: pointer to xdr_stream struct
-+ * @buf: pointer to an empty buffer
-+ * @buflen: size of 'buf'
-+ *
-+ * The scratch buffer is used when decoding from an array of pages.
-+ * If an xdr_inline_decode() call spans across page boundaries, then
-+ * we copy the data into the scratch buffer in order to allow linear
-+ * access.
-+ */
-+static inline void
-+xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen)
-+{
-+ xdr->scratch.iov_base = buf;
-+ xdr->scratch.iov_len = buflen;
-+}
-+
-+/**
-+ * xdr_set_scratch_page - Attach a scratch buffer for decoding data
-+ * @xdr: pointer to xdr_stream struct
-+ * @page: an anonymous page
-+ *
-+ * See xdr_set_scratch_buffer().
-+ */
-+static inline void
-+xdr_set_scratch_page(struct xdr_stream *xdr, struct page *page)
-+{
-+ xdr_set_scratch_buffer(xdr, page_address(page), PAGE_SIZE);
-+}
-+
-+/**
-+ * xdr_reset_scratch_buffer - Clear scratch buffer information
-+ * @xdr: pointer to xdr_stream struct
-+ *
-+ * See xdr_set_scratch_buffer().
-+ */
-+static inline void
-+xdr_reset_scratch_buffer(struct xdr_stream *xdr)
-+{
-+ xdr_set_scratch_buffer(xdr, NULL, 0);
-+}
-+
- /**
- * xdr_stream_remaining - Return the number of bytes remaining in the stream
- * @xdr: pointer to struct xdr_stream
-diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c
-index 2ff7b7083eba..c636c648849b 100644
---- a/net/sunrpc/auth_gss/gss_rpc_xdr.c
-+++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c
-@@ -789,7 +789,7 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
- scratch = alloc_page(GFP_KERNEL);
- if (!scratch)
- return -ENOMEM;
-- xdr_set_scratch_buffer(xdr, page_address(scratch), PAGE_SIZE);
-+ xdr_set_scratch_page(xdr, scratch);
-
- /* res->status */
- err = gssx_dec_status(xdr, &res->status);
-diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
-index d84bb5037bb5..02adc5c7f034 100644
---- a/net/sunrpc/xdr.c
-+++ b/net/sunrpc/xdr.c
-@@ -669,7 +669,7 @@ void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p,
- struct kvec *iov = buf->head;
- int scratch_len = buf->buflen - buf->page_len - buf->tail[0].iov_len;
-
-- xdr_set_scratch_buffer(xdr, NULL, 0);
-+ xdr_reset_scratch_buffer(xdr);
- BUG_ON(scratch_len < 0);
- xdr->buf = buf;
- xdr->iov = iov;
-@@ -713,7 +713,7 @@ inline void xdr_commit_encode(struct xdr_stream *xdr)
- page = page_address(*xdr->page_ptr);
- memcpy(xdr->scratch.iov_base, page, shift);
- memmove(page, page + shift, (void *)xdr->p - page);
-- xdr->scratch.iov_len = 0;
-+ xdr_reset_scratch_buffer(xdr);
- }
- EXPORT_SYMBOL_GPL(xdr_commit_encode);
-
-@@ -743,8 +743,7 @@ static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr,
- * the "scratch" iov to track any temporarily unused fragment of
- * space at the end of the previous buffer:
- */
-- xdr->scratch.iov_base = xdr->p;
-- xdr->scratch.iov_len = frag1bytes;
-+ xdr_set_scratch_buffer(xdr, xdr->p, frag1bytes);
- p = page_address(*xdr->page_ptr);
- /*
- * Note this is where the next encode will start after we've
-@@ -1056,8 +1055,7 @@ void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p,
- struct rpc_rqst *rqst)
- {
- xdr->buf = buf;
-- xdr->scratch.iov_base = NULL;
-- xdr->scratch.iov_len = 0;
-+ xdr_reset_scratch_buffer(xdr);
- xdr->nwords = XDR_QUADLEN(buf->len);
- if (buf->head[0].iov_len != 0)
- xdr_set_iov(xdr, buf->head, buf->len);
-@@ -1105,24 +1103,6 @@ static __be32 * __xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes)
- return p;
- }
-
--/**
-- * xdr_set_scratch_buffer - Attach a scratch buffer for decoding data.
-- * @xdr: pointer to xdr_stream struct
-- * @buf: pointer to an empty buffer
-- * @buflen: size of 'buf'
-- *
-- * The scratch buffer is used when decoding from an array of pages.
-- * If an xdr_inline_decode() call spans across page boundaries, then
-- * we copy the data into the scratch buffer in order to allow linear
-- * access.
-- */
--void xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen)
--{
-- xdr->scratch.iov_base = buf;
-- xdr->scratch.iov_len = buflen;
--}
--EXPORT_SYMBOL_GPL(xdr_set_scratch_buffer);
--
- static __be32 *xdr_copy_to_scratch(struct xdr_stream *xdr, size_t nbytes)
- {
- __be32 *p;
---
-2.35.1
-
+++ /dev/null
-From ba564cda1b99d035764257f9c3fc615b81efb780 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 5 Nov 2020 11:19:42 -0500
-Subject: SUNRPC: Prepare for xdr_stream-style decoding on the server-side
-
-From: Chuck Lever <chuck.lever@oracle.com>
-
-[ 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>
-Stable-dep-of: 401bc1f90874 ("NFSD: Protect against send buffer overflow in NFSv2 READ")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nfsd/nfssvc.c | 2 ++
- include/linux/sunrpc/svc.h | 16 ++++++++++++++++
- net/sunrpc/svc.c | 5 +++++
- 3 files changed, 23 insertions(+)
-
-diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
-index 9323e30a7eaf..ad6fedf37a40 100644
---- a/fs/nfsd/nfssvc.c
-+++ b/fs/nfsd/nfssvc.c
-@@ -1019,6 +1019,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;
-
-diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
-index 386628b36bc7..6ce2e12589cb 100644
---- a/include/linux/sunrpc/svc.h
-+++ b/include/linux/sunrpc/svc.h
-@@ -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 */
-diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
-index d38788cd9433..bb55f124b62e 100644
---- a/net/sunrpc/svc.c
-+++ b/net/sunrpc/svc.c
-@@ -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;
-@@ -842,6 +846,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);
---
-2.35.1
-