All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 000/118] Update NFSD XDR functions
@ 2020-11-20 20:33 Chuck Lever
  2020-11-20 20:33 ` [PATCH v2 001/118] NFSD: Fix returned READDIR offset cookie Chuck Lever
                   ` (117 more replies)
  0 siblings, 118 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:33 UTC (permalink / raw)
  To: linux-nfs

My apologies for piling on.

The purpose of this series is to convert the NFSD XDR encoder and
decoder functions to use the struct xdr_stream API. This is largely
a refactor/clean-up, but there are some long-term benefits:

- More robust input sanitization in the NFSD decoders
- Help make it possible to use common kernel library functions with
  XDR stream APIs (for example, GSS-API)
- Align the code itself with the RFCs so it is easier to learn,
  understand, and verify our XDR implementation
- Removal of more than a hundred hidden dprintk() call sites
- Removal of as much explicit manipulation of pages as possible to
  help make the transition to xdr->bvecs smoother

The series contains only decoder changes for the moment. I have
encoder changes for NFSv2 and NFSv3 in development. It makes sense
to put those off for a separate review/merge window cycle.

These patches are available in a topic branch in my git repo:

 git://git.linux-nfs.org/projects/cel/cel-2.6.git nfsd-xdr_stream


Changes since v1:
- Broke up larger patches (fattr4, LOCK, OPEN, EXCHANGE_ID, and so on)
- Replaced goto spaghetti in NFSv4 decoders
- Cleaned up function synopses
- Replaced nfsd4_decode_bitmap() with generic XDR helper
- The posted series now contains changes to NFSv2 and NFSv3 decoders

---

Chuck Lever (118):
      NFSD: Fix returned READDIR offset cookie
      SUNRPC: Add xdr_set_scratch_page() and xdr_reset_scratch_buffer()
      SUNRPC: Prepare for xdr_stream-style decoding on the server-side
      NFSD: Add common helpers to decode void args and encode void results
      NFSD: Replace the internals of the READ_BUF() macro
      NFSD: Replace READ* macros in nfsd4_decode_access()
      NFSD: Replace READ* macros in nfsd4_decode_stateid()
      NFSD: Replace READ* macros in nfsd4_decode_close()
      NFSD: Replace READ* macros in nfsd4_decode_commit()
      NFSD: Change the way the expected length of a fattr4 is checked
      NFSD: Replace READ* macros that decode the fattr4 size attribute
      NFSD: Replace READ* macros that decode the fattr4 acl attribute
      NFSD: Replace READ* macros that decode the fattr4 mode attribute
      NFSD: Replace READ* macros that decode the fattr4 owner attribute
      NFSD: Replace READ* macros that decode the fattr4 owner_group attribute
      NFSD: Replace READ* macros that decode the fattr4 time_set attributes
      NFSD: Replace READ* macros that decode the fattr4 security label attribute
      NFSD: Replace READ* macros that decode the fattr4 umask attribute
      NFSD: Replace READ* macros in nfsd4_decode_fattr()
      NFSD: Replace READ* macros in nfsd4_decode_create()
      NFSD: Replace READ* macros in nfsd4_decode_getattr()
      NFSD: Replace READ* macros in nfsd4_decode_link()
      NFSD: Relocate nfsd4_decode_opaque()
      NFSD: Add helpers to decode a clientid4 and an NFSv4 state owner
      NFSD: Add helper for decoding locker4
      NFSD: Replace READ* macros in nfsd4_decode_lock()
      NFSD: Replace READ* macros in nfsd4_decode_lockt()
      NFSD: Replace READ* macros in nfsd4_decode_locku()
      NFSD: Replace READ* macros in nfsd4_decode_lookup()
      NFSD: Add helper to decode NFSv4 verifiers
      NFSD: Add helper to decode OPEN's createhow4 argument
      NFSD: Add helper to decode OPEN's openflag4 argument
      NFSD: Replace READ* macros in nfsd4_decode_share_access()
      NFSD: Replace READ* macros in nfsd4_decode_share_deny()
      NFSD: Add helper to decode OPEN's open_claim4 argument
      NFSD: Replace READ* macros in nfsd4_decode_open()
      NFSD: Replace READ* macros in nfsd4_decode_open_confirm()
      NFSD: Replace READ* macros in nfsd4_decode_open_downgrade()
      NFSD: Replace READ* macros in nfsd4_decode_putfh()
      NFSD: Replace READ* macros in nfsd4_decode_read()
      NFSD: Replace READ* macros in nfsd4_decode_readdir()
      NFSD: Replace READ* macros in nfsd4_decode_remove()
      NFSD: Replace READ* macros in nfsd4_decode_rename()
      NFSD: Replace READ* macros in nfsd4_decode_renew()
      NFSD: Replace READ* macros in nfsd4_decode_secinfo()
      NFSD: Replace READ* macros in nfsd4_decode_setclientid()
      NFSD: Replace READ* macros in nfsd4_decode_setclientid_confirm()
      NFSD: Replace READ* macros in nfsd4_decode_verify()
      NFSD: Replace READ* macros in nfsd4_decode_write()
      NFSD: Replace READ* macros in nfsd4_decode_release_lockowner()
      NFSD: Replace READ* macros in nfsd4_decode_cb_sec()
      NFSD: Replace READ* macros in nfsd4_decode_backchannel_ctl()
      NFSD: Replace READ* macros in nfsd4_decode_bind_conn_to_session()
      NFSD: Add a separate decoder to handle state_protect_ops
      NFSD: Add a separate decoder for ssv_sp_parms
      NFSD: Add a helper to decode state_protect4_a
      NFSD: Add a helper to decode nfs_impl_id4
      NFSD: Add a helper to decode channel_attrs4
      NFSD: Replace READ* macros in nfsd4_decode_create_session()
      NFSD: Replace READ* macros in nfsd4_decode_destroy_session()
      NFSD: Replace READ* macros in nfsd4_decode_free_stateid()
      NFSD: Replace READ* macros in nfsd4_decode_getdeviceinfo()
      NFSD: Replace READ* macros in nfsd4_decode_layoutcommit()
      NFSD: Replace READ* macros in nfsd4_decode_layoutget()
      NFSD: Replace READ* macros in nfsd4_decode_layoutreturn()
      NFSD: Replace READ* macros in nfsd4_decode_secinfo_no_name()
      NFSD: Replace READ* macros in nfsd4_decode_sequence()
      NFSD: Replace READ* macros in nfsd4_decode_test_stateid()
      NFSD: Replace READ* macros in nfsd4_decode_destroy_clientid()
      NFSD: Replace READ* macros in nfsd4_decode_reclaim_complete()
      NFSD: Replace READ* macros in nfsd4_decode_fallocate()
      NFSD: Replace READ* macros in nfsd4_decode_clone()
      NFSD: Replace READ* macros in nfsd4_decode_nl4_server()
      NFSD: Replace READ* macros in nfsd4_decode_copy()
      NFSD: Replace READ* macros in nfsd4_decode_seek()
      NFSD: Replace READ* macros in nfsd4_decode_xattr_name()
      NFSD: Replace READ* macros in nfsd4_decode_setxattr()
      NFSD: Replace READ* macros in nfsd4_decode_listxattrs()
      NFSD: Replace READ* macros in nfsd4_decode_compound()
      NFSD: Remove macros that are no longer used
      NFSD: Update GETATTR3args decoder to use struct xdr_stream
      NFSD: Update ACCESS3arg decoder to use struct xdr_stream
      NFSD: Update READ3arg decoder to use struct xdr_stream
      NFSD: Update WRITE3arg decoder to use struct xdr_stream
      NFSD: Update READLINK3arg decoder to use struct xdr_stream
      NFSD: Add helper to set up the pages where the dirlist is encoded
      NFSD: Update READDIR3args decoders to use struct xdr_stream
      NFSD: Update COMMIT3arg decoder to use struct xdr_stream
      NFSD: Update the NFSv3 DIROPargs decoder to use struct xdr_stream
      NFSD: Update the RENAME3args decoder to use struct xdr_stream
      NFSD: Update the LINK3args decoder to use struct xdr_stream
      NFSD: Update the SETATTR3args decoder to use struct xdr_stream
      NFSD: Update the CREATE3args decoder to use struct xdr_stream
      NFSD: Update the MKDIR3args decoder to use struct xdr_stream
      NFSD: Update the SYMLINK3args decoder to use struct xdr_stream
      NFSD: Update the MKNOD3args decoder to use struct xdr_stream
      NFSD: Update the NFSv2 GETATTR argument decoder to use struct xdr_stream
      NFSD: Update the NFSv2 READ argument decoder to use struct xdr_stream
      NFSD: Update the NFSv2 WRITE argument decoder to use struct xdr_stream
      NFSD: Update the NFSv2 READLINK argument decoder to use struct xdr_stream
      NFSD: Add helper to set up the pages where the dirlist is encoded
      NFSD: Update the NFSv2 READDIR argument decoder to use struct xdr_stream
      NFSD: Update NFSv2 diropargs decoding to use struct xdr_stream
      NFSD: Update the NFSv2 RENAME argument decoder to use struct xdr_stream
      NFSD: Update the NFSv2 LINK argument decoder to use struct xdr_stream
      NFSD: Update the NFSv2 SETATTR argument decoder to use struct xdr_stream
      NFSD: Update the NFSv2 CREATE argument decoder to use struct xdr_stream
      NFSD: Update the NFSv2 SYMLINK argument decoder to use struct xdr_stream
      NFSD: Remove argument length checking in nfsd_dispatch()
      NFSD: Update the NFSv2 GETACL argument decoder to use struct xdr_stream
      NFSD: Add an xdr_stream-based decoder for NFSv2/3 ACLs
      NFSD: Update the NFSv2 SETACL argument decoder to use struct xdr_stream
      NFSD: Update the NFSv2 ACL GETATTR argument decoder to use struct xdr_stream
      NFSD: Update the NFSv2 ACL ACCESS argument decoder to use struct xdr_stream
      NFSD: Clean up after updating NFSv2 ACL decoders
      NFSD: Update the NFSv3 GETACL argument decoder to use struct xdr_stream
      NFSD: Update the NFSv2 SETACL argument decoder to use struct xdr_stream
      NFSD: Clean up after updating NFSv3 ACL decoders


 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/nfs_common/nfsacl.c                    |   53 +
 fs/nfsd/nfs2acl.c                         |   96 +-
 fs/nfsd/nfs3acl.c                         |   60 +-
 fs/nfsd/nfs3proc.c                        |   74 +-
 fs/nfsd/nfs3xdr.c                         |  588 ++---
 fs/nfsd/nfs4proc.c                        |   24 +-
 fs/nfsd/nfs4state.c                       |    2 +-
 fs/nfsd/nfs4xdr.c                         | 2419 +++++++++++----------
 fs/nfsd/nfsd.h                            |    8 +
 fs/nfsd/nfsproc.c                         |   99 +-
 fs/nfsd/nfssvc.c                          |   66 +-
 fs/nfsd/nfsxdr.c                          |  370 ++--
 fs/nfsd/xdr.h                             |   15 +-
 fs/nfsd/xdr3.h                            |   22 +-
 fs/nfsd/xdr4.h                            |   30 +-
 include/linux/nfsacl.h                    |    3 +
 include/linux/sunrpc/svc.h                |   16 +
 include/linux/sunrpc/xdr.h                |   93 +-
 include/uapi/linux/nfs3.h                 |    6 +
 net/sunrpc/auth_gss/gss_rpc_xdr.c         |    2 +-
 net/sunrpc/svc.c                          |    5 +
 net/sunrpc/xdr.c                          |   72 +-
 31 files changed, 2184 insertions(+), 1961 deletions(-)

--
Chuck Lever


^ permalink raw reply	[flat|nested] 127+ messages in thread

* [PATCH v2 001/118] NFSD: Fix returned READDIR offset cookie
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
@ 2020-11-20 20:33 ` Chuck Lever
  2020-11-21  0:59   ` J. Bruce Fields
  2020-11-20 20:33 ` [PATCH v2 002/118] SUNRPC: Add xdr_set_scratch_page() and xdr_reset_scratch_buffer() Chuck Lever
                   ` (116 subsequent siblings)
  117 siblings, 1 reply; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:33 UTC (permalink / raw)
  To: linux-nfs

Code inspection shows that the server's NFSv3 READDIR implementation
returns the same offset cookie as the client sent, instead of the
last cookie it returns in the reply's dirlist. This is unlike the
NFSv2 READDIR, NFSv3 READDIRPLUS, and NFSv4 READDIR implementations,
and it's been like this since the beginning of kernel git history.

I copied the logic from nfsd3_proc_readdirplus().

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3proc.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index d9be589fed15..e0ad18d6b5a8 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -430,6 +430,7 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
 	struct nfsd3_readdirargs *argp = rqstp->rq_argp;
 	struct nfsd3_readdirres  *resp = rqstp->rq_resp;
 	int		count = 0;
+	loff_t		offset;
 	struct page	**p;
 	caddr_t		page_addr = NULL;
 
@@ -448,7 +449,9 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
 	resp->common.err = nfs_ok;
 	resp->buffer = argp->buffer;
 	resp->rqstp = rqstp;
-	resp->status = nfsd_readdir(rqstp, &resp->fh, (loff_t *)&argp->cookie,
+	offset = argp->cookie;
+
+	resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
 				    &resp->common, nfs3svc_encode_entry);
 	memcpy(resp->verf, argp->verf, 8);
 	count = 0;
@@ -464,8 +467,6 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
 	}
 	resp->count = count >> 2;
 	if (resp->offset) {
-		loff_t offset = argp->cookie;
-
 		if (unlikely(resp->offset1)) {
 			/* we ended up with offset on a page boundary */
 			*resp->offset = htonl(offset >> 32);



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 002/118] SUNRPC: Add xdr_set_scratch_page() and xdr_reset_scratch_buffer()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
  2020-11-20 20:33 ` [PATCH v2 001/118] NFSD: Fix returned READDIR offset cookie Chuck Lever
@ 2020-11-20 20:33 ` Chuck Lever
  2020-11-20 20:34 ` [PATCH v2 003/118] SUNRPC: Prepare for xdr_stream-style decoding on the server-side Chuck Lever
                   ` (115 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:33 UTC (permalink / raw)
  To: linux-nfs

Clean up: De-duplicate some frequently-used code.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 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 4e011adaf967..8a24fe20dccf 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 7f5aa0403e16..d158a500c25c 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 a163533446fa..d7010686d39a 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 3eda40a320a5..c9b61b818ec1 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 6e060a88f98c..cb5d4da2308f 100644
--- a/fs/nfs/nfs42xdr.c
+++ b/fs/nfs/nfs42xdr.c
@@ -1540,7 +1540,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 c6dbfcae7517..2eabe5add344 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -6403,10 +6403,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 e83b21778816..20772f6b0b2d 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -2276,7 +2276,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 ec2a22ccdc2a..2729d2d6efce 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -248,7 +248,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);
@@ -256,6 +255,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 28f81769a27c..c607744b3ea8 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
@@ -1052,8 +1051,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);
@@ -1101,24 +1099,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;



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 003/118] SUNRPC: Prepare for xdr_stream-style decoding on the server-side
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
  2020-11-20 20:33 ` [PATCH v2 001/118] NFSD: Fix returned READDIR offset cookie Chuck Lever
  2020-11-20 20:33 ` [PATCH v2 002/118] SUNRPC: Add xdr_set_scratch_page() and xdr_reset_scratch_buffer() Chuck Lever
@ 2020-11-20 20:34 ` Chuck Lever
  2020-11-23 18:49   ` J. Bruce Fields
  2020-11-20 20:34 ` [PATCH v2 004/118] NFSD: Add common helpers to decode void args and encode void results Chuck Lever
                   ` (114 subsequent siblings)
  117 siblings, 1 reply; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:34 UTC (permalink / raw)
  To: linux-nfs

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>
---
 fs/nfsd/nfs4xdr.c          |    3 ++-
 fs/nfsd/nfssvc.c           |    4 +++-
 include/linux/sunrpc/svc.h |   16 ++++++++++++++++
 include/linux/sunrpc/xdr.h |    5 +++++
 net/sunrpc/svc.c           |    5 +++++
 5 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index e3c6bea83bd6..66274ad05a9c 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -5321,7 +5321,8 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p)
 	args->ops = args->iops;
 	args->rqstp = rqstp;
 
-	return !nfsd4_decode_compound(args);
+	return nfsd4_decode_compound(args) == nfs_ok ?	XDR_DECODE_DONE :
+							XDR_DECODE_FAILED;
 }
 
 int
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 27b1ad136150..daeab72975a3 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -1020,7 +1020,9 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 	 * (necessary in the NFSv4.0 compound case)
 	 */
 	rqstp->rq_cachetype = proc->pc_cachetype;
-	if (!proc->pc_decode(rqstp, argv->iov_base))
+
+	svcxdr_init_decode(rqstp, argv->iov_base);
+	if (proc->pc_decode(rqstp, argv->iov_base) == XDR_DECODE_FAILED)
 		goto out_decode_err;
 
 	switch (nfsd_cache_lookup(rqstp)) {
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index c220b734fa69..bb6c93283697 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -248,6 +248,8 @@ struct svc_rqst {
 	size_t			rq_xprt_hlen;	/* xprt header len */
 	struct xdr_buf		rq_arg;
 	struct xdr_buf		rq_res;
+	struct xdr_stream	rq_xdr_stream;
+	struct page		*rq_scratch_page;
 	struct page		*rq_pages[RPCSVC_MAXPAGES + 1];
 	struct page *		*rq_respages;	/* points into rq_pages */
 	struct page *		*rq_next_page; /* next reply page to use */
@@ -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
+ * @p: Starting position
+ *
+ */
+static inline void svcxdr_init_decode(struct svc_rqst *rqstp, __be32 *p)
+{
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
+
+	xdr_init_decode(xdr, &rqstp->rq_arg, p, NULL);
+	xdr_set_scratch_page(xdr, rqstp->rq_scratch_page);
+}
+
 #endif /* SUNRPC_SVC_H */
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index 2729d2d6efce..abbb032de4e8 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -19,6 +19,11 @@
 struct bio_vec;
 struct rpc_rqst;
 
+enum xdr_decode_result {
+	XDR_DECODE_FAILED = 0,
+	XDR_DECODE_DONE = 1,
+};
+
 /*
  * Buffer adjustment
  */
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index b41500645c3f..4187745887f0 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);



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 004/118] NFSD: Add common helpers to decode void args and encode void results
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (2 preceding siblings ...)
  2020-11-20 20:34 ` [PATCH v2 003/118] SUNRPC: Prepare for xdr_stream-style decoding on the server-side Chuck Lever
@ 2020-11-20 20:34 ` Chuck Lever
  2020-11-20 20:34 ` [PATCH v2 005/118] NFSD: Replace the internals of the READ_BUF() macro Chuck Lever
                   ` (113 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:34 UTC (permalink / raw)
  To: linux-nfs

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>
---
 fs/nfsd/nfs2acl.c  |   21 ++++-----------------
 fs/nfsd/nfs3acl.c  |    8 ++++----
 fs/nfsd/nfs3proc.c |   10 ++++------
 fs/nfsd/nfs3xdr.c  |   11 -----------
 fs/nfsd/nfs4proc.c |    8 ++++----
 fs/nfsd/nfs4xdr.c  |   12 ------------
 fs/nfsd/nfsd.h     |    8 ++++++++
 fs/nfsd/nfsproc.c  |   25 ++++++++++++-------------
 fs/nfsd/nfssvc.c   |   23 +++++++++++++++++++++++
 fs/nfsd/nfsxdr.c   |   10 ----------
 fs/nfsd/xdr.h      |    2 --
 fs/nfsd/xdr3.h     |    2 --
 fs/nfsd/xdr4.h     |    2 --
 13 files changed, 59 insertions(+), 83 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 e0ad18d6b5a8..581a93b17bee 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -693,8 +693,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 */
@@ -705,10 +703,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 186b07a72373..a6718b952975 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 20772f6b0b2d..9280740941db 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -3301,10 +3301,10 @@ 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 66274ad05a9c..6c3d45f68b75 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -5271,12 +5271,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;
@@ -5294,12 +5288,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 0d71549f9d42..9473d048efec 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 daeab72975a3..cae6fbf10514 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -28,6 +28,7 @@
 #include "vfs.h"
 #include "netns.h"
 #include "filecache.h"
+#include "xdr.h"
 
 #define NFSDDBG_FACILITY	NFSDDBG_SVC
 
@@ -1075,6 +1076,28 @@ 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
+ *
+ */
+int nfssvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
+{
+	return XDR_DECODE_DONE;
+}
+
+/**
+ * nfssvc_encode_voidres - Encode void results
+ * @rqstp: Server RPC transaction context
+ * @p: buffer in which to encode results
+ *
+ */
+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 9e00a902113e..7aa6e8aca2c1 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 0ff336b0b25f..ad77387734cc 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);



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 005/118] NFSD: Replace the internals of the READ_BUF() macro
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (3 preceding siblings ...)
  2020-11-20 20:34 ` [PATCH v2 004/118] NFSD: Add common helpers to decode void args and encode void results Chuck Lever
@ 2020-11-20 20:34 ` Chuck Lever
  2020-11-23 19:18   ` J. Bruce Fields
  2020-11-20 20:34 ` [PATCH v2 006/118] NFSD: Replace READ* macros in nfsd4_decode_access() Chuck Lever
                   ` (112 subsequent siblings)
  117 siblings, 1 reply; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:34 UTC (permalink / raw)
  To: linux-nfs

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>
---
 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           |   44 +++++++++++
 5 files changed, 76 insertions(+), 165 deletions(-)

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 9280740941db..dc5c9fb1888b 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1023,8 +1023,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 6c3d45f68b75..26265d649c39 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;
@@ -5279,8 +5160,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;
@@ -5293,19 +5172,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_xdr_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 abbb032de4e8..8f458addfcf0 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -259,6 +259,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 c607744b3ea8..272c9d566e6a 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -1407,6 +1407,50 @@ int xdr_buf_subsegment(const 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 occurred; @xdr is unchanged.
+ */
+bool xdr_stream_subsegment(struct xdr_stream *xdr, struct xdr_buf *subbuf,
+			   unsigned int nbytes)
+{
+	unsigned int len, remaining, offset;
+
+	if (xdr_buf_subsegment(xdr->buf, subbuf, xdr_stream_pos(xdr), nbytes))
+		return false;
+
+	if (subbuf->head[0].iov_len)
+		__xdr_inline_decode(xdr, subbuf->head[0].iov_len);
+
+	remaining = subbuf->page_len;
+	offset = subbuf->page_base;
+	while (remaining) {
+		len = min_t(unsigned int, remaining, PAGE_SIZE);
+		len -= offset;
+
+		if (xdr->p == xdr->end)
+			xdr_set_next_buffer(xdr);
+		__xdr_inline_decode(xdr, len);
+
+		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



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 006/118] NFSD: Replace READ* macros in nfsd4_decode_access()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (4 preceding siblings ...)
  2020-11-20 20:34 ` [PATCH v2 005/118] NFSD: Replace the internals of the READ_BUF() macro Chuck Lever
@ 2020-11-20 20:34 ` Chuck Lever
  2020-11-20 20:34 ` [PATCH v2 007/118] NFSD: Replace READ* macros in nfsd4_decode_stateid() Chuck Lever
                   ` (111 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:34 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 26265d649c39..5ef14c41fabe 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -437,17 +437,6 @@ nfsd4_decode_stateid(struct nfsd4_compoundargs *argp, stateid_t *sid)
 	DECODE_TAIL;
 }
 
-static __be32
-nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access)
-{
-	DECODE_HEAD;
-
-	READ_BUF(4);
-	access->ac_req_access = be32_to_cpup(p++);
-
-	DECODE_TAIL;
-}
-
 static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs)
 {
 	DECODE_HEAD;
@@ -529,6 +518,19 @@ static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_
 	DECODE_TAIL;
 }
 
+/*
+ * NFSv4 operation argument decoders
+ */
+
+static __be32
+nfsd4_decode_access(struct nfsd4_compoundargs *argp,
+		    struct nfsd4_access *access)
+{
+	if (xdr_stream_decode_u32(argp->xdr, &access->ac_req_access) < 0)
+		return nfserr_bad_xdr;
+	return nfs_ok;
+}
+
 static __be32 nfsd4_decode_backchannel_ctl(struct nfsd4_compoundargs *argp, struct nfsd4_backchannel_ctl *bc)
 {
 	DECODE_HEAD;



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 007/118] NFSD: Replace READ* macros in nfsd4_decode_stateid()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (5 preceding siblings ...)
  2020-11-20 20:34 ` [PATCH v2 006/118] NFSD: Replace READ* macros in nfsd4_decode_access() Chuck Lever
@ 2020-11-20 20:34 ` Chuck Lever
  2020-11-20 20:34 ` [PATCH v2 008/118] NFSD: Replace READ* macros in nfsd4_decode_close() Chuck Lever
                   ` (110 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:34 UTC (permalink / raw)
  To: linux-nfs

And also rename it to reflect the actual name of the stateid4 type
defined in RFC 8881.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   61 +++++++++++++++++++++++++++--------------------------
 1 file changed, 31 insertions(+), 30 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 5ef14c41fabe..027582d682ae 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -426,15 +426,16 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 }
 
 static __be32
-nfsd4_decode_stateid(struct nfsd4_compoundargs *argp, stateid_t *sid)
+nfsd4_decode_stateid4(struct nfsd4_compoundargs *argp, stateid_t *sid)
 {
-	DECODE_HEAD;
+	__be32 *p;
 
-	READ_BUF(sizeof(stateid_t));
+	p = xdr_inline_decode(argp->xdr, NFS4_STATEID_SIZE);
+	if (!p)
+		return nfserr_bad_xdr;
 	sid->si_generation = be32_to_cpup(p++);
-	COPYMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
-
-	DECODE_TAIL;
+	memcpy(&sid->si_opaque, p, sizeof(sid->si_opaque));
+	return nfs_ok;
 }
 
 static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs)
@@ -561,7 +562,7 @@ nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
 
 	READ_BUF(4);
 	close->cl_seqid = be32_to_cpup(p++);
-	return nfsd4_decode_stateid(argp, &close->cl_stateid);
+	return nfsd4_decode_stateid4(argp, &close->cl_stateid);
 
 	DECODE_TAIL;
 }
@@ -627,7 +628,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
 static inline __be32
 nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr)
 {
-	return nfsd4_decode_stateid(argp, &dr->dr_stateid);
+	return nfsd4_decode_stateid4(argp, &dr->dr_stateid);
 }
 
 static inline __be32
@@ -671,7 +672,7 @@ nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
 	if (lock->lk_is_new) {
 		READ_BUF(4);
 		lock->lk_new_open_seqid = be32_to_cpup(p++);
-		status = nfsd4_decode_stateid(argp, &lock->lk_new_open_stateid);
+		status = nfsd4_decode_stateid4(argp, &lock->lk_new_open_stateid);
 		if (status)
 			return status;
 		READ_BUF(8 + sizeof(clientid_t));
@@ -681,7 +682,7 @@ nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
 		READ_BUF(lock->lk_new_owner.len);
 		READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len);
 	} else {
-		status = nfsd4_decode_stateid(argp, &lock->lk_old_lock_stateid);
+		status = nfsd4_decode_stateid4(argp, &lock->lk_old_lock_stateid);
 		if (status)
 			return status;
 		READ_BUF(4);
@@ -720,7 +721,7 @@ nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
 	if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT))
 		goto xdr_error;
 	locku->lu_seqid = be32_to_cpup(p++);
-	status = nfsd4_decode_stateid(argp, &locku->lu_stateid);
+	status = nfsd4_decode_stateid4(argp, &locku->lu_stateid);
 	if (status)
 		return status;
 	READ_BUF(16);
@@ -913,7 +914,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 		open->op_delegate_type = be32_to_cpup(p++);
 		break;
 	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
-		status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid);
+		status = nfsd4_decode_stateid4(argp, &open->op_delegate_stateid);
 		if (status)
 			return status;
 		READ_BUF(4);
@@ -932,7 +933,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 	case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
 		if (argp->minorversion < 1)
 			goto xdr_error;
-		status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid);
+		status = nfsd4_decode_stateid4(argp, &open->op_delegate_stateid);
 		if (status)
 			return status;
 		break;
@@ -951,7 +952,7 @@ nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_con
 	if (argp->minorversion >= 1)
 		return nfserr_notsupp;
 
-	status = nfsd4_decode_stateid(argp, &open_conf->oc_req_stateid);
+	status = nfsd4_decode_stateid4(argp, &open_conf->oc_req_stateid);
 	if (status)
 		return status;
 	READ_BUF(4);
@@ -965,7 +966,7 @@ nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_d
 {
 	DECODE_HEAD;
 		    
-	status = nfsd4_decode_stateid(argp, &open_down->od_stateid);
+	status = nfsd4_decode_stateid4(argp, &open_down->od_stateid);
 	if (status)
 		return status;
 	READ_BUF(4);
@@ -1008,7 +1009,7 @@ nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
 {
 	DECODE_HEAD;
 
-	status = nfsd4_decode_stateid(argp, &read->rd_stateid);
+	status = nfsd4_decode_stateid4(argp, &read->rd_stateid);
 	if (status)
 		return status;
 	READ_BUF(12);
@@ -1116,7 +1117,7 @@ nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *seta
 {
 	__be32 status;
 
-	status = nfsd4_decode_stateid(argp, &setattr->sa_stateid);
+	status = nfsd4_decode_stateid4(argp, &setattr->sa_stateid);
 	if (status)
 		return status;
 	return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr,
@@ -1193,7 +1194,7 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
 {
 	DECODE_HEAD;
 
-	status = nfsd4_decode_stateid(argp, &write->wr_stateid);
+	status = nfsd4_decode_stateid4(argp, &write->wr_stateid);
 	if (status)
 		return status;
 	READ_BUF(16);
@@ -1438,7 +1439,7 @@ nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_sta
 		INIT_LIST_HEAD(&stateid->ts_id_list);
 		list_add_tail(&stateid->ts_id_list, &test_stateid->ts_stateid_list);
 
-		status = nfsd4_decode_stateid(argp, &stateid->ts_id_stateid);
+		status = nfsd4_decode_stateid4(argp, &stateid->ts_id_stateid);
 		if (status)
 			goto out;
 	}
@@ -1514,7 +1515,7 @@ nfsd4_decode_layoutget(struct nfsd4_compoundargs *argp,
 	p = xdr_decode_hyper(p, &lgp->lg_seg.length);
 	p = xdr_decode_hyper(p, &lgp->lg_minlength);
 
-	status = nfsd4_decode_stateid(argp, &lgp->lg_sid);
+	status = nfsd4_decode_stateid4(argp, &lgp->lg_sid);
 	if (status)
 		return status;
 
@@ -1536,7 +1537,7 @@ nfsd4_decode_layoutcommit(struct nfsd4_compoundargs *argp,
 	p = xdr_decode_hyper(p, &lcp->lc_seg.length);
 	lcp->lc_reclaim = be32_to_cpup(p++);
 
-	status = nfsd4_decode_stateid(argp, &lcp->lc_sid);
+	status = nfsd4_decode_stateid4(argp, &lcp->lc_sid);
 	if (status)
 		return status;
 
@@ -1588,7 +1589,7 @@ nfsd4_decode_layoutreturn(struct nfsd4_compoundargs *argp,
 		p = xdr_decode_hyper(p, &lrp->lr_seg.offset);
 		p = xdr_decode_hyper(p, &lrp->lr_seg.length);
 
-		status = nfsd4_decode_stateid(argp, &lrp->lr_sid);
+		status = nfsd4_decode_stateid4(argp, &lrp->lr_sid);
 		if (status)
 			return status;
 
@@ -1613,7 +1614,7 @@ nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp,
 {
 	DECODE_HEAD;
 
-	status = nfsd4_decode_stateid(argp, &fallocate->falloc_stateid);
+	status = nfsd4_decode_stateid4(argp, &fallocate->falloc_stateid);
 	if (status)
 		return status;
 
@@ -1629,10 +1630,10 @@ nfsd4_decode_clone(struct nfsd4_compoundargs *argp, struct nfsd4_clone *clone)
 {
 	DECODE_HEAD;
 
-	status = nfsd4_decode_stateid(argp, &clone->cl_src_stateid);
+	status = nfsd4_decode_stateid4(argp, &clone->cl_src_stateid);
 	if (status)
 		return status;
-	status = nfsd4_decode_stateid(argp, &clone->cl_dst_stateid);
+	status = nfsd4_decode_stateid4(argp, &clone->cl_dst_stateid);
 	if (status)
 		return status;
 
@@ -1685,10 +1686,10 @@ nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)
 	struct nl4_server *ns_dummy;
 	int i, count;
 
-	status = nfsd4_decode_stateid(argp, &copy->cp_src_stateid);
+	status = nfsd4_decode_stateid4(argp, &copy->cp_src_stateid);
 	if (status)
 		return status;
-	status = nfsd4_decode_stateid(argp, &copy->cp_dst_stateid);
+	status = nfsd4_decode_stateid4(argp, &copy->cp_dst_stateid);
 	if (status)
 		return status;
 
@@ -1732,7 +1733,7 @@ static __be32
 nfsd4_decode_offload_status(struct nfsd4_compoundargs *argp,
 			    struct nfsd4_offload_status *os)
 {
-	return nfsd4_decode_stateid(argp, &os->stateid);
+	return nfsd4_decode_stateid4(argp, &os->stateid);
 }
 
 static __be32
@@ -1741,7 +1742,7 @@ nfsd4_decode_copy_notify(struct nfsd4_compoundargs *argp,
 {
 	__be32 status;
 
-	status = nfsd4_decode_stateid(argp, &cn->cpn_src_stateid);
+	status = nfsd4_decode_stateid4(argp, &cn->cpn_src_stateid);
 	if (status)
 		return status;
 	return nfsd4_decode_nl4_server(argp, &cn->cpn_dst);
@@ -1752,7 +1753,7 @@ nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek)
 {
 	DECODE_HEAD;
 
-	status = nfsd4_decode_stateid(argp, &seek->seek_stateid);
+	status = nfsd4_decode_stateid4(argp, &seek->seek_stateid);
 	if (status)
 		return status;
 



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 008/118] NFSD: Replace READ* macros in nfsd4_decode_close()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (6 preceding siblings ...)
  2020-11-20 20:34 ` [PATCH v2 007/118] NFSD: Replace READ* macros in nfsd4_decode_stateid() Chuck Lever
@ 2020-11-20 20:34 ` Chuck Lever
  2020-11-20 20:34 ` [PATCH v2 009/118] NFSD: Replace READ* macros in nfsd4_decode_commit() Chuck Lever
                   ` (109 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:34 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |    8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 027582d682ae..06028e4f1b5d 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -558,13 +558,9 @@ static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp,
 static __be32
 nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
 {
-	DECODE_HEAD;
-
-	READ_BUF(4);
-	close->cl_seqid = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &close->cl_seqid) < 0)
+		return nfserr_bad_xdr;
 	return nfsd4_decode_stateid4(argp, &close->cl_stateid);
-
-	DECODE_TAIL;
 }
 
 



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 009/118] NFSD: Replace READ* macros in nfsd4_decode_commit()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (7 preceding siblings ...)
  2020-11-20 20:34 ` [PATCH v2 008/118] NFSD: Replace READ* macros in nfsd4_decode_close() Chuck Lever
@ 2020-11-20 20:34 ` Chuck Lever
  2020-11-20 20:34 ` [PATCH v2 010/118] NFSD: Change the way the expected length of a fattr4 is checked Chuck Lever
                   ` (108 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:34 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 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 06028e4f1b5d..d4b98bd8a859 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -567,13 +567,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 8f458addfcf0..22b00104bc1a 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -576,6 +576,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



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 010/118] NFSD: Change the way the expected length of a fattr4 is checked
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (8 preceding siblings ...)
  2020-11-20 20:34 ` [PATCH v2 009/118] NFSD: Replace READ* macros in nfsd4_decode_commit() Chuck Lever
@ 2020-11-20 20:34 ` Chuck Lever
  2020-11-20 20:34 ` [PATCH v2 011/118] NFSD: Replace READ* macros that decode the fattr4 size attribute Chuck Lever
                   ` (107 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:34 UTC (permalink / raw)
  To: linux-nfs

Because the fattr4 is now managed in an xdr_stream, all that is
needed is to store the initial position of the stream before
decoding the attribute list. Then the actual length of the list
is computed using the final stream position, after decoding is
complete.

No behavior change is expected.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   34 +++++++++++-----------------------
 1 file changed, 11 insertions(+), 23 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index d4b98bd8a859..a076bb42e98a 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -248,7 +248,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 		   struct iattr *iattr, struct nfs4_acl **acl,
 		   struct xdr_netobj *label, int *umask)
 {
-	int expected_len, len = 0;
+	unsigned int starting_pos;
+	u32 attrlist4_count;
 	u32 dummy32;
 	char *buf;
 
@@ -265,12 +266,12 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 		return nfserr_attrnotsupp;
 	}
 
-	READ_BUF(4);
-	expected_len = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &attrlist4_count) < 0)
+		return nfserr_bad_xdr;
+	starting_pos = xdr_stream_pos(argp->xdr);
 
 	if (bmval[0] & FATTR4_WORD0_SIZE) {
 		READ_BUF(8);
-		len += 8;
 		p = xdr_decode_hyper(p, &iattr->ia_size);
 		iattr->ia_valid |= ATTR_SIZE;
 	}
@@ -278,7 +279,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 		u32 nace;
 		struct nfs4_ace *ace;
 
-		READ_BUF(4); len += 4;
+		READ_BUF(4);
 		nace = be32_to_cpup(p++);
 
 		if (nace > xdr_stream_remaining(argp->xdr) / sizeof(struct nfs4_ace))
@@ -295,13 +296,12 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 
 		(*acl)->naces = nace;
 		for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) {
-			READ_BUF(16); len += 16;
+			READ_BUF(16);
 			ace->type = be32_to_cpup(p++);
 			ace->flag = be32_to_cpup(p++);
 			ace->access_mask = be32_to_cpup(p++);
 			dummy32 = be32_to_cpup(p++);
 			READ_BUF(dummy32);
-			len += XDR_QUADLEN(dummy32) << 2;
 			READMEM(buf, dummy32);
 			ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
 			status = nfs_ok;
@@ -320,17 +320,14 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 		*acl = NULL;
 	if (bmval[1] & FATTR4_WORD1_MODE) {
 		READ_BUF(4);
-		len += 4;
 		iattr->ia_mode = be32_to_cpup(p++);
 		iattr->ia_mode &= (S_IFMT | S_IALLUGO);
 		iattr->ia_valid |= ATTR_MODE;
 	}
 	if (bmval[1] & FATTR4_WORD1_OWNER) {
 		READ_BUF(4);
-		len += 4;
 		dummy32 = be32_to_cpup(p++);
 		READ_BUF(dummy32);
-		len += (XDR_QUADLEN(dummy32) << 2);
 		READMEM(buf, dummy32);
 		if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
 			return status;
@@ -338,10 +335,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 	}
 	if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) {
 		READ_BUF(4);
-		len += 4;
 		dummy32 = be32_to_cpup(p++);
 		READ_BUF(dummy32);
-		len += (XDR_QUADLEN(dummy32) << 2);
 		READMEM(buf, dummy32);
 		if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
 			return status;
@@ -349,11 +344,9 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 	}
 	if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
 		READ_BUF(4);
-		len += 4;
 		dummy32 = be32_to_cpup(p++);
 		switch (dummy32) {
 		case NFS4_SET_TO_CLIENT_TIME:
-			len += 12;
 			status = nfsd4_decode_time(argp, &iattr->ia_atime);
 			if (status)
 				return status;
@@ -368,11 +361,9 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 	}
 	if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
 		READ_BUF(4);
-		len += 4;
 		dummy32 = be32_to_cpup(p++);
 		switch (dummy32) {
 		case NFS4_SET_TO_CLIENT_TIME:
-			len += 12;
 			status = nfsd4_decode_time(argp, &iattr->ia_mtime);
 			if (status)
 				return status;
@@ -390,18 +381,14 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 	if (IS_ENABLED(CONFIG_NFSD_V4_SECURITY_LABEL) &&
 	    bmval[2] & FATTR4_WORD2_SECURITY_LABEL) {
 		READ_BUF(4);
-		len += 4;
 		dummy32 = be32_to_cpup(p++); /* lfs: we don't use it */
 		READ_BUF(4);
-		len += 4;
 		dummy32 = be32_to_cpup(p++); /* pi: we don't use it either */
 		READ_BUF(4);
-		len += 4;
 		dummy32 = be32_to_cpup(p++);
 		READ_BUF(dummy32);
 		if (dummy32 > NFS4_MAXLABELLEN)
 			return nfserr_badlabel;
-		len += (XDR_QUADLEN(dummy32) << 2);
 		READMEM(buf, dummy32);
 		label->len = dummy32;
 		label->data = svcxdr_dupstr(argp, buf, dummy32);
@@ -412,15 +399,16 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 		if (!umask)
 			goto xdr_error;
 		READ_BUF(8);
-		len += 8;
 		dummy32 = be32_to_cpup(p++);
 		iattr->ia_mode = dummy32 & (S_IFMT | S_IALLUGO);
 		dummy32 = be32_to_cpup(p++);
 		*umask = dummy32 & S_IRWXUGO;
 		iattr->ia_valid |= ATTR_MODE;
 	}
-	if (len != expected_len)
-		goto xdr_error;
+
+	/* request sanity: did we get the right number of words? */
+	if (attrlist4_count != xdr_stream_pos(argp->xdr) - starting_pos)
+		return nfserr_bad_xdr;
 
 	DECODE_TAIL;
 }



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 011/118] NFSD: Replace READ* macros that decode the fattr4 size attribute
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (9 preceding siblings ...)
  2020-11-20 20:34 ` [PATCH v2 010/118] NFSD: Change the way the expected length of a fattr4 is checked Chuck Lever
@ 2020-11-20 20:34 ` Chuck Lever
  2020-11-20 20:34 ` [PATCH v2 012/118] NFSD: Replace READ* macros that decode the fattr4 acl attribute Chuck Lever
                   ` (106 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:34 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index a076bb42e98a..9f121698aa92 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -271,8 +271,11 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 	starting_pos = xdr_stream_pos(argp->xdr);
 
 	if (bmval[0] & FATTR4_WORD0_SIZE) {
-		READ_BUF(8);
-		p = xdr_decode_hyper(p, &iattr->ia_size);
+		u64 size;
+
+		if (xdr_stream_decode_u64(argp->xdr, &size) < 0)
+			return nfserr_bad_xdr;
+		iattr->ia_size = size;
 		iattr->ia_valid |= ATTR_SIZE;
 	}
 	if (bmval[0] & FATTR4_WORD0_ACL) {



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 012/118] NFSD: Replace READ* macros that decode the fattr4 acl attribute
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (10 preceding siblings ...)
  2020-11-20 20:34 ` [PATCH v2 011/118] NFSD: Replace READ* macros that decode the fattr4 size attribute Chuck Lever
@ 2020-11-20 20:34 ` Chuck Lever
  2020-11-20 20:34 ` [PATCH v2 013/118] NFSD: Replace READ* macros that decode the fattr4 mode attribute Chuck Lever
                   ` (105 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:34 UTC (permalink / raw)
  To: linux-nfs

Refactor for clarity and to move infrequently-used code out of line.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |  107 +++++++++++++++++++++++++++++++++--------------------
 1 file changed, 67 insertions(+), 40 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 9f121698aa92..54c553ef35bf 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -243,6 +243,70 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
 	DECODE_TAIL;
 }
 
+static __be32
+nfsd4_decode_nfsace4(struct nfsd4_compoundargs *argp, struct nfs4_ace *ace)
+{
+	__be32 *p, status;
+	u32 length;
+
+	if (xdr_stream_decode_u32(argp->xdr, &ace->type) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &ace->flag) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &ace->access_mask) < 0)
+		return nfserr_bad_xdr;
+
+	if (xdr_stream_decode_u32(argp->xdr, &length) < 0)
+		return nfserr_bad_xdr;
+	p = xdr_inline_decode(argp->xdr, length);
+	if (!p)
+		return nfserr_bad_xdr;
+	ace->whotype = nfs4_acl_get_whotype((char *)p, length);
+	if (ace->whotype != NFS4_ACL_WHO_NAMED)
+		status = nfs_ok;
+	else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
+		status = nfsd_map_name_to_gid(argp->rqstp,
+				(char *)p, length, &ace->who_gid);
+	else
+		status = nfsd_map_name_to_uid(argp->rqstp,
+				(char *)p, length, &ace->who_uid);
+
+	return status;
+}
+
+/* A counted array of nfsace4's */
+static noinline __be32
+nfsd4_decode_acl(struct nfsd4_compoundargs *argp, struct nfs4_acl **acl)
+{
+	struct nfs4_ace *ace;
+	__be32 status;
+	u32 count;
+
+	if (xdr_stream_decode_u32(argp->xdr, &count) < 0)
+		return nfserr_bad_xdr;
+
+	if (count > 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
+		 * going on:
+		 */
+		return nfserr_fbig;
+
+	*acl = svcxdr_tmpalloc(argp, nfs4_acl_bytes(count));
+	if (*acl == NULL)
+		return nfserr_jukebox;
+
+	(*acl)->naces = count;
+	for (ace = (*acl)->aces; ace < (*acl)->aces + count; ace++) {
+		status = nfsd4_decode_nfsace4(argp, ace);
+		if (status)
+			return status;
+	}
+
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 		   struct iattr *iattr, struct nfs4_acl **acl,
@@ -279,46 +343,9 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 		iattr->ia_valid |= ATTR_SIZE;
 	}
 	if (bmval[0] & FATTR4_WORD0_ACL) {
-		u32 nace;
-		struct nfs4_ace *ace;
-
-		READ_BUF(4);
-		nace = be32_to_cpup(p++);
-
-		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
-			 * going on:
-			 */
-			return nfserr_fbig;
-
-		*acl = svcxdr_tmpalloc(argp, nfs4_acl_bytes(nace));
-		if (*acl == NULL)
-			return nfserr_jukebox;
-
-		(*acl)->naces = nace;
-		for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) {
-			READ_BUF(16);
-			ace->type = be32_to_cpup(p++);
-			ace->flag = be32_to_cpup(p++);
-			ace->access_mask = be32_to_cpup(p++);
-			dummy32 = be32_to_cpup(p++);
-			READ_BUF(dummy32);
-			READMEM(buf, dummy32);
-			ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
-			status = nfs_ok;
-			if (ace->whotype != NFS4_ACL_WHO_NAMED)
-				;
-			else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
-				status = nfsd_map_name_to_gid(argp->rqstp,
-						buf, dummy32, &ace->who_gid);
-			else
-				status = nfsd_map_name_to_uid(argp->rqstp,
-						buf, dummy32, &ace->who_uid);
-			if (status)
-				return status;
-		}
+		status = nfsd4_decode_acl(argp, acl);
+		if (status)
+			return status;
 	} else
 		*acl = NULL;
 	if (bmval[1] & FATTR4_WORD1_MODE) {



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 013/118] NFSD: Replace READ* macros that decode the fattr4 mode attribute
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (11 preceding siblings ...)
  2020-11-20 20:34 ` [PATCH v2 012/118] NFSD: Replace READ* macros that decode the fattr4 acl attribute Chuck Lever
@ 2020-11-20 20:34 ` Chuck Lever
  2020-11-20 20:35 ` [PATCH v2 014/118] NFSD: Replace READ* macros that decode the fattr4 owner attribute Chuck Lever
                   ` (104 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:34 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 54c553ef35bf..821a03121d22 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -349,8 +349,11 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 	} else
 		*acl = NULL;
 	if (bmval[1] & FATTR4_WORD1_MODE) {
-		READ_BUF(4);
-		iattr->ia_mode = be32_to_cpup(p++);
+		u32 mode;
+
+		if (xdr_stream_decode_u32(argp->xdr, &mode) < 0)
+			return nfserr_bad_xdr;
+		iattr->ia_mode = mode;
 		iattr->ia_mode &= (S_IFMT | S_IALLUGO);
 		iattr->ia_valid |= ATTR_MODE;
 	}



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 014/118] NFSD: Replace READ* macros that decode the fattr4 owner attribute
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (12 preceding siblings ...)
  2020-11-20 20:34 ` [PATCH v2 013/118] NFSD: Replace READ* macros that decode the fattr4 mode attribute Chuck Lever
@ 2020-11-20 20:35 ` Chuck Lever
  2020-11-20 20:35 ` [PATCH v2 015/118] NFSD: Replace READ* macros that decode the fattr4 owner_group attribute Chuck Lever
                   ` (103 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:35 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 821a03121d22..7e9c1112cfea 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -358,11 +358,16 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 		iattr->ia_valid |= ATTR_MODE;
 	}
 	if (bmval[1] & FATTR4_WORD1_OWNER) {
-		READ_BUF(4);
-		dummy32 = be32_to_cpup(p++);
-		READ_BUF(dummy32);
-		READMEM(buf, dummy32);
-		if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
+		u32 length;
+
+		if (xdr_stream_decode_u32(argp->xdr, &length) < 0)
+			return nfserr_bad_xdr;
+		p = xdr_inline_decode(argp->xdr, length);
+		if (!p)
+			return nfserr_bad_xdr;
+		status = nfsd_map_name_to_uid(argp->rqstp, (char *)p, length,
+					      &iattr->ia_uid);
+		if (status)
 			return status;
 		iattr->ia_valid |= ATTR_UID;
 	}



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 015/118] NFSD: Replace READ* macros that decode the fattr4 owner_group attribute
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (13 preceding siblings ...)
  2020-11-20 20:35 ` [PATCH v2 014/118] NFSD: Replace READ* macros that decode the fattr4 owner attribute Chuck Lever
@ 2020-11-20 20:35 ` Chuck Lever
  2020-11-20 20:35 ` [PATCH v2 016/118] NFSD: Replace READ* macros that decode the fattr4 time_set attributes Chuck Lever
                   ` (102 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:35 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 7e9c1112cfea..53cd69ff54f7 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -372,11 +372,16 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 		iattr->ia_valid |= ATTR_UID;
 	}
 	if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) {
-		READ_BUF(4);
-		dummy32 = be32_to_cpup(p++);
-		READ_BUF(dummy32);
-		READMEM(buf, dummy32);
-		if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
+		u32 length;
+
+		if (xdr_stream_decode_u32(argp->xdr, &length) < 0)
+			return nfserr_bad_xdr;
+		p = xdr_inline_decode(argp->xdr, length);
+		if (!p)
+			return nfserr_bad_xdr;
+		status = nfsd_map_name_to_gid(argp->rqstp, (char *)p, length,
+					      &iattr->ia_gid);
+		if (status)
 			return status;
 		iattr->ia_valid |= ATTR_GID;
 	}



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 016/118] NFSD: Replace READ* macros that decode the fattr4 time_set attributes
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (14 preceding siblings ...)
  2020-11-20 20:35 ` [PATCH v2 015/118] NFSD: Replace READ* macros that decode the fattr4 owner_group attribute Chuck Lever
@ 2020-11-20 20:35 ` Chuck Lever
  2020-11-20 20:35 ` [PATCH v2 017/118] NFSD: Replace READ* macros that decode the fattr4 security label attribute Chuck Lever
                   ` (101 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:35 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   39 +++++++++++++++++++++++++++++----------
 1 file changed, 29 insertions(+), 10 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 53cd69ff54f7..16aded9bcf3a 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -217,6 +217,21 @@ nfsd4_decode_time(struct nfsd4_compoundargs *argp, struct timespec64 *tv)
 	DECODE_TAIL;
 }
 
+static __be32
+nfsd4_decode_nfstime4(struct nfsd4_compoundargs *argp, struct timespec64 *tv)
+{
+	__be32 *p;
+
+	p = xdr_inline_decode(argp->xdr, XDR_UNIT * 3);
+	if (!p)
+		return nfserr_bad_xdr;
+	p = xdr_decode_hyper(p, &tv->tv_sec);
+	tv->tv_nsec = be32_to_cpup(p++);
+	if (tv->tv_nsec >= (u32)1000000000)
+		return nfserr_inval;
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
 {
@@ -386,11 +401,13 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 		iattr->ia_valid |= ATTR_GID;
 	}
 	if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
-		READ_BUF(4);
-		dummy32 = be32_to_cpup(p++);
-		switch (dummy32) {
+		u32 set_it;
+
+		if (xdr_stream_decode_u32(argp->xdr, &set_it) < 0)
+			return nfserr_bad_xdr;
+		switch (set_it) {
 		case NFS4_SET_TO_CLIENT_TIME:
-			status = nfsd4_decode_time(argp, &iattr->ia_atime);
+			status = nfsd4_decode_nfstime4(argp, &iattr->ia_atime);
 			if (status)
 				return status;
 			iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
@@ -399,15 +416,17 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 			iattr->ia_valid |= ATTR_ATIME;
 			break;
 		default:
-			goto xdr_error;
+			return nfserr_bad_xdr;
 		}
 	}
 	if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
-		READ_BUF(4);
-		dummy32 = be32_to_cpup(p++);
-		switch (dummy32) {
+		u32 set_it;
+
+		if (xdr_stream_decode_u32(argp->xdr, &set_it) < 0)
+			return nfserr_bad_xdr;
+		switch (set_it) {
 		case NFS4_SET_TO_CLIENT_TIME:
-			status = nfsd4_decode_time(argp, &iattr->ia_mtime);
+			status = nfsd4_decode_nfstime4(argp, &iattr->ia_mtime);
 			if (status)
 				return status;
 			iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
@@ -416,7 +435,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 			iattr->ia_valid |= ATTR_MTIME;
 			break;
 		default:
-			goto xdr_error;
+			return nfserr_bad_xdr;
 		}
 	}
 



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 017/118] NFSD: Replace READ* macros that decode the fattr4 security label attribute
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (15 preceding siblings ...)
  2020-11-20 20:35 ` [PATCH v2 016/118] NFSD: Replace READ* macros that decode the fattr4 time_set attributes Chuck Lever
@ 2020-11-20 20:35 ` Chuck Lever
  2020-11-20 20:35 ` [PATCH v2 018/118] NFSD: Replace READ* macros that decode the fattr4 umask attribute Chuck Lever
                   ` (100 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:35 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   46 ++++++++++++++++++++++++++++++----------------
 1 file changed, 30 insertions(+), 16 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 16aded9bcf3a..a5207a36199c 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -322,6 +322,33 @@ nfsd4_decode_acl(struct nfsd4_compoundargs *argp, struct nfs4_acl **acl)
 	return nfs_ok;
 }
 
+static noinline __be32
+nfsd4_decode_seclabel(struct nfsd4_compoundargs *argp,
+		      struct xdr_netobj *label)
+{
+	u32 lfs, pi, length;
+	__be32 *p;
+
+	if (xdr_stream_decode_u32(argp->xdr, &lfs) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &pi) < 0)
+		return nfserr_bad_xdr;
+
+	if (xdr_stream_decode_u32(argp->xdr, &length) < 0)
+		return nfserr_bad_xdr;
+	if (length > NFS4_MAXLABELLEN)
+		return nfserr_badlabel;
+	p = xdr_inline_decode(argp->xdr, length);
+	if (!p)
+		return nfserr_bad_xdr;
+	label->len = length;
+	label->data = svcxdr_dupstr(argp, p, length);
+	if (!label->data)
+		return nfserr_jukebox;
+
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 		   struct iattr *iattr, struct nfs4_acl **acl,
@@ -330,7 +357,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 	unsigned int starting_pos;
 	u32 attrlist4_count;
 	u32 dummy32;
-	char *buf;
 
 	DECODE_HEAD;
 	iattr->ia_valid = 0;
@@ -438,24 +464,12 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 			return nfserr_bad_xdr;
 		}
 	}
-
 	label->len = 0;
 	if (IS_ENABLED(CONFIG_NFSD_V4_SECURITY_LABEL) &&
 	    bmval[2] & FATTR4_WORD2_SECURITY_LABEL) {
-		READ_BUF(4);
-		dummy32 = be32_to_cpup(p++); /* lfs: we don't use it */
-		READ_BUF(4);
-		dummy32 = be32_to_cpup(p++); /* pi: we don't use it either */
-		READ_BUF(4);
-		dummy32 = be32_to_cpup(p++);
-		READ_BUF(dummy32);
-		if (dummy32 > NFS4_MAXLABELLEN)
-			return nfserr_badlabel;
-		READMEM(buf, dummy32);
-		label->len = dummy32;
-		label->data = svcxdr_dupstr(argp, buf, dummy32);
-		if (!label->data)
-			return nfserr_jukebox;
+		status = nfsd4_decode_seclabel(argp, label);
+		if (status)
+			return status;
 	}
 	if (bmval[2] & FATTR4_WORD2_MODE_UMASK) {
 		if (!umask)



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 018/118] NFSD: Replace READ* macros that decode the fattr4 umask attribute
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (16 preceding siblings ...)
  2020-11-20 20:35 ` [PATCH v2 017/118] NFSD: Replace READ* macros that decode the fattr4 security label attribute Chuck Lever
@ 2020-11-20 20:35 ` Chuck Lever
  2020-11-20 20:35 ` [PATCH v2 019/118] NFSD: Replace READ* macros in nfsd4_decode_fattr() Chuck Lever
                   ` (99 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:35 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index a5207a36199c..046fe62bfa29 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -356,7 +356,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 {
 	unsigned int starting_pos;
 	u32 attrlist4_count;
-	u32 dummy32;
 
 	DECODE_HEAD;
 	iattr->ia_valid = 0;
@@ -472,13 +471,16 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 			return status;
 	}
 	if (bmval[2] & FATTR4_WORD2_MODE_UMASK) {
+		u32 mode, mask;
+
 		if (!umask)
-			goto xdr_error;
-		READ_BUF(8);
-		dummy32 = be32_to_cpup(p++);
-		iattr->ia_mode = dummy32 & (S_IFMT | S_IALLUGO);
-		dummy32 = be32_to_cpup(p++);
-		*umask = dummy32 & S_IRWXUGO;
+			return nfserr_bad_xdr;
+		if (xdr_stream_decode_u32(argp->xdr, &mode) < 0)
+			return nfserr_bad_xdr;
+		iattr->ia_mode = mode & (S_IFMT | S_IALLUGO);
+		if (xdr_stream_decode_u32(argp->xdr, &mask) < 0)
+			return nfserr_bad_xdr;
+		*umask = mask & S_IRWXUGO;
 		iattr->ia_valid |= ATTR_MODE;
 	}
 



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 019/118] NFSD: Replace READ* macros in nfsd4_decode_fattr()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (17 preceding siblings ...)
  2020-11-20 20:35 ` [PATCH v2 018/118] NFSD: Replace READ* macros that decode the fattr4 umask attribute Chuck Lever
@ 2020-11-20 20:35 ` Chuck Lever
  2020-11-20 20:35 ` [PATCH v2 020/118] NFSD: Replace READ* macros in nfsd4_decode_create() Chuck Lever
                   ` (98 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:35 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   41 +++++++++++++++++++++++------------------
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 046fe62bfa29..c7f14f0db432 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -350,17 +350,17 @@ nfsd4_decode_seclabel(struct nfsd4_compoundargs *argp,
 }
 
 static __be32
-nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
-		   struct iattr *iattr, struct nfs4_acl **acl,
-		   struct xdr_netobj *label, int *umask)
+nfsd4_decode_fattr4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen,
+		    struct iattr *iattr, struct nfs4_acl **acl,
+		    struct xdr_netobj *label, int *umask)
 {
 	unsigned int starting_pos;
 	u32 attrlist4_count;
+	__be32 *p, status;
 
-	DECODE_HEAD;
 	iattr->ia_valid = 0;
-	if ((status = nfsd4_decode_bitmap(argp, bmval)))
-		return status;
+	if (xdr_stream_decode_uint32_array(argp->xdr, bmval, bmlen) < 0)
+		return nfserr_bad_xdr;
 
 	if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
 	    || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
@@ -488,7 +488,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 	if (attrlist4_count != xdr_stream_pos(argp->xdr) - starting_pos)
 		return nfserr_bad_xdr;
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32
@@ -676,9 +676,10 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
 	if ((status = check_filename(create->cr_name, create->cr_namelen)))
 		return status;
 
-	status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
-				    &create->cr_acl, &create->cr_label,
-				    &create->cr_umask);
+	status = nfsd4_decode_fattr4(argp, create->cr_bmval,
+				    ARRAY_SIZE(create->cr_bmval),
+				    &create->cr_iattr, &create->cr_acl,
+				    &create->cr_label, &create->cr_umask);
 	if (status)
 		goto out;
 
@@ -927,9 +928,10 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 		switch (open->op_createmode) {
 		case NFS4_CREATE_UNCHECKED:
 		case NFS4_CREATE_GUARDED:
-			status = nfsd4_decode_fattr(argp, open->op_bmval,
-				&open->op_iattr, &open->op_acl, &open->op_label,
-				&open->op_umask);
+			status = nfsd4_decode_fattr4(argp, open->op_bmval,
+						     ARRAY_SIZE(open->op_bmval),
+						     &open->op_iattr, &open->op_acl,
+						     &open->op_label, &open->op_umask);
 			if (status)
 				goto out;
 			break;
@@ -942,9 +944,10 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 				goto xdr_error;
 			READ_BUF(NFS4_VERIFIER_SIZE);
 			COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
-			status = nfsd4_decode_fattr(argp, open->op_bmval,
-				&open->op_iattr, &open->op_acl, &open->op_label,
-				&open->op_umask);
+			status = nfsd4_decode_fattr4(argp, open->op_bmval,
+						     ARRAY_SIZE(open->op_bmval),
+						     &open->op_iattr, &open->op_acl,
+						     &open->op_label, &open->op_umask);
 			if (status)
 				goto out;
 			break;
@@ -1180,8 +1183,10 @@ nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *seta
 	status = nfsd4_decode_stateid4(argp, &setattr->sa_stateid);
 	if (status)
 		return status;
-	return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr,
-				  &setattr->sa_acl, &setattr->sa_label, NULL);
+	return nfsd4_decode_fattr4(argp, setattr->sa_bmval,
+				   ARRAY_SIZE(setattr->sa_bmval),
+				   &setattr->sa_iattr, &setattr->sa_acl,
+				   &setattr->sa_label, NULL);
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 020/118] NFSD: Replace READ* macros in nfsd4_decode_create()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (18 preceding siblings ...)
  2020-11-20 20:35 ` [PATCH v2 019/118] NFSD: Replace READ* macros in nfsd4_decode_fattr() Chuck Lever
@ 2020-11-20 20:35 ` Chuck Lever
  2020-11-20 20:35 ` [PATCH v2 021/118] NFSD: Replace READ* macros in nfsd4_decode_getattr() Chuck Lever
                   ` (97 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:35 UTC (permalink / raw)
  To: linux-nfs

A dedicated decoder for component4 is introduced here, which will be
used by other operation decoders in subsequent patches.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   58 +++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 40 insertions(+), 18 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index c7f14f0db432..4a5b7bc21dab 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -90,6 +90,8 @@ check_filename(char *str, int len)
 
 	if (len == 0)
 		return nfserr_inval;
+	if (len > NFS4_MAXNAMLEN)
+		return nfserr_nametoolong;
 	if (isdotent(str, len))
 		return nfserr_badname;
 	for (i = 0; i < len; i++)
@@ -203,6 +205,27 @@ static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
 	return ret;
 }
 
+static __be32
+nfsd4_decode_component4(struct nfsd4_compoundargs *argp, char **namp, u32 *lenp)
+{
+	__be32 *p, status;
+
+	if (xdr_stream_decode_u32(argp->xdr, lenp) < 0)
+		return nfserr_bad_xdr;
+	p = xdr_inline_decode(argp->xdr, *lenp);
+	if (!p)
+		return nfserr_bad_xdr;
+	status = check_filename((char *)p, *lenp);
+	if (status)
+		return status;
+	*namp = svcxdr_tmpalloc(argp, *lenp);
+	if (!*namp)
+		return nfserr_jukebox;
+	memcpy(*namp, p, *lenp);
+
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_time(struct nfsd4_compoundargs *argp, struct timespec64 *tv)
 {
@@ -643,24 +666,27 @@ nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit
 static __be32
 nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create)
 {
-	DECODE_HEAD;
+	__be32 *p, status;
 
-	READ_BUF(4);
-	create->cr_type = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &create->cr_type) < 0)
+		return nfserr_bad_xdr;
 	switch (create->cr_type) {
 	case NF4LNK:
-		READ_BUF(4);
-		create->cr_datalen = be32_to_cpup(p++);
-		READ_BUF(create->cr_datalen);
+		if (xdr_stream_decode_u32(argp->xdr, &create->cr_datalen) < 0)
+			return nfserr_bad_xdr;
+		p = xdr_inline_decode(argp->xdr, create->cr_datalen);
+		if (!p)
+			return nfserr_bad_xdr;
 		create->cr_data = svcxdr_dupstr(argp, p, create->cr_datalen);
 		if (!create->cr_data)
 			return nfserr_jukebox;
 		break;
 	case NF4BLK:
 	case NF4CHR:
-		READ_BUF(8);
-		create->cr_specdata1 = be32_to_cpup(p++);
-		create->cr_specdata2 = be32_to_cpup(p++);
+		if (xdr_stream_decode_u32(argp->xdr, &create->cr_specdata1) < 0)
+			return nfserr_bad_xdr;
+		if (xdr_stream_decode_u32(argp->xdr, &create->cr_specdata2) < 0)
+			return nfserr_bad_xdr;
 		break;
 	case NF4SOCK:
 	case NF4FIFO:
@@ -668,22 +694,18 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
 	default:
 		break;
 	}
-
-	READ_BUF(4);
-	create->cr_namelen = be32_to_cpup(p++);
-	READ_BUF(create->cr_namelen);
-	SAVEMEM(create->cr_name, create->cr_namelen);
-	if ((status = check_filename(create->cr_name, create->cr_namelen)))
+	status = nfsd4_decode_component4(argp, &create->cr_name,
+					 &create->cr_namelen);
+	if (status)
 		return status;
-
 	status = nfsd4_decode_fattr4(argp, create->cr_bmval,
 				    ARRAY_SIZE(create->cr_bmval),
 				    &create->cr_iattr, &create->cr_acl,
 				    &create->cr_label, &create->cr_umask);
 	if (status)
-		goto out;
+		return status;
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static inline __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 021/118] NFSD: Replace READ* macros in nfsd4_decode_getattr()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (19 preceding siblings ...)
  2020-11-20 20:35 ` [PATCH v2 020/118] NFSD: Replace READ* macros in nfsd4_decode_create() Chuck Lever
@ 2020-11-20 20:35 ` Chuck Lever
  2020-11-20 20:35 ` [PATCH v2 022/118] NFSD: Replace READ* macros in nfsd4_decode_link() Chuck Lever
                   ` (96 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:35 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 4a5b7bc21dab..8594d8751b7b 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -717,7 +717,10 @@ nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegretu
 static inline __be32
 nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr)
 {
-	return nfsd4_decode_bitmap(argp, getattr->ga_bmval);
+	if (xdr_stream_decode_uint32_array(argp->xdr, getattr->ga_bmval,
+					   ARRAY_SIZE(getattr->ga_bmval)) < 0)
+		return nfserr_bad_xdr;
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 022/118] NFSD: Replace READ* macros in nfsd4_decode_link()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (20 preceding siblings ...)
  2020-11-20 20:35 ` [PATCH v2 021/118] NFSD: Replace READ* macros in nfsd4_decode_getattr() Chuck Lever
@ 2020-11-20 20:35 ` Chuck Lever
  2020-11-20 20:35 ` [PATCH v2 023/118] NFSD: Relocate nfsd4_decode_opaque() Chuck Lever
                   ` (95 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:35 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 8594d8751b7b..8c0d4c4d7b42 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -726,16 +726,7 @@ nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *geta
 static __be32
 nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
 {
-	DECODE_HEAD;
-
-	READ_BUF(4);
-	link->li_namelen = be32_to_cpup(p++);
-	READ_BUF(link->li_namelen);
-	SAVEMEM(link->li_name, link->li_namelen);
-	if ((status = check_filename(link->li_name, link->li_namelen)))
-		return status;
-
-	DECODE_TAIL;
+	return nfsd4_decode_component4(argp, &link->li_name, &link->li_namelen);
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 023/118] NFSD: Relocate nfsd4_decode_opaque()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (21 preceding siblings ...)
  2020-11-20 20:35 ` [PATCH v2 022/118] NFSD: Replace READ* macros in nfsd4_decode_link() Chuck Lever
@ 2020-11-20 20:35 ` Chuck Lever
  2020-11-20 20:35 ` [PATCH v2 024/118] NFSD: Add helpers to decode a clientid4 and an NFSv4 state owner Chuck Lever
                   ` (94 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:35 UTC (permalink / raw)
  To: linux-nfs

Enable nfsd4_decode_opaque() to be used in more decoders, and
replace the READ* macros in nfsd4_decode_opaque().

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   43 +++++++++++++++++++++++++++----------------
 1 file changed, 27 insertions(+), 16 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 8c0d4c4d7b42..ec2cad8477e0 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -205,6 +205,33 @@ static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
 	return ret;
 }
 
+
+/*
+ * NFSv4 basic data type decoders
+ */
+
+static __be32
+nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o)
+{
+	__be32 *p;
+	u32 len;
+
+	if (xdr_stream_decode_u32(argp->xdr, &len) < 0)
+		return nfserr_bad_xdr;
+	if (len == 0 || len > NFS4_OPAQUE_LIMIT)
+		return nfserr_bad_xdr;
+	p = xdr_inline_decode(argp->xdr, len);
+	if (!p)
+		return nfserr_bad_xdr;
+	o->data = svcxdr_tmpalloc(argp, len);
+	if (!o->data)
+		return nfserr_jukebox;
+	o->len = len;
+	memcpy(o->data, p, len);
+
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_component4(struct nfsd4_compoundargs *argp, char **namp, u32 *lenp)
 {
@@ -890,22 +917,6 @@ static __be32 nfsd4_decode_share_deny(struct nfsd4_compoundargs *argp, u32 *x)
 	return nfserr_bad_xdr;
 }
 
-static __be32 nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o)
-{
-	DECODE_HEAD;
-
-	READ_BUF(4);
-	o->len = be32_to_cpup(p++);
-
-	if (o->len == 0 || o->len > NFS4_OPAQUE_LIMIT)
-		return nfserr_bad_xdr;
-
-	READ_BUF(o->len);
-	SAVEMEM(o->data, o->len);
-
-	DECODE_TAIL;
-}
-
 static __be32
 nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 {



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 024/118] NFSD: Add helpers to decode a clientid4 and an NFSv4 state owner
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (22 preceding siblings ...)
  2020-11-20 20:35 ` [PATCH v2 023/118] NFSD: Relocate nfsd4_decode_opaque() Chuck Lever
@ 2020-11-20 20:35 ` Chuck Lever
  2020-11-20 20:35 ` [PATCH v2 025/118] NFSD: Add helper for decoding locker4 Chuck Lever
                   ` (93 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:35 UTC (permalink / raw)
  To: linux-nfs

These helpers will also be used to simplify decoders in subsequent
patches.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   34 +++++++++++++++++++++++++++++-----
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index ec2cad8477e0..a7c9a0368951 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -541,6 +541,30 @@ nfsd4_decode_fattr4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen,
 	return nfs_ok;
 }
 
+static __be32
+nfsd4_decode_clientid4(struct nfsd4_compoundargs *argp, clientid_t *clientid)
+{
+	__be32 *p;
+
+	p = xdr_inline_decode(argp->xdr, sizeof(__be64));
+	if (!p)
+		return nfserr_bad_xdr;
+	memcpy(clientid, p, sizeof(*clientid));
+	return nfs_ok;
+}
+
+static __be32
+nfsd4_decode_state_owner4(struct nfsd4_compoundargs *argp,
+			  clientid_t *clientid, struct xdr_netobj *owner)
+{
+	__be32 status;
+
+	status = nfsd4_decode_clientid4(argp, clientid);
+	if (status)
+		return status;
+	return nfsd4_decode_opaque(argp, owner);
+}
+
 static __be32
 nfsd4_decode_stateid4(struct nfsd4_compoundargs *argp, stateid_t *sid)
 {
@@ -779,12 +803,12 @@ nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
 		status = nfsd4_decode_stateid4(argp, &lock->lk_new_open_stateid);
 		if (status)
 			return status;
-		READ_BUF(8 + sizeof(clientid_t));
+		READ_BUF(4);
 		lock->lk_new_lock_seqid = be32_to_cpup(p++);
-		COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t));
-		lock->lk_new_owner.len = be32_to_cpup(p++);
-		READ_BUF(lock->lk_new_owner.len);
-		READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len);
+		status = nfsd4_decode_state_owner4(argp, &lock->lk_new_clientid,
+						   &lock->lk_new_owner);
+		if (status)
+			return status;
 	} else {
 		status = nfsd4_decode_stateid4(argp, &lock->lk_old_lock_stateid);
 		if (status)



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 025/118] NFSD: Add helper for decoding locker4
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (23 preceding siblings ...)
  2020-11-20 20:35 ` [PATCH v2 024/118] NFSD: Add helpers to decode a clientid4 and an NFSv4 state owner Chuck Lever
@ 2020-11-20 20:35 ` Chuck Lever
  2020-11-20 20:36 ` [PATCH v2 026/118] NFSD: Replace READ* macros in nfsd4_decode_lock() Chuck Lever
                   ` (92 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:35 UTC (permalink / raw)
  To: linux-nfs

Refactor for clarity.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c          |   64 ++++++++++++++++++++++++++++++--------------
 include/linux/sunrpc/xdr.h |   21 ++++++++++++++
 2 files changed, 64 insertions(+), 21 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index a7c9a0368951..94219ceb2ea2 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -780,6 +780,48 @@ nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
 	return nfsd4_decode_component4(argp, &link->li_name, &link->li_namelen);
 }
 
+static __be32
+nfsd4_decode_open_to_lock_owner4(struct nfsd4_compoundargs *argp,
+				 struct nfsd4_lock *lock)
+{
+	__be32 status;
+
+	if (xdr_stream_decode_u32(argp->xdr, &lock->lk_new_open_seqid) < 0)
+		return nfserr_bad_xdr;
+	status = nfsd4_decode_stateid4(argp, &lock->lk_new_open_stateid);
+	if (status)
+		return status;
+	if (xdr_stream_decode_u32(argp->xdr, &lock->lk_new_lock_seqid) < 0)
+		return nfserr_bad_xdr;
+	return nfsd4_decode_state_owner4(argp, &lock->lk_new_clientid,
+					 &lock->lk_new_owner);
+}
+
+static __be32
+nfsd4_decode_exist_lock_owner4(struct nfsd4_compoundargs *argp,
+			       struct nfsd4_lock *lock)
+{
+	__be32 status;
+
+	status = nfsd4_decode_stateid4(argp, &lock->lk_old_lock_stateid);
+	if (status)
+		return status;
+	if (xdr_stream_decode_u32(argp->xdr, &lock->lk_old_lock_seqid) < 0)
+		return nfserr_bad_xdr;
+
+	return nfs_ok;
+}
+
+static __be32
+nfsd4_decode_locker4(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
+{
+	if (xdr_stream_decode_bool(argp->xdr, &lock->lk_is_new) < 0)
+		return nfserr_bad_xdr;
+	if (lock->lk_is_new)
+		return nfsd4_decode_open_to_lock_owner4(argp, lock);
+	return nfsd4_decode_exist_lock_owner4(argp, lock);
+}
+
 static __be32
 nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
 {
@@ -795,27 +837,7 @@ nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
 	lock->lk_reclaim = be32_to_cpup(p++);
 	p = xdr_decode_hyper(p, &lock->lk_offset);
 	p = xdr_decode_hyper(p, &lock->lk_length);
-	lock->lk_is_new = be32_to_cpup(p++);
-
-	if (lock->lk_is_new) {
-		READ_BUF(4);
-		lock->lk_new_open_seqid = be32_to_cpup(p++);
-		status = nfsd4_decode_stateid4(argp, &lock->lk_new_open_stateid);
-		if (status)
-			return status;
-		READ_BUF(4);
-		lock->lk_new_lock_seqid = be32_to_cpup(p++);
-		status = nfsd4_decode_state_owner4(argp, &lock->lk_new_clientid,
-						   &lock->lk_new_owner);
-		if (status)
-			return status;
-	} else {
-		status = nfsd4_decode_stateid4(argp, &lock->lk_old_lock_stateid);
-		if (status)
-			return status;
-		READ_BUF(4);
-		lock->lk_old_lock_seqid = be32_to_cpup(p++);
-	}
+	status = nfsd4_decode_locker4(argp, lock);
 
 	DECODE_TAIL;
 }
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index 22b00104bc1a..abd45f03634f 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -555,6 +555,27 @@ static inline bool xdr_item_is_present(const __be32 *p)
 	return *p != xdr_zero;
 }
 
+/**
+ * xdr_stream_decode_bool - Decode a boolean
+ * @xdr: pointer to xdr_stream
+ * @ptr: pointer to a u32 in which to store the result
+ *
+ * Return values:
+ *   %0 on success
+ *   %-EBADMSG on XDR buffer overflow
+ */
+static inline ssize_t
+xdr_stream_decode_bool(struct xdr_stream *xdr, __u32 *ptr)
+{
+	const size_t count = sizeof(*ptr);
+	__be32 *p = xdr_inline_decode(xdr, count);
+
+	if (unlikely(!p))
+		return -EBADMSG;
+	*ptr = (*p != xdr_zero);
+	return 0;
+}
+
 /**
  * xdr_stream_decode_u32 - Decode a 32-bit integer
  * @xdr: pointer to xdr_stream



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 026/118] NFSD: Replace READ* macros in nfsd4_decode_lock()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (24 preceding siblings ...)
  2020-11-20 20:35 ` [PATCH v2 025/118] NFSD: Add helper for decoding locker4 Chuck Lever
@ 2020-11-20 20:36 ` Chuck Lever
  2020-11-20 20:36 ` [PATCH v2 027/118] NFSD: Replace READ* macros in nfsd4_decode_lockt() Chuck Lever
                   ` (91 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:36 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   24 ++++++++++--------------
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 94219ceb2ea2..83a8f872ae9a 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -825,21 +825,17 @@ nfsd4_decode_locker4(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
 static __be32
 nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
 {
-	DECODE_HEAD;
-
-	/*
-	* type, reclaim(boolean), offset, length, new_lock_owner(boolean)
-	*/
-	READ_BUF(28);
-	lock->lk_type = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &lock->lk_type) < 0)
+		return nfserr_bad_xdr;
 	if ((lock->lk_type < NFS4_READ_LT) || (lock->lk_type > NFS4_WRITEW_LT))
-		goto xdr_error;
-	lock->lk_reclaim = be32_to_cpup(p++);
-	p = xdr_decode_hyper(p, &lock->lk_offset);
-	p = xdr_decode_hyper(p, &lock->lk_length);
-	status = nfsd4_decode_locker4(argp, lock);
-
-	DECODE_TAIL;
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_bool(argp->xdr, &lock->lk_reclaim) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u64(argp->xdr, &lock->lk_offset) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u64(argp->xdr, &lock->lk_length) < 0)
+		return nfserr_bad_xdr;
+	return nfsd4_decode_locker4(argp, lock);
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 027/118] NFSD: Replace READ* macros in nfsd4_decode_lockt()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (25 preceding siblings ...)
  2020-11-20 20:36 ` [PATCH v2 026/118] NFSD: Replace READ* macros in nfsd4_decode_lock() Chuck Lever
@ 2020-11-20 20:36 ` Chuck Lever
  2020-11-20 20:36 ` [PATCH v2 028/118] NFSD: Replace READ* macros in nfsd4_decode_locku() Chuck Lever
                   ` (90 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:36 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   24 ++++++++++--------------
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 83a8f872ae9a..a465fb04d9ac 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -841,20 +841,16 @@ nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
 static __be32
 nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt)
 {
-	DECODE_HEAD;
-		        
-	READ_BUF(32);
-	lockt->lt_type = be32_to_cpup(p++);
-	if((lockt->lt_type < NFS4_READ_LT) || (lockt->lt_type > NFS4_WRITEW_LT))
-		goto xdr_error;
-	p = xdr_decode_hyper(p, &lockt->lt_offset);
-	p = xdr_decode_hyper(p, &lockt->lt_length);
-	COPYMEM(&lockt->lt_clientid, 8);
-	lockt->lt_owner.len = be32_to_cpup(p++);
-	READ_BUF(lockt->lt_owner.len);
-	READMEM(lockt->lt_owner.data, lockt->lt_owner.len);
-
-	DECODE_TAIL;
+	if (xdr_stream_decode_u32(argp->xdr, &lockt->lt_type) < 0)
+		return nfserr_bad_xdr;
+	if ((lockt->lt_type < NFS4_READ_LT) || (lockt->lt_type > NFS4_WRITEW_LT))
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u64(argp->xdr, &lockt->lt_offset) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u64(argp->xdr, &lockt->lt_length) < 0)
+		return nfserr_bad_xdr;
+	return nfsd4_decode_state_owner4(argp, &lockt->lt_clientid,
+					 &lockt->lt_owner);
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 028/118] NFSD: Replace READ* macros in nfsd4_decode_locku()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (26 preceding siblings ...)
  2020-11-20 20:36 ` [PATCH v2 027/118] NFSD: Replace READ* macros in nfsd4_decode_lockt() Chuck Lever
@ 2020-11-20 20:36 ` Chuck Lever
  2020-11-20 20:36 ` [PATCH v2 029/118] NFSD: Replace READ* macros in nfsd4_decode_lookup() Chuck Lever
                   ` (89 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:36 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index a465fb04d9ac..9b532e500e55 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -856,21 +856,23 @@ nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt)
 static __be32
 nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
 {
-	DECODE_HEAD;
+	__be32 status;
 
-	READ_BUF(8);
-	locku->lu_type = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &locku->lu_type) < 0)
+		return nfserr_bad_xdr;
 	if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT))
-		goto xdr_error;
-	locku->lu_seqid = be32_to_cpup(p++);
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &locku->lu_seqid) < 0)
+		return nfserr_bad_xdr;
 	status = nfsd4_decode_stateid4(argp, &locku->lu_stateid);
 	if (status)
 		return status;
-	READ_BUF(16);
-	p = xdr_decode_hyper(p, &locku->lu_offset);
-	p = xdr_decode_hyper(p, &locku->lu_length);
+	if (xdr_stream_decode_u64(argp->xdr, &locku->lu_offset) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u64(argp->xdr, &locku->lu_length) < 0)
+		return nfserr_bad_xdr;
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 029/118] NFSD: Replace READ* macros in nfsd4_decode_lookup()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (27 preceding siblings ...)
  2020-11-20 20:36 ` [PATCH v2 028/118] NFSD: Replace READ* macros in nfsd4_decode_locku() Chuck Lever
@ 2020-11-20 20:36 ` Chuck Lever
  2020-11-20 20:36 ` [PATCH v2 030/118] NFSD: Add helper to decode NFSv4 verifiers Chuck Lever
                   ` (88 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:36 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 9b532e500e55..2fe719f64ec9 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -878,16 +878,7 @@ nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
 static __be32
 nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup)
 {
-	DECODE_HEAD;
-
-	READ_BUF(4);
-	lookup->lo_len = be32_to_cpup(p++);
-	READ_BUF(lookup->lo_len);
-	SAVEMEM(lookup->lo_name, lookup->lo_len);
-	if ((status = check_filename(lookup->lo_name, lookup->lo_len)))
-		return status;
-
-	DECODE_TAIL;
+	return nfsd4_decode_component4(argp, &lookup->lo_name, &lookup->lo_len);
 }
 
 static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *share_access, u32 *deleg_want, u32 *deleg_when)



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 030/118] NFSD: Add helper to decode NFSv4 verifiers
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (28 preceding siblings ...)
  2020-11-20 20:36 ` [PATCH v2 029/118] NFSD: Replace READ* macros in nfsd4_decode_lookup() Chuck Lever
@ 2020-11-20 20:36 ` Chuck Lever
  2020-11-20 20:36 ` [PATCH v2 031/118] NFSD: Add helper to decode OPEN's createhow4 argument Chuck Lever
                   ` (87 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:36 UTC (permalink / raw)
  To: linux-nfs

This helper will be used to simplify decoders in subsequent
patches.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 2fe719f64ec9..1bbb637d4625 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -282,6 +282,18 @@ nfsd4_decode_nfstime4(struct nfsd4_compoundargs *argp, struct timespec64 *tv)
 	return nfs_ok;
 }
 
+static __be32
+nfsd4_decode_verifier4(struct nfsd4_compoundargs *argp, nfs4_verifier *verf)
+{
+	__be32 *p;
+
+	p = xdr_inline_decode(argp->xdr, NFS4_VERIFIER_SIZE);
+	if (!p)
+		return nfserr_bad_xdr;
+	memcpy(verf->data, p, sizeof(verf->data));
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
 {
@@ -994,14 +1006,16 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 				goto out;
 			break;
 		case NFS4_CREATE_EXCLUSIVE:
-			READ_BUF(NFS4_VERIFIER_SIZE);
-			COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
+			status = nfsd4_decode_verifier4(argp, &open->op_verf);
+			if (status)
+				return status;
 			break;
 		case NFS4_CREATE_EXCLUSIVE4_1:
 			if (argp->minorversion < 1)
 				goto xdr_error;
-			READ_BUF(NFS4_VERIFIER_SIZE);
-			COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
+			status = nfsd4_decode_verifier4(argp, &open->op_verf);
+			if (status)
+				return status;
 			status = nfsd4_decode_fattr4(argp, open->op_bmval,
 						     ARRAY_SIZE(open->op_bmval),
 						     &open->op_iattr, &open->op_acl,



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 031/118] NFSD: Add helper to decode OPEN's createhow4 argument
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (29 preceding siblings ...)
  2020-11-20 20:36 ` [PATCH v2 030/118] NFSD: Add helper to decode NFSv4 verifiers Chuck Lever
@ 2020-11-20 20:36 ` Chuck Lever
  2020-11-20 20:36 ` [PATCH v2 032/118] NFSD: Add helper to decode OPEN's openflag4 argument Chuck Lever
                   ` (86 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:36 UTC (permalink / raw)
  To: linux-nfs

Refactor for clarity.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   78 +++++++++++++++++++++++++++++++----------------------
 1 file changed, 45 insertions(+), 33 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 1bbb637d4625..e8646f1e0b6a 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -893,6 +893,48 @@ nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup
 	return nfsd4_decode_component4(argp, &lookup->lo_name, &lookup->lo_len);
 }
 
+static __be32
+nfsd4_decode_createhow4(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
+{
+	__be32 status;
+
+	if (xdr_stream_decode_u32(argp->xdr, &open->op_createmode) < 0)
+		return nfserr_bad_xdr;
+	switch (open->op_createmode) {
+	case NFS4_CREATE_UNCHECKED:
+	case NFS4_CREATE_GUARDED:
+		status = nfsd4_decode_fattr4(argp, open->op_bmval,
+					     ARRAY_SIZE(open->op_bmval),
+					     &open->op_iattr, &open->op_acl,
+					     &open->op_label, &open->op_umask);
+		if (status)
+			return status;
+		break;
+	case NFS4_CREATE_EXCLUSIVE:
+		status = nfsd4_decode_verifier4(argp, &open->op_verf);
+		if (status)
+			return status;
+		break;
+	case NFS4_CREATE_EXCLUSIVE4_1:
+		if (argp->minorversion < 1)
+			return nfserr_bad_xdr;
+		status = nfsd4_decode_verifier4(argp, &open->op_verf);
+		if (status)
+			return status;
+		status = nfsd4_decode_fattr4(argp, open->op_bmval,
+					     ARRAY_SIZE(open->op_bmval),
+					     &open->op_iattr, &open->op_acl,
+					     &open->op_label, &open->op_umask);
+		if (status)
+			return status;
+		break;
+	default:
+		return nfserr_bad_xdr;
+	}
+
+	return nfs_ok;
+}
+
 static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *share_access, u32 *deleg_want, u32 *deleg_when)
 {
 	__be32 *p;
@@ -993,39 +1035,9 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 	case NFS4_OPEN_NOCREATE:
 		break;
 	case NFS4_OPEN_CREATE:
-		READ_BUF(4);
-		open->op_createmode = be32_to_cpup(p++);
-		switch (open->op_createmode) {
-		case NFS4_CREATE_UNCHECKED:
-		case NFS4_CREATE_GUARDED:
-			status = nfsd4_decode_fattr4(argp, open->op_bmval,
-						     ARRAY_SIZE(open->op_bmval),
-						     &open->op_iattr, &open->op_acl,
-						     &open->op_label, &open->op_umask);
-			if (status)
-				goto out;
-			break;
-		case NFS4_CREATE_EXCLUSIVE:
-			status = nfsd4_decode_verifier4(argp, &open->op_verf);
-			if (status)
-				return status;
-			break;
-		case NFS4_CREATE_EXCLUSIVE4_1:
-			if (argp->minorversion < 1)
-				goto xdr_error;
-			status = nfsd4_decode_verifier4(argp, &open->op_verf);
-			if (status)
-				return status;
-			status = nfsd4_decode_fattr4(argp, open->op_bmval,
-						     ARRAY_SIZE(open->op_bmval),
-						     &open->op_iattr, &open->op_acl,
-						     &open->op_label, &open->op_umask);
-			if (status)
-				goto out;
-			break;
-		default:
-			goto xdr_error;
-		}
+		status = nfsd4_decode_createhow4(argp, open);
+		if (status)
+			return status;
 		break;
 	default:
 		goto xdr_error;



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 032/118] NFSD: Add helper to decode OPEN's openflag4 argument
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (30 preceding siblings ...)
  2020-11-20 20:36 ` [PATCH v2 031/118] NFSD: Add helper to decode OPEN's createhow4 argument Chuck Lever
@ 2020-11-20 20:36 ` Chuck Lever
  2020-11-20 20:36 ` [PATCH v2 033/118] NFSD: Replace READ* macros in nfsd4_decode_share_access() Chuck Lever
                   ` (85 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:36 UTC (permalink / raw)
  To: linux-nfs

Refactor for clarity.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   38 +++++++++++++++++++++++++-------------
 1 file changed, 25 insertions(+), 13 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index e8646f1e0b6a..608cb5e38c63 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -935,6 +935,28 @@ nfsd4_decode_createhow4(struct nfsd4_compoundargs *argp, struct nfsd4_open *open
 	return nfs_ok;
 }
 
+static __be32
+nfsd4_decode_openflag4(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
+{
+	__be32 status;
+
+	if (xdr_stream_decode_u32(argp->xdr, &open->op_create) < 0)
+		return nfserr_bad_xdr;
+	switch (open->op_create) {
+	case NFS4_OPEN_NOCREATE:
+		break;
+	case NFS4_OPEN_CREATE:
+		status = nfsd4_decode_createhow4(argp, open);
+		if (status)
+			return status;
+		break;
+	default:
+		return nfserr_bad_xdr;
+	}
+
+	return nfs_ok;
+}
+
 static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *share_access, u32 *deleg_want, u32 *deleg_when)
 {
 	__be32 *p;
@@ -1029,19 +1051,9 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 	status = nfsd4_decode_opaque(argp, &open->op_owner);
 	if (status)
 		goto xdr_error;
-	READ_BUF(4);
-	open->op_create = be32_to_cpup(p++);
-	switch (open->op_create) {
-	case NFS4_OPEN_NOCREATE:
-		break;
-	case NFS4_OPEN_CREATE:
-		status = nfsd4_decode_createhow4(argp, open);
-		if (status)
-			return status;
-		break;
-	default:
-		goto xdr_error;
-	}
+	status = nfsd4_decode_openflag4(argp, open);
+	if (status)
+		return status;
 
 	/* open_claim */
 	READ_BUF(4);



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 033/118] NFSD: Replace READ* macros in nfsd4_decode_share_access()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (31 preceding siblings ...)
  2020-11-20 20:36 ` [PATCH v2 032/118] NFSD: Add helper to decode OPEN's openflag4 argument Chuck Lever
@ 2020-11-20 20:36 ` Chuck Lever
  2020-11-20 20:36 ` [PATCH v2 034/118] NFSD: Replace READ* macros in nfsd4_decode_share_deny() Chuck Lever
                   ` (84 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:36 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 608cb5e38c63..29b7c096b5f8 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -959,11 +959,10 @@ nfsd4_decode_openflag4(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 
 static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *share_access, u32 *deleg_want, u32 *deleg_when)
 {
-	__be32 *p;
 	u32 w;
 
-	READ_BUF(4);
-	w = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &w) < 0)
+		return nfserr_bad_xdr;
 	*share_access = w & NFS4_SHARE_ACCESS_MASK;
 	*deleg_want = w & NFS4_SHARE_WANT_MASK;
 	if (deleg_when)
@@ -1006,7 +1005,6 @@ static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *sh
 	      NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED):
 		return nfs_ok;
 	}
-xdr_error:
 	return nfserr_bad_xdr;
 }
 



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 034/118] NFSD: Replace READ* macros in nfsd4_decode_share_deny()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (32 preceding siblings ...)
  2020-11-20 20:36 ` [PATCH v2 033/118] NFSD: Replace READ* macros in nfsd4_decode_share_access() Chuck Lever
@ 2020-11-20 20:36 ` Chuck Lever
  2020-11-20 20:36 ` [PATCH v2 035/118] NFSD: Add helper to decode OPEN's open_claim4 argument Chuck Lever
                   ` (83 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:36 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |    9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 29b7c096b5f8..fa16bc32f3c9 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1010,16 +1010,13 @@ static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *sh
 
 static __be32 nfsd4_decode_share_deny(struct nfsd4_compoundargs *argp, u32 *x)
 {
-	__be32 *p;
-
-	READ_BUF(4);
-	*x = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, x) < 0)
+		return nfserr_bad_xdr;
 	/* Note: unlinke access bits, deny bits may be zero. */
 	if (*x & ~NFS4_SHARE_DENY_BOTH)
 		return nfserr_bad_xdr;
+
 	return nfs_ok;
-xdr_error:
-	return nfserr_bad_xdr;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 035/118] NFSD: Add helper to decode OPEN's open_claim4 argument
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (33 preceding siblings ...)
  2020-11-20 20:36 ` [PATCH v2 034/118] NFSD: Replace READ* macros in nfsd4_decode_share_deny() Chuck Lever
@ 2020-11-20 20:36 ` Chuck Lever
  2020-11-20 20:36 ` [PATCH v2 036/118] NFSD: Replace READ* macros in nfsd4_decode_open() Chuck Lever
                   ` (82 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:36 UTC (permalink / raw)
  To: linux-nfs

Refactor for clarity.

Note that op_fname is the only instance of an NFSv4 filename stored
in a struct xdr_netobj. Convert it to a u32/char * pair so that the
new nfsd4_decode_filename() helper can be used.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4proc.c |    8 ++--
 fs/nfsd/nfs4xdr.c  |   95 +++++++++++++++++++++++++++-------------------------
 fs/nfsd/xdr4.h     |    3 +-
 3 files changed, 56 insertions(+), 50 deletions(-)

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index dc5c9fb1888b..07756483aa70 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -257,8 +257,8 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru
 		 * in NFSv4 as in v3 except EXCLUSIVE4_1.
 		 */
 		current->fs->umask = open->op_umask;
-		status = do_nfsd_create(rqstp, current_fh, open->op_fname.data,
-					open->op_fname.len, &open->op_iattr,
+		status = do_nfsd_create(rqstp, current_fh, open->op_fname,
+					open->op_fnamelen, &open->op_iattr,
 					*resfh, open->op_createmode,
 					(u32 *)open->op_verf.data,
 					&open->op_truncate, &open->op_created);
@@ -283,7 +283,7 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru
 		 * a chance to an acquire a delegation if appropriate.
 		 */
 		status = nfsd_lookup(rqstp, current_fh,
-				     open->op_fname.data, open->op_fname.len, *resfh);
+				     open->op_fname, open->op_fnamelen, *resfh);
 	if (status)
 		goto out;
 	status = nfsd_check_obj_isreg(*resfh);
@@ -360,7 +360,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	bool reclaim = false;
 
 	dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p\n",
-		(int)open->op_fname.len, open->op_fname.data,
+		(int)open->op_fnamelen, open->op_fname,
 		open->op_openowner);
 
 	/* This check required by spec. */
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index fa16bc32f3c9..32929a1106a2 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1019,6 +1019,55 @@ static __be32 nfsd4_decode_share_deny(struct nfsd4_compoundargs *argp, u32 *x)
 	return nfs_ok;
 }
 
+static __be32
+nfsd4_decode_open_claim4(struct nfsd4_compoundargs *argp,
+			 struct nfsd4_open *open)
+{
+	__be32 status;
+
+	if (xdr_stream_decode_u32(argp->xdr, &open->op_claim_type) < 0)
+		return nfserr_bad_xdr;
+	switch (open->op_claim_type) {
+	case NFS4_OPEN_CLAIM_NULL:
+	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
+		status = nfsd4_decode_component4(argp, &open->op_fname,
+						 &open->op_fnamelen);
+		if (status)
+			return status;
+		break;
+	case NFS4_OPEN_CLAIM_PREVIOUS:
+		if (xdr_stream_decode_u32(argp->xdr, &open->op_delegate_type) < 0)
+			return nfserr_bad_xdr;
+		break;
+	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
+		status = nfsd4_decode_stateid4(argp, &open->op_delegate_stateid);
+		if (status)
+			return status;
+		status = nfsd4_decode_component4(argp, &open->op_fname,
+						 &open->op_fnamelen);
+		if (status)
+			return status;
+		break;
+	case NFS4_OPEN_CLAIM_FH:
+	case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
+		if (argp->minorversion < 1)
+			return nfserr_bad_xdr;
+		/* void */
+		break;
+	case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
+		if (argp->minorversion < 1)
+			return nfserr_bad_xdr;
+		status = nfsd4_decode_stateid4(argp, &open->op_delegate_stateid);
+		if (status)
+			return status;
+		break;
+	default:
+		return nfserr_bad_xdr;
+	}
+
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 {
@@ -1049,51 +1098,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 	status = nfsd4_decode_openflag4(argp, open);
 	if (status)
 		return status;
-
-	/* open_claim */
-	READ_BUF(4);
-	open->op_claim_type = be32_to_cpup(p++);
-	switch (open->op_claim_type) {
-	case NFS4_OPEN_CLAIM_NULL:
-	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
-		READ_BUF(4);
-		open->op_fname.len = be32_to_cpup(p++);
-		READ_BUF(open->op_fname.len);
-		SAVEMEM(open->op_fname.data, open->op_fname.len);
-		if ((status = check_filename(open->op_fname.data, open->op_fname.len)))
-			return status;
-		break;
-	case NFS4_OPEN_CLAIM_PREVIOUS:
-		READ_BUF(4);
-		open->op_delegate_type = be32_to_cpup(p++);
-		break;
-	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
-		status = nfsd4_decode_stateid4(argp, &open->op_delegate_stateid);
-		if (status)
-			return status;
-		READ_BUF(4);
-		open->op_fname.len = be32_to_cpup(p++);
-		READ_BUF(open->op_fname.len);
-		SAVEMEM(open->op_fname.data, open->op_fname.len);
-		if ((status = check_filename(open->op_fname.data, open->op_fname.len)))
-			return status;
-		break;
-	case NFS4_OPEN_CLAIM_FH:
-	case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
-		if (argp->minorversion < 1)
-			goto xdr_error;
-		/* void */
-		break;
-	case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
-		if (argp->minorversion < 1)
-			goto xdr_error;
-		status = nfsd4_decode_stateid4(argp, &open->op_delegate_stateid);
-		if (status)
-			return status;
-		break;
-	default:
-		goto xdr_error;
-	}
+	status = nfsd4_decode_open_claim4(argp, open);
 
 	DECODE_TAIL;
 }
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 0eb13bd603ea..6245004a9993 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -252,7 +252,8 @@ struct nfsd4_listxattrs {
 
 struct nfsd4_open {
 	u32		op_claim_type;      /* request */
-	struct xdr_netobj op_fname;	    /* request - everything but CLAIM_PREV */
+	u32		op_fnamelen;
+	char *		op_fname;	    /* request - everything but CLAIM_PREV */
 	u32		op_delegate_type;   /* request - CLAIM_PREV only */
 	stateid_t       op_delegate_stateid; /* request - response */
 	u32		op_why_no_deleg;    /* response - DELEG_NONE_EXT only */



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 036/118] NFSD: Replace READ* macros in nfsd4_decode_open()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (34 preceding siblings ...)
  2020-11-20 20:36 ` [PATCH v2 035/118] NFSD: Add helper to decode OPEN's open_claim4 argument Chuck Lever
@ 2020-11-20 20:36 ` Chuck Lever
  2020-11-20 20:37 ` [PATCH v2 037/118] NFSD: Replace READ* macros in nfsd4_decode_open_confirm() Chuck Lever
                   ` (81 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:36 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   24 ++++++++++--------------
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 32929a1106a2..f6fb167c7715 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1071,7 +1071,7 @@ nfsd4_decode_open_claim4(struct nfsd4_compoundargs *argp,
 static __be32
 nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 {
-	DECODE_HEAD;
+	__be32 status;
 	u32 dummy;
 
 	memset(open->op_bmval, 0, sizeof(open->op_bmval));
@@ -1079,28 +1079,24 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 	open->op_openowner = NULL;
 
 	open->op_xdr_error = 0;
-	/* seqid, share_access, share_deny, clientid, ownerlen */
-	READ_BUF(4);
-	open->op_seqid = be32_to_cpup(p++);
-	/* decode, yet ignore deleg_when until supported */
+	if (xdr_stream_decode_u32(argp->xdr, &open->op_seqid) < 0)
+		return nfserr_bad_xdr;
+	/* decode, yet ignore deleg_want until supported */
 	status = nfsd4_decode_share_access(argp, &open->op_share_access,
 					   &open->op_deleg_want, &dummy);
 	if (status)
-		goto xdr_error;
+		return status;
 	status = nfsd4_decode_share_deny(argp, &open->op_share_deny);
 	if (status)
-		goto xdr_error;
-	READ_BUF(sizeof(clientid_t));
-	COPYMEM(&open->op_clientid, sizeof(clientid_t));
-	status = nfsd4_decode_opaque(argp, &open->op_owner);
+		return status;
+	status = nfsd4_decode_state_owner4(argp, &open->op_clientid,
+					   &open->op_owner);
 	if (status)
-		goto xdr_error;
+		return status;
 	status = nfsd4_decode_openflag4(argp, open);
 	if (status)
 		return status;
-	status = nfsd4_decode_open_claim4(argp, open);
-
-	DECODE_TAIL;
+	return nfsd4_decode_open_claim4(argp, open);
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 037/118] NFSD: Replace READ* macros in nfsd4_decode_open_confirm()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (35 preceding siblings ...)
  2020-11-20 20:36 ` [PATCH v2 036/118] NFSD: Replace READ* macros in nfsd4_decode_open() Chuck Lever
@ 2020-11-20 20:37 ` Chuck Lever
  2020-11-20 20:37 ` [PATCH v2 038/118] NFSD: Replace READ* macros in nfsd4_decode_open_downgrade() Chuck Lever
                   ` (80 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:37 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index f6fb167c7715..ad3f392de382 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1102,7 +1102,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 static __be32
 nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf)
 {
-	DECODE_HEAD;
+	__be32 status;
 
 	if (argp->minorversion >= 1)
 		return nfserr_notsupp;
@@ -1110,10 +1110,10 @@ nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_con
 	status = nfsd4_decode_stateid4(argp, &open_conf->oc_req_stateid);
 	if (status)
 		return status;
-	READ_BUF(4);
-	open_conf->oc_seqid = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &open_conf->oc_seqid) < 0)
+		return nfserr_bad_xdr;
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 038/118] NFSD: Replace READ* macros in nfsd4_decode_open_downgrade()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (36 preceding siblings ...)
  2020-11-20 20:37 ` [PATCH v2 037/118] NFSD: Replace READ* macros in nfsd4_decode_open_confirm() Chuck Lever
@ 2020-11-20 20:37 ` Chuck Lever
  2020-11-20 20:37 ` [PATCH v2 039/118] NFSD: Replace READ* macros in nfsd4_decode_putfh() Chuck Lever
                   ` (79 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:37 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index ad3f392de382..fdc6ba702132 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1119,21 +1119,18 @@ nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_con
 static __be32
 nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down)
 {
-	DECODE_HEAD;
-		    
+	__be32 status;
+
 	status = nfsd4_decode_stateid4(argp, &open_down->od_stateid);
 	if (status)
 		return status;
-	READ_BUF(4);
-	open_down->od_seqid = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &open_down->od_seqid) < 0)
+		return nfserr_bad_xdr;
 	status = nfsd4_decode_share_access(argp, &open_down->od_share_access,
 					   &open_down->od_deleg_want, NULL);
 	if (status)
 		return status;
-	status = nfsd4_decode_share_deny(argp, &open_down->od_share_deny);
-	if (status)
-		return status;
-	DECODE_TAIL;
+	return nfsd4_decode_share_deny(argp, &open_down->od_share_deny);
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 039/118] NFSD: Replace READ* macros in nfsd4_decode_putfh()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (37 preceding siblings ...)
  2020-11-20 20:37 ` [PATCH v2 038/118] NFSD: Replace READ* macros in nfsd4_decode_open_downgrade() Chuck Lever
@ 2020-11-20 20:37 ` Chuck Lever
  2020-11-20 20:37 ` [PATCH v2 040/118] NFSD: Replace READ* macros in nfsd4_decode_read() Chuck Lever
                   ` (78 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:37 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index fdc6ba702132..1f06101a3b36 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1136,16 +1136,21 @@ nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_d
 static __be32
 nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
 {
-	DECODE_HEAD;
+	__be32 *p;
 
-	READ_BUF(4);
-	putfh->pf_fhlen = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &putfh->pf_fhlen) < 0)
+		return nfserr_bad_xdr;
 	if (putfh->pf_fhlen > NFS4_FHSIZE)
-		goto xdr_error;
-	READ_BUF(putfh->pf_fhlen);
-	SAVEMEM(putfh->pf_fhval, putfh->pf_fhlen);
+		return nfserr_bad_xdr;
+	p = xdr_inline_decode(argp->xdr, putfh->pf_fhlen);
+	if (!p)
+		return nfserr_bad_xdr;
+	putfh->pf_fhval = svcxdr_tmpalloc(argp, putfh->pf_fhlen);
+	if (!putfh->pf_fhval)
+		return nfserr_jukebox;
+	memcpy(putfh->pf_fhval, p, putfh->pf_fhlen);
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 040/118] NFSD: Replace READ* macros in nfsd4_decode_read()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (38 preceding siblings ...)
  2020-11-20 20:37 ` [PATCH v2 039/118] NFSD: Replace READ* macros in nfsd4_decode_putfh() Chuck Lever
@ 2020-11-20 20:37 ` Chuck Lever
  2020-11-20 20:37 ` [PATCH v2 041/118] NFSD: Replace READ* macros in nfsd4_decode_readdir() Chuck Lever
                   ` (77 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:37 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 1f06101a3b36..ecc922cd5d29 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1164,16 +1164,17 @@ nfsd4_decode_putpubfh(struct nfsd4_compoundargs *argp, void *p)
 static __be32
 nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
 {
-	DECODE_HEAD;
+	__be32 status;
 
 	status = nfsd4_decode_stateid4(argp, &read->rd_stateid);
 	if (status)
 		return status;
-	READ_BUF(12);
-	p = xdr_decode_hyper(p, &read->rd_offset);
-	read->rd_length = be32_to_cpup(p++);
+	if (xdr_stream_decode_u64(argp->xdr, &read->rd_offset) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &read->rd_length) < 0)
+		return nfserr_bad_xdr;
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 041/118] NFSD: Replace READ* macros in nfsd4_decode_readdir()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (39 preceding siblings ...)
  2020-11-20 20:37 ` [PATCH v2 040/118] NFSD: Replace READ* macros in nfsd4_decode_read() Chuck Lever
@ 2020-11-20 20:37 ` Chuck Lever
  2020-11-20 20:37 ` [PATCH v2 042/118] NFSD: Replace READ* macros in nfsd4_decode_remove() Chuck Lever
                   ` (76 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:37 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index ecc922cd5d29..3a7b615aef62 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1180,17 +1180,22 @@ nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
 static __be32
 nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir)
 {
-	DECODE_HEAD;
+	__be32 status;
 
-	READ_BUF(24);
-	p = xdr_decode_hyper(p, &readdir->rd_cookie);
-	COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data));
-	readdir->rd_dircount = be32_to_cpup(p++);
-	readdir->rd_maxcount = be32_to_cpup(p++);
-	if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval)))
-		goto out;
+	if (xdr_stream_decode_u64(argp->xdr, &readdir->rd_cookie) < 0)
+		return nfserr_bad_xdr;
+	status = nfsd4_decode_verifier4(argp, &readdir->rd_verf);
+	if (status)
+		return status;
+	if (xdr_stream_decode_u32(argp->xdr, &readdir->rd_dircount) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &readdir->rd_maxcount) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_uint32_array(argp->xdr, readdir->rd_bmval,
+					   ARRAY_SIZE(readdir->rd_bmval)) < 0)
+		return nfserr_bad_xdr;
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 042/118] NFSD: Replace READ* macros in nfsd4_decode_remove()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (40 preceding siblings ...)
  2020-11-20 20:37 ` [PATCH v2 041/118] NFSD: Replace READ* macros in nfsd4_decode_readdir() Chuck Lever
@ 2020-11-20 20:37 ` Chuck Lever
  2020-11-20 20:37 ` [PATCH v2 043/118] NFSD: Replace READ* macros in nfsd4_decode_rename() Chuck Lever
                   ` (75 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:37 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 3a7b615aef62..964cfe3d9409 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1201,16 +1201,7 @@ nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *read
 static __be32
 nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove)
 {
-	DECODE_HEAD;
-
-	READ_BUF(4);
-	remove->rm_namelen = be32_to_cpup(p++);
-	READ_BUF(remove->rm_namelen);
-	SAVEMEM(remove->rm_name, remove->rm_namelen);
-	if ((status = check_filename(remove->rm_name, remove->rm_namelen)))
-		return status;
-
-	DECODE_TAIL;
+	return nfsd4_decode_component4(argp, &remove->rm_name, &remove->rm_namelen);
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 043/118] NFSD: Replace READ* macros in nfsd4_decode_rename()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (41 preceding siblings ...)
  2020-11-20 20:37 ` [PATCH v2 042/118] NFSD: Replace READ* macros in nfsd4_decode_remove() Chuck Lever
@ 2020-11-20 20:37 ` Chuck Lever
  2020-11-20 20:37 ` [PATCH v2 044/118] NFSD: Replace READ* macros in nfsd4_decode_renew() Chuck Lever
                   ` (74 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:37 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   18 ++++--------------
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 964cfe3d9409..0c78f115dac9 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1207,22 +1207,12 @@ nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove
 static __be32
 nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename)
 {
-	DECODE_HEAD;
+	__be32 status;
 
-	READ_BUF(4);
-	rename->rn_snamelen = be32_to_cpup(p++);
-	READ_BUF(rename->rn_snamelen);
-	SAVEMEM(rename->rn_sname, rename->rn_snamelen);
-	READ_BUF(4);
-	rename->rn_tnamelen = be32_to_cpup(p++);
-	READ_BUF(rename->rn_tnamelen);
-	SAVEMEM(rename->rn_tname, rename->rn_tnamelen);
-	if ((status = check_filename(rename->rn_sname, rename->rn_snamelen)))
-		return status;
-	if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen)))
+	status = nfsd4_decode_component4(argp, &rename->rn_sname, &rename->rn_snamelen);
+	if (status)
 		return status;
-
-	DECODE_TAIL;
+	return nfsd4_decode_component4(argp, &rename->rn_tname, &rename->rn_tnamelen);
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 044/118] NFSD: Replace READ* macros in nfsd4_decode_renew()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (42 preceding siblings ...)
  2020-11-20 20:37 ` [PATCH v2 043/118] NFSD: Replace READ* macros in nfsd4_decode_rename() Chuck Lever
@ 2020-11-20 20:37 ` Chuck Lever
  2020-11-20 20:37 ` [PATCH v2 045/118] NFSD: Replace READ* macros in nfsd4_decode_secinfo() Chuck Lever
                   ` (73 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:37 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 0c78f115dac9..19e8a61c8409 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1218,15 +1218,7 @@ nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename
 static __be32
 nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
 {
-	DECODE_HEAD;
-
-	if (argp->minorversion >= 1)
-		return nfserr_notsupp;
-
-	READ_BUF(sizeof(clientid_t));
-	COPYMEM(clientid, sizeof(clientid_t));
-
-	DECODE_TAIL;
+	return nfsd4_decode_clientid4(argp, clientid);
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 045/118] NFSD: Replace READ* macros in nfsd4_decode_secinfo()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (43 preceding siblings ...)
  2020-11-20 20:37 ` [PATCH v2 044/118] NFSD: Replace READ* macros in nfsd4_decode_renew() Chuck Lever
@ 2020-11-20 20:37 ` Chuck Lever
  2020-11-20 20:37 ` [PATCH v2 046/118] NFSD: Replace READ* macros in nfsd4_decode_setclientid() Chuck Lever
                   ` (72 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:37 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 19e8a61c8409..98297182118d 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1225,16 +1225,7 @@ static __be32
 nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
 		     struct nfsd4_secinfo *secinfo)
 {
-	DECODE_HEAD;
-
-	READ_BUF(4);
-	secinfo->si_namelen = be32_to_cpup(p++);
-	READ_BUF(secinfo->si_namelen);
-	SAVEMEM(secinfo->si_name, secinfo->si_namelen);
-	status = check_filename(secinfo->si_name, secinfo->si_namelen);
-	if (status)
-		return status;
-	DECODE_TAIL;
+	return nfsd4_decode_component4(argp, &secinfo->si_name, &secinfo->si_namelen);
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 046/118] NFSD: Replace READ* macros in nfsd4_decode_setclientid()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (44 preceding siblings ...)
  2020-11-20 20:37 ` [PATCH v2 045/118] NFSD: Replace READ* macros in nfsd4_decode_secinfo() Chuck Lever
@ 2020-11-20 20:37 ` Chuck Lever
  2020-11-20 20:37 ` [PATCH v2 047/118] NFSD: Replace READ* macros in nfsd4_decode_setclientid_confirm() Chuck Lever
                   ` (71 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:37 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   47 +++++++++++++++++++++++++++++++----------------
 1 file changed, 31 insertions(+), 16 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 98297182118d..bd950ad7021c 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1256,31 +1256,46 @@ nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *seta
 static __be32
 nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid)
 {
-	DECODE_HEAD;
+	__be32 *p, status;
 
 	if (argp->minorversion >= 1)
 		return nfserr_notsupp;
 
-	READ_BUF(NFS4_VERIFIER_SIZE);
-	COPYMEM(setclientid->se_verf.data, NFS4_VERIFIER_SIZE);
-
+	status = nfsd4_decode_verifier4(argp, &setclientid->se_verf);
+	if (status)
+		return status;
 	status = nfsd4_decode_opaque(argp, &setclientid->se_name);
 	if (status)
+		return status;
+	if (xdr_stream_decode_u32(argp->xdr, &setclientid->se_callback_prog) < 0)
 		return nfserr_bad_xdr;
-	READ_BUF(8);
-	setclientid->se_callback_prog = be32_to_cpup(p++);
-	setclientid->se_callback_netid_len = be32_to_cpup(p++);
-	READ_BUF(setclientid->se_callback_netid_len);
-	SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len);
-	READ_BUF(4);
-	setclientid->se_callback_addr_len = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &setclientid->se_callback_netid_len) < 0)
+		return nfserr_bad_xdr;
+	p = xdr_inline_decode(argp->xdr, setclientid->se_callback_netid_len);
+	if (!p)
+		return nfserr_bad_xdr;
+	setclientid->se_callback_netid_val = svcxdr_tmpalloc(argp,
+						setclientid->se_callback_netid_len);
+	if (!setclientid->se_callback_netid_val)
+		return nfserr_jukebox;
+	memcpy(setclientid->se_callback_netid_val, p,
+	       setclientid->se_callback_netid_len);
 
-	READ_BUF(setclientid->se_callback_addr_len);
-	SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len);
-	READ_BUF(4);
-	setclientid->se_callback_ident = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &setclientid->se_callback_addr_len) < 0)
+		return nfserr_bad_xdr;
+	p = xdr_inline_decode(argp->xdr, setclientid->se_callback_addr_len);
+	if (!p)
+		return nfserr_bad_xdr;
+	setclientid->se_callback_addr_val = svcxdr_tmpalloc(argp,
+						setclientid->se_callback_addr_len);
+	if (!setclientid->se_callback_addr_val)
+		return nfserr_jukebox;
+	memcpy(setclientid->se_callback_addr_val, p,
+	       setclientid->se_callback_addr_len);
+	if (xdr_stream_decode_u32(argp->xdr, &setclientid->se_callback_ident) < 0)
+		return nfserr_bad_xdr;
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 047/118] NFSD: Replace READ* macros in nfsd4_decode_setclientid_confirm()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (45 preceding siblings ...)
  2020-11-20 20:37 ` [PATCH v2 046/118] NFSD: Replace READ* macros in nfsd4_decode_setclientid() Chuck Lever
@ 2020-11-20 20:37 ` Chuck Lever
  2020-11-20 20:38 ` [PATCH v2 048/118] NFSD: Replace READ* macros in nfsd4_decode_verify() Chuck Lever
                   ` (70 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:37 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index bd950ad7021c..5266a5a1bdc6 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1301,16 +1301,15 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient
 static __be32
 nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c)
 {
-	DECODE_HEAD;
+	__be32 status;
 
 	if (argp->minorversion >= 1)
 		return nfserr_notsupp;
 
-	READ_BUF(8 + NFS4_VERIFIER_SIZE);
-	COPYMEM(&scd_c->sc_clientid, 8);
-	COPYMEM(&scd_c->sc_confirm, NFS4_VERIFIER_SIZE);
-
-	DECODE_TAIL;
+	status = nfsd4_decode_clientid4(argp, &scd_c->sc_clientid);
+	if (status)
+		return status;
+	return nfsd4_decode_verifier4(argp, &scd_c->sc_confirm);
 }
 
 /* Also used for NVERIFY */



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 048/118] NFSD: Replace READ* macros in nfsd4_decode_verify()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (46 preceding siblings ...)
  2020-11-20 20:37 ` [PATCH v2 047/118] NFSD: Replace READ* macros in nfsd4_decode_setclientid_confirm() Chuck Lever
@ 2020-11-20 20:38 ` Chuck Lever
  2020-11-20 20:38 ` [PATCH v2 049/118] NFSD: Replace READ* macros in nfsd4_decode_write() Chuck Lever
                   ` (69 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:38 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 5266a5a1bdc6..69262f9ea5a5 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1316,20 +1316,26 @@ nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_s
 static __be32
 nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify)
 {
-	DECODE_HEAD;
+	__be32 *p;
 
-	if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval)))
-		goto out;
+	if (xdr_stream_decode_uint32_array(argp->xdr, verify->ve_bmval,
+					   ARRAY_SIZE(verify->ve_bmval)) < 0)
+		return nfserr_bad_xdr;
 
 	/* For convenience's sake, we compare raw xdr'd attributes in
 	 * nfsd4_proc_verify */
 
-	READ_BUF(4);
-	verify->ve_attrlen = be32_to_cpup(p++);
-	READ_BUF(verify->ve_attrlen);
-	SAVEMEM(verify->ve_attrval, verify->ve_attrlen);
+	if (xdr_stream_decode_u32(argp->xdr, &verify->ve_attrlen) < 0)
+		return nfserr_bad_xdr;
+	p = xdr_inline_decode(argp->xdr, verify->ve_attrlen);
+	if (!p)
+		return nfserr_bad_xdr;
+	verify->ve_attrval = svcxdr_tmpalloc(argp, verify->ve_attrlen);
+	if (!verify->ve_attrval)
+		return nfserr_jukebox;
+	memcpy(verify->ve_attrval, p, verify->ve_attrlen);
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 049/118] NFSD: Replace READ* macros in nfsd4_decode_write()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (47 preceding siblings ...)
  2020-11-20 20:38 ` [PATCH v2 048/118] NFSD: Replace READ* macros in nfsd4_decode_verify() Chuck Lever
@ 2020-11-20 20:38 ` Chuck Lever
  2020-11-20 20:38 ` [PATCH v2 050/118] NFSD: Replace READ* macros in nfsd4_decode_release_lockowner() Chuck Lever
                   ` (68 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:38 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 69262f9ea5a5..65c34bb52d16 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1341,22 +1341,23 @@ nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify
 static __be32
 nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
 {
-	DECODE_HEAD;
+	__be32 status;
 
 	status = nfsd4_decode_stateid4(argp, &write->wr_stateid);
 	if (status)
 		return status;
-	READ_BUF(16);
-	p = xdr_decode_hyper(p, &write->wr_offset);
-	write->wr_stable_how = be32_to_cpup(p++);
+	if (xdr_stream_decode_u64(argp->xdr, &write->wr_offset) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &write->wr_stable_how) < 0)
+		return nfserr_bad_xdr;
 	if (write->wr_stable_how > NFS_FILE_SYNC)
-		goto xdr_error;
-	write->wr_buflen = be32_to_cpup(p++);
-
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &write->wr_buflen) < 0)
+		return nfserr_bad_xdr;
 	if (!xdr_stream_subsegment(argp->xdr, &write->wr_payload, write->wr_buflen))
-		goto xdr_error;
+		return nfserr_bad_xdr;
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 050/118] NFSD: Replace READ* macros in nfsd4_decode_release_lockowner()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (48 preceding siblings ...)
  2020-11-20 20:38 ` [PATCH v2 049/118] NFSD: Replace READ* macros in nfsd4_decode_write() Chuck Lever
@ 2020-11-20 20:38 ` Chuck Lever
  2020-11-20 20:38 ` [PATCH v2 051/118] NFSD: Replace READ* macros in nfsd4_decode_cb_sec() Chuck Lever
                   ` (67 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:38 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 65c34bb52d16..8e2609658904 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1363,20 +1363,20 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
 static __be32
 nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner)
 {
-	DECODE_HEAD;
+	__be32 status;
 
 	if (argp->minorversion >= 1)
 		return nfserr_notsupp;
 
-	READ_BUF(12);
-	COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t));
-	rlockowner->rl_owner.len = be32_to_cpup(p++);
-	READ_BUF(rlockowner->rl_owner.len);
-	READMEM(rlockowner->rl_owner.data, rlockowner->rl_owner.len);
+	status = nfsd4_decode_state_owner4(argp, &rlockowner->rl_clientid,
+					   &rlockowner->rl_owner);
+	if (status)
+		return status;
 
 	if (argp->minorversion && !zero_clientid(&rlockowner->rl_clientid))
 		return nfserr_inval;
-	DECODE_TAIL;
+
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 051/118] NFSD: Replace READ* macros in nfsd4_decode_cb_sec()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (49 preceding siblings ...)
  2020-11-20 20:38 ` [PATCH v2 050/118] NFSD: Replace READ* macros in nfsd4_decode_release_lockowner() Chuck Lever
@ 2020-11-20 20:38 ` Chuck Lever
  2020-11-20 20:38 ` [PATCH v2 052/118] NFSD: Replace READ* macros in nfsd4_decode_backchannel_ctl() Chuck Lever
                   ` (66 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:38 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |  165 ++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 107 insertions(+), 58 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 8e2609658904..d9c57b2f3fcf 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -210,6 +210,25 @@ static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
  * NFSv4 basic data type decoders
  */
 
+/*
+ * This helper handles variable-length opaques which belong to protocol
+ * elements that this implementation does not support.
+ */
+static __be32
+nfsd4_decode_ignored_string(struct nfsd4_compoundargs *argp, u32 maxlen)
+{
+	u32 len;
+
+	if (xdr_stream_decode_u32(argp->xdr, &len) < 0)
+		return nfserr_bad_xdr;
+	if (maxlen && len > maxlen)
+		return nfserr_bad_xdr;
+	if (!xdr_inline_decode(argp->xdr, len))
+		return nfserr_bad_xdr;
+
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o)
 {
@@ -590,87 +609,117 @@ nfsd4_decode_stateid4(struct nfsd4_compoundargs *argp, stateid_t *sid)
 	return nfs_ok;
 }
 
-static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs)
+/* Defined in Appendix A of RFC 5531 */
+static __be32
+nfsd4_decode_authsys_parms(struct nfsd4_compoundargs *argp,
+			   struct nfsd4_cb_sec *cbs)
 {
-	DECODE_HEAD;
-	struct user_namespace *userns = nfsd_user_namespace(argp->rqstp);
-	u32 dummy, uid, gid;
-	char *machine_name;
-	int i;
-	int nr_secflavs;
+	u32 stamp, gidcount, uid, gid;
+	__be32 *p, status;
+
+	if (xdr_stream_decode_u32(argp->xdr, &stamp) < 0)
+		return nfserr_bad_xdr;
+	/* machine name */
+	status = nfsd4_decode_ignored_string(argp, 255);
+	if (status)
+		return status;
+	if (xdr_stream_decode_u32(argp->xdr, &uid) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &gid) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &gidcount) < 0)
+		return nfserr_bad_xdr;
+	if (gidcount > 16)
+		return nfserr_bad_xdr;
+	p = xdr_inline_decode(argp->xdr, gidcount << 2);
+	if (!p)
+		return nfserr_bad_xdr;
+	if (cbs->flavor == (u32)(-1)) {
+		struct user_namespace *userns = nfsd_user_namespace(argp->rqstp);
+
+		kuid_t kuid = make_kuid(userns, uid);
+		kgid_t kgid = make_kgid(userns, gid);
+		if (uid_valid(kuid) && gid_valid(kgid)) {
+			cbs->uid = kuid;
+			cbs->gid = kgid;
+			cbs->flavor = RPC_AUTH_UNIX;
+		} else {
+			dprintk("RPC_AUTH_UNIX with invalid uid or gid, ignoring!\n");
+		}
+	}
+
+	return nfs_ok;
+}
+
+static __be32
+nfsd4_decode_gss_cb_handles4(struct nfsd4_compoundargs *argp,
+			     struct nfsd4_cb_sec *cbs)
+{
+	__be32 status;
+	u32 service;
+
+	dprintk("RPC_AUTH_GSS callback secflavor not supported!\n");
+
+	if (xdr_stream_decode_u32(argp->xdr, &service) < 0)
+		return nfserr_bad_xdr;
+	if (service < RPC_GSS_SVC_NONE || service > RPC_GSS_SVC_PRIVACY)
+		return nfserr_bad_xdr;
+	/* gcbp_handle_from_server */
+	status = nfsd4_decode_ignored_string(argp, 0);
+	if (status)
+		return status;
+	/* gcbp_handle_from_client */
+	status = nfsd4_decode_ignored_string(argp, 0);
+	if (status)
+		return status;
+
+	return nfs_ok;
+}
+
+/* a counted array of callback_sec_parms4 */
+static __be32
+nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs)
+{
+	u32 i, secflavor, nr_secflavs;
+	__be32 status;
 
 	/* callback_sec_params4 */
-	READ_BUF(4);
-	nr_secflavs = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &nr_secflavs) < 0)
+		return nfserr_bad_xdr;
 	if (nr_secflavs)
 		cbs->flavor = (u32)(-1);
 	else
 		/* Is this legal? Be generous, take it to mean AUTH_NONE: */
 		cbs->flavor = 0;
+
 	for (i = 0; i < nr_secflavs; ++i) {
-		READ_BUF(4);
-		dummy = be32_to_cpup(p++);
-		switch (dummy) {
+		if (xdr_stream_decode_u32(argp->xdr, &secflavor) < 0)
+			return nfserr_bad_xdr;
+		switch (secflavor) {
 		case RPC_AUTH_NULL:
-			/* Nothing to read */
+			/* void */
 			if (cbs->flavor == (u32)(-1))
 				cbs->flavor = RPC_AUTH_NULL;
 			break;
 		case RPC_AUTH_UNIX:
-			READ_BUF(8);
-			/* stamp */
-			dummy = be32_to_cpup(p++);
-
-			/* machine name */
-			dummy = be32_to_cpup(p++);
-			READ_BUF(dummy);
-			SAVEMEM(machine_name, dummy);
-
-			/* uid, gid */
-			READ_BUF(8);
-			uid = be32_to_cpup(p++);
-			gid = be32_to_cpup(p++);
-
-			/* more gids */
-			READ_BUF(4);
-			dummy = be32_to_cpup(p++);
-			READ_BUF(dummy * 4);
-			if (cbs->flavor == (u32)(-1)) {
-				kuid_t kuid = make_kuid(userns, uid);
-				kgid_t kgid = make_kgid(userns, gid);
-				if (uid_valid(kuid) && gid_valid(kgid)) {
-					cbs->uid = kuid;
-					cbs->gid = kgid;
-					cbs->flavor = RPC_AUTH_UNIX;
-				} else {
-					dprintk("RPC_AUTH_UNIX with invalid"
-						"uid or gid ignoring!\n");
-				}
-			}
+			status = nfsd4_decode_authsys_parms(argp, cbs);
+			if (status)
+				return status;
 			break;
 		case RPC_AUTH_GSS:
-			dprintk("RPC_AUTH_GSS callback secflavor "
-				"not supported!\n");
-			READ_BUF(8);
-			/* gcbp_service */
-			dummy = be32_to_cpup(p++);
-			/* gcbp_handle_from_server */
-			dummy = be32_to_cpup(p++);
-			READ_BUF(dummy);
-			p += XDR_QUADLEN(dummy);
-			/* gcbp_handle_from_client */
-			READ_BUF(4);
-			dummy = be32_to_cpup(p++);
-			READ_BUF(dummy);
+			status = nfsd4_decode_gss_cb_handles4(argp, cbs);
+			if (status)
+				return status;
 			break;
 		default:
-			dprintk("Illegal callback secflavor\n");
 			return nfserr_inval;
 		}
 	}
-	DECODE_TAIL;
+
+	return nfs_ok;
 }
 
+
 /*
  * NFSv4 operation argument decoders
  */



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 052/118] NFSD: Replace READ* macros in nfsd4_decode_backchannel_ctl()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (50 preceding siblings ...)
  2020-11-20 20:38 ` [PATCH v2 051/118] NFSD: Replace READ* macros in nfsd4_decode_cb_sec() Chuck Lever
@ 2020-11-20 20:38 ` Chuck Lever
  2020-11-20 20:38 ` [PATCH v2 053/118] NFSD: Replace READ* macros in nfsd4_decode_bind_conn_to_session() Chuck Lever
                   ` (65 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:38 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index d9c57b2f3fcf..82282fceec5d 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -733,17 +733,6 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp,
 	return nfs_ok;
 }
 
-static __be32 nfsd4_decode_backchannel_ctl(struct nfsd4_compoundargs *argp, struct nfsd4_backchannel_ctl *bc)
-{
-	DECODE_HEAD;
-
-	READ_BUF(4);
-	bc->bc_cb_program = be32_to_cpup(p++);
-	nfsd4_decode_cb_sec(argp, &bc->bc_cb_sec);
-
-	DECODE_TAIL;
-}
-
 static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts)
 {
 	DECODE_HEAD;
@@ -1428,6 +1417,13 @@ nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_rel
 	return nfs_ok;
 }
 
+static __be32 nfsd4_decode_backchannel_ctl(struct nfsd4_compoundargs *argp, struct nfsd4_backchannel_ctl *bc)
+{
+	if (xdr_stream_decode_u32(argp->xdr, &bc->bc_cb_program) < 0)
+		return nfserr_bad_xdr;
+	return nfsd4_decode_cb_sec(argp, &bc->bc_cb_sec);
+}
+
 static __be32
 nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
 			 struct nfsd4_exchange_id *exid)



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 053/118] NFSD: Replace READ* macros in nfsd4_decode_bind_conn_to_session()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (51 preceding siblings ...)
  2020-11-20 20:38 ` [PATCH v2 052/118] NFSD: Replace READ* macros in nfsd4_decode_backchannel_ctl() Chuck Lever
@ 2020-11-20 20:38 ` Chuck Lever
  2020-11-20 20:38 ` [PATCH v2 054/118] NFSD: Add a separate decoder to handle state_protect_ops Chuck Lever
                   ` (64 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:38 UTC (permalink / raw)
  To: linux-nfs

A dedicated sessionid4 decoder is introduced that will be used by
other operation decoders in subsequent patches.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   41 +++++++++++++++++++++++++++++------------
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 82282fceec5d..48cb409f11c2 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -609,6 +609,19 @@ nfsd4_decode_stateid4(struct nfsd4_compoundargs *argp, stateid_t *sid)
 	return nfs_ok;
 }
 
+static __be32
+nfsd4_decode_sessionid(struct nfsd4_compoundargs *argp,
+		       struct nfs4_sessionid *sessionid)
+{
+	__be32 *p;
+
+	p = xdr_inline_decode(argp->xdr, NFS4_MAX_SESSIONID_LEN);
+	if (!p)
+		return nfserr_bad_xdr;
+	memcpy(sessionid->data, p, sizeof(sessionid->data));
+	return nfs_ok;
+}
+
 /* Defined in Appendix A of RFC 5531 */
 static __be32
 nfsd4_decode_authsys_parms(struct nfsd4_compoundargs *argp,
@@ -733,18 +746,6 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp,
 	return nfs_ok;
 }
 
-static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts)
-{
-	DECODE_HEAD;
-
-	READ_BUF(NFS4_MAX_SESSIONID_LEN + 8);
-	COPYMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN);
-	bcts->dir = be32_to_cpup(p++);
-	/* XXX: skipping ctsa_use_conn_in_rdma_mode.  Perhaps Tom Tucker
-	 * could help us figure out we should be using it. */
-	DECODE_TAIL;
-}
-
 static __be32
 nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
 {
@@ -1424,6 +1425,22 @@ static __be32 nfsd4_decode_backchannel_ctl(struct nfsd4_compoundargs *argp, stru
 	return nfsd4_decode_cb_sec(argp, &bc->bc_cb_sec);
 }
 
+static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts)
+{
+	u32 use_conn_in_rdma_mode;
+	__be32 status;
+
+	status = nfsd4_decode_sessionid(argp, &bcts->sessionid);
+	if (status)
+		return status;
+	if (xdr_stream_decode_u32(argp->xdr, &bcts->dir) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &use_conn_in_rdma_mode) < 0)
+		return nfserr_bad_xdr;
+
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
 			 struct nfsd4_exchange_id *exid)



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 054/118] NFSD: Add a separate decoder to handle state_protect_ops
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (52 preceding siblings ...)
  2020-11-20 20:38 ` [PATCH v2 053/118] NFSD: Replace READ* macros in nfsd4_decode_bind_conn_to_session() Chuck Lever
@ 2020-11-20 20:38 ` Chuck Lever
  2020-11-20 20:38 ` [PATCH v2 055/118] NFSD: Add a separate decoder for ssv_sp_parms Chuck Lever
                   ` (63 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:38 UTC (permalink / raw)
  To: linux-nfs

Refactor for clarity and de-duplication of code.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   66 ++++++++++++++++++-----------------------------------
 1 file changed, 23 insertions(+), 43 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 48cb409f11c2..a74d86564eb7 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -313,32 +313,6 @@ nfsd4_decode_verifier4(struct nfsd4_compoundargs *argp, nfs4_verifier *verf)
 	return nfs_ok;
 }
 
-static __be32
-nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
-{
-	u32 bmlen;
-	DECODE_HEAD;
-
-	bmval[0] = 0;
-	bmval[1] = 0;
-	bmval[2] = 0;
-
-	READ_BUF(4);
-	bmlen = be32_to_cpup(p++);
-	if (bmlen > 1000)
-		goto xdr_error;
-
-	READ_BUF(bmlen << 2);
-	if (bmlen > 0)
-		bmval[0] = be32_to_cpup(p++);
-	if (bmlen > 1)
-		bmval[1] = be32_to_cpup(p++);
-	if (bmlen > 2)
-		bmval[2] = be32_to_cpup(p++);
-
-	DECODE_TAIL;
-}
-
 static __be32
 nfsd4_decode_nfsace4(struct nfsd4_compoundargs *argp, struct nfs4_ace *ace)
 {
@@ -1441,12 +1415,25 @@ static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp,
 	return nfs_ok;
 }
 
+static __be32 nfsd4_decode_state_protect_ops(struct nfsd4_compoundargs *argp,
+					     u32 *must_enforce, u32 me_len,
+					     u32 *must_allow, u32 ma_len)
+{
+	if (xdr_stream_decode_uint32_array(argp->xdr, must_enforce, me_len) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_uint32_array(argp->xdr, must_allow, ma_len) < 0)
+		return nfserr_bad_xdr;
+
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
 			 struct nfsd4_exchange_id *exid)
 {
 	int dummy, tmp;
 	DECODE_HEAD;
+	u32 bm[3];
 
 	READ_BUF(NFS4_VERIFIER_SIZE);
 	COPYMEM(exid->verifier.data, NFS4_VERIFIER_SIZE);
@@ -1465,27 +1452,20 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
 	case SP4_NONE:
 		break;
 	case SP4_MACH_CRED:
-		/* spo_must_enforce */
-		status = nfsd4_decode_bitmap(argp,
-					exid->spo_must_enforce);
-		if (status)
-			goto out;
-		/* spo_must_allow */
-		status = nfsd4_decode_bitmap(argp, exid->spo_must_allow);
+		status = nfsd4_decode_state_protect_ops(argp,
+							exid->spo_must_enforce,
+							ARRAY_SIZE(exid->spo_must_enforce),
+							exid->spo_must_allow,
+							ARRAY_SIZE(exid->spo_must_allow));
 		if (status)
-			goto out;
+			return status;
 		break;
 	case SP4_SSV:
 		/* ssp_ops */
-		READ_BUF(4);
-		dummy = be32_to_cpup(p++);
-		READ_BUF(dummy * 4);
-		p += dummy;
-
-		READ_BUF(4);
-		dummy = be32_to_cpup(p++);
-		READ_BUF(dummy * 4);
-		p += dummy;
+		status = nfsd4_decode_state_protect_ops(argp, bm, ARRAY_SIZE(bm),
+							bm, ARRAY_SIZE(bm));
+		if (status)
+			return status;
 
 		/* ssp_hash_algs<> */
 		READ_BUF(4);



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 055/118] NFSD: Add a separate decoder for ssv_sp_parms
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (53 preceding siblings ...)
  2020-11-20 20:38 ` [PATCH v2 054/118] NFSD: Add a separate decoder to handle state_protect_ops Chuck Lever
@ 2020-11-20 20:38 ` Chuck Lever
  2020-11-20 20:38 ` [PATCH v2 056/118] NFSD: Add a helper to decode state_protect4_a Chuck Lever
                   ` (62 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:38 UTC (permalink / raw)
  To: linux-nfs

Refactor for clarity.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   71 ++++++++++++++++++++++++++++++++---------------------
 1 file changed, 43 insertions(+), 28 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index a74d86564eb7..dc39b004bcb4 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1427,13 +1427,53 @@ static __be32 nfsd4_decode_state_protect_ops(struct nfsd4_compoundargs *argp,
 	return nfs_ok;
 }
 
+/*
+ * This implementation currently does not support SP4_SSV.
+ * This decoder simply skips over these arguments.
+ */
+static __be32 nfsd4_decode_ssv_sp_parms(struct nfsd4_compoundargs *argp)
+{
+	u32 bm[3], count, window, num_gss_handles;
+	__be32 status;
+
+	/* ssp_ops */
+	status = nfsd4_decode_state_protect_ops(argp, bm, ARRAY_SIZE(bm),
+						bm, ARRAY_SIZE(bm));
+	if (status)
+		return status;
+
+	/* ssp_hash_algs<> */
+	if (xdr_stream_decode_u32(argp->xdr, &count) < 0)
+		return nfserr_bad_xdr;
+	while (count--) {
+		status = nfsd4_decode_ignored_string(argp, 0);
+		if (status)
+			return status;
+	}
+
+	/* ssp_encr_algs<> */
+	if (xdr_stream_decode_u32(argp->xdr, &count) < 0)
+		return nfserr_bad_xdr;
+	while (count--) {
+		status = nfsd4_decode_ignored_string(argp, 0);
+		if (status)
+			return status;
+	}
+
+	if (xdr_stream_decode_u32(argp->xdr, &window) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &num_gss_handles) < 0)
+		return nfserr_bad_xdr;
+
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
 			 struct nfsd4_exchange_id *exid)
 {
-	int dummy, tmp;
 	DECODE_HEAD;
-	u32 bm[3];
+	int dummy;
 
 	READ_BUF(NFS4_VERIFIER_SIZE);
 	COPYMEM(exid->verifier.data, NFS4_VERIFIER_SIZE);
@@ -1461,34 +1501,9 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
 			return status;
 		break;
 	case SP4_SSV:
-		/* ssp_ops */
-		status = nfsd4_decode_state_protect_ops(argp, bm, ARRAY_SIZE(bm),
-							bm, ARRAY_SIZE(bm));
+		status = nfsd4_decode_ssv_sp_parms(argp);
 		if (status)
 			return status;
-
-		/* ssp_hash_algs<> */
-		READ_BUF(4);
-		tmp = be32_to_cpup(p++);
-		while (tmp--) {
-			READ_BUF(4);
-			dummy = be32_to_cpup(p++);
-			READ_BUF(dummy);
-			p += XDR_QUADLEN(dummy);
-		}
-
-		/* ssp_encr_algs<> */
-		READ_BUF(4);
-		tmp = be32_to_cpup(p++);
-		while (tmp--) {
-			READ_BUF(4);
-			dummy = be32_to_cpup(p++);
-			READ_BUF(dummy);
-			p += XDR_QUADLEN(dummy);
-		}
-
-		/* ignore ssp_window and ssp_num_gss_handles: */
-		READ_BUF(8);
 		break;
 	default:
 		goto xdr_error;



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 056/118] NFSD: Add a helper to decode state_protect4_a
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (54 preceding siblings ...)
  2020-11-20 20:38 ` [PATCH v2 055/118] NFSD: Add a separate decoder for ssv_sp_parms Chuck Lever
@ 2020-11-20 20:38 ` Chuck Lever
  2020-11-20 20:38 ` [PATCH v2 057/118] NFSD: Add a helper to decode nfs_impl_id4 Chuck Lever
                   ` (61 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:38 UTC (permalink / raw)
  To: linux-nfs

Refactor for clarity.

Also, remove a stale comment. Commit ed94164398c9 ("nfsd: implement
machine credential support for some operations") added support for
SP4_MACH_CRED, so state_protect_a is no longer completely ignored.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4state.c |    2 +-
 fs/nfsd/nfs4xdr.c   |   45 +++++++++++++++++++++++++++------------------
 fs/nfsd/xdr4.h      |    2 +-
 3 files changed, 29 insertions(+), 20 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index d7f27ed6b794..be6dcc4c2ab0 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3066,7 +3066,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
 	rpc_ntop(sa, addr_str, sizeof(addr_str));
 	dprintk("%s rqstp=%p exid=%p clname.len=%u clname.data=%p "
-		"ip_addr=%s flags %x, spa_how %d\n",
+		"ip_addr=%s flags %x, spa_how %u\n",
 		__func__, rqstp, exid, exid->clname.len, exid->clname.data,
 		addr_str, exid->flags, exid->spa_how);
 
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index dc39b004bcb4..bb2e83ad61a4 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1468,26 +1468,13 @@ static __be32 nfsd4_decode_ssv_sp_parms(struct nfsd4_compoundargs *argp)
 	return nfs_ok;
 }
 
-static __be32
-nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
-			 struct nfsd4_exchange_id *exid)
+static __be32 nfsd4_decode_state_protect4_a(struct nfsd4_compoundargs *argp,
+					    struct nfsd4_exchange_id *exid)
 {
-	DECODE_HEAD;
-	int dummy;
-
-	READ_BUF(NFS4_VERIFIER_SIZE);
-	COPYMEM(exid->verifier.data, NFS4_VERIFIER_SIZE);
+	__be32 status;
 
-	status = nfsd4_decode_opaque(argp, &exid->clname);
-	if (status)
+	if (xdr_stream_decode_u32(argp->xdr, &exid->spa_how) < 0)
 		return nfserr_bad_xdr;
-
-	READ_BUF(4);
-	exid->flags = be32_to_cpup(p++);
-
-	/* Ignore state_protect4_a */
-	READ_BUF(4);
-	exid->spa_how = be32_to_cpup(p++);
 	switch (exid->spa_how) {
 	case SP4_NONE:
 		break;
@@ -1506,9 +1493,31 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
 			return status;
 		break;
 	default:
-		goto xdr_error;
+		return nfserr_bad_xdr;
 	}
 
+	return nfs_ok;
+}
+
+static __be32
+nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
+			 struct nfsd4_exchange_id *exid)
+{
+	DECODE_HEAD;
+	int dummy;
+
+	status = nfsd4_decode_verifier4(argp, &exid->verifier);
+	if (status)
+		return status;
+	status = nfsd4_decode_opaque(argp, &exid->clname);
+	if (status)
+		return status;
+	if (xdr_stream_decode_u32(argp->xdr, &exid->flags) < 0)
+		return nfserr_bad_xdr;
+	status = nfsd4_decode_state_protect4_a(argp, exid);
+	if (status)
+		return status;
+
 	READ_BUF(4);    /* nfs_impl_id4 array length */
 	dummy = be32_to_cpup(p++);
 
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 6245004a9993..232529bc1b79 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -433,7 +433,7 @@ struct nfsd4_exchange_id {
 	u32		flags;
 	clientid_t	clientid;
 	u32		seqid;
-	int		spa_how;
+	u32		spa_how;
 	u32             spo_must_enforce[3];
 	u32             spo_must_allow[3];
 	struct xdr_netobj nii_domain;



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 057/118] NFSD: Add a helper to decode nfs_impl_id4
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (55 preceding siblings ...)
  2020-11-20 20:38 ` [PATCH v2 056/118] NFSD: Add a helper to decode state_protect4_a Chuck Lever
@ 2020-11-20 20:38 ` Chuck Lever
  2020-11-20 20:38 ` [PATCH v2 058/118] NFSD: Add a helper to decode channel_attrs4 Chuck Lever
                   ` (60 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:38 UTC (permalink / raw)
  To: linux-nfs

Refactor for clarity.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   63 ++++++++++++++++++++++++++++++++---------------------
 1 file changed, 38 insertions(+), 25 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index bb2e83ad61a4..18b41af204a6 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1499,12 +1499,47 @@ static __be32 nfsd4_decode_state_protect4_a(struct nfsd4_compoundargs *argp,
 	return nfs_ok;
 }
 
+static __be32
+nfsd4_decode_nfs_impl_id4(struct nfsd4_compoundargs *argp,
+			  struct nfsd4_exchange_id *exid)
+{
+	__be32 status;
+	u32 count;
+
+	if (xdr_stream_decode_u32(argp->xdr, &count) < 0)
+		return nfserr_bad_xdr;
+	switch (count) {
+	case 0:
+		break;
+	case 1:
+		/* Note that RFC 8881 places no length limit on
+		 * nii_domain, but this implementation permits no
+		 * more than NFS4_OPAQUE_LIMIT bytes */
+		status = nfsd4_decode_opaque(argp, &exid->nii_domain);
+		if (status)
+			return status;
+		/* Note that RFC 8881 places no length limit on
+		 * nii_name, but this implementation permits no
+		 * more than NFS4_OPAQUE_LIMIT bytes */
+		status = nfsd4_decode_opaque(argp, &exid->nii_name);
+		if (status)
+			return status;
+		status = nfsd4_decode_nfstime4(argp, &exid->nii_time);
+		if (status)
+			return status;
+		break;
+	default:
+		return nfserr_bad_xdr;
+	}
+
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
 			 struct nfsd4_exchange_id *exid)
 {
-	DECODE_HEAD;
-	int dummy;
+	__be32 status;
 
 	status = nfsd4_decode_verifier4(argp, &exid->verifier);
 	if (status)
@@ -1517,29 +1552,7 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
 	status = nfsd4_decode_state_protect4_a(argp, exid);
 	if (status)
 		return status;
-
-	READ_BUF(4);    /* nfs_impl_id4 array length */
-	dummy = be32_to_cpup(p++);
-
-	if (dummy > 1)
-		goto xdr_error;
-
-	if (dummy == 1) {
-		status = nfsd4_decode_opaque(argp, &exid->nii_domain);
-		if (status)
-			goto xdr_error;
-
-		/* nii_name */
-		status = nfsd4_decode_opaque(argp, &exid->nii_name);
-		if (status)
-			goto xdr_error;
-
-		/* nii_date */
-		status = nfsd4_decode_time(argp, &exid->nii_time);
-		if (status)
-			goto xdr_error;
-	}
-	DECODE_TAIL;
+	return nfsd4_decode_nfs_impl_id4(argp, exid);
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 058/118] NFSD: Add a helper to decode channel_attrs4
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (56 preceding siblings ...)
  2020-11-20 20:38 ` [PATCH v2 057/118] NFSD: Add a helper to decode nfs_impl_id4 Chuck Lever
@ 2020-11-20 20:38 ` Chuck Lever
  2020-11-20 20:38 ` [PATCH v2 059/118] NFSD: Replace READ* macros in nfsd4_decode_create_session() Chuck Lever
                   ` (59 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:38 UTC (permalink / raw)
  To: linux-nfs

De-duplicate some code.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   71 ++++++++++++++++++++++++++++-------------------------
 1 file changed, 38 insertions(+), 33 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 18b41af204a6..e2b0895c2a32 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1555,6 +1555,38 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
 	return nfsd4_decode_nfs_impl_id4(argp, exid);
 }
 
+static __be32
+nfsd4_decode_channel_attrs4(struct nfsd4_compoundargs *argp,
+			    struct nfsd4_channel_attrs *ca)
+{
+	__be32 *p;
+
+	p = xdr_inline_decode(argp->xdr, XDR_UNIT * 7);
+	if (!p)
+		return nfserr_bad_xdr;
+
+	/* headerpadsz is ignored */
+	p++;
+	ca->maxreq_sz = be32_to_cpup(p++);
+	ca->maxresp_sz = be32_to_cpup(p++);
+	ca->maxresp_cached = be32_to_cpup(p++);
+	ca->maxops = be32_to_cpup(p++);
+	ca->maxreqs = be32_to_cpup(p++);
+	ca->nr_rdma_attrs = be32_to_cpup(p);
+	switch (ca->nr_rdma_attrs) {
+	case 0:
+		break;
+	case 1:
+		if (xdr_stream_decode_u32(argp->xdr, &ca->rdma_attrs) < 0)
+			return nfserr_bad_xdr;
+		break;
+	default:
+		return nfserr_bad_xdr;
+	}
+
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
 			    struct nfsd4_create_session *sess)
@@ -1566,39 +1598,12 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
 	sess->seqid = be32_to_cpup(p++);
 	sess->flags = be32_to_cpup(p++);
 
-	/* Fore channel attrs */
-	READ_BUF(28);
-	p++; /* headerpadsz is always 0 */
-	sess->fore_channel.maxreq_sz = be32_to_cpup(p++);
-	sess->fore_channel.maxresp_sz = be32_to_cpup(p++);
-	sess->fore_channel.maxresp_cached = be32_to_cpup(p++);
-	sess->fore_channel.maxops = be32_to_cpup(p++);
-	sess->fore_channel.maxreqs = be32_to_cpup(p++);
-	sess->fore_channel.nr_rdma_attrs = be32_to_cpup(p++);
-	if (sess->fore_channel.nr_rdma_attrs == 1) {
-		READ_BUF(4);
-		sess->fore_channel.rdma_attrs = be32_to_cpup(p++);
-	} else if (sess->fore_channel.nr_rdma_attrs > 1) {
-		dprintk("Too many fore channel attr bitmaps!\n");
-		goto xdr_error;
-	}
-
-	/* Back channel attrs */
-	READ_BUF(28);
-	p++; /* headerpadsz is always 0 */
-	sess->back_channel.maxreq_sz = be32_to_cpup(p++);
-	sess->back_channel.maxresp_sz = be32_to_cpup(p++);
-	sess->back_channel.maxresp_cached = be32_to_cpup(p++);
-	sess->back_channel.maxops = be32_to_cpup(p++);
-	sess->back_channel.maxreqs = be32_to_cpup(p++);
-	sess->back_channel.nr_rdma_attrs = be32_to_cpup(p++);
-	if (sess->back_channel.nr_rdma_attrs == 1) {
-		READ_BUF(4);
-		sess->back_channel.rdma_attrs = be32_to_cpup(p++);
-	} else if (sess->back_channel.nr_rdma_attrs > 1) {
-		dprintk("Too many back channel attr bitmaps!\n");
-		goto xdr_error;
-	}
+	status = nfsd4_decode_channel_attrs4(argp, &sess->fore_channel);
+	if (status)
+		return status;
+	status = nfsd4_decode_channel_attrs4(argp, &sess->back_channel);
+	if (status)
+		return status;
 
 	READ_BUF(4);
 	sess->callback_prog = be32_to_cpup(p++);



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 059/118] NFSD: Replace READ* macros in nfsd4_decode_create_session()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (57 preceding siblings ...)
  2020-11-20 20:38 ` [PATCH v2 058/118] NFSD: Add a helper to decode channel_attrs4 Chuck Lever
@ 2020-11-20 20:38 ` Chuck Lever
  2020-11-20 20:39 ` [PATCH v2 060/118] NFSD: Replace READ* macros in nfsd4_decode_destroy_session() Chuck Lever
                   ` (58 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:38 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index e2b0895c2a32..38a54bd9f1cb 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1591,24 +1591,28 @@ static __be32
 nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
 			    struct nfsd4_create_session *sess)
 {
-	DECODE_HEAD;
-
-	READ_BUF(16);
-	COPYMEM(&sess->clientid, 8);
-	sess->seqid = be32_to_cpup(p++);
-	sess->flags = be32_to_cpup(p++);
+	__be32 status;
 
+	status = nfsd4_decode_clientid4(argp, &sess->clientid);
+	if (status)
+		return status;
+	if (xdr_stream_decode_u32(argp->xdr, &sess->seqid) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &sess->flags) < 0)
+		return nfserr_bad_xdr;
 	status = nfsd4_decode_channel_attrs4(argp, &sess->fore_channel);
 	if (status)
 		return status;
 	status = nfsd4_decode_channel_attrs4(argp, &sess->back_channel);
+	if (status)
+		return status;
+	if (xdr_stream_decode_u32(argp->xdr, &sess->callback_prog) < 0)
+		return nfserr_bad_xdr;
+	status = nfsd4_decode_cb_sec(argp, &sess->cb_sec);
 	if (status)
 		return status;
 
-	READ_BUF(4);
-	sess->callback_prog = be32_to_cpup(p++);
-	nfsd4_decode_cb_sec(argp, &sess->cb_sec);
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 060/118] NFSD: Replace READ* macros in nfsd4_decode_destroy_session()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (58 preceding siblings ...)
  2020-11-20 20:38 ` [PATCH v2 059/118] NFSD: Replace READ* macros in nfsd4_decode_create_session() Chuck Lever
@ 2020-11-20 20:39 ` Chuck Lever
  2020-11-20 20:39 ` [PATCH v2 061/118] NFSD: Replace READ* macros in nfsd4_decode_free_stateid() Chuck Lever
                   ` (57 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:39 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |    6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 38a54bd9f1cb..9c17cf541e8c 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1619,11 +1619,7 @@ static __be32
 nfsd4_decode_destroy_session(struct nfsd4_compoundargs *argp,
 			     struct nfsd4_destroy_session *destroy_session)
 {
-	DECODE_HEAD;
-	READ_BUF(NFS4_MAX_SESSIONID_LEN);
-	COPYMEM(destroy_session->sessionid.data, NFS4_MAX_SESSIONID_LEN);
-
-	DECODE_TAIL;
+	return nfsd4_decode_sessionid(argp, &destroy_session->sessionid);
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 061/118] NFSD: Replace READ* macros in nfsd4_decode_free_stateid()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (59 preceding siblings ...)
  2020-11-20 20:39 ` [PATCH v2 060/118] NFSD: Replace READ* macros in nfsd4_decode_destroy_session() Chuck Lever
@ 2020-11-20 20:39 ` Chuck Lever
  2020-11-20 20:39 ` [PATCH v2 062/118] NFSD: Replace READ* macros in nfsd4_decode_getdeviceinfo() Chuck Lever
                   ` (56 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:39 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |    8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 9c17cf541e8c..1fb79a597b47 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1626,13 +1626,7 @@ static __be32
 nfsd4_decode_free_stateid(struct nfsd4_compoundargs *argp,
 			  struct nfsd4_free_stateid *free_stateid)
 {
-	DECODE_HEAD;
-
-	READ_BUF(sizeof(stateid_t));
-	free_stateid->fr_stateid.si_generation = be32_to_cpup(p++);
-	COPYMEM(&free_stateid->fr_stateid.si_opaque, sizeof(stateid_opaque_t));
-
-	DECODE_TAIL;
+	return nfsd4_decode_stateid4(argp, &free_stateid->fr_stateid);
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 062/118] NFSD: Replace READ* macros in nfsd4_decode_getdeviceinfo()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (60 preceding siblings ...)
  2020-11-20 20:39 ` [PATCH v2 061/118] NFSD: Replace READ* macros in nfsd4_decode_free_stateid() Chuck Lever
@ 2020-11-20 20:39 ` Chuck Lever
  2020-11-20 20:39 ` [PATCH v2 063/118] NFSD: Replace READ* macros in nfsd4_decode_layoutcommit() Chuck Lever
                   ` (55 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:39 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   50 +++++++++++++++++++++++++++++---------------------
 1 file changed, 29 insertions(+), 21 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 1fb79a597b47..04dfb578bec8 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -583,6 +583,21 @@ nfsd4_decode_stateid4(struct nfsd4_compoundargs *argp, stateid_t *sid)
 	return nfs_ok;
 }
 
+#ifdef CONFIG_NFSD_PNFS
+static __be32
+nfsd4_decode_deviceid4(struct nfsd4_compoundargs *argp,
+		       struct nfsd4_deviceid *devid)
+{
+	__be32 *p;
+
+	p = xdr_inline_decode(argp->xdr, NFS4_DEVICEID4_SIZE);
+	if (!p)
+		return nfserr_bad_xdr;
+	memcpy(devid, p, sizeof(*devid));
+	return nfs_ok;
+}
+#endif /* CONFIG_NFSD_PNFS */
+
 static __be32
 nfsd4_decode_sessionid(struct nfsd4_compoundargs *argp,
 		       struct nfs4_sessionid *sessionid)
@@ -1706,27 +1721,20 @@ static __be32
 nfsd4_decode_getdeviceinfo(struct nfsd4_compoundargs *argp,
 		struct nfsd4_getdeviceinfo *gdev)
 {
-	DECODE_HEAD;
-	u32 num, i;
-
-	READ_BUF(sizeof(struct nfsd4_deviceid) + 3 * 4);
-	COPYMEM(&gdev->gd_devid, sizeof(struct nfsd4_deviceid));
-	gdev->gd_layout_type = be32_to_cpup(p++);
-	gdev->gd_maxcount = be32_to_cpup(p++);
-	num = be32_to_cpup(p++);
-	if (num) {
-		if (num > 1000)
-			goto xdr_error;
-		READ_BUF(4 * num);
-		gdev->gd_notify_types = be32_to_cpup(p++);
-		for (i = 1; i < num; i++) {
-			if (be32_to_cpup(p++)) {
-				status = nfserr_inval;
-				goto out;
-			}
-		}
-	}
-	DECODE_TAIL;
+	__be32 status;
+
+	status = nfsd4_decode_deviceid4(argp, &gdev->gd_devid);
+	if (status)
+		return status;
+	if (xdr_stream_decode_u32(argp->xdr, &gdev->gd_layout_type) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &gdev->gd_maxcount) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_uint32_array(argp->xdr,
+					   &gdev->gd_notify_types, 1) < 0)
+		return nfserr_bad_xdr;
+
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 063/118] NFSD: Replace READ* macros in nfsd4_decode_layoutcommit()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (61 preceding siblings ...)
  2020-11-20 20:39 ` [PATCH v2 062/118] NFSD: Replace READ* macros in nfsd4_decode_getdeviceinfo() Chuck Lever
@ 2020-11-20 20:39 ` Chuck Lever
  2020-11-20 20:39 ` [PATCH v2 064/118] NFSD: Replace READ* macros in nfsd4_decode_layoutget() Chuck Lever
                   ` (54 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:39 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |  119 +++++++++++++++++++++++++----------------------------
 1 file changed, 57 insertions(+), 62 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 04dfb578bec8..2c75e5d3b2f2 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -272,20 +272,6 @@ nfsd4_decode_component4(struct nfsd4_compoundargs *argp, char **namp, u32 *lenp)
 	return nfs_ok;
 }
 
-static __be32
-nfsd4_decode_time(struct nfsd4_compoundargs *argp, struct timespec64 *tv)
-{
-	DECODE_HEAD;
-
-	READ_BUF(12);
-	p = xdr_decode_hyper(p, &tv->tv_sec);
-	tv->tv_nsec = be32_to_cpup(p++);
-	if (tv->tv_nsec >= (u32)1000000000)
-		return nfserr_inval;
-
-	DECODE_TAIL;
-}
-
 static __be32
 nfsd4_decode_nfstime4(struct nfsd4_compoundargs *argp, struct timespec64 *tv)
 {
@@ -596,6 +582,29 @@ nfsd4_decode_deviceid4(struct nfsd4_compoundargs *argp,
 	memcpy(devid, p, sizeof(*devid));
 	return nfs_ok;
 }
+
+static __be32
+nfsd4_decode_layoutupdate4(struct nfsd4_compoundargs *argp,
+			   struct nfsd4_layoutcommit *lcp)
+{
+	if (xdr_stream_decode_u32(argp->xdr, &lcp->lc_layout_type) < 0)
+		return nfserr_bad_xdr;
+	if (lcp->lc_layout_type < LAYOUT_NFSV4_1_FILES)
+		return nfserr_bad_xdr;
+	if (lcp->lc_layout_type >= LAYOUT_TYPE_MAX)
+		return nfserr_bad_xdr;
+
+	if (xdr_stream_decode_u32(argp->xdr, &lcp->lc_up_len) < 0)
+		return nfserr_bad_xdr;
+	if (lcp->lc_up_len > 0) {
+		lcp->lc_up_layout = xdr_inline_decode(argp->xdr, lcp->lc_up_len);
+		if (!lcp->lc_up_layout)
+			return nfserr_bad_xdr;
+	}
+
+	return nfs_ok;
+}
+
 #endif /* CONFIG_NFSD_PNFS */
 
 static __be32
@@ -1737,6 +1746,40 @@ nfsd4_decode_getdeviceinfo(struct nfsd4_compoundargs *argp,
 	return nfs_ok;
 }
 
+static __be32 nfsd4_decode_layoutcommit(struct nfsd4_compoundargs *argp,
+					struct nfsd4_layoutcommit *lcp)
+{
+	__be32 *p, status;
+
+	if (xdr_stream_decode_u64(argp->xdr, &lcp->lc_seg.offset) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u64(argp->xdr, &lcp->lc_seg.length) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_bool(argp->xdr, &lcp->lc_reclaim) < 0)
+		return nfserr_bad_xdr;
+	status = nfsd4_decode_stateid4(argp, &lcp->lc_sid);
+	if (status)
+		return status;
+	if (xdr_stream_decode_u32(argp->xdr, &lcp->lc_newoffset) < 0)
+		return nfserr_bad_xdr;
+	if (lcp->lc_newoffset) {
+		if (xdr_stream_decode_u64(argp->xdr, &lcp->lc_last_wr) < 0)
+			return nfserr_bad_xdr;
+	} else
+		lcp->lc_last_wr = 0;
+	p = xdr_inline_decode(argp->xdr, XDR_UNIT);
+	if (!p)
+		return nfserr_bad_xdr;
+	if (xdr_item_is_present(p)) {
+		status = nfsd4_decode_nfstime4(argp, &lcp->lc_mtime);
+		if (status)
+			return status;
+	} else {
+		lcp->lc_mtime.tv_nsec = UTIME_NOW;
+	}
+	return nfsd4_decode_layoutupdate4(argp, lcp);
+}
+
 static __be32
 nfsd4_decode_layoutget(struct nfsd4_compoundargs *argp,
 		struct nfsd4_layoutget *lgp)
@@ -1761,54 +1804,6 @@ nfsd4_decode_layoutget(struct nfsd4_compoundargs *argp,
 	DECODE_TAIL;
 }
 
-static __be32
-nfsd4_decode_layoutcommit(struct nfsd4_compoundargs *argp,
-		struct nfsd4_layoutcommit *lcp)
-{
-	DECODE_HEAD;
-	u32 timechange;
-
-	READ_BUF(20);
-	p = xdr_decode_hyper(p, &lcp->lc_seg.offset);
-	p = xdr_decode_hyper(p, &lcp->lc_seg.length);
-	lcp->lc_reclaim = be32_to_cpup(p++);
-
-	status = nfsd4_decode_stateid4(argp, &lcp->lc_sid);
-	if (status)
-		return status;
-
-	READ_BUF(4);
-	lcp->lc_newoffset = be32_to_cpup(p++);
-	if (lcp->lc_newoffset) {
-		READ_BUF(8);
-		p = xdr_decode_hyper(p, &lcp->lc_last_wr);
-	} else
-		lcp->lc_last_wr = 0;
-	READ_BUF(4);
-	timechange = be32_to_cpup(p++);
-	if (timechange) {
-		status = nfsd4_decode_time(argp, &lcp->lc_mtime);
-		if (status)
-			return status;
-	} else {
-		lcp->lc_mtime.tv_nsec = UTIME_NOW;
-	}
-	READ_BUF(8);
-	lcp->lc_layout_type = be32_to_cpup(p++);
-
-	/*
-	 * Save the layout update in XDR format and let the layout driver deal
-	 * with it later.
-	 */
-	lcp->lc_up_len = be32_to_cpup(p++);
-	if (lcp->lc_up_len > 0) {
-		READ_BUF(lcp->lc_up_len);
-		READMEM(lcp->lc_up_layout, lcp->lc_up_len);
-	}
-
-	DECODE_TAIL;
-}
-
 static __be32
 nfsd4_decode_layoutreturn(struct nfsd4_compoundargs *argp,
 		struct nfsd4_layoutreturn *lrp)



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 064/118] NFSD: Replace READ* macros in nfsd4_decode_layoutget()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (62 preceding siblings ...)
  2020-11-20 20:39 ` [PATCH v2 063/118] NFSD: Replace READ* macros in nfsd4_decode_layoutcommit() Chuck Lever
@ 2020-11-20 20:39 ` Chuck Lever
  2020-11-20 20:39 ` [PATCH v2 065/118] NFSD: Replace READ* macros in nfsd4_decode_layoutreturn() Chuck Lever
                   ` (53 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:39 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 2c75e5d3b2f2..8add9b5242f1 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1784,24 +1784,27 @@ static __be32
 nfsd4_decode_layoutget(struct nfsd4_compoundargs *argp,
 		struct nfsd4_layoutget *lgp)
 {
-	DECODE_HEAD;
-
-	READ_BUF(36);
-	lgp->lg_signal = be32_to_cpup(p++);
-	lgp->lg_layout_type = be32_to_cpup(p++);
-	lgp->lg_seg.iomode = be32_to_cpup(p++);
-	p = xdr_decode_hyper(p, &lgp->lg_seg.offset);
-	p = xdr_decode_hyper(p, &lgp->lg_seg.length);
-	p = xdr_decode_hyper(p, &lgp->lg_minlength);
+	__be32 status;
 
+	if (xdr_stream_decode_u32(argp->xdr, &lgp->lg_signal) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &lgp->lg_layout_type) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &lgp->lg_seg.iomode) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u64(argp->xdr, &lgp->lg_seg.offset) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u64(argp->xdr, &lgp->lg_seg.length) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u64(argp->xdr, &lgp->lg_minlength) < 0)
+		return nfserr_bad_xdr;
 	status = nfsd4_decode_stateid4(argp, &lgp->lg_sid);
 	if (status)
 		return status;
+	if (xdr_stream_decode_u32(argp->xdr, &lgp->lg_maxcount) < 0)
+		return nfserr_bad_xdr;
 
-	READ_BUF(4);
-	lgp->lg_maxcount = be32_to_cpup(p++);
-
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 065/118] NFSD: Replace READ* macros in nfsd4_decode_layoutreturn()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (63 preceding siblings ...)
  2020-11-20 20:39 ` [PATCH v2 064/118] NFSD: Replace READ* macros in nfsd4_decode_layoutget() Chuck Lever
@ 2020-11-20 20:39 ` Chuck Lever
  2020-11-20 20:39 ` [PATCH v2 066/118] NFSD: Replace READ* macros in nfsd4_decode_secinfo_no_name() Chuck Lever
                   ` (52 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:39 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   72 ++++++++++++++++++++++++++++++++---------------------
 1 file changed, 44 insertions(+), 28 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 8add9b5242f1..e4ff29ab918c 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -605,6 +605,43 @@ nfsd4_decode_layoutupdate4(struct nfsd4_compoundargs *argp,
 	return nfs_ok;
 }
 
+static __be32
+nfsd4_decode_layoutreturn4(struct nfsd4_compoundargs *argp,
+			   struct nfsd4_layoutreturn *lrp)
+{
+	__be32 status;
+
+	if (xdr_stream_decode_u32(argp->xdr, &lrp->lr_return_type) < 0)
+		return nfserr_bad_xdr;
+	switch (lrp->lr_return_type) {
+	case RETURN_FILE:
+		if (xdr_stream_decode_u64(argp->xdr, &lrp->lr_seg.offset) < 0)
+			return nfserr_bad_xdr;
+		if (xdr_stream_decode_u64(argp->xdr, &lrp->lr_seg.length) < 0)
+			return nfserr_bad_xdr;
+		status = nfsd4_decode_stateid4(argp, &lrp->lr_sid);
+		if (status)
+			return status;
+		if (xdr_stream_decode_u32(argp->xdr, &lrp->lrf_body_len) < 0)
+			return nfserr_bad_xdr;
+		if (lrp->lrf_body_len > 0) {
+			lrp->lrf_body = xdr_inline_decode(argp->xdr, lrp->lrf_body_len);
+			if (!lrp->lrf_body)
+				return nfserr_bad_xdr;
+		}
+		break;
+	case RETURN_FSID:
+	case RETURN_ALL:
+		lrp->lr_seg.offset = 0;
+		lrp->lr_seg.length = NFS4_MAX_UINT64;
+		break;
+	default:
+		return nfserr_bad_xdr;
+	}
+
+	return nfs_ok;
+}
+
 #endif /* CONFIG_NFSD_PNFS */
 
 static __be32
@@ -1811,34 +1848,13 @@ static __be32
 nfsd4_decode_layoutreturn(struct nfsd4_compoundargs *argp,
 		struct nfsd4_layoutreturn *lrp)
 {
-	DECODE_HEAD;
-
-	READ_BUF(16);
-	lrp->lr_reclaim = be32_to_cpup(p++);
-	lrp->lr_layout_type = be32_to_cpup(p++);
-	lrp->lr_seg.iomode = be32_to_cpup(p++);
-	lrp->lr_return_type = be32_to_cpup(p++);
-	if (lrp->lr_return_type == RETURN_FILE) {
-		READ_BUF(16);
-		p = xdr_decode_hyper(p, &lrp->lr_seg.offset);
-		p = xdr_decode_hyper(p, &lrp->lr_seg.length);
-
-		status = nfsd4_decode_stateid4(argp, &lrp->lr_sid);
-		if (status)
-			return status;
-
-		READ_BUF(4);
-		lrp->lrf_body_len = be32_to_cpup(p++);
-		if (lrp->lrf_body_len > 0) {
-			READ_BUF(lrp->lrf_body_len);
-			READMEM(lrp->lrf_body, lrp->lrf_body_len);
-		}
-	} else {
-		lrp->lr_seg.offset = 0;
-		lrp->lr_seg.length = NFS4_MAX_UINT64;
-	}
-
-	DECODE_TAIL;
+	if (xdr_stream_decode_bool(argp->xdr, &lrp->lr_reclaim) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &lrp->lr_layout_type) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &lrp->lr_seg.iomode) < 0)
+		return nfserr_bad_xdr;
+	return nfsd4_decode_layoutreturn4(argp, lrp);
 }
 #endif /* CONFIG_NFSD_PNFS */
 



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 066/118] NFSD: Replace READ* macros in nfsd4_decode_secinfo_no_name()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (64 preceding siblings ...)
  2020-11-20 20:39 ` [PATCH v2 065/118] NFSD: Replace READ* macros in nfsd4_decode_layoutreturn() Chuck Lever
@ 2020-11-20 20:39 ` Chuck Lever
  2020-11-20 20:39 ` [PATCH v2 067/118] NFSD: Replace READ* macros in nfsd4_decode_sequence() Chuck Lever
                   ` (51 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:39 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index e4ff29ab918c..1e9bd20faa96 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1302,17 +1302,6 @@ nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
 	return nfsd4_decode_component4(argp, &secinfo->si_name, &secinfo->si_namelen);
 }
 
-static __be32
-nfsd4_decode_secinfo_no_name(struct nfsd4_compoundargs *argp,
-		     struct nfsd4_secinfo_no_name *sin)
-{
-	DECODE_HEAD;
-
-	READ_BUF(4);
-	sin->sin_style = be32_to_cpup(p++);
-	DECODE_TAIL;
-}
-
 static __be32
 nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
 {
@@ -1858,6 +1847,14 @@ nfsd4_decode_layoutreturn(struct nfsd4_compoundargs *argp,
 }
 #endif /* CONFIG_NFSD_PNFS */
 
+static __be32 nfsd4_decode_secinfo_no_name(struct nfsd4_compoundargs *argp,
+					   struct nfsd4_secinfo_no_name *sin)
+{
+	if (xdr_stream_decode_u32(argp->xdr, &sin->sin_style) < 0)
+		return nfserr_bad_xdr;
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp,
 		       struct nfsd4_fallocate *fallocate)



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 067/118] NFSD: Replace READ* macros in nfsd4_decode_sequence()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (65 preceding siblings ...)
  2020-11-20 20:39 ` [PATCH v2 066/118] NFSD: Replace READ* macros in nfsd4_decode_secinfo_no_name() Chuck Lever
@ 2020-11-20 20:39 ` Chuck Lever
  2020-11-20 20:39 ` [PATCH v2 068/118] NFSD: Replace READ* macros in nfsd4_decode_test_stateid() Chuck Lever
                   ` (50 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:39 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   36 ++++++++++++++++++++----------------
 1 file changed, 20 insertions(+), 16 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 1e9bd20faa96..5544e85b8897 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1679,22 +1679,6 @@ nfsd4_decode_free_stateid(struct nfsd4_compoundargs *argp,
 	return nfsd4_decode_stateid4(argp, &free_stateid->fr_stateid);
 }
 
-static __be32
-nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
-		      struct nfsd4_sequence *seq)
-{
-	DECODE_HEAD;
-
-	READ_BUF(NFS4_MAX_SESSIONID_LEN + 16);
-	COPYMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN);
-	seq->seqid = be32_to_cpup(p++);
-	seq->slotid = be32_to_cpup(p++);
-	seq->maxslots = be32_to_cpup(p++);
-	seq->cachethis = be32_to_cpup(p++);
-
-	DECODE_TAIL;
-}
-
 static __be32
 nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid)
 {
@@ -1855,6 +1839,26 @@ static __be32 nfsd4_decode_secinfo_no_name(struct nfsd4_compoundargs *argp,
 	return nfs_ok;
 }
 
+static __be32
+nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
+		      struct nfsd4_sequence *seq)
+{
+	__be32 *p, status;
+
+	status = nfsd4_decode_sessionid(argp, &seq->sessionid);
+	if (status)
+		return status;
+	p = xdr_inline_decode(argp->xdr, XDR_UNIT * 4);
+	if (!p)
+		return nfserr_bad_xdr;
+	seq->seqid = be32_to_cpup(p++);
+	seq->slotid = be32_to_cpup(p++);
+	seq->maxslots = be32_to_cpup(p++);
+	seq->cachethis = be32_to_cpup(p);
+
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp,
 		       struct nfsd4_fallocate *fallocate)



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 068/118] NFSD: Replace READ* macros in nfsd4_decode_test_stateid()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (66 preceding siblings ...)
  2020-11-20 20:39 ` [PATCH v2 067/118] NFSD: Replace READ* macros in nfsd4_decode_sequence() Chuck Lever
@ 2020-11-20 20:39 ` Chuck Lever
  2020-11-20 20:39 ` [PATCH v2 069/118] NFSD: Replace READ* macros in nfsd4_decode_destroy_clientid() Chuck Lever
                   ` (49 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:39 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   61 ++++++++++++++++++++++-------------------------------
 1 file changed, 25 insertions(+), 36 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 5544e85b8897..c6301393c422 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1679,42 +1679,6 @@ nfsd4_decode_free_stateid(struct nfsd4_compoundargs *argp,
 	return nfsd4_decode_stateid4(argp, &free_stateid->fr_stateid);
 }
 
-static __be32
-nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid)
-{
-	int i;
-	__be32 *p, status;
-	struct nfsd4_test_stateid_id *stateid;
-
-	READ_BUF(4);
-	test_stateid->ts_num_ids = ntohl(*p++);
-
-	INIT_LIST_HEAD(&test_stateid->ts_stateid_list);
-
-	for (i = 0; i < test_stateid->ts_num_ids; i++) {
-		stateid = svcxdr_tmpalloc(argp, sizeof(*stateid));
-		if (!stateid) {
-			status = nfserrno(-ENOMEM);
-			goto out;
-		}
-
-		INIT_LIST_HEAD(&stateid->ts_id_list);
-		list_add_tail(&stateid->ts_id_list, &test_stateid->ts_stateid_list);
-
-		status = nfsd4_decode_stateid4(argp, &stateid->ts_id_stateid);
-		if (status)
-			goto out;
-	}
-
-	status = 0;
-out:
-	return status;
-xdr_error:
-	dprintk("NFSD: xdr error (%s:%d)\n", __FILE__, __LINE__);
-	status = nfserr_bad_xdr;
-	goto out;
-}
-
 static __be32 nfsd4_decode_destroy_clientid(struct nfsd4_compoundargs *argp, struct nfsd4_destroy_clientid *dc)
 {
 	DECODE_HEAD;
@@ -1859,6 +1823,31 @@ nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
 	return nfs_ok;
 }
 
+static __be32
+nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid)
+{
+	struct nfsd4_test_stateid_id *stateid;
+	__be32 status;
+	u32 i;
+
+	if (xdr_stream_decode_u32(argp->xdr, &test_stateid->ts_num_ids) < 0)
+		return nfserr_bad_xdr;
+
+	INIT_LIST_HEAD(&test_stateid->ts_stateid_list);
+	for (i = 0; i < test_stateid->ts_num_ids; i++) {
+		stateid = svcxdr_tmpalloc(argp, sizeof(*stateid));
+		if (!stateid)
+			return nfserrno(-ENOMEM);	/* XXX: not jukebox? */
+		INIT_LIST_HEAD(&stateid->ts_id_list);
+		list_add_tail(&stateid->ts_id_list, &test_stateid->ts_stateid_list);
+		status = nfsd4_decode_stateid4(argp, &stateid->ts_id_stateid);
+		if (status)
+			return status;
+	}
+
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp,
 		       struct nfsd4_fallocate *fallocate)



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 069/118] NFSD: Replace READ* macros in nfsd4_decode_destroy_clientid()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (67 preceding siblings ...)
  2020-11-20 20:39 ` [PATCH v2 068/118] NFSD: Replace READ* macros in nfsd4_decode_test_stateid() Chuck Lever
@ 2020-11-20 20:39 ` Chuck Lever
  2020-11-20 20:39 ` [PATCH v2 070/118] NFSD: Replace READ* macros in nfsd4_decode_reclaim_complete() Chuck Lever
                   ` (48 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:39 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index c6301393c422..6bfc9f69c660 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1679,16 +1679,6 @@ nfsd4_decode_free_stateid(struct nfsd4_compoundargs *argp,
 	return nfsd4_decode_stateid4(argp, &free_stateid->fr_stateid);
 }
 
-static __be32 nfsd4_decode_destroy_clientid(struct nfsd4_compoundargs *argp, struct nfsd4_destroy_clientid *dc)
-{
-	DECODE_HEAD;
-
-	READ_BUF(8);
-	COPYMEM(&dc->clientid, 8);
-
-	DECODE_TAIL;
-}
-
 static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc)
 {
 	DECODE_HEAD;
@@ -1848,6 +1838,12 @@ nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_sta
 	return nfs_ok;
 }
 
+static __be32 nfsd4_decode_destroy_clientid(struct nfsd4_compoundargs *argp,
+					    struct nfsd4_destroy_clientid *dc)
+{
+	return nfsd4_decode_clientid4(argp, &dc->clientid);
+}
+
 static __be32
 nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp,
 		       struct nfsd4_fallocate *fallocate)



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 070/118] NFSD: Replace READ* macros in nfsd4_decode_reclaim_complete()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (68 preceding siblings ...)
  2020-11-20 20:39 ` [PATCH v2 069/118] NFSD: Replace READ* macros in nfsd4_decode_destroy_clientid() Chuck Lever
@ 2020-11-20 20:39 ` Chuck Lever
  2020-11-20 20:40 ` [PATCH v2 071/118] NFSD: Replace READ* macros in nfsd4_decode_fallocate() Chuck Lever
                   ` (47 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:39 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 6bfc9f69c660..6325b71f3d7e 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1679,16 +1679,6 @@ nfsd4_decode_free_stateid(struct nfsd4_compoundargs *argp,
 	return nfsd4_decode_stateid4(argp, &free_stateid->fr_stateid);
 }
 
-static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc)
-{
-	DECODE_HEAD;
-
-	READ_BUF(4);
-	rc->rca_one_fs = be32_to_cpup(p++);
-
-	DECODE_TAIL;
-}
-
 #ifdef CONFIG_NFSD_PNFS
 static __be32
 nfsd4_decode_getdeviceinfo(struct nfsd4_compoundargs *argp,
@@ -1844,6 +1834,14 @@ static __be32 nfsd4_decode_destroy_clientid(struct nfsd4_compoundargs *argp,
 	return nfsd4_decode_clientid4(argp, &dc->clientid);
 }
 
+static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp,
+					    struct nfsd4_reclaim_complete *rc)
+{
+	if (xdr_stream_decode_bool(argp->xdr, &rc->rca_one_fs) < 0)
+		return nfserr_bad_xdr;
+	return nfs_ok;
+}
+
 static __be32
 nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp,
 		       struct nfsd4_fallocate *fallocate)



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 071/118] NFSD: Replace READ* macros in nfsd4_decode_fallocate()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (69 preceding siblings ...)
  2020-11-20 20:39 ` [PATCH v2 070/118] NFSD: Replace READ* macros in nfsd4_decode_reclaim_complete() Chuck Lever
@ 2020-11-20 20:40 ` Chuck Lever
  2020-11-20 20:40 ` [PATCH v2 072/118] NFSD: Replace READ* macros in nfsd4_decode_clone() Chuck Lever
                   ` (46 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:40 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 6325b71f3d7e..0509f2c00310 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1846,17 +1846,17 @@ static __be32
 nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp,
 		       struct nfsd4_fallocate *fallocate)
 {
-	DECODE_HEAD;
+	__be32 status;
 
 	status = nfsd4_decode_stateid4(argp, &fallocate->falloc_stateid);
 	if (status)
 		return status;
+	if (xdr_stream_decode_u64(argp->xdr, &fallocate->falloc_offset) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u64(argp->xdr, &fallocate->falloc_length) < 0)
+		return nfserr_bad_xdr;
 
-	READ_BUF(16);
-	p = xdr_decode_hyper(p, &fallocate->falloc_offset);
-	xdr_decode_hyper(p, &fallocate->falloc_length);
-
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 072/118] NFSD: Replace READ* macros in nfsd4_decode_clone()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (70 preceding siblings ...)
  2020-11-20 20:40 ` [PATCH v2 071/118] NFSD: Replace READ* macros in nfsd4_decode_fallocate() Chuck Lever
@ 2020-11-20 20:40 ` Chuck Lever
  2020-11-20 20:40 ` [PATCH v2 073/118] NFSD: Replace READ* macros in nfsd4_decode_nl4_server() Chuck Lever
                   ` (45 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:40 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 0509f2c00310..ed1e6460b655 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1862,7 +1862,7 @@ nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp,
 static __be32
 nfsd4_decode_clone(struct nfsd4_compoundargs *argp, struct nfsd4_clone *clone)
 {
-	DECODE_HEAD;
+	__be32 status;
 
 	status = nfsd4_decode_stateid4(argp, &clone->cl_src_stateid);
 	if (status)
@@ -1870,12 +1870,14 @@ nfsd4_decode_clone(struct nfsd4_compoundargs *argp, struct nfsd4_clone *clone)
 	status = nfsd4_decode_stateid4(argp, &clone->cl_dst_stateid);
 	if (status)
 		return status;
+	if (xdr_stream_decode_u64(argp->xdr, &clone->cl_src_pos) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u64(argp->xdr, &clone->cl_dst_pos) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u64(argp->xdr, &clone->cl_count) < 0)
+		return nfserr_bad_xdr;
 
-	READ_BUF(8 + 8 + 8);
-	p = xdr_decode_hyper(p, &clone->cl_src_pos);
-	p = xdr_decode_hyper(p, &clone->cl_dst_pos);
-	p = xdr_decode_hyper(p, &clone->cl_count);
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32 nfsd4_decode_nl4_server(struct nfsd4_compoundargs *argp,



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 073/118] NFSD: Replace READ* macros in nfsd4_decode_nl4_server()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (71 preceding siblings ...)
  2020-11-20 20:40 ` [PATCH v2 072/118] NFSD: Replace READ* macros in nfsd4_decode_clone() Chuck Lever
@ 2020-11-20 20:40 ` Chuck Lever
  2020-11-20 20:40 ` [PATCH v2 074/118] NFSD: Replace READ* macros in nfsd4_decode_copy() Chuck Lever
                   ` (44 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:40 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   34 ++++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index ed1e6460b655..6108f8ff36b2 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1883,36 +1883,42 @@ nfsd4_decode_clone(struct nfsd4_compoundargs *argp, struct nfsd4_clone *clone)
 static __be32 nfsd4_decode_nl4_server(struct nfsd4_compoundargs *argp,
 				      struct nl4_server *ns)
 {
-	DECODE_HEAD;
 	struct nfs42_netaddr *naddr;
+	__be32 *p;
 
-	READ_BUF(4);
-	ns->nl4_type = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &ns->nl4_type) < 0)
+		return nfserr_bad_xdr;
 
 	/* currently support for 1 inter-server source server */
 	switch (ns->nl4_type) {
 	case NL4_NETADDR:
 		naddr = &ns->u.nl4_addr;
 
-		READ_BUF(4);
-		naddr->netid_len = be32_to_cpup(p++);
+		if (xdr_stream_decode_u32(argp->xdr, &naddr->netid_len) < 0)
+			return nfserr_bad_xdr;
 		if (naddr->netid_len > RPCBIND_MAXNETIDLEN)
-			goto xdr_error;
+			return nfserr_bad_xdr;
 
-		READ_BUF(naddr->netid_len + 4); /* 4 for uaddr len */
-		COPYMEM(naddr->netid, naddr->netid_len);
+		p = xdr_inline_decode(argp->xdr, naddr->netid_len);
+		if (!p)
+			return nfserr_bad_xdr;
+		memcpy(naddr->netid, p, naddr->netid_len);
 
-		naddr->addr_len = be32_to_cpup(p++);
+		if (xdr_stream_decode_u32(argp->xdr, &naddr->addr_len) < 0)
+			return nfserr_bad_xdr;
 		if (naddr->addr_len > RPCBIND_MAXUADDRLEN)
-			goto xdr_error;
+			return nfserr_bad_xdr;
 
-		READ_BUF(naddr->addr_len);
-		COPYMEM(naddr->addr, naddr->addr_len);
+		p = xdr_inline_decode(argp->xdr, naddr->addr_len);
+		if (!p)
+			return nfserr_bad_xdr;
+		memcpy(naddr->addr, p, naddr->addr_len);
 		break;
 	default:
-		goto xdr_error;
+		return nfserr_bad_xdr;
 	}
-	DECODE_TAIL;
+
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 074/118] NFSD: Replace READ* macros in nfsd4_decode_copy()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (72 preceding siblings ...)
  2020-11-20 20:40 ` [PATCH v2 073/118] NFSD: Replace READ* macros in nfsd4_decode_nl4_server() Chuck Lever
@ 2020-11-20 20:40 ` Chuck Lever
  2020-11-20 20:40 ` [PATCH v2 075/118] NFSD: Replace READ* macros in nfsd4_decode_seek() Chuck Lever
                   ` (43 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:40 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   37 ++++++++++++++++++++-----------------
 fs/nfsd/xdr4.h    |    2 +-
 2 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 6108f8ff36b2..84d69c436fd3 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1924,9 +1924,9 @@ static __be32 nfsd4_decode_nl4_server(struct nfsd4_compoundargs *argp,
 static __be32
 nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)
 {
-	DECODE_HEAD;
 	struct nl4_server *ns_dummy;
-	int i, count;
+	u32 consecutive, i, count;
+	__be32 status;
 
 	status = nfsd4_decode_stateid4(argp, &copy->cp_src_stateid);
 	if (status)
@@ -1934,30 +1934,34 @@ nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)
 	status = nfsd4_decode_stateid4(argp, &copy->cp_dst_stateid);
 	if (status)
 		return status;
+	if (xdr_stream_decode_u64(argp->xdr, &copy->cp_src_pos) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u64(argp->xdr, &copy->cp_dst_pos) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u64(argp->xdr, &copy->cp_count) < 0)
+		return nfserr_bad_xdr;
+	/* ca_consecutive: we always do consecutive copies */
+	if (xdr_stream_decode_u32(argp->xdr, &consecutive) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &copy->cp_synchronous) < 0)
+		return nfserr_bad_xdr;
 
-	READ_BUF(8 + 8 + 8 + 4 + 4 + 4);
-	p = xdr_decode_hyper(p, &copy->cp_src_pos);
-	p = xdr_decode_hyper(p, &copy->cp_dst_pos);
-	p = xdr_decode_hyper(p, &copy->cp_count);
-	p++; /* ca_consecutive: we always do consecutive copies */
-	copy->cp_synchronous = be32_to_cpup(p++);
-
-	count = be32_to_cpup(p++);
-
+	if (xdr_stream_decode_u32(argp->xdr, &count) < 0)
+		return nfserr_bad_xdr;
 	copy->cp_intra = false;
 	if (count == 0) { /* intra-server copy */
 		copy->cp_intra = true;
-		goto intra;
+		return nfs_ok;
 	}
 
-	/* decode all the supplied server addresses but use first */
+	/* decode all the supplied server addresses but use only the first */
 	status = nfsd4_decode_nl4_server(argp, &copy->cp_src);
 	if (status)
 		return status;
 
 	ns_dummy = kmalloc(sizeof(struct nl4_server), GFP_KERNEL);
 	if (ns_dummy == NULL)
-		return nfserrno(-ENOMEM);
+		return nfserrno(-ENOMEM);	/* XXX: jukebox? */
 	for (i = 0; i < count - 1; i++) {
 		status = nfsd4_decode_nl4_server(argp, ns_dummy);
 		if (status) {
@@ -1966,9 +1970,8 @@ nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)
 		}
 	}
 	kfree(ns_dummy);
-intra:
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32
@@ -4718,7 +4721,7 @@ nfsd4_encode_copy(struct nfsd4_compoundres *resp, __be32 nfserr,
 	__be32 *p;
 
 	nfserr = nfsd42_encode_write_res(resp, &copy->cp_res,
-			copy->cp_synchronous);
+					 !!copy->cp_synchronous);
 	if (nfserr)
 		return nfserr;
 
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 232529bc1b79..facc5762bf83 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -554,7 +554,7 @@ struct nfsd4_copy {
 	bool			cp_intra;
 
 	/* both */
-	bool		cp_synchronous;
+	u32			cp_synchronous;
 
 	/* response */
 	struct nfsd42_write_res	cp_res;



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 075/118] NFSD: Replace READ* macros in nfsd4_decode_seek()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (73 preceding siblings ...)
  2020-11-20 20:40 ` [PATCH v2 074/118] NFSD: Replace READ* macros in nfsd4_decode_copy() Chuck Lever
@ 2020-11-20 20:40 ` Chuck Lever
  2020-11-20 20:40 ` [PATCH v2 076/118] NFSD: Replace READ* macros in nfsd4_decode_xattr_name() Chuck Lever
                   ` (42 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:40 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 84d69c436fd3..520a3c78ea5b 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1996,17 +1996,17 @@ nfsd4_decode_copy_notify(struct nfsd4_compoundargs *argp,
 static __be32
 nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek)
 {
-	DECODE_HEAD;
+	__be32 status;
 
 	status = nfsd4_decode_stateid4(argp, &seek->seek_stateid);
 	if (status)
 		return status;
+	if (xdr_stream_decode_u64(argp->xdr, &seek->seek_offset) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &seek->seek_whence) < 0)
+		return nfserr_bad_xdr;
 
-	READ_BUF(8 + 4);
-	p = xdr_decode_hyper(p, &seek->seek_offset);
-	seek->seek_whence = be32_to_cpup(p);
-
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 /*



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 076/118] NFSD: Replace READ* macros in nfsd4_decode_xattr_name()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (74 preceding siblings ...)
  2020-11-20 20:40 ` [PATCH v2 075/118] NFSD: Replace READ* macros in nfsd4_decode_seek() Chuck Lever
@ 2020-11-20 20:40 ` Chuck Lever
  2020-11-20 20:40 ` [PATCH v2 077/118] NFSD: Replace READ* macros in nfsd4_decode_setxattr() Chuck Lever
                   ` (41 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:40 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 520a3c78ea5b..e1f8de971c0a 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2069,25 +2069,22 @@ nfsd4_vbuf_from_vector(struct nfsd4_compoundargs *argp, struct xdr_buf *xdr,
 static __be32
 nfsd4_decode_xattr_name(struct nfsd4_compoundargs *argp, char **namep)
 {
-	DECODE_HEAD;
 	char *name, *sp, *dp;
 	u32 namelen, cnt;
+	__be32 *p;
 
-	READ_BUF(4);
-	namelen = be32_to_cpup(p++);
-
+	if (xdr_stream_decode_u32(argp->xdr, &namelen) < 0)
+		return nfserr_bad_xdr;
 	if (namelen > (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN))
 		return nfserr_nametoolong;
-
 	if (namelen == 0)
-		goto xdr_error;
-
-	READ_BUF(namelen);
-
+		return nfserr_bad_xdr;
+	p = xdr_inline_decode(argp->xdr, namelen);
+	if (!p)
+		return nfserr_bad_xdr;
 	name = svcxdr_tmpalloc(argp, namelen + XATTR_USER_PREFIX_LEN + 1);
 	if (!name)
 		return nfserr_jukebox;
-
 	memcpy(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
 
 	/*
@@ -2100,14 +2097,14 @@ nfsd4_decode_xattr_name(struct nfsd4_compoundargs *argp, char **namep)
 
 	while (cnt-- > 0) {
 		if (*sp == '\0')
-			goto xdr_error;
+			return nfserr_bad_xdr;
 		*dp++ = *sp++;
 	}
 	*dp = '\0';
 
 	*namep = name;
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 /*



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 077/118] NFSD: Replace READ* macros in nfsd4_decode_setxattr()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (75 preceding siblings ...)
  2020-11-20 20:40 ` [PATCH v2 076/118] NFSD: Replace READ* macros in nfsd4_decode_xattr_name() Chuck Lever
@ 2020-11-20 20:40 ` Chuck Lever
  2020-11-20 20:40 ` [PATCH v2 078/118] NFSD: Replace READ* macros in nfsd4_decode_listxattrs() Chuck Lever
                   ` (40 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:40 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index e1f8de971c0a..6c471fa1fae3 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2136,11 +2136,11 @@ static __be32
 nfsd4_decode_setxattr(struct nfsd4_compoundargs *argp,
 		      struct nfsd4_setxattr *setxattr)
 {
-	DECODE_HEAD;
 	u32 flags, maxcount, size;
+	__be32 status;
 
-	READ_BUF(4);
-	flags = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &flags) < 0)
+		return nfserr_bad_xdr;
 
 	if (flags > SETXATTR4_REPLACE)
 		return nfserr_inval;
@@ -2153,8 +2153,8 @@ nfsd4_decode_setxattr(struct nfsd4_compoundargs *argp,
 	maxcount = svc_max_payload(argp->rqstp);
 	maxcount = min_t(u32, XATTR_SIZE_MAX, maxcount);
 
-	READ_BUF(4);
-	size = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &size) < 0)
+		return nfserr_bad_xdr;
 	if (size > maxcount)
 		return nfserr_xattr2big;
 
@@ -2163,12 +2163,12 @@ nfsd4_decode_setxattr(struct nfsd4_compoundargs *argp,
 		struct xdr_buf payload;
 
 		if (!xdr_stream_subsegment(argp->xdr, &payload, size))
-			goto xdr_error;
+			return nfserr_bad_xdr;
 		status = nfsd4_vbuf_from_vector(argp, &payload,
 						&setxattr->setxa_buf, size);
 	}
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 078/118] NFSD: Replace READ* macros in nfsd4_decode_listxattrs()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (76 preceding siblings ...)
  2020-11-20 20:40 ` [PATCH v2 077/118] NFSD: Replace READ* macros in nfsd4_decode_setxattr() Chuck Lever
@ 2020-11-20 20:40 ` Chuck Lever
  2020-11-20 20:40 ` [PATCH v2 079/118] NFSD: Replace READ* macros in nfsd4_decode_compound() Chuck Lever
                   ` (39 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:40 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 6c471fa1fae3..84c95a255826 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2175,11 +2175,10 @@ static __be32
 nfsd4_decode_listxattrs(struct nfsd4_compoundargs *argp,
 			struct nfsd4_listxattrs *listxattrs)
 {
-	DECODE_HEAD;
 	u32 maxcount;
 
-	READ_BUF(12);
-	p = xdr_decode_hyper(p, &listxattrs->lsxa_cookie);
+	if (xdr_stream_decode_u64(argp->xdr, &listxattrs->lsxa_cookie) < 0)
+		return nfserr_bad_xdr;
 
 	/*
 	 * If the cookie  is too large to have even one user.x attribute
@@ -2189,7 +2188,8 @@ nfsd4_decode_listxattrs(struct nfsd4_compoundargs *argp,
 	    (XATTR_LIST_MAX / (XATTR_USER_PREFIX_LEN + 2)))
 		return nfserr_badcookie;
 
-	maxcount = be32_to_cpup(p++);
+	if (xdr_stream_decode_u32(argp->xdr, &maxcount) < 0)
+		return nfserr_bad_xdr;
 	if (maxcount < 8)
 		/* Always need at least 2 words (length and one character) */
 		return nfserr_inval;
@@ -2197,7 +2197,7 @@ nfsd4_decode_listxattrs(struct nfsd4_compoundargs *argp,
 	maxcount = min(maxcount, svc_max_payload(argp->rqstp));
 	listxattrs->lsxa_maxcount = maxcount;
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 079/118] NFSD: Replace READ* macros in nfsd4_decode_compound()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (77 preceding siblings ...)
  2020-11-20 20:40 ` [PATCH v2 078/118] NFSD: Replace READ* macros in nfsd4_decode_listxattrs() Chuck Lever
@ 2020-11-20 20:40 ` Chuck Lever
  2020-11-20 20:40 ` [PATCH v2 080/118] NFSD: Remove macros that are no longer used Chuck Lever
                   ` (38 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:40 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4proc.c |    2 +
 fs/nfsd/nfs4xdr.c  |   70 ++++++++++++++++++++++------------------------------
 fs/nfsd/xdr4.h     |    2 +
 3 files changed, 31 insertions(+), 43 deletions(-)

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 07756483aa70..b1a3f5cc8319 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -3282,7 +3282,7 @@ int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op)
 void warn_on_nonidempotent_op(struct nfsd4_op *op)
 {
 	if (OPDESC(op)->op_flags & OP_MODIFIES_SOMETHING) {
-		pr_err("unable to encode reply to nonidempotent op %d (%s)\n",
+		pr_err("unable to encode reply to nonidempotent op %u (%s)\n",
 			op->opnum, nfsd4_op_name(op->opnum));
 		WARN_ON_ONCE(1);
 	}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 84c95a255826..da9b458cf9dc 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -184,28 +184,6 @@ svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, u32 len)
 	return p;
 }
 
-/**
- * savemem - duplicate a chunk of memory for later processing
- * @argp: NFSv4 compound argument structure to be freed with
- * @p: pointer to be duplicated
- * @nbytes: length to be duplicated
- *
- * Returns a pointer to a copy of @nbytes bytes of memory at @p
- * that are preserved until processing of the NFSv4 compound
- * operation described by @argp finishes.
- */
-static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
-{
-	void *ret;
-
-	ret = svcxdr_tmpalloc(argp, nbytes);
-	if (!ret)
-		return NULL;
-	memcpy(ret, p, nbytes);
-	return ret;
-}
-
-
 /*
  * NFSv4 basic data type decoders
  */
@@ -2327,40 +2305,51 @@ nfsd4_opnum_in_range(struct nfsd4_compoundargs *argp, struct nfsd4_op *op)
 static __be32
 nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
 {
-	DECODE_HEAD;
 	struct nfsd4_op *op;
 	bool cachethis = false;
 	int auth_slack= argp->rqstp->rq_auth_slack;
 	int max_reply = auth_slack + 8; /* opcnt, status */
 	int readcount = 0;
 	int readbytes = 0;
+	__be32 *p;
 	int i;
 
-	READ_BUF(4);
-	argp->taglen = be32_to_cpup(p++);
-	READ_BUF(argp->taglen);
-	SAVEMEM(argp->tag, argp->taglen);
-	READ_BUF(8);
-	argp->minorversion = be32_to_cpup(p++);
-	argp->opcnt = be32_to_cpup(p++);
-	max_reply += 4 + (XDR_QUADLEN(argp->taglen) << 2);
-
-	if (argp->taglen > NFSD4_MAX_TAGLEN)
-		goto xdr_error;
+	if (xdr_stream_decode_u32(argp->xdr, &argp->taglen) < 0)
+		return nfserr_bad_xdr;
+	max_reply += XDR_UNIT;
+	argp->tag = NULL;
+	if (unlikely(argp->taglen)) {
+		if (argp->taglen > NFSD4_MAX_TAGLEN)
+			return nfserr_bad_xdr;
+		p = xdr_inline_decode(argp->xdr, argp->taglen);
+		if (!p)
+			return nfserr_bad_xdr;
+		argp->tag = svcxdr_tmpalloc(argp, argp->taglen);
+		if (!argp->tag)
+			return nfserr_jukebox;
+		memcpy(argp->tag, p, argp->taglen);
+		max_reply += xdr_align_size(argp->taglen);
+	}
+
+	if (xdr_stream_decode_u32(argp->xdr, &argp->minorversion) < 0)
+		return nfserr_bad_xdr;
+	if (xdr_stream_decode_u32(argp->xdr, &argp->opcnt) < 0)
+		return nfserr_bad_xdr;
+
 	/*
 	 * NFS4ERR_RESOURCE is a more helpful error than GARBAGE_ARGS
 	 * here, so we return success at the xdr level so that
 	 * nfsd4_proc can handle this is an NFS-level error.
 	 */
 	if (argp->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
-		return 0;
+		return nfs_ok;
 
 	if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
 		argp->ops = kzalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL);
 		if (!argp->ops) {
 			argp->ops = argp->iops;
 			dprintk("nfsd: couldn't allocate room for COMPOUND\n");
-			goto xdr_error;
+			return nfserr_bad_xdr;
 		}
 	}
 
@@ -2371,9 +2360,8 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
 		op = &argp->ops[i];
 		op->replay = NULL;
 
-		READ_BUF(4);
-		op->opnum = be32_to_cpup(p++);
-
+		if (xdr_stream_decode_u32(argp->xdr, &op->opnum) < 0)
+			return nfserr_bad_xdr;
 		if (nfsd4_opnum_in_range(argp, op))
 			op->status = nfsd4_dec_ops[op->opnum](argp, &op->u);
 		else {
@@ -2415,7 +2403,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
 	if (readcount > 1 || max_reply > PAGE_SIZE - auth_slack)
 		clear_bit(RQ_SPLICE_OK, &argp->rqstp->rq_flags);
 
-	DECODE_TAIL;
+	return nfs_ok;
 }
 
 static __be32 *encode_change(__be32 *p, struct kstat *stat, struct inode *inode,
@@ -5325,7 +5313,7 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
 	if (op->status && opdesc &&
 			!(opdesc->op_flags & OP_NONTRIVIAL_ERROR_ENCODE))
 		goto status;
-	BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) ||
+	BUG_ON(op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) ||
 	       !nfsd4_enc_ops[op->opnum]);
 	encoder = nfsd4_enc_ops[op->opnum];
 	op->status = encoder(resp, op->status, &op->u);
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index facc5762bf83..2c31f3a7d7c7 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -615,7 +615,7 @@ struct nfsd4_copy_notify {
 };
 
 struct nfsd4_op {
-	int					opnum;
+	u32					opnum;
 	const struct nfsd4_operation *		opdesc;
 	__be32					status;
 	union nfsd4_op_u {



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 080/118] NFSD: Remove macros that are no longer used
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (78 preceding siblings ...)
  2020-11-20 20:40 ` [PATCH v2 079/118] NFSD: Replace READ* macros in nfsd4_decode_compound() Chuck Lever
@ 2020-11-20 20:40 ` Chuck Lever
  2020-11-20 20:40 ` [PATCH v2 081/118] NFSD: Update GETATTR3args decoder to use struct xdr_stream Chuck Lever
                   ` (37 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:40 UTC (permalink / raw)
  To: linux-nfs

Now that all the NFSv4 decoder functions have been converted to
make direct calls to the xdr helpers, remove the unused C macros.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |   40 ----------------------------------------
 fs/nfsd/xdr4.h    |    9 ---------
 2 files changed, 49 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index da9b458cf9dc..b101b8b3ddbe 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -100,45 +100,6 @@ check_filename(char *str, int len)
 	return 0;
 }
 
-#define DECODE_HEAD				\
-	__be32 *p;				\
-	__be32 status
-#define DECODE_TAIL				\
-	status = 0;				\
-out:						\
-	return status;				\
-xdr_error:					\
-	dprintk("NFSD: xdr error (%s:%d)\n",	\
-			__FILE__, __LINE__);	\
-	status = nfserr_bad_xdr;		\
-	goto out
-
-#define READMEM(x,nbytes) do {			\
-	x = (char *)p;				\
-	p += XDR_QUADLEN(nbytes);		\
-} while (0)
-#define SAVEMEM(x,nbytes) do {			\
-	if (!(x = (p==argp->tmp || p == argp->tmpp) ? \
- 		savemem(argp, p, nbytes) :	\
- 		(char *)p)) {			\
-		dprintk("NFSD: xdr error (%s:%d)\n", \
-				__FILE__, __LINE__); \
-		goto xdr_error;			\
-		}				\
-	p += XDR_QUADLEN(nbytes);		\
-} while (0)
-#define COPYMEM(x,nbytes) do {			\
-	memcpy((x), p, nbytes);			\
-	p += XDR_QUADLEN(nbytes);		\
-} while (0)
-#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)
 {
 	return (clid->cl_boot == 0) && (clid->cl_id == 0);
@@ -5406,7 +5367,6 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p)
 	struct nfsd4_compoundargs *args = rqstp->rq_argp;
 
 	/* svcxdr_tmp_alloc */
-	args->tmpp = NULL;
 	args->to_free = NULL;
 
 	args->xdr = &rqstp->rq_xdr_stream;
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 2c31f3a7d7c7..e12fbe382e3f 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -386,13 +386,6 @@ struct nfsd4_setclientid_confirm {
 	nfs4_verifier	sc_confirm;
 };
 
-struct nfsd4_saved_compoundargs {
-	__be32 *p;
-	__be32 *end;
-	int pagelen;
-	struct page **pagelist;
-};
-
 struct nfsd4_test_stateid_id {
 	__be32			ts_id_status;
 	stateid_t		ts_id_stateid;
@@ -696,8 +689,6 @@ struct svcxdr_tmpbuf {
 
 struct nfsd4_compoundargs {
 	/* scratch variables for XDR decode */
-	__be32				tmp[8];
-	__be32 *			tmpp;
 	struct xdr_stream		*xdr;
 	struct svcxdr_tmpbuf		*to_free;
 	struct svc_rqst			*rqstp;



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 081/118] NFSD: Update GETATTR3args decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (79 preceding siblings ...)
  2020-11-20 20:40 ` [PATCH v2 080/118] NFSD: Remove macros that are no longer used Chuck Lever
@ 2020-11-20 20:40 ` Chuck Lever
  2020-11-20 20:41 ` [PATCH v2 082/118] NFSD: Update ACCESS3arg " Chuck Lever
                   ` (36 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:40 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 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 581a93b17bee..b6c2c1c837a0 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -684,7 +684,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
@@ -715,7 +714,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 a6718b952975..f1bff0547da9 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 enum xdr_decode_result
+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 XDR_DECODE_FAILED;
+	if (size == 0 || size > NFS3_FHSIZE)
+		return XDR_DECODE_FAILED;
+	p = xdr_inline_decode(xdr, size);
+	if (!p)
+		return XDR_DECODE_FAILED;
+	fh_init(fhp, NFS3_FHSIZE);
+	fhp->fh_handle.fh_size = size;
+	memcpy(&fhp->fh_handle.fh_base, p, size);
+
+	return XDR_DECODE_DONE;
+}
+
 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_xdr_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 *);



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 082/118] NFSD: Update ACCESS3arg decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (80 preceding siblings ...)
  2020-11-20 20:40 ` [PATCH v2 081/118] NFSD: Update GETATTR3args decoder to use struct xdr_stream Chuck Lever
@ 2020-11-20 20:41 ` Chuck Lever
  2020-11-20 20:41 ` [PATCH v2 083/118] NFSD: Update READ3arg " Chuck Lever
                   ` (35 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:41 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3xdr.c |   11 ++++++-----
 fs/nfsd/xdr3.h    |    2 +-
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index f1bff0547da9..600bc45db66e 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -369,14 +369,15 @@ nfs3svc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfs3svc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_accessargs *args = rqstp->rq_argp;
 
-	p = decode_fh(p, &args->fh);
-	if (!p)
-		return 0;
-	args->access = ntohl(*p++);
+	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u32(xdr, &args->access) < 0)
+		return XDR_DECODE_FAILED;
 
-	return xdr_argsize_check(rqstp, p);
+	return XDR_DECODE_DONE;
 }
 
 int
diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
index 62ea669768cf..a4dce4baec7c 100644
--- a/fs/nfsd/xdr3.h
+++ b/fs/nfsd/xdr3.h
@@ -25,7 +25,7 @@ struct nfsd3_diropargs {
 
 struct nfsd3_accessargs {
 	struct svc_fh		fh;
-	unsigned int		access;
+	__u32			access;
 };
 
 struct nfsd3_readargs {



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 083/118] NFSD: Update READ3arg decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (81 preceding siblings ...)
  2020-11-20 20:41 ` [PATCH v2 082/118] NFSD: Update ACCESS3arg " Chuck Lever
@ 2020-11-20 20:41 ` Chuck Lever
  2020-11-20 20:41 ` [PATCH v2 084/118] NFSD: Update WRITE3arg " Chuck Lever
                   ` (34 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:41 UTC (permalink / raw)
  To: linux-nfs

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>
---
 fs/nfsd/nfs3proc.c |   23 ++++++++++++++++++-----
 fs/nfsd/nfs3xdr.c  |   27 +++++++--------------------
 fs/nfsd/xdr3.h     |    1 -
 3 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index b6c2c1c837a0..5c0664486485 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 600bc45db66e..2b51686c238f 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -383,31 +383,18 @@ 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_xdr_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 (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
+		return XDR_DECODE_FAILED;
+	p = xdr_inline_decode(xdr, sizeof(__be32) * 3);
 	if (!p)
-		return 0;
+		return XDR_DECODE_FAILED;
 	p = xdr_decode_hyper(p, &args->offset);
+	args->count = be32_to_cpup(p);
 
-	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 XDR_DECODE_DONE;
 }
 
 int
diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
index a4dce4baec7c..7dfeeaa4e1df 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 {



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 084/118] NFSD: Update WRITE3arg decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (82 preceding siblings ...)
  2020-11-20 20:41 ` [PATCH v2 083/118] NFSD: Update READ3arg " Chuck Lever
@ 2020-11-20 20:41 ` Chuck Lever
  2020-11-20 20:41 ` [PATCH v2 085/118] NFSD: Update READLINK3arg " Chuck Lever
                   ` (33 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:41 UTC (permalink / raw)
  To: linux-nfs

As part of the update, open code that sanity-checks the size of the
data payload against the length of the RPC Call message has to be
re-implemented to use xdr_stream infrastructure.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3xdr.c |   56 +++++++++++++++++++++--------------------------------
 1 file changed, 22 insertions(+), 34 deletions(-)

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 2b51686c238f..38dad447a760 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -400,53 +400,41 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_writeargs *args = rqstp->rq_argp;
-	unsigned int len, hdr, dlen;
 	u32 max_blocksize = svc_max_payload(rqstp);
 	struct kvec *head = rqstp->rq_arg.head;
 	struct kvec *tail = rqstp->rq_arg.tail;
+	size_t remaining;
 
-	p = decode_fh(p, &args->fh);
+	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
+		return XDR_DECODE_FAILED;
+	p = xdr_inline_decode(xdr, sizeof(__be32) * 5);
 	if (!p)
-		return 0;
+		return XDR_DECODE_FAILED;
 	p = xdr_decode_hyper(p, &args->offset);
+	args->count = be32_to_cpup(p++);
+	args->stable = be32_to_cpup(p++);
 
-	args->count = ntohl(*p++);
-	args->stable = ntohl(*p++);
-	len = args->len = ntohl(*p++);
-	if ((void *)p > head->iov_base + head->iov_len)
-		return 0;
-	/*
-	 * The count must equal the amount of data passed.
-	 */
-	if (args->count != args->len)
-		return 0;
-
-	/*
-	 * Check to make sure that we got the right number of
-	 * bytes.
-	 */
-	hdr = (void*)p - head->iov_base;
-	dlen = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len - hdr;
-	/*
-	 * Round the length of the data which was specified up to
-	 * the next multiple of XDR units and then compare that
-	 * against the length which was actually received.
-	 * Note that when RPCSEC/GSS (for example) is used, the
-	 * data buffer can be padded so dlen might be larger
-	 * than required.  It must never be smaller.
-	 */
-	if (dlen < XDR_QUADLEN(len)*4)
-		return 0;
+	/* opaque data */
+	args->len = be32_to_cpup(p++);
 
+	/* request sanity */
+	if (args->count != args->len)
+		return XDR_DECODE_FAILED;
+	remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len;
+	remaining -= xdr_stream_pos(xdr);
+	if (remaining < xdr_align_size(args->len))
+		return XDR_DECODE_FAILED;
 	if (args->count > max_blocksize) {
 		args->count = max_blocksize;
-		len = args->len = max_blocksize;
+		args->len = max_blocksize;
 	}
 
-	args->first.iov_base = (void *)p;
-	args->first.iov_len = head->iov_len - hdr;
-	return 1;
+	args->first.iov_base = p;
+	args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
+
+	return XDR_DECODE_DONE;
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 085/118] NFSD: Update READLINK3arg decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (83 preceding siblings ...)
  2020-11-20 20:41 ` [PATCH v2 084/118] NFSD: Update WRITE3arg " Chuck Lever
@ 2020-11-20 20:41 ` Chuck Lever
  2020-11-20 20:41 ` [PATCH v2 086/118] NFSD: Add helper to set up the pages where the dirlist is encoded Chuck Lever
                   ` (32 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:41 UTC (permalink / raw)
  To: linux-nfs

The NFSv3 READLINK request takes a single filehandle, so it can
re-use GETATTR's decoder.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3proc.c |    9 +++++----
 fs/nfsd/nfs3xdr.c  |   13 -------------
 fs/nfsd/xdr3.h     |    6 ------
 3 files changed, 5 insertions(+), 23 deletions(-)

diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 5c0664486485..2c4fe7b8723d 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -124,15 +124,16 @@ nfsd3_proc_access(struct svc_rqst *rqstp)
 static __be32
 nfsd3_proc_readlink(struct svc_rqst *rqstp)
 {
-	struct nfsd3_readlinkargs *argp = rqstp->rq_argp;
+	struct nfsd_fhandle *argp = rqstp->rq_argp;
 	struct nfsd3_readlinkres *resp = rqstp->rq_resp;
+	char *buffer = page_address(*(rqstp->rq_next_page++));
 
 	dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
 
 	/* Read the symlink. */
 	fh_copy(&resp->fh, &argp->fh);
 	resp->len = NFS3_MAXPATHLEN;
-	resp->status = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len);
+	resp->status = nfsd_readlink(rqstp, &resp->fh, buffer, &resp->len);
 	return rpc_success;
 }
 
@@ -764,10 +765,10 @@ static const struct svc_procedure nfsd_procedures3[22] = {
 	},
 	[NFS3PROC_READLINK] = {
 		.pc_func = nfsd3_proc_readlink,
-		.pc_decode = nfs3svc_decode_readlinkargs,
+		.pc_decode = nfs3svc_decode_fhandleargs,
 		.pc_encode = nfs3svc_encode_readlinkres,
 		.pc_release = nfs3svc_release_fhandle,
-		.pc_argsize = sizeof(struct nfsd3_readlinkargs),
+		.pc_argsize = sizeof(struct nfsd_fhandle),
 		.pc_ressize = sizeof(struct nfsd3_readlinkres),
 		.pc_cachetype = RC_NOCACHE,
 		.pc_xdrressize = ST+pAT+1+NFS3_MAXPATHLEN/4,
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 38dad447a760..35804abc9c1f 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -537,19 +537,6 @@ nfs3svc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p)
 	return xdr_argsize_check(rqstp, p);
 }
 
-int
-nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p)
-{
-	struct nfsd3_readlinkargs *args = rqstp->rq_argp;
-
-	p = decode_fh(p, &args->fh);
-	if (!p)
-		return 0;
-	args->buffer = page_address(*(rqstp->rq_next_page++));
-
-	return xdr_argsize_check(rqstp, p);
-}
-
 int
 nfs3svc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p)
 {
diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
index 7dfeeaa4e1df..08f909142ddf 100644
--- a/fs/nfsd/xdr3.h
+++ b/fs/nfsd/xdr3.h
@@ -70,11 +70,6 @@ struct nfsd3_renameargs {
 	unsigned int		tlen;
 };
 
-struct nfsd3_readlinkargs {
-	struct svc_fh		fh;
-	char *			buffer;
-};
-
 struct nfsd3_linkargs {
 	struct svc_fh		ffh;
 	struct svc_fh		tfh;
@@ -282,7 +277,6 @@ int nfs3svc_decode_createargs(struct svc_rqst *, __be32 *);
 int nfs3svc_decode_mkdirargs(struct svc_rqst *, __be32 *);
 int nfs3svc_decode_mknodargs(struct svc_rqst *, __be32 *);
 int nfs3svc_decode_renameargs(struct svc_rqst *, __be32 *);
-int nfs3svc_decode_readlinkargs(struct svc_rqst *, __be32 *);
 int nfs3svc_decode_linkargs(struct svc_rqst *, __be32 *);
 int nfs3svc_decode_symlinkargs(struct svc_rqst *, __be32 *);
 int nfs3svc_decode_readdirargs(struct svc_rqst *, __be32 *);



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 086/118] NFSD: Add helper to set up the pages where the dirlist is encoded
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (84 preceding siblings ...)
  2020-11-20 20:41 ` [PATCH v2 085/118] NFSD: Update READLINK3arg " Chuck Lever
@ 2020-11-20 20:41 ` Chuck Lever
  2020-11-20 20:41 ` [PATCH v2 087/118] NFSD: Update READDIR3args decoders to use struct xdr_stream Chuck Lever
                   ` (31 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:41 UTC (permalink / raw)
  To: linux-nfs

De-duplicate some code that is used by both READDIR and READDIRPLUS
to build the dirlist in the Reply. Because this code is not related
to decoding READ arguments, it is moved to a more appropriate spot.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3proc.c |   29 +++++++++++++++++++----------
 fs/nfsd/nfs3xdr.c  |   20 --------------------
 fs/nfsd/xdr3.h     |    1 -
 3 files changed, 19 insertions(+), 31 deletions(-)

diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 2c4fe7b8723d..a8aafbb4c0ac 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -435,6 +435,23 @@ nfsd3_proc_link(struct svc_rqst *rqstp)
 	return rpc_success;
 }
 
+static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp,
+				     struct nfsd3_readdirres *resp,
+				     int count)
+{
+	count = min_t(u32, count, svc_max_payload(rqstp));
+
+	/* Convert byte count to number of words (i.e. >> 2),
+	 * and reserve room for the NULL ptr & eof flag (-2 words) */
+	resp->buflen = (count >> 2) - 2;
+
+	resp->buffer = page_address(*rqstp->rq_next_page);
+	while (count > 0) {
+		rqstp->rq_next_page++;
+		count -= PAGE_SIZE;
+	}
+}
+
 /*
  * Read a portion of a directory.
  */
@@ -452,16 +469,12 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
 				SVCFH_fmt(&argp->fh),
 				argp->count, (u32) argp->cookie);
 
-	/* Make sure we've room for the NULL ptr & eof flag, and shrink to
-	 * client read size */
-	count = (argp->count >> 2) - 2;
+	nfsd3_init_dirlist_pages(rqstp, resp, argp->count);
 
 	/* Read directory and encode entries on the fly */
 	fh_copy(&resp->fh, &argp->fh);
 
-	resp->buflen = count;
 	resp->common.err = nfs_ok;
-	resp->buffer = argp->buffer;
 	resp->rqstp = rqstp;
 	offset = argp->cookie;
 
@@ -513,16 +526,12 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp)
 				SVCFH_fmt(&argp->fh),
 				argp->count, (u32) argp->cookie);
 
-	/* Convert byte count to number of words (i.e. >> 2),
-	 * and reserve room for the NULL ptr & eof flag (-2 words) */
-	resp->count = (argp->count >> 2) - 2;
+	nfsd3_init_dirlist_pages(rqstp, resp, argp->count);
 
 	/* Read directory and encode entries on the fly */
 	fh_copy(&resp->fh, &argp->fh);
 
 	resp->common.err = nfs_ok;
-	resp->buffer = argp->buffer;
-	resp->buflen = resp->count;
 	resp->rqstp = rqstp;
 	offset = argp->cookie;
 
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 35804abc9c1f..eceeda96f576 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -554,8 +554,6 @@ int
 nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p)
 {
 	struct nfsd3_readdirargs *args = rqstp->rq_argp;
-	int len;
-	u32 max_blocksize = svc_max_payload(rqstp);
 
 	p = decode_fh(p, &args->fh);
 	if (!p)
@@ -564,14 +562,6 @@ nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p)
 	args->verf   = p; p += 2;
 	args->dircount = ~0;
 	args->count  = ntohl(*p++);
-	len = args->count  = min_t(u32, args->count, max_blocksize);
-
-	while (len > 0) {
-		struct page *p = *(rqstp->rq_next_page++);
-		if (!args->buffer)
-			args->buffer = page_address(p);
-		len -= PAGE_SIZE;
-	}
 
 	return xdr_argsize_check(rqstp, p);
 }
@@ -580,8 +570,6 @@ int
 nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p)
 {
 	struct nfsd3_readdirargs *args = rqstp->rq_argp;
-	int len;
-	u32 max_blocksize = svc_max_payload(rqstp);
 
 	p = decode_fh(p, &args->fh);
 	if (!p)
@@ -591,14 +579,6 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p)
 	args->dircount = ntohl(*p++);
 	args->count    = ntohl(*p++);
 
-	len = args->count = min(args->count, max_blocksize);
-	while (len > 0) {
-		struct page *p = *(rqstp->rq_next_page++);
-		if (!args->buffer)
-			args->buffer = page_address(p);
-		len -= PAGE_SIZE;
-	}
-
 	return xdr_argsize_check(rqstp, p);
 }
 
diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
index 08f909142ddf..789a364d5e69 100644
--- a/fs/nfsd/xdr3.h
+++ b/fs/nfsd/xdr3.h
@@ -93,7 +93,6 @@ struct nfsd3_readdirargs {
 	__u32			dircount;
 	__u32			count;
 	__be32 *		verf;
-	__be32 *		buffer;
 };
 
 struct nfsd3_commitargs {



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 087/118] NFSD: Update READDIR3args decoders to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (85 preceding siblings ...)
  2020-11-20 20:41 ` [PATCH v2 086/118] NFSD: Add helper to set up the pages where the dirlist is encoded Chuck Lever
@ 2020-11-20 20:41 ` Chuck Lever
  2020-11-23 20:55   ` J. Bruce Fields
  2020-11-20 20:41 ` [PATCH v2 088/118] NFSD: Update COMMIT3arg decoder " Chuck Lever
                   ` (30 subsequent siblings)
  117 siblings, 1 reply; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:41 UTC (permalink / raw)
  To: linux-nfs

As an additional clean up, neither nfsd3_proc_readdir() nor
nfsd3_proc_readdirplus() make use of the dircount argument, so
remove it.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3xdr.c |   41 +++++++++++++++++++++++++----------------
 fs/nfsd/xdr3.h    |    1 -
 2 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index eceeda96f576..05fa16d91564 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -553,33 +553,42 @@ nfs3svc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_readdirargs *args = rqstp->rq_argp;
 
-	p = decode_fh(p, &args->fh);
-	if (!p)
-		return 0;
-	p = xdr_decode_hyper(p, &args->cookie);
-	args->verf   = p; p += 2;
-	args->dircount = ~0;
-	args->count  = ntohl(*p++);
+	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
+		return XDR_DECODE_FAILED;
+	args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
+	if (!args->verf)
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
+		return XDR_DECODE_FAILED;
 
-	return xdr_argsize_check(rqstp, p);
+	return XDR_DECODE_DONE;
 }
 
 int
 nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_readdirargs *args = rqstp->rq_argp;
+	u32 dircount;
 
-	p = decode_fh(p, &args->fh);
-	if (!p)
-		return 0;
-	p = xdr_decode_hyper(p, &args->cookie);
-	args->verf     = p; p += 2;
-	args->dircount = ntohl(*p++);
-	args->count    = ntohl(*p++);
+	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
+		return XDR_DECODE_FAILED;
+	args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
+	if (!args->verf)
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u32(xdr, &dircount) < 0)
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
+		return XDR_DECODE_FAILED;
 
-	return xdr_argsize_check(rqstp, p);
+	return XDR_DECODE_DONE;
 }
 
 int
diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
index 789a364d5e69..64af5b01c5d7 100644
--- a/fs/nfsd/xdr3.h
+++ b/fs/nfsd/xdr3.h
@@ -90,7 +90,6 @@ struct nfsd3_symlinkargs {
 struct nfsd3_readdirargs {
 	struct svc_fh		fh;
 	__u64			cookie;
-	__u32			dircount;
 	__u32			count;
 	__be32 *		verf;
 };



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 088/118] NFSD: Update COMMIT3arg decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (86 preceding siblings ...)
  2020-11-20 20:41 ` [PATCH v2 087/118] NFSD: Update READDIR3args decoders to use struct xdr_stream Chuck Lever
@ 2020-11-20 20:41 ` Chuck Lever
  2020-11-20 20:41 ` [PATCH v2 089/118] NFSD: Update the NFSv3 DIROPargs " Chuck Lever
                   ` (29 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:41 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3xdr.c |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 05fa16d91564..a74c309ad429 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -594,14 +594,18 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_commitargs *args = rqstp->rq_argp;
-	p = decode_fh(p, &args->fh);
+
+	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
+		return XDR_DECODE_FAILED;
+	p = xdr_inline_decode(xdr, sizeof(__be32) * 3);
 	if (!p)
-		return 0;
+		return XDR_DECODE_FAILED;
 	p = xdr_decode_hyper(p, &args->offset);
-	args->count = ntohl(*p++);
+	args->count = be32_to_cpup(p);
 
-	return xdr_argsize_check(rqstp, p);
+	return XDR_DECODE_DONE;
 }
 
 /*



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 089/118] NFSD: Update the NFSv3 DIROPargs decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (87 preceding siblings ...)
  2020-11-20 20:41 ` [PATCH v2 088/118] NFSD: Update COMMIT3arg decoder " Chuck Lever
@ 2020-11-20 20:41 ` Chuck Lever
  2020-11-20 20:41 ` [PATCH v2 090/118] NFSD: Update the RENAME3args " Chuck Lever
                   ` (28 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:41 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3xdr.c |   41 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 36 insertions(+), 5 deletions(-)

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index a74c309ad429..763bac27cfda 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -117,6 +117,40 @@ decode_filename(__be32 *p, char **namp, unsigned int *lenp)
 	return p;
 }
 
+static enum xdr_decode_result
+svcxdr_decode_filename3(struct xdr_stream *xdr, char **name, unsigned int *len)
+{
+	u32 size, i;
+	__be32 *p;
+	char *c;
+
+	if (xdr_stream_decode_u32(xdr, &size) < 0)
+		return XDR_DECODE_FAILED;
+	if (size == 0 || size > NFS3_MAXNAMLEN)
+		return XDR_DECODE_FAILED;
+	p = xdr_inline_decode(xdr, size);
+	if (!p)
+		return XDR_DECODE_FAILED;
+
+	*len = size;
+	*name = (char *)p;
+	for (i = 0, c = *name; i < size; i++, c++) {
+		if (*c == '\0' || *c == '/')
+			return XDR_DECODE_FAILED;
+	}
+
+	return XDR_DECODE_DONE;
+}
+
+static enum xdr_decode_result
+svcxdr_decode_diropargs3(struct xdr_stream *xdr, struct svc_fh *fhp,
+			 char **name, unsigned int *len)
+{
+	if (!svcxdr_decode_nfs_fh3(xdr, fhp))
+		return XDR_DECODE_FAILED;
+	return svcxdr_decode_filename3(xdr, name, len);
+}
+
 static __be32 *
 decode_sattr3(__be32 *p, struct iattr *iap, struct user_namespace *userns)
 {
@@ -357,13 +391,10 @@ nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfs3svc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_diropargs *args = rqstp->rq_argp;
 
-	if (!(p = decode_fh(p, &args->fh))
-	 || !(p = decode_filename(p, &args->name, &args->len)))
-		return 0;
-
-	return xdr_argsize_check(rqstp, p);
+	return svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len);
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 090/118] NFSD: Update the RENAME3args decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (88 preceding siblings ...)
  2020-11-20 20:41 ` [PATCH v2 089/118] NFSD: Update the NFSv3 DIROPargs " Chuck Lever
@ 2020-11-20 20:41 ` Chuck Lever
  2020-11-20 20:41 ` [PATCH v2 091/118] NFSD: Update the LINK3args " Chuck Lever
                   ` (27 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:41 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3xdr.c |   11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 763bac27cfda..f941bd740963 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -557,15 +557,12 @@ nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfs3svc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_renameargs *args = rqstp->rq_argp;
 
-	if (!(p = decode_fh(p, &args->ffh))
-	 || !(p = decode_filename(p, &args->fname, &args->flen))
-	 || !(p = decode_fh(p, &args->tfh))
-	 || !(p = decode_filename(p, &args->tname, &args->tlen)))
-		return 0;
-
-	return xdr_argsize_check(rqstp, p);
+	if (!svcxdr_decode_diropargs3(xdr, &args->ffh, &args->fname, &args->flen))
+		return XDR_DECODE_FAILED;
+	return svcxdr_decode_diropargs3(xdr, &args->tfh, &args->tname, &args->tlen);
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 091/118] NFSD: Update the LINK3args decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (89 preceding siblings ...)
  2020-11-20 20:41 ` [PATCH v2 090/118] NFSD: Update the RENAME3args " Chuck Lever
@ 2020-11-20 20:41 ` Chuck Lever
  2020-11-20 20:41 ` [PATCH v2 092/118] NFSD: Update the SETATTR3args " Chuck Lever
                   ` (26 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:41 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3xdr.c |   10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index f941bd740963..b27c04c642b7 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -568,14 +568,12 @@ nfs3svc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfs3svc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_linkargs *args = rqstp->rq_argp;
 
-	if (!(p = decode_fh(p, &args->ffh))
-	 || !(p = decode_fh(p, &args->tfh))
-	 || !(p = decode_filename(p, &args->tname, &args->tlen)))
-		return 0;
-
-	return xdr_argsize_check(rqstp, p);
+	if (!svcxdr_decode_nfs_fh3(xdr, &args->ffh))
+		return XDR_DECODE_FAILED;
+	return svcxdr_decode_diropargs3(xdr, &args->tfh, &args->tname, &args->tlen);
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 092/118] NFSD: Update the SETATTR3args decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (90 preceding siblings ...)
  2020-11-20 20:41 ` [PATCH v2 091/118] NFSD: Update the LINK3args " Chuck Lever
@ 2020-11-20 20:41 ` Chuck Lever
  2020-11-20 20:42 ` [PATCH v2 093/118] NFSD: Update the CREATE3args " Chuck Lever
                   ` (25 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:41 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3xdr.c         |  150 ++++++++++++++++++++++++++++++++++++++++-----
 include/uapi/linux/nfs3.h |    6 ++
 2 files changed, 139 insertions(+), 17 deletions(-)

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index b27c04c642b7..5c46ab972a23 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -39,12 +39,18 @@ encode_time3(__be32 *p, struct timespec64 *time)
 	return p;
 }
 
-static __be32 *
-decode_time3(__be32 *p, struct timespec64 *time)
+static enum xdr_decode_result
+svcxdr_decode_nfstime3(struct xdr_stream *xdr, struct timespec64 *timep)
 {
-	time->tv_sec = ntohl(*p++);
-	time->tv_nsec = ntohl(*p++);
-	return p;
+	__be32 *p;
+
+	p = xdr_inline_decode(xdr, sizeof(__be32) * 2);
+	if (!p)
+		return XDR_DECODE_FAILED;
+	timep->tv_sec = be32_to_cpup(p++);
+	timep->tv_nsec = be32_to_cpup(p);
+
+	return XDR_DECODE_DONE;
 }
 
 static enum xdr_decode_result
@@ -151,6 +157,122 @@ svcxdr_decode_diropargs3(struct xdr_stream *xdr, struct svc_fh *fhp,
 	return svcxdr_decode_filename3(xdr, name, len);
 }
 
+static enum xdr_decode_result
+svcxdr_decode_sattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
+		     struct iattr *iap)
+{
+	u32 set_it;
+	__be32 *p;
+
+	iap->ia_valid = 0;
+
+	p = xdr_inline_decode(xdr, sizeof(__be32));
+	if (!p)
+		return XDR_DECODE_FAILED;
+	if (xdr_item_is_present(p)) {
+		u32 mode;
+
+		if (xdr_stream_decode_u32(xdr, &mode) < 0)
+			return XDR_DECODE_FAILED;
+		iap->ia_valid |= ATTR_MODE;
+		iap->ia_mode = mode;
+	}
+
+	p = xdr_inline_decode(xdr, sizeof(__be32));
+	if (!p)
+		return XDR_DECODE_FAILED;
+	if (xdr_item_is_present(p)) {
+		u32 uid;
+
+		if (xdr_stream_decode_u32(xdr, &uid) < 0)
+			return XDR_DECODE_FAILED;
+		iap->ia_uid = make_kuid(nfsd_user_namespace(rqstp), uid);
+		if (uid_valid(iap->ia_uid))
+			iap->ia_valid |= ATTR_UID;
+	}
+
+	p = xdr_inline_decode(xdr, sizeof(__be32));
+	if (!p)
+		return XDR_DECODE_FAILED;
+	if (xdr_item_is_present(p)) {
+		u32 gid;
+
+		if (xdr_stream_decode_u32(xdr, &gid) < 0)
+			return XDR_DECODE_FAILED;
+		iap->ia_gid = make_kgid(nfsd_user_namespace(rqstp), gid);
+		if (gid_valid(iap->ia_gid))
+			iap->ia_valid |= ATTR_GID;
+	}
+
+	p = xdr_inline_decode(xdr, sizeof(__be32));
+	if (!p)
+		return XDR_DECODE_FAILED;
+	if (xdr_item_is_present(p)) {
+		u64 newsize;
+
+		if (xdr_stream_decode_u64(xdr, &newsize) < 0)
+			return XDR_DECODE_FAILED;
+		iap->ia_valid |= ATTR_SIZE;
+		iap->ia_size = min_t(u64, newsize, NFS_OFFSET_MAX);
+	}
+
+	if (xdr_stream_decode_u32(xdr, &set_it) < 0)
+		return XDR_DECODE_FAILED;
+	switch (set_it) {
+	case DONT_CHANGE:
+		break;
+	case SET_TO_SERVER_TIME:
+		iap->ia_valid |= ATTR_ATIME;
+		break;
+	case SET_TO_CLIENT_TIME:
+		if (!svcxdr_decode_nfstime3(xdr, &iap->ia_atime))
+			return XDR_DECODE_FAILED;
+		iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
+		break;
+	default:
+		return XDR_DECODE_FAILED;
+	}
+
+	if (xdr_stream_decode_u32(xdr, &set_it) < 0)
+		return XDR_DECODE_FAILED;
+	switch (set_it) {
+	case DONT_CHANGE:
+		break;
+	case SET_TO_SERVER_TIME:
+		iap->ia_valid |= ATTR_MTIME;
+		break;
+	case SET_TO_CLIENT_TIME:
+		if (!svcxdr_decode_nfstime3(xdr, &iap->ia_mtime))
+			return XDR_DECODE_FAILED;
+		iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
+		break;
+	default:
+		return XDR_DECODE_FAILED;
+	}
+
+	return XDR_DECODE_DONE;
+}
+
+static enum xdr_decode_result
+svcxdr_decode_sattrguard3(struct xdr_stream *xdr, struct nfsd3_sattrargs *args)
+{
+	__be32 *p;
+
+	p = xdr_inline_decode(xdr, sizeof(__be32));
+	if (!p)
+		return XDR_DECODE_FAILED;
+	if (xdr_item_is_present(p)) {
+		p = xdr_inline_decode(xdr, sizeof(__be32) * 2);
+		if (!p)
+			return XDR_DECODE_FAILED;
+		args->check_guard = 1;
+		args->guardtime = be32_to_cpup(p);
+	} else
+		args->check_guard = 0;
+
+	return XDR_DECODE_DONE;
+}
+
 static __be32 *
 decode_sattr3(__be32 *p, struct iattr *iap, struct user_namespace *userns)
 {
@@ -372,20 +494,14 @@ nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_sattrargs *args = rqstp->rq_argp;
 
-	p = decode_fh(p, &args->fh);
-	if (!p)
-		return 0;
-	p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
-
-	if ((args->check_guard = ntohl(*p++)) != 0) { 
-		struct timespec64 time;
-		p = decode_time3(p, &time);
-		args->guardtime = time.tv_sec;
-	}
-
-	return xdr_argsize_check(rqstp, p);
+	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
+		return XDR_DECODE_FAILED;
+	if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs))
+		return XDR_DECODE_FAILED;
+	return svcxdr_decode_sattrguard3(xdr, args);
 }
 
 int
diff --git a/include/uapi/linux/nfs3.h b/include/uapi/linux/nfs3.h
index 37e4b34e6b43..c22ab77713bd 100644
--- a/include/uapi/linux/nfs3.h
+++ b/include/uapi/linux/nfs3.h
@@ -63,6 +63,12 @@ enum nfs3_ftype {
 	NF3BAD  = 8
 };
 
+enum nfs3_time_how {
+	DONT_CHANGE		= 0,
+	SET_TO_SERVER_TIME	= 1,
+	SET_TO_CLIENT_TIME	= 2,
+};
+
 struct nfs3_fh {
 	unsigned short size;
 	unsigned char  data[NFS3_FHSIZE];



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 093/118] NFSD: Update the CREATE3args decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (91 preceding siblings ...)
  2020-11-20 20:41 ` [PATCH v2 092/118] NFSD: Update the SETATTR3args " Chuck Lever
@ 2020-11-20 20:42 ` Chuck Lever
  2020-11-20 20:42 ` [PATCH v2 094/118] NFSD: Update the MKDIR3args " Chuck Lever
                   ` (24 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:42 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3xdr.c |   24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 5c46ab972a23..ba1b24f54443 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -587,26 +587,26 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_createargs *args = rqstp->rq_argp;
 
-	if (!(p = decode_fh(p, &args->fh))
-	 || !(p = decode_filename(p, &args->name, &args->len)))
-		return 0;
-
-	switch (args->createmode = ntohl(*p++)) {
+	if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u32(xdr, &args->createmode) < 0)
+		return XDR_DECODE_FAILED;
+	switch (args->createmode) {
 	case NFS3_CREATE_UNCHECKED:
 	case NFS3_CREATE_GUARDED:
-		p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
-		break;
+		return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
 	case NFS3_CREATE_EXCLUSIVE:
-		args->verf = p;
-		p += 2;
+		args->verf = xdr_inline_decode(xdr, NFS3_CREATEVERFSIZE);
+		if (!args->verf)
+			return XDR_DECODE_FAILED;
 		break;
 	default:
-		return 0;
+		return XDR_DECODE_FAILED;
 	}
-
-	return xdr_argsize_check(rqstp, p);
+	return XDR_DECODE_DONE;
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 094/118] NFSD: Update the MKDIR3args decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (92 preceding siblings ...)
  2020-11-20 20:42 ` [PATCH v2 093/118] NFSD: Update the CREATE3args " Chuck Lever
@ 2020-11-20 20:42 ` Chuck Lever
  2020-11-20 20:42 ` [PATCH v2 095/118] NFSD: Update the SYMLINK3args " Chuck Lever
                   ` (23 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:42 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3xdr.c |   10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index ba1b24f54443..ec4778f01472 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -612,14 +612,12 @@ nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_createargs *args = rqstp->rq_argp;
 
-	if (!(p = decode_fh(p, &args->fh)) ||
-	    !(p = decode_filename(p, &args->name, &args->len)))
-		return 0;
-	p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
-
-	return xdr_argsize_check(rqstp, p);
+	if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
+		return XDR_DECODE_FAILED;
+	return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 095/118] NFSD: Update the SYMLINK3args decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (93 preceding siblings ...)
  2020-11-20 20:42 ` [PATCH v2 094/118] NFSD: Update the MKDIR3args " Chuck Lever
@ 2020-11-20 20:42 ` Chuck Lever
  2020-11-20 20:42 ` [PATCH v2 096/118] NFSD: Update the MKNOD3args " Chuck Lever
                   ` (22 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:42 UTC (permalink / raw)
  To: linux-nfs

Similar to the WRITE decoder, code that checks the sanity of the
payload size is re-wired to work with xdr_stream infrastructure.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3xdr.c |   33 ++++++++++++++++++---------------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index ec4778f01472..6dfab4bd6c2c 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -623,26 +623,29 @@ nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_symlinkargs *args = rqstp->rq_argp;
-	char *base = (char *)p;
-	size_t dlen;
+	struct kvec *head = rqstp->rq_arg.head;
+	struct kvec *tail = rqstp->rq_arg.tail;
+	size_t remaining;
 
-	if (!(p = decode_fh(p, &args->ffh)) ||
-	    !(p = decode_filename(p, &args->fname, &args->flen)))
-		return 0;
-	p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
+	if (!svcxdr_decode_diropargs3(xdr, &args->ffh, &args->fname, &args->flen))
+		return XDR_DECODE_FAILED;
+	if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs))
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u32(xdr, &args->tlen) < 0)
+		return XDR_DECODE_FAILED;
 
-	args->tlen = ntohl(*p++);
+	/* request sanity */
+	remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len;
+	remaining -= xdr_stream_pos(xdr);
+	if (remaining < xdr_align_size(args->tlen))
+		return XDR_DECODE_FAILED;
 
-	args->first.iov_base = p;
-	args->first.iov_len = rqstp->rq_arg.head[0].iov_len;
-	args->first.iov_len -= (char *)p - base;
+	args->first.iov_base = xdr->p;
+	args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
 
-	dlen = args->first.iov_len + rqstp->rq_arg.page_len +
-	       rqstp->rq_arg.tail[0].iov_len;
-	if (dlen < XDR_QUADLEN(args->tlen) << 2)
-		return 0;
-	return 1;
+	return XDR_DECODE_DONE;
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 096/118] NFSD: Update the MKNOD3args decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (94 preceding siblings ...)
  2020-11-20 20:42 ` [PATCH v2 095/118] NFSD: Update the SYMLINK3args " Chuck Lever
@ 2020-11-20 20:42 ` Chuck Lever
  2020-11-20 20:42 ` [PATCH v2 097/118] NFSD: Update the NFSv2 GETATTR argument " Chuck Lever
                   ` (21 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:42 UTC (permalink / raw)
  To: linux-nfs

This commit removes the last usage of the original decode_sattr3(),
so it is removed as a clean-up.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3xdr.c |  110 ++++++++++++++++++-----------------------------------
 1 file changed, 37 insertions(+), 73 deletions(-)

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 6dfab4bd6c2c..df593dd9924b 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -103,26 +103,6 @@ encode_fh(__be32 *p, struct svc_fh *fhp)
 	return p + XDR_QUADLEN(size);
 }
 
-/*
- * Decode a file name and make sure that the path contains
- * no slashes or null bytes.
- */
-static __be32 *
-decode_filename(__be32 *p, char **namp, unsigned int *lenp)
-{
-	char		*name;
-	unsigned int	i;
-
-	if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXNAMLEN)) != NULL) {
-		for (i = 0, name = *namp; i < *lenp; i++, name++) {
-			if (*name == '\0' || *name == '/')
-				return NULL;
-		}
-	}
-
-	return p;
-}
-
 static enum xdr_decode_result
 svcxdr_decode_filename3(struct xdr_stream *xdr, char **name, unsigned int *len)
 {
@@ -273,49 +253,27 @@ svcxdr_decode_sattrguard3(struct xdr_stream *xdr, struct nfsd3_sattrargs *args)
 	return XDR_DECODE_DONE;
 }
 
-static __be32 *
-decode_sattr3(__be32 *p, struct iattr *iap, struct user_namespace *userns)
+static enum xdr_decode_result
+svcxdr_decode_specdata3(struct xdr_stream *xdr, struct nfsd3_mknodargs *args)
 {
-	u32	tmp;
+	__be32 *p;
 
-	iap->ia_valid = 0;
+	p = xdr_inline_decode(xdr, sizeof(__be32) * 2);
+	if (!p)
+		return XDR_DECODE_FAILED;
+	args->major = be32_to_cpup(p++);
+	args->minor = be32_to_cpup(p);
 
-	if (*p++) {
-		iap->ia_valid |= ATTR_MODE;
-		iap->ia_mode = ntohl(*p++);
-	}
-	if (*p++) {
-		iap->ia_uid = make_kuid(userns, ntohl(*p++));
-		if (uid_valid(iap->ia_uid))
-			iap->ia_valid |= ATTR_UID;
-	}
-	if (*p++) {
-		iap->ia_gid = make_kgid(userns, ntohl(*p++));
-		if (gid_valid(iap->ia_gid))
-			iap->ia_valid |= ATTR_GID;
-	}
-	if (*p++) {
-		u64	newsize;
+	return XDR_DECODE_DONE;
+}
 
-		iap->ia_valid |= ATTR_SIZE;
-		p = xdr_decode_hyper(p, &newsize);
-		iap->ia_size = min_t(u64, newsize, NFS_OFFSET_MAX);
-	}
-	if ((tmp = ntohl(*p++)) == 1) {	/* set to server time */
-		iap->ia_valid |= ATTR_ATIME;
-	} else if (tmp == 2) {		/* set to client time */
-		iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
-		iap->ia_atime.tv_sec = ntohl(*p++);
-		iap->ia_atime.tv_nsec = ntohl(*p++);
-	}
-	if ((tmp = ntohl(*p++)) == 1) {	/* set to server time */
-		iap->ia_valid |= ATTR_MTIME;
-	} else if (tmp == 2) {		/* set to client time */
-		iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
-		iap->ia_mtime.tv_sec = ntohl(*p++);
-		iap->ia_mtime.tv_nsec = ntohl(*p++);
-	}
-	return p;
+static enum xdr_decode_result
+svcxdr_decode_devicedata3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
+			  struct nfsd3_mknodargs *args)
+{
+	if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs))
+		return XDR_DECODE_FAILED;
+	return svcxdr_decode_specdata3(xdr, args);
 }
 
 static __be32 *encode_fsid(__be32 *p, struct svc_fh *fhp)
@@ -651,24 +609,30 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_mknodargs *args = rqstp->rq_argp;
 
-	if (!(p = decode_fh(p, &args->fh))
-	 || !(p = decode_filename(p, &args->name, &args->len)))
-		return 0;
-
-	args->ftype = ntohl(*p++);
-
-	if (args->ftype == NF3BLK  || args->ftype == NF3CHR
-	 || args->ftype == NF3SOCK || args->ftype == NF3FIFO)
-		p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
-
-	if (args->ftype == NF3BLK || args->ftype == NF3CHR) {
-		args->major = ntohl(*p++);
-		args->minor = ntohl(*p++);
+	if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u32(xdr, &args->ftype) < 0)
+		return XDR_DECODE_FAILED;
+	switch (args->ftype) {
+	case NF3CHR:
+	case NF3BLK:
+		return svcxdr_decode_devicedata3(rqstp, xdr, args);
+	case NF3SOCK:
+	case NF3FIFO:
+		return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
+	case NF3REG:
+	case NF3DIR:
+	case NF3LNK:
+		/* Valid XDR but illegal file types */
+		break;
+	default:
+		return XDR_DECODE_FAILED;
 	}
 
-	return xdr_argsize_check(rqstp, p);
+	return XDR_DECODE_DONE;
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 097/118] NFSD: Update the NFSv2 GETATTR argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (95 preceding siblings ...)
  2020-11-20 20:42 ` [PATCH v2 096/118] NFSD: Update the MKNOD3args " Chuck Lever
@ 2020-11-20 20:42 ` Chuck Lever
  2020-11-20 20:42 ` [PATCH v2 098/118] NFSD: Update the NFSv2 READ " Chuck Lever
                   ` (20 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:42 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 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 9473d048efec..5b8436af43a9 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 7aa6e8aca2c1..36765a96abae 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 enum xdr_decode_result
+svcxdr_decode_fhandle(struct xdr_stream *xdr, struct svc_fh *fhp)
+{
+	__be32 *p;
+
+	p = xdr_inline_decode(xdr, NFS_FHSIZE);
+	if (!p)
+		return XDR_DECODE_FAILED;
+	fh_init(fhp, NFS_FHSIZE);
+	memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
+	fhp->fh_handle.fh_size = NFS_FHSIZE;
+
+	return XDR_DECODE_DONE;
+}
+
 /* 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_xdr_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 ad77387734cc..84256a6a1ba1 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 *);



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 098/118] NFSD: Update the NFSv2 READ argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (96 preceding siblings ...)
  2020-11-20 20:42 ` [PATCH v2 097/118] NFSD: Update the NFSv2 GETATTR argument " Chuck Lever
@ 2020-11-20 20:42 ` Chuck Lever
  2020-11-20 20:42 ` [PATCH v2 099/118] NFSD: Update the NFSv2 WRITE " Chuck Lever
                   ` (19 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:42 UTC (permalink / raw)
  To: linux-nfs

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>
---
 fs/nfsd/nfsproc.c |   32 ++++++++++++++++++--------------
 fs/nfsd/nfsxdr.c  |   34 ++++++++++------------------------
 fs/nfsd/xdr.h     |    1 -
 3 files changed, 28 insertions(+), 39 deletions(-)

diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 5b8436af43a9..998a1f94c6f8 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 36765a96abae..7488fb396627 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -246,33 +246,19 @@ 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_xdr_stream;
 	struct nfsd_readargs *args = rqstp->rq_argp;
-	unsigned int len;
-	int v;
-	p = decode_fh(p, &args->fh);
-	if (!p)
-		return 0;
-
-	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 XDR_DECODE_FAILED;
+	p = xdr_inline_decode(xdr, sizeof(__be32) * 3);
+	if (!p)
+		return XDR_DECODE_FAILED;
+	args->offset = be32_to_cpup(p++);
+	args->count = be32_to_cpup(p);
+	/* totalcount is ignored */
 
-	/* 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 XDR_DECODE_DONE;
 }
 
 int
diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
index 84256a6a1ba1..d2ffda96975d 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 {



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 099/118] NFSD: Update the NFSv2 WRITE argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (97 preceding siblings ...)
  2020-11-20 20:42 ` [PATCH v2 098/118] NFSD: Update the NFSv2 READ " Chuck Lever
@ 2020-11-20 20:42 ` Chuck Lever
  2020-11-20 20:42 ` [PATCH v2 100/118] NFSD: Update the NFSv2 READLINK " Chuck Lever
                   ` (18 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:42 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfsxdr.c |   56 ++++++++++++++++++++----------------------------------
 1 file changed, 21 insertions(+), 35 deletions(-)

diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 7488fb396627..68a17a9b750f 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -264,47 +264,33 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd_writeargs *args = rqstp->rq_argp;
-	unsigned int len, hdr, dlen;
 	struct kvec *head = rqstp->rq_arg.head;
+	struct kvec *tail = rqstp->rq_arg.tail;
+	size_t remaining;
 
-	p = decode_fh(p, &args->fh);
+	if (!svcxdr_decode_fhandle(xdr, &args->fh))
+		return XDR_DECODE_FAILED;
+	p = xdr_inline_decode(xdr, sizeof(__be32) * 4);
 	if (!p)
-		return 0;
-
-	p++;				/* beginoffset */
-	args->offset = ntohl(*p++);	/* offset */
-	p++;				/* totalcount */
-	len = args->len = ntohl(*p++);
-	/*
-	 * The protocol specifies a maximum of 8192 bytes.
-	 */
-	if (len > NFSSVC_MAXBLKSIZE_V2)
-		return 0;
-
-	/*
-	 * Check to make sure that we got the right number of
-	 * bytes.
-	 */
-	hdr = (void*)p - head->iov_base;
-	if (hdr > head->iov_len)
-		return 0;
-	dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
+		return XDR_DECODE_FAILED;
+	p++;	/* beginoffset is ignored */
+	args->offset = be32_to_cpup(p++);
+	p++;	/* totalcount is ignored */
 
-	/*
-	 * Round the length of the data which was specified up to
-	 * the next multiple of XDR units and then compare that
-	 * against the length which was actually received.
-	 * Note that when RPCSEC/GSS (for example) is used, the
-	 * data buffer can be padded so dlen might be larger
-	 * than required.  It must never be smaller.
-	 */
-	if (dlen < XDR_QUADLEN(len)*4)
-		return 0;
+	/* opaque data */
+	args->len = be32_to_cpup(p++);
+	if (args->len > NFSSVC_MAXBLKSIZE_V2)
+		return XDR_DECODE_FAILED;
+	remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len;
+	remaining -= xdr_stream_pos(xdr);
+	if (remaining < xdr_align_size(args->len))
+		return XDR_DECODE_FAILED;
+	args->first.iov_base = p;
+	args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
 
-	args->first.iov_base = (void *)p;
-	args->first.iov_len = head->iov_len - hdr;
-	return 1;
+	return XDR_DECODE_DONE;
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 100/118] NFSD: Update the NFSv2 READLINK argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (98 preceding siblings ...)
  2020-11-20 20:42 ` [PATCH v2 099/118] NFSD: Update the NFSv2 WRITE " Chuck Lever
@ 2020-11-20 20:42 ` Chuck Lever
  2020-11-20 20:42 ` [PATCH v2 101/118] NFSD: Add helper to set up the pages where the dirlist is encoded Chuck Lever
                   ` (17 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:42 UTC (permalink / raw)
  To: linux-nfs

If the code that sets up the sink buffer for nfsd_readlink() is
moved adjacent to the nfsd_readlink() call site that uses it, then
the only argument is a file handle, and the fhandle decoder can be
used instead.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfsproc.c |    9 +++++----
 fs/nfsd/nfsxdr.c  |   13 -------------
 fs/nfsd/xdr.h     |    6 ------
 3 files changed, 5 insertions(+), 23 deletions(-)

diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 998a1f94c6f8..94b1fa0c3c58 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -149,14 +149,15 @@ nfsd_proc_lookup(struct svc_rqst *rqstp)
 static __be32
 nfsd_proc_readlink(struct svc_rqst *rqstp)
 {
-	struct nfsd_readlinkargs *argp = rqstp->rq_argp;
+	struct nfsd_fhandle *argp = rqstp->rq_argp;
 	struct nfsd_readlinkres *resp = rqstp->rq_resp;
+	char *buffer = page_address(*(rqstp->rq_next_page++));
 
 	dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));
 
 	/* Read the symlink. */
 	resp->len = NFS_MAXPATHLEN;
-	resp->status = nfsd_readlink(rqstp, &argp->fh, argp->buffer, &resp->len);
+	resp->status = nfsd_readlink(rqstp, &argp->fh, buffer, &resp->len);
 
 	fh_put(&argp->fh);
 	return rpc_success;
@@ -669,9 +670,9 @@ static const struct svc_procedure nfsd_procedures2[18] = {
 	},
 	[NFSPROC_READLINK] = {
 		.pc_func = nfsd_proc_readlink,
-		.pc_decode = nfssvc_decode_readlinkargs,
+		.pc_decode = nfssvc_decode_fhandleargs,
 		.pc_encode = nfssvc_encode_readlinkres,
-		.pc_argsize = sizeof(struct nfsd_readlinkargs),
+		.pc_argsize = sizeof(struct nfsd_fhandle),
 		.pc_ressize = sizeof(struct nfsd_readlinkres),
 		.pc_cachetype = RC_NOCACHE,
 		.pc_xdrressize = ST+1+NFS_MAXPATHLEN/4,
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 68a17a9b750f..d2af4ab51418 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -320,19 +320,6 @@ nfssvc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p)
 	return xdr_argsize_check(rqstp, p);
 }
 
-int
-nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p)
-{
-	struct nfsd_readlinkargs *args = rqstp->rq_argp;
-
-	p = decode_fh(p, &args->fh);
-	if (!p)
-		return 0;
-	args->buffer = page_address(*(rqstp->rq_next_page++));
-
-	return xdr_argsize_check(rqstp, p);
-}
-
 int
 nfssvc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p)
 {
diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
index d2ffda96975d..288c29a999db 100644
--- a/fs/nfsd/xdr.h
+++ b/fs/nfsd/xdr.h
@@ -52,11 +52,6 @@ struct nfsd_renameargs {
 	unsigned int		tlen;
 };
 
-struct nfsd_readlinkargs {
-	struct svc_fh		fh;
-	char *			buffer;
-};
-	
 struct nfsd_linkargs {
 	struct svc_fh		ffh;
 	struct svc_fh		tfh;
@@ -150,7 +145,6 @@ int nfssvc_decode_readargs(struct svc_rqst *, __be32 *);
 int nfssvc_decode_writeargs(struct svc_rqst *, __be32 *);
 int nfssvc_decode_createargs(struct svc_rqst *, __be32 *);
 int nfssvc_decode_renameargs(struct svc_rqst *, __be32 *);
-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 *);



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 101/118] NFSD: Add helper to set up the pages where the dirlist is encoded
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (99 preceding siblings ...)
  2020-11-20 20:42 ` [PATCH v2 100/118] NFSD: Update the NFSv2 READLINK " Chuck Lever
@ 2020-11-20 20:42 ` Chuck Lever
  2020-11-20 20:42 ` [PATCH v2 102/118] NFSD: Update the NFSv2 READDIR argument decoder to use struct xdr_stream Chuck Lever
                   ` (16 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:42 UTC (permalink / raw)
  To: linux-nfs

Add a helper similar to nfsd3_init_dirlist_pages().

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfsproc.c |   29 ++++++++++++++++++-----------
 fs/nfsd/nfsxdr.c  |    2 --
 fs/nfsd/xdr.h     |    1 -
 3 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 94b1fa0c3c58..3bbbb2a000bb 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -553,6 +553,20 @@ nfsd_proc_rmdir(struct svc_rqst *rqstp)
 	return rpc_success;
 }
 
+static void nfsd_init_dirlist_pages(struct svc_rqst *rqstp,
+				    struct nfsd_readdirres *resp,
+				    int count)
+{
+	count = min_t(u32, count, PAGE_SIZE);
+
+	/* Convert byte count to number of words (i.e. >> 2),
+	 * and reserve room for the NULL ptr & eof flag (-2 words) */
+	resp->buflen = (count >> 2) - 2;
+
+	resp->buffer = page_address(*rqstp->rq_next_page);
+	rqstp->rq_next_page++;
+}
+
 /*
  * Read a portion of a directory.
  */
@@ -561,31 +575,24 @@ nfsd_proc_readdir(struct svc_rqst *rqstp)
 {
 	struct nfsd_readdirargs *argp = rqstp->rq_argp;
 	struct nfsd_readdirres *resp = rqstp->rq_resp;
-	int		count;
 	loff_t		offset;
+	__be32		*buffer;
 
 	dprintk("nfsd: READDIR  %s %d bytes at %d\n",
 		SVCFH_fmt(&argp->fh),		
 		argp->count, argp->cookie);
 
-	/* Shrink to the client read size */
-	count = (argp->count >> 2) - 2;
-
-	/* Make sure we've room for the NULL ptr & eof flag */
-	count -= 2;
-	if (count < 0)
-		count = 0;
+	nfsd_init_dirlist_pages(rqstp, resp, argp->count);
+	buffer = resp->buffer;
 
-	resp->buffer = argp->buffer;
 	resp->offset = NULL;
-	resp->buflen = count;
 	resp->common.err = nfs_ok;
 	/* Read directory and encode entries on the fly */
 	offset = argp->cookie;
 	resp->status = nfsd_readdir(rqstp, &argp->fh, &offset,
 				    &resp->common, nfssvc_encode_entry);
 
-	resp->count = resp->buffer - argp->buffer;
+	resp->count = resp->buffer - buffer;
 	if (resp->offset)
 		*resp->offset = htonl(offset);
 
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index d2af4ab51418..2664101aa1dc 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -382,8 +382,6 @@ nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p)
 		return 0;
 	args->cookie = ntohl(*p++);
 	args->count  = ntohl(*p++);
-	args->count  = min_t(u32, args->count, PAGE_SIZE);
-	args->buffer = page_address(*(rqstp->rq_next_page++));
 
 	return xdr_argsize_check(rqstp, p);
 }
diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
index 288c29a999db..d700838f6512 100644
--- a/fs/nfsd/xdr.h
+++ b/fs/nfsd/xdr.h
@@ -73,7 +73,6 @@ struct nfsd_readdirargs {
 	struct svc_fh		fh;
 	__u32			cookie;
 	__u32			count;
-	__be32 *		buffer;
 };
 
 struct nfsd_stat {



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 102/118] NFSD: Update the NFSv2 READDIR argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (100 preceding siblings ...)
  2020-11-20 20:42 ` [PATCH v2 101/118] NFSD: Add helper to set up the pages where the dirlist is encoded Chuck Lever
@ 2020-11-20 20:42 ` Chuck Lever
  2020-11-20 20:42 ` [PATCH v2 103/118] NFSD: Update NFSv2 diropargs decoding " Chuck Lever
                   ` (15 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:42 UTC (permalink / raw)
  To: linux-nfs

As an additional clean up, move code not related to XDR decoding
into readdir's .pc_func call out.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfsxdr.c |   13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 2664101aa1dc..6f4115303f58 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -375,15 +375,18 @@ nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd_readdirargs *args = rqstp->rq_argp;
 
-	p = decode_fh(p, &args->fh);
+	if (!svcxdr_decode_fhandle(xdr, &args->fh))
+		return XDR_DECODE_FAILED;
+	p = xdr_inline_decode(xdr, sizeof(__be32) * 2);
 	if (!p)
-		return 0;
-	args->cookie = ntohl(*p++);
-	args->count  = ntohl(*p++);
+		return XDR_DECODE_FAILED;
+	args->cookie = be32_to_cpup(p++);
+	args->count = be32_to_cpup(p);
 
-	return xdr_argsize_check(rqstp, p);
+	return XDR_DECODE_DONE;
 }
 
 /*



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 103/118] NFSD: Update NFSv2 diropargs decoding to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (101 preceding siblings ...)
  2020-11-20 20:42 ` [PATCH v2 102/118] NFSD: Update the NFSv2 READDIR argument decoder to use struct xdr_stream Chuck Lever
@ 2020-11-20 20:42 ` Chuck Lever
  2020-11-20 20:42 ` [PATCH v2 104/118] NFSD: Update the NFSv2 RENAME argument decoder " Chuck Lever
                   ` (14 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:42 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfsxdr.c |   40 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 35 insertions(+), 5 deletions(-)

diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 6f4115303f58..9986b4ea78f4 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -86,6 +86,39 @@ decode_filename(__be32 *p, char **namp, unsigned int *lenp)
 	return p;
 }
 
+static enum xdr_decode_result
+svcxdr_decode_filename(struct xdr_stream *xdr, char **name, unsigned int *len)
+{
+	u32 size, i;
+	__be32 *p;
+	char *c;
+
+	if (xdr_stream_decode_u32(xdr, &size) < 0)
+		return XDR_DECODE_FAILED;
+	if (size == 0 || size > NFS_MAXNAMLEN)
+		return XDR_DECODE_FAILED;
+	p = xdr_inline_decode(xdr, size);
+	if (!p)
+		return XDR_DECODE_FAILED;
+
+	*len = size;
+	*name = (char *)p;
+	for (i = 0, c = *name; i < size; i++, c++)
+		if (*c == '\0' || *c == '/')
+			return XDR_DECODE_FAILED;
+
+	return XDR_DECODE_DONE;
+}
+
+static enum xdr_decode_result
+svcxdr_decode_diropargs(struct xdr_stream *xdr, struct svc_fh *fhp,
+			char **name, unsigned int *len)
+{
+	if (!svcxdr_decode_fhandle(xdr, fhp))
+		return XDR_DECODE_FAILED;
+	return svcxdr_decode_filename(xdr, name, len);
+}
+
 static __be32 *
 decode_sattr(__be32 *p, struct iattr *iap, struct user_namespace *userns)
 {
@@ -234,13 +267,10 @@ nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfssvc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd_diropargs *args = rqstp->rq_argp;
 
-	if (!(p = decode_fh(p, &args->fh))
-	 || !(p = decode_filename(p, &args->name, &args->len)))
-		return 0;
-
-	return xdr_argsize_check(rqstp, p);
+	return svcxdr_decode_diropargs(xdr, &args->fh, &args->name, &args->len);
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 104/118] NFSD: Update the NFSv2 RENAME argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (102 preceding siblings ...)
  2020-11-20 20:42 ` [PATCH v2 103/118] NFSD: Update NFSv2 diropargs decoding " Chuck Lever
@ 2020-11-20 20:42 ` Chuck Lever
  2020-11-20 20:43 ` [PATCH v2 105/118] NFSD: Update the NFSv2 LINK " Chuck Lever
                   ` (13 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:42 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfsxdr.c |   11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 9986b4ea78f4..94c637a0a24d 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -339,15 +339,12 @@ nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfssvc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd_renameargs *args = rqstp->rq_argp;
 
-	if (!(p = decode_fh(p, &args->ffh))
-	 || !(p = decode_filename(p, &args->fname, &args->flen))
-	 || !(p = decode_fh(p, &args->tfh))
-	 || !(p = decode_filename(p, &args->tname, &args->tlen)))
-		return 0;
-
-	return xdr_argsize_check(rqstp, p);
+	if (!svcxdr_decode_diropargs(xdr, &args->ffh, &args->fname, &args->flen))
+		return XDR_DECODE_FAILED;
+	return svcxdr_decode_diropargs(xdr, &args->tfh, &args->tname, &args->tlen);
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 105/118] NFSD: Update the NFSv2 LINK argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (103 preceding siblings ...)
  2020-11-20 20:42 ` [PATCH v2 104/118] NFSD: Update the NFSv2 RENAME argument decoder " Chuck Lever
@ 2020-11-20 20:43 ` Chuck Lever
  2020-11-20 20:43 ` [PATCH v2 106/118] NFSD: Update the NFSv2 SETATTR " Chuck Lever
                   ` (12 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:43 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfsxdr.c |   10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 94c637a0a24d..40def4a461df 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -350,14 +350,12 @@ nfssvc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfssvc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd_linkargs *args = rqstp->rq_argp;
 
-	if (!(p = decode_fh(p, &args->ffh))
-	 || !(p = decode_fh(p, &args->tfh))
-	 || !(p = decode_filename(p, &args->tname, &args->tlen)))
-		return 0;
-
-	return xdr_argsize_check(rqstp, p);
+	if (!svcxdr_decode_fhandle(xdr, &args->ffh))
+		return XDR_DECODE_FAILED;
+	return svcxdr_decode_diropargs(xdr, &args->tfh, &args->tname, &args->tlen);
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 106/118] NFSD: Update the NFSv2 SETATTR argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (104 preceding siblings ...)
  2020-11-20 20:43 ` [PATCH v2 105/118] NFSD: Update the NFSv2 LINK " Chuck Lever
@ 2020-11-20 20:43 ` Chuck Lever
  2020-11-20 20:43 ` [PATCH v2 107/118] NFSD: Update the NFSv2 CREATE " Chuck Lever
                   ` (11 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:43 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfsxdr.c |   83 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 77 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 40def4a461df..c34446c650ca 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -174,6 +174,79 @@ decode_sattr(__be32 *p, struct iattr *iap, struct user_namespace *userns)
 	return p;
 }
 
+static enum xdr_decode_result
+svcxdr_decode_sattr(struct svc_rqst *rqstp, struct xdr_stream *xdr,
+		    struct iattr *iap)
+{
+	u32 tmp1, tmp2;
+	__be32 *p;
+
+	p = xdr_inline_decode(xdr, sizeof(__be32) * 8);
+	if (!p)
+		return XDR_DECODE_FAILED;
+
+	iap->ia_valid = 0;
+
+	/*
+	 * Some Sun clients put 0xffff in the mode field when they
+	 * mean 0xffffffff.
+	 */
+	tmp1 = be32_to_cpup(p++);
+	if (tmp1 != (u32)-1 && tmp1 != 0xffff) {
+		iap->ia_valid |= ATTR_MODE;
+		iap->ia_mode = tmp1;
+	}
+
+	tmp1 = be32_to_cpup(p++);
+	if (tmp1 != (u32)-1) {
+		iap->ia_uid = make_kuid(nfsd_user_namespace(rqstp), tmp1);
+		if (uid_valid(iap->ia_uid))
+			iap->ia_valid |= ATTR_UID;
+	}
+
+	tmp1 = be32_to_cpup(p++);
+	if (tmp1 != (u32)-1) {
+		iap->ia_gid = make_kgid(nfsd_user_namespace(rqstp), tmp1);
+		if (gid_valid(iap->ia_gid))
+			iap->ia_valid |= ATTR_GID;
+	}
+
+	tmp1 = be32_to_cpup(p++);
+	if (tmp1 != (u32)-1) {
+		iap->ia_valid |= ATTR_SIZE;
+		iap->ia_size = tmp1;
+	}
+
+	tmp1 = be32_to_cpup(p++);
+	tmp2 = be32_to_cpup(p++);
+	if (tmp1 != (u32)-1 && tmp2 != (u32)-1) {
+		iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
+		iap->ia_atime.tv_sec = tmp1;
+		iap->ia_atime.tv_nsec = tmp2 * NSEC_PER_USEC;
+	}
+
+	tmp1 = be32_to_cpup(p++);
+	tmp2 = be32_to_cpup(p++);
+	if (tmp1 != (u32)-1 && tmp2 != (u32)-1) {
+		iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
+		iap->ia_mtime.tv_sec = tmp1;
+		iap->ia_mtime.tv_nsec = tmp2 * NSEC_PER_USEC;
+		/*
+		 * Passing the invalid value useconds=1000000 for mtime
+		 * is a Sun convention for "set both mtime and atime to
+		 * current server time".  It's needed to make permissions
+		 * checks for the "touch" program across v2 mounts to
+		 * Solaris and Irix boxes work correctly. See description of
+		 * sattr in section 6.1 of "NFS Illustrated" by
+		 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
+		 */
+		if (tmp2 == 1000000)
+			iap->ia_valid &= ~(ATTR_ATIME_SET|ATTR_MTIME_SET);
+	}
+
+	return XDR_DECODE_DONE;
+}
+
 static __be32 *
 encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
 	     struct kstat *stat)
@@ -254,14 +327,12 @@ nfssvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd_sattrargs *args = rqstp->rq_argp;
 
-	p = decode_fh(p, &args->fh);
-	if (!p)
-		return 0;
-	p = decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp));
-
-	return xdr_argsize_check(rqstp, p);
+	if (!svcxdr_decode_fhandle(xdr, &args->fh))
+		return XDR_DECODE_FAILED;
+	return svcxdr_decode_sattr(rqstp, xdr, &args->attrs);
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 107/118] NFSD: Update the NFSv2 CREATE argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (105 preceding siblings ...)
  2020-11-20 20:43 ` [PATCH v2 106/118] NFSD: Update the NFSv2 SETATTR " Chuck Lever
@ 2020-11-20 20:43 ` Chuck Lever
  2020-11-20 20:43 ` [PATCH v2 108/118] NFSD: Update the NFSv2 SYMLINK " Chuck Lever
                   ` (10 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:43 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfsxdr.c |   10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index c34446c650ca..f02fef8a805e 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -397,14 +397,12 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd_createargs *args = rqstp->rq_argp;
 
-	if (   !(p = decode_fh(p, &args->fh))
-	    || !(p = decode_filename(p, &args->name, &args->len)))
-		return 0;
-	p = decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp));
-
-	return xdr_argsize_check(rqstp, p);
+	if (!svcxdr_decode_diropargs(xdr, &args->fh, &args->name, &args->len))
+		return XDR_DECODE_FAILED;
+	return svcxdr_decode_sattr(rqstp, xdr, &args->attrs);
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 108/118] NFSD: Update the NFSv2 SYMLINK argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (106 preceding siblings ...)
  2020-11-20 20:43 ` [PATCH v2 107/118] NFSD: Update the NFSv2 CREATE " Chuck Lever
@ 2020-11-20 20:43 ` Chuck Lever
  2020-11-20 20:43 ` [PATCH v2 109/118] NFSD: Remove argument length checking in nfsd_dispatch() Chuck Lever
                   ` (9 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:43 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfsxdr.c |  117 ++++++------------------------------------------------
 1 file changed, 12 insertions(+), 105 deletions(-)

diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index f02fef8a805e..92e9143842d3 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -66,26 +66,6 @@ encode_fh(__be32 *p, struct svc_fh *fhp)
 	return p + (NFS_FHSIZE>> 2);
 }
 
-/*
- * Decode a file name and make sure that the path contains
- * no slashes or null bytes.
- */
-static __be32 *
-decode_filename(__be32 *p, char **namp, unsigned int *lenp)
-{
-	char		*name;
-	unsigned int	i;
-
-	if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXNAMLEN)) != NULL) {
-		for (i = 0, name = *namp; i < *lenp; i++, name++) {
-			if (*name == '\0' || *name == '/')
-				return NULL;
-		}
-	}
-
-	return p;
-}
-
 static enum xdr_decode_result
 svcxdr_decode_filename(struct xdr_stream *xdr, char **name, unsigned int *len)
 {
@@ -119,61 +99,6 @@ svcxdr_decode_diropargs(struct xdr_stream *xdr, struct svc_fh *fhp,
 	return svcxdr_decode_filename(xdr, name, len);
 }
 
-static __be32 *
-decode_sattr(__be32 *p, struct iattr *iap, struct user_namespace *userns)
-{
-	u32	tmp, tmp1;
-
-	iap->ia_valid = 0;
-
-	/* Sun client bug compatibility check: some sun clients seem to
-	 * put 0xffff in the mode field when they mean 0xffffffff.
-	 * Quoting the 4.4BSD nfs server code: Nah nah nah nah na nah.
-	 */
-	if ((tmp = ntohl(*p++)) != (u32)-1 && tmp != 0xffff) {
-		iap->ia_valid |= ATTR_MODE;
-		iap->ia_mode = tmp;
-	}
-	if ((tmp = ntohl(*p++)) != (u32)-1) {
-		iap->ia_uid = make_kuid(userns, tmp);
-		if (uid_valid(iap->ia_uid))
-			iap->ia_valid |= ATTR_UID;
-	}
-	if ((tmp = ntohl(*p++)) != (u32)-1) {
-		iap->ia_gid = make_kgid(userns, tmp);
-		if (gid_valid(iap->ia_gid))
-			iap->ia_valid |= ATTR_GID;
-	}
-	if ((tmp = ntohl(*p++)) != (u32)-1) {
-		iap->ia_valid |= ATTR_SIZE;
-		iap->ia_size = tmp;
-	}
-	tmp  = ntohl(*p++); tmp1 = ntohl(*p++);
-	if (tmp != (u32)-1 && tmp1 != (u32)-1) {
-		iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
-		iap->ia_atime.tv_sec = tmp;
-		iap->ia_atime.tv_nsec = tmp1 * 1000; 
-	}
-	tmp  = ntohl(*p++); tmp1 = ntohl(*p++);
-	if (tmp != (u32)-1 && tmp1 != (u32)-1) {
-		iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
-		iap->ia_mtime.tv_sec = tmp;
-		iap->ia_mtime.tv_nsec = tmp1 * 1000; 
-		/*
-		 * Passing the invalid value useconds=1000000 for mtime
-		 * is a Sun convention for "set both mtime and atime to
-		 * current server time".  It's needed to make permissions
-		 * checks for the "touch" program across v2 mounts to
-		 * Solaris and Irix boxes work correctly. See description of
-		 * sattr in section 6.1 of "NFS Illustrated" by
-		 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
-		 */
-		if (tmp1 == 1000000)
-			iap->ia_valid &= ~(ATTR_ATIME_SET|ATTR_MTIME_SET);
-	}
-	return p;
-}
-
 static enum xdr_decode_result
 svcxdr_decode_sattr(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 		    struct iattr *iap)
@@ -430,40 +355,22 @@ nfssvc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p)
 int
 nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd_symlinkargs *args = rqstp->rq_argp;
-	char *base = (char *)p;
-	size_t xdrlen;
-
-	if (   !(p = decode_fh(p, &args->ffh))
-	    || !(p = decode_filename(p, &args->fname, &args->flen)))
-		return 0;
+	struct kvec *head = rqstp->rq_arg.head;
 
-	args->tlen = ntohl(*p++);
+	if (!svcxdr_decode_diropargs(xdr, &args->ffh, &args->fname, &args->flen))
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u32(xdr, &args->tlen) < 0)
+		return XDR_DECODE_FAILED;
 	if (args->tlen == 0)
-		return 0;
-
-	args->first.iov_base = p;
-	args->first.iov_len = rqstp->rq_arg.head[0].iov_len;
-	args->first.iov_len -= (char *)p - base;
-
-	/* This request is never larger than a page. Therefore,
-	 * transport will deliver either:
-	 * 1. pathname in the pagelist -> sattr is in the tail.
-	 * 2. everything in the head buffer -> sattr is in the head.
-	 */
-	if (rqstp->rq_arg.page_len) {
-		if (args->tlen != rqstp->rq_arg.page_len)
-			return 0;
-		p = rqstp->rq_arg.tail[0].iov_base;
-	} else {
-		xdrlen = XDR_QUADLEN(args->tlen);
-		if (xdrlen > args->first.iov_len - (8 * sizeof(__be32)))
-			return 0;
-		p += xdrlen;
-	}
-	decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp));
+		return XDR_DECODE_FAILED;
 
-	return 1;
+	args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
+	args->first.iov_base = xdr_inline_decode(xdr, args->tlen);
+	if (!args->first.iov_base)
+		return XDR_DECODE_FAILED;
+	return svcxdr_decode_sattr(rqstp, xdr, &args->attrs);
 }
 
 int



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 109/118] NFSD: Remove argument length checking in nfsd_dispatch()
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (107 preceding siblings ...)
  2020-11-20 20:43 ` [PATCH v2 108/118] NFSD: Update the NFSv2 SYMLINK " Chuck Lever
@ 2020-11-20 20:43 ` Chuck Lever
  2020-11-20 20:43 ` [PATCH v2 110/118] NFSD: Update the NFSv2 GETACL argument decoder to use struct xdr_stream Chuck Lever
                   ` (8 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:43 UTC (permalink / raw)
  To: linux-nfs

Now that the decoders for NFSv2, NFSv3, and NFSACL all use the
xdr_stream mechanism, the special length checking logic in
nfsd_dispatch() is no longer necessary.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfssvc.c |   39 ---------------------------------------
 1 file changed, 39 deletions(-)

diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index cae6fbf10514..c51287de9a8d 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -961,37 +961,6 @@ nfsd(void *vrqstp)
 	return 0;
 }
 
-/*
- * 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
- * reply that can both be larger than a page.  The xdr code has taken
- * advantage of this assumption to be a sloppy about bounds checking in
- * some cases.  Pending a rewrite of the NFSv2/v3 xdr code to fix that
- * problem, we enforce these assumptions here:
- */
-static bool nfs_request_too_big(struct svc_rqst *rqstp,
-				const struct svc_procedure *proc)
-{
-	/*
-	 * The ACL code has more careful bounds-checking and is not
-	 * susceptible to this problem:
-	 */
-	if (rqstp->rq_prog != NFS_PROGRAM)
-		return false;
-	/*
-	 * Ditto NFSv4 (which can in theory have argument and reply both
-	 * more than a page):
-	 */
-	if (rqstp->rq_vers >= 4)
-		return false;
-	/* The reply will be small, we're OK: */
-	if (proc->pc_xdrressize > 0 &&
-	    proc->pc_xdrressize < XDR_QUADLEN(PAGE_SIZE))
-		return false;
-
-	return rqstp->rq_arg.len > PAGE_SIZE;
-}
-
 /**
  * nfsd_dispatch - Process an NFS or NFSACL Request
  * @rqstp: incoming request
@@ -1013,9 +982,6 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 	dprintk("nfsd_dispatch: vers %d proc %d\n",
 				rqstp->rq_vers, rqstp->rq_proc);
 
-	if (nfs_request_too_big(rqstp, proc))
-		goto out_too_large;
-
 	/*
 	 * Give the xdr decoder a chance to change this if it wants
 	 * (necessary in the NFSv4.0 compound case)
@@ -1053,11 +1019,6 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 out_cached_reply:
 	return 1;
 
-out_too_large:
-	dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);
-	*statp = rpc_garbage_args;
-	return 1;
-
 out_decode_err:
 	dprintk("nfsd: failed to decode arguments!\n");
 	*statp = rpc_garbage_args;



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 110/118] NFSD: Update the NFSv2 GETACL argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (108 preceding siblings ...)
  2020-11-20 20:43 ` [PATCH v2 109/118] NFSD: Remove argument length checking in nfsd_dispatch() Chuck Lever
@ 2020-11-20 20:43 ` Chuck Lever
  2020-11-20 20:43 ` [PATCH v2 111/118] NFSD: Add an xdr_stream-based decoder for NFSv2/3 ACLs Chuck Lever
                   ` (7 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:43 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs2acl.c |   12 ++++++------
 fs/nfsd/nfsxdr.c  |   11 ++++++++++-
 fs/nfsd/xdr.h     |    2 ++
 fs/nfsd/xdr3.h    |    2 +-
 4 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index b0f66604532a..0e62c3b53a58 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -188,17 +188,17 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp)
 
 static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_getaclargs *argp = rqstp->rq_argp;
 
-	p = nfs2svc_decode_fh(p, &argp->fh);
-	if (!p)
-		return 0;
-	argp->mask = ntohl(*p); p++;
+	if (!svcxdr_decode_fhandle(xdr, &argp->fh))
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u32(xdr, &argp->mask) < 0)
+		return XDR_DECODE_FAILED;
 
-	return xdr_argsize_check(rqstp, p);
+	return XDR_DECODE_DONE;
 }
 
-
 static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
 {
 	struct nfsd3_setaclargs *argp = rqstp->rq_argp;
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 92e9143842d3..efa2760316eb 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -38,7 +38,16 @@ decode_fh(__be32 *p, struct svc_fh *fhp)
 	return p + (NFS_FHSIZE >> 2);
 }
 
-static enum xdr_decode_result
+/**
+ * svcxdr_decode_fhandle - Decode an NFSv2 file handle
+ * @xdr: XDR stream positioned at an encoded NFSv2 FH
+ * @fhp: OUT: filled-in server file handle
+ *
+ * Return values:
+ *  %XDR_DECODE_FAILED: The encoded file handle was not valid
+ *  %XDR_DECODE_DONE: Success
+ */
+enum xdr_decode_result
 svcxdr_decode_fhandle(struct xdr_stream *xdr, struct svc_fh *fhp)
 {
 	__be32 *p;
diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
index d700838f6512..6d3fb133f366 100644
--- a/fs/nfsd/xdr.h
+++ b/fs/nfsd/xdr.h
@@ -165,5 +165,7 @@ void nfssvc_release_readres(struct svc_rqst *rqstp);
 /* Helper functions for NFSv2 ACL code */
 __be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, struct kstat *stat);
 __be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp);
+enum xdr_decode_result
+svcxdr_decode_fhandle(struct xdr_stream *xdr, struct svc_fh *fhp);
 
 #endif /* LINUX_NFSD_H */
diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
index 64af5b01c5d7..43db4206cd25 100644
--- a/fs/nfsd/xdr3.h
+++ b/fs/nfsd/xdr3.h
@@ -102,7 +102,7 @@ struct nfsd3_commitargs {
 
 struct nfsd3_getaclargs {
 	struct svc_fh		fh;
-	int			mask;
+	__u32			mask;
 };
 
 struct posix_acl;



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 111/118] NFSD: Add an xdr_stream-based decoder for NFSv2/3 ACLs
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (109 preceding siblings ...)
  2020-11-20 20:43 ` [PATCH v2 110/118] NFSD: Update the NFSv2 GETACL argument decoder to use struct xdr_stream Chuck Lever
@ 2020-11-20 20:43 ` Chuck Lever
  2020-11-20 20:43 ` [PATCH v2 112/118] NFSD: Update the NFSv2 SETACL argument decoder to use struct xdr_stream Chuck Lever
                   ` (6 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:43 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfs_common/nfsacl.c |   53 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/nfsacl.h |    3 +++
 2 files changed, 56 insertions(+)

diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c
index d056ad2fdefd..e2ec0f241a4f 100644
--- a/fs/nfs_common/nfsacl.c
+++ b/fs/nfs_common/nfsacl.c
@@ -295,3 +295,56 @@ int nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt,
 		   nfsacl_desc.desc.array_len;
 }
 EXPORT_SYMBOL_GPL(nfsacl_decode);
+
+/**
+ * nfs_stream_decode_acl - Decode an NFSv3 ACL
+ *
+ * @xdr: an xdr_stream positioned at an encoded ACL
+ * @aclcnt: OUT: count of ACEs in decoded posix_acl
+ * @pacl: OUT: a dynamically-allocated buffer containing the decoded posix_acl
+ *
+ * Return values:
+ *   %XDR_DECODE_FAILED: The encoded ACL is not valid
+ *   %XDR_DECODE_DONE: @pacl contains a decoded ACL, and @xdr is advanced
+ *
+ * On a successful return, caller must release *pacl using posix_acl_release().
+ */
+enum xdr_decode_result
+nfs_stream_decode_acl(struct xdr_stream *xdr, unsigned int *aclcnt,
+		      struct posix_acl **pacl)
+{
+	const size_t elem_size = sizeof(__be32) * 3;
+	struct nfsacl_decode_desc nfsacl_desc = {
+		.desc = {
+			.elem_size = elem_size,
+			.xcode = pacl ? xdr_nfsace_decode : NULL,
+		},
+	};
+	unsigned int base;
+	u32 entries;
+
+	if (xdr_stream_decode_u32(xdr, &entries) < 0)
+		return XDR_DECODE_FAILED;
+	if (entries > NFS_ACL_MAX_ENTRIES)
+		return XDR_DECODE_FAILED;
+
+	base = xdr_stream_pos(xdr);
+	if (!xdr_inline_decode(xdr, sizeof(__be32) + elem_size * entries))
+		return XDR_DECODE_FAILED;
+	nfsacl_desc.desc.array_maxlen = entries;
+	if (xdr_decode_array2(xdr->buf, base, &nfsacl_desc.desc))
+		return XDR_DECODE_FAILED;
+
+	if (pacl) {
+		if (entries != nfsacl_desc.desc.array_len ||
+		    posix_acl_from_nfsacl(nfsacl_desc.acl) != 0) {
+			posix_acl_release(nfsacl_desc.acl);
+			return XDR_DECODE_FAILED;
+		}
+		*pacl = nfsacl_desc.acl;
+	}
+	if (aclcnt)
+		*aclcnt = entries;
+	return XDR_DECODE_DONE;
+}
+EXPORT_SYMBOL_GPL(nfs_stream_decode_acl);
diff --git a/include/linux/nfsacl.h b/include/linux/nfsacl.h
index 103d44695323..434471cc4b62 100644
--- a/include/linux/nfsacl.h
+++ b/include/linux/nfsacl.h
@@ -38,5 +38,8 @@ nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode,
 extern int
 nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt,
 	      struct posix_acl **pacl);
+extern enum xdr_decode_result
+nfs_stream_decode_acl(struct xdr_stream *xdr, unsigned int *aclcnt,
+		      struct posix_acl **pacl);
 
 #endif  /* __LINUX_NFSACL_H */



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 112/118] NFSD: Update the NFSv2 SETACL argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (110 preceding siblings ...)
  2020-11-20 20:43 ` [PATCH v2 111/118] NFSD: Add an xdr_stream-based decoder for NFSv2/3 ACLs Chuck Lever
@ 2020-11-20 20:43 ` Chuck Lever
  2020-11-20 20:43 ` [PATCH v2 113/118] NFSD: Update the NFSv2 ACL GETATTR " Chuck Lever
                   ` (5 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:43 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs2acl.c |   33 ++++++++++++++-------------------
 fs/nfsd/xdr3.h    |    2 +-
 2 files changed, 15 insertions(+), 20 deletions(-)

diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 0e62c3b53a58..2e44b56e33ad 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -201,28 +201,23 @@ static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
 
 static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_setaclargs *argp = rqstp->rq_argp;
-	struct kvec *head = rqstp->rq_arg.head;
-	unsigned int base;
-	int n;
 
-	p = nfs2svc_decode_fh(p, &argp->fh);
-	if (!p)
-		return 0;
-	argp->mask = ntohl(*p++);
-	if (argp->mask & ~NFS_ACL_MASK ||
-	    !xdr_argsize_check(rqstp, p))
-		return 0;
+	if (!svcxdr_decode_fhandle(xdr, &argp->fh))
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u32(xdr, &argp->mask) < 0)
+		return XDR_DECODE_FAILED;
+	if (argp->mask & ~NFS_ACL_MASK)
+		return XDR_DECODE_FAILED;
+	if (!nfs_stream_decode_acl(xdr, NULL, (argp->mask & NFS_ACL) ?
+				   &argp->acl_access : NULL))
+		return XDR_DECODE_FAILED;
+	if (!nfs_stream_decode_acl(xdr, NULL, (argp->mask & NFS_DFACL) ?
+				   &argp->acl_default : NULL))
+		return XDR_DECODE_FAILED;
 
-	base = (char *)p - (char *)head->iov_base;
-	n = nfsacl_decode(&rqstp->rq_arg, base, NULL,
-			  (argp->mask & NFS_ACL) ?
-			  &argp->acl_access : NULL);
-	if (n > 0)
-		n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL,
-				  (argp->mask & NFS_DFACL) ?
-				  &argp->acl_default : NULL);
-	return (n > 0);
+	return XDR_DECODE_DONE;
 }
 
 static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p)
diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
index 43db4206cd25..5afb3ce4f062 100644
--- a/fs/nfsd/xdr3.h
+++ b/fs/nfsd/xdr3.h
@@ -108,7 +108,7 @@ struct nfsd3_getaclargs {
 struct posix_acl;
 struct nfsd3_setaclargs {
 	struct svc_fh		fh;
-	int			mask;
+	__u32			mask;
 	struct posix_acl	*acl_access;
 	struct posix_acl	*acl_default;
 };



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 113/118] NFSD: Update the NFSv2 ACL GETATTR argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (111 preceding siblings ...)
  2020-11-20 20:43 ` [PATCH v2 112/118] NFSD: Update the NFSv2 SETACL argument decoder to use struct xdr_stream Chuck Lever
@ 2020-11-20 20:43 ` Chuck Lever
  2020-11-20 20:43 ` [PATCH v2 114/118] NFSD: Update the NFSv2 ACL ACCESS " Chuck Lever
                   ` (4 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:43 UTC (permalink / raw)
  To: linux-nfs

Since the ACL GETATTR procedure is the same as the normal GETATTR
procedure, simply re-use nfssvc_decode_fhandleargs.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs2acl.c |   12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 2e44b56e33ad..bc5303f654e5 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -220,16 +220,6 @@ static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
 	return XDR_DECODE_DONE;
 }
 
-static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p)
-{
-	struct nfsd_fhandle *argp = rqstp->rq_argp;
-
-	p = nfs2svc_decode_fh(p, &argp->fh);
-	if (!p)
-		return 0;
-	return xdr_argsize_check(rqstp, p);
-}
-
 static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p)
 {
 	struct nfsd3_accessargs *argp = rqstp->rq_argp;
@@ -389,7 +379,7 @@ static const struct svc_procedure nfsd_acl_procedures2[5] = {
 	},
 	[ACLPROC2_GETATTR] = {
 		.pc_func = nfsacld_proc_getattr,
-		.pc_decode = nfsaclsvc_decode_fhandleargs,
+		.pc_decode = nfssvc_decode_fhandleargs,
 		.pc_encode = nfsaclsvc_encode_attrstatres,
 		.pc_release = nfsaclsvc_release_attrstat,
 		.pc_argsize = sizeof(struct nfsd_fhandle),



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 114/118] NFSD: Update the NFSv2 ACL ACCESS argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (112 preceding siblings ...)
  2020-11-20 20:43 ` [PATCH v2 113/118] NFSD: Update the NFSv2 ACL GETATTR " Chuck Lever
@ 2020-11-20 20:43 ` Chuck Lever
  2020-11-20 20:43 ` [PATCH v2 115/118] NFSD: Clean up after updating NFSv2 ACL decoders Chuck Lever
                   ` (3 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:43 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs2acl.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index bc5303f654e5..fa8c2d746df2 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -222,14 +222,14 @@ static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
 
 static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p)
 {
-	struct nfsd3_accessargs *argp = rqstp->rq_argp;
-
-	p = nfs2svc_decode_fh(p, &argp->fh);
-	if (!p)
-		return 0;
-	argp->access = ntohl(*p++);
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
+	struct nfsd3_accessargs *args = rqstp->rq_argp;
 
-	return xdr_argsize_check(rqstp, p);
+	if (!svcxdr_decode_fhandle(xdr, &args->fh))
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u32(xdr, &args->access) < 0)
+		return XDR_DECODE_FAILED;
+	return XDR_DECODE_DONE;
 }
 
 /*



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 115/118] NFSD: Clean up after updating NFSv2 ACL decoders
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (113 preceding siblings ...)
  2020-11-20 20:43 ` [PATCH v2 114/118] NFSD: Update the NFSv2 ACL ACCESS " Chuck Lever
@ 2020-11-20 20:43 ` Chuck Lever
  2020-11-20 20:44 ` [PATCH v2 116/118] NFSD: Update the NFSv3 GETACL argument decoder to use struct xdr_stream Chuck Lever
                   ` (2 subsequent siblings)
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:43 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfsxdr.c |   18 ------------------
 fs/nfsd/xdr.h    |    1 -
 2 files changed, 19 deletions(-)

diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index efa2760316eb..416a53d4be16 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -26,18 +26,6 @@ static u32	nfs_ftypes[] = {
  * Basic NFSv2 data types (RFC 1094 Section 2.3)
  */
 
-static __be32 *
-decode_fh(__be32 *p, struct svc_fh *fhp)
-{
-	fh_init(fhp, NFS_FHSIZE);
-	memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
-	fhp->fh_handle.fh_size = NFS_FHSIZE;
-
-	/* FIXME: Look up export pointer here and verify
-	 * Sun Secure RPC if requested */
-	return p + (NFS_FHSIZE >> 2);
-}
-
 /**
  * svcxdr_decode_fhandle - Decode an NFSv2 file handle
  * @xdr: XDR stream positioned at an encoded NFSv2 FH
@@ -62,12 +50,6 @@ svcxdr_decode_fhandle(struct xdr_stream *xdr, struct svc_fh *fhp)
 	return XDR_DECODE_DONE;
 }
 
-/* Helper function for NFSv2 ACL code */
-__be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp)
-{
-	return decode_fh(p, fhp);
-}
-
 static __be32 *
 encode_fh(__be32 *p, struct svc_fh *fhp)
 {
diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
index 6d3fb133f366..dc5fc2f77f4b 100644
--- a/fs/nfsd/xdr.h
+++ b/fs/nfsd/xdr.h
@@ -164,7 +164,6 @@ void nfssvc_release_readres(struct svc_rqst *rqstp);
 
 /* Helper functions for NFSv2 ACL code */
 __be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, struct kstat *stat);
-__be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp);
 enum xdr_decode_result
 svcxdr_decode_fhandle(struct xdr_stream *xdr, struct svc_fh *fhp);
 



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 116/118] NFSD: Update the NFSv3 GETACL argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (114 preceding siblings ...)
  2020-11-20 20:43 ` [PATCH v2 115/118] NFSD: Clean up after updating NFSv2 ACL decoders Chuck Lever
@ 2020-11-20 20:44 ` Chuck Lever
  2020-11-20 20:44 ` [PATCH v2 117/118] NFSD: Update the NFSv2 SETACL " Chuck Lever
  2020-11-20 20:44 ` [PATCH v2 118/118] NFSD: Clean up after updating NFSv3 ACL decoders Chuck Lever
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:44 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3acl.c |   13 +++++++------
 fs/nfsd/nfs3xdr.c |   11 ++++++++++-
 fs/nfsd/xdr3.h    |    2 ++
 3 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index 7c30876a31a1..b8c452b951dc 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -124,19 +124,20 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst *rqstp)
 /*
  * XDR decode functions
  */
+
 static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
 {
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
 	struct nfsd3_getaclargs *args = rqstp->rq_argp;
 
-	p = nfs3svc_decode_fh(p, &args->fh);
-	if (!p)
-		return 0;
-	args->mask = ntohl(*p); p++;
+	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u32(xdr, &args->mask) < 0)
+		return XDR_DECODE_FAILED;
 
-	return xdr_argsize_check(rqstp, p);
+	return XDR_DECODE_DONE;
 }
 
-
 static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
 {
 	struct nfsd3_setaclargs *args = rqstp->rq_argp;
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index df593dd9924b..091baf06c494 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -53,7 +53,16 @@ svcxdr_decode_nfstime3(struct xdr_stream *xdr, struct timespec64 *timep)
 	return XDR_DECODE_DONE;
 }
 
-static enum xdr_decode_result
+/**
+ * svcxdr_decode_nfs_fh3 - Decode an NFSv3 file handle
+ * @xdr: XDR stream positioned at an undecoded NFSv3 FH
+ * @fhp: OUT: filled-in server file handle
+ *
+ * Return values:
+ *  %XDR_DECODE_FAILED: The encoded file handle was not valid
+ *  %XDR_DECODE_DONE: Success
+ */
+enum xdr_decode_result
 svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp)
 {
 	__be32 *p;
diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
index 5afb3ce4f062..1fd5328d867a 100644
--- a/fs/nfsd/xdr3.h
+++ b/fs/nfsd/xdr3.h
@@ -308,6 +308,8 @@ int nfs3svc_encode_entry_plus(void *, const char *name,
 __be32 *nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p,
 				struct svc_fh *fhp);
 __be32 *nfs3svc_decode_fh(__be32 *p, struct svc_fh *fhp);
+enum xdr_decode_result
+svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp);
 
 
 #endif /* _LINUX_NFSD_XDR3_H */



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 117/118] NFSD: Update the NFSv2 SETACL argument decoder to use struct xdr_stream
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (115 preceding siblings ...)
  2020-11-20 20:44 ` [PATCH v2 116/118] NFSD: Update the NFSv3 GETACL argument decoder to use struct xdr_stream Chuck Lever
@ 2020-11-20 20:44 ` Chuck Lever
  2020-11-20 20:44 ` [PATCH v2 118/118] NFSD: Clean up after updating NFSv3 ACL decoders Chuck Lever
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:44 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3acl.c |   39 +++++++++++++++++----------------------
 1 file changed, 17 insertions(+), 22 deletions(-)

diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index b8c452b951dc..8deb0d22e62a 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -140,28 +140,23 @@ static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
 
 static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
 {
-	struct nfsd3_setaclargs *args = rqstp->rq_argp;
-	struct kvec *head = rqstp->rq_arg.head;
-	unsigned int base;
-	int n;
-
-	p = nfs3svc_decode_fh(p, &args->fh);
-	if (!p)
-		return 0;
-	args->mask = ntohl(*p++);
-	if (args->mask & ~NFS_ACL_MASK ||
-	    !xdr_argsize_check(rqstp, p))
-		return 0;
-
-	base = (char *)p - (char *)head->iov_base;
-	n = nfsacl_decode(&rqstp->rq_arg, base, NULL,
-			  (args->mask & NFS_ACL) ?
-			  &args->acl_access : NULL);
-	if (n > 0)
-		n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL,
-				  (args->mask & NFS_DFACL) ?
-				  &args->acl_default : NULL);
-	return (n > 0);
+	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
+	struct nfsd3_setaclargs *argp = rqstp->rq_argp;
+
+	if (!svcxdr_decode_nfs_fh3(xdr, &argp->fh))
+		return XDR_DECODE_FAILED;
+	if (xdr_stream_decode_u32(xdr, &argp->mask) < 0)
+		return XDR_DECODE_FAILED;
+	if (argp->mask & ~NFS_ACL_MASK)
+		return XDR_DECODE_FAILED;
+	if (!nfs_stream_decode_acl(xdr, NULL, (argp->mask & NFS_ACL) ?
+				   &argp->acl_access : NULL))
+		return XDR_DECODE_FAILED;
+	if (!nfs_stream_decode_acl(xdr, NULL, (argp->mask & NFS_DFACL) ?
+				   &argp->acl_default : NULL))
+		return XDR_DECODE_FAILED;
+
+	return XDR_DECODE_DONE;
 }
 
 /*



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* [PATCH v2 118/118] NFSD: Clean up after updating NFSv3 ACL decoders
  2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
                   ` (116 preceding siblings ...)
  2020-11-20 20:44 ` [PATCH v2 117/118] NFSD: Update the NFSv2 SETACL " Chuck Lever
@ 2020-11-20 20:44 ` Chuck Lever
  117 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-20 20:44 UTC (permalink / raw)
  To: linux-nfs

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs3xdr.c |   20 --------------------
 fs/nfsd/xdr3.h    |    1 -
 2 files changed, 21 deletions(-)

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 091baf06c494..6ed396f50a76 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -82,26 +82,6 @@ svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp)
 	return XDR_DECODE_DONE;
 }
 
-static __be32 *
-decode_fh(__be32 *p, struct svc_fh *fhp)
-{
-	unsigned int size;
-	fh_init(fhp, NFS3_FHSIZE);
-	size = ntohl(*p++);
-	if (size > NFS3_FHSIZE)
-		return NULL;
-
-	memcpy(&fhp->fh_handle.fh_base, p, size);
-	fhp->fh_handle.fh_size = size;
-	return p + XDR_QUADLEN(size);
-}
-
-/* Helper function for NFSv3 ACL code */
-__be32 *nfs3svc_decode_fh(__be32 *p, struct svc_fh *fhp)
-{
-	return decode_fh(p, fhp);
-}
-
 static __be32 *
 encode_fh(__be32 *p, struct svc_fh *fhp)
 {
diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
index 1fd5328d867a..59027a9244fb 100644
--- a/fs/nfsd/xdr3.h
+++ b/fs/nfsd/xdr3.h
@@ -307,7 +307,6 @@ int nfs3svc_encode_entry_plus(void *, const char *name,
 /* Helper functions for NFSv3 ACL code */
 __be32 *nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p,
 				struct svc_fh *fhp);
-__be32 *nfs3svc_decode_fh(__be32 *p, struct svc_fh *fhp);
 enum xdr_decode_result
 svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp);
 



^ permalink raw reply related	[flat|nested] 127+ messages in thread

* Re: [PATCH v2 001/118] NFSD: Fix returned READDIR offset cookie
  2020-11-20 20:33 ` [PATCH v2 001/118] NFSD: Fix returned READDIR offset cookie Chuck Lever
@ 2020-11-21  0:59   ` J. Bruce Fields
  2020-11-21 16:15     ` Chuck Lever
  0 siblings, 1 reply; 127+ messages in thread
From: J. Bruce Fields @ 2020-11-21  0:59 UTC (permalink / raw)
  To: Chuck Lever; +Cc: linux-nfs

On Fri, Nov 20, 2020 at 03:33:51PM -0500, Chuck Lever wrote:
> Code inspection shows that the server's NFSv3 READDIR implementation
> returns the same offset cookie as the client sent, instead of the
> last cookie it returns in the reply's dirlist. This is unlike the
> NFSv2 READDIR, NFSv3 READDIRPLUS, and NFSv4 READDIR implementations,
> and it's been like this since the beginning of kernel git history.

Surely this should have caused actual failures in practice.

> I copied the logic from nfsd3_proc_readdirplus().
> 
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> ---
>  fs/nfsd/nfs3proc.c |    7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
> index d9be589fed15..e0ad18d6b5a8 100644
> --- a/fs/nfsd/nfs3proc.c
> +++ b/fs/nfsd/nfs3proc.c
> @@ -430,6 +430,7 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
>  	struct nfsd3_readdirargs *argp = rqstp->rq_argp;
>  	struct nfsd3_readdirres  *resp = rqstp->rq_resp;
>  	int		count = 0;
> +	loff_t		offset;
>  	struct page	**p;
>  	caddr_t		page_addr = NULL;
>  
> @@ -448,7 +449,9 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
>  	resp->common.err = nfs_ok;
>  	resp->buffer = argp->buffer;
>  	resp->rqstp = rqstp;
> -	resp->status = nfsd_readdir(rqstp, &resp->fh, (loff_t *)&argp->cookie,

Doesn't nfsd_readdir() update argp->cookie to point to the last offset?

> +	offset = argp->cookie;
> +
> +	resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
>  				    &resp->common, nfs3svc_encode_entry);
>  	memcpy(resp->verf, argp->verf, 8);
>  	count = 0;
> @@ -464,8 +467,6 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
>  	}
>  	resp->count = count >> 2;
>  	if (resp->offset) {
> -		loff_t offset = argp->cookie;

So, this shouldn't be equal to the initial cookie any more.

Am I missing something?

--b.

> -
>  		if (unlikely(resp->offset1)) {
>  			/* we ended up with offset on a page boundary */
>  			*resp->offset = htonl(offset >> 32);
> 

^ permalink raw reply	[flat|nested] 127+ messages in thread

* Re: [PATCH v2 001/118] NFSD: Fix returned READDIR offset cookie
  2020-11-21  0:59   ` J. Bruce Fields
@ 2020-11-21 16:15     ` Chuck Lever
  2020-11-21 16:32       ` Bruce Fields
  0 siblings, 1 reply; 127+ messages in thread
From: Chuck Lever @ 2020-11-21 16:15 UTC (permalink / raw)
  To: Bruce Fields; +Cc: Linux NFS Mailing List



> On Nov 20, 2020, at 7:59 PM, bfields@fieldses.org wrote:
> 
> On Fri, Nov 20, 2020 at 03:33:51PM -0500, Chuck Lever wrote:
>> Code inspection shows that the server's NFSv3 READDIR implementation
>> returns the same offset cookie as the client sent, instead of the
>> last cookie it returns in the reply's dirlist. This is unlike the
>> NFSv2 READDIR, NFSv3 READDIRPLUS, and NFSv4 READDIR implementations,
>> and it's been like this since the beginning of kernel git history.
> 
> Surely this should have caused actual failures in practice.
> 
>> I copied the logic from nfsd3_proc_readdirplus().
>> 
>> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
>> ---
>> fs/nfsd/nfs3proc.c |    7 ++++---
>> 1 file changed, 4 insertions(+), 3 deletions(-)
>> 
>> diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
>> index d9be589fed15..e0ad18d6b5a8 100644
>> --- a/fs/nfsd/nfs3proc.c
>> +++ b/fs/nfsd/nfs3proc.c
>> @@ -430,6 +430,7 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
>> 	struct nfsd3_readdirargs *argp = rqstp->rq_argp;
>> 	struct nfsd3_readdirres  *resp = rqstp->rq_resp;
>> 	int		count = 0;
>> +	loff_t		offset;
>> 	struct page	**p;
>> 	caddr_t		page_addr = NULL;
>> 
>> @@ -448,7 +449,9 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
>> 	resp->common.err = nfs_ok;
>> 	resp->buffer = argp->buffer;
>> 	resp->rqstp = rqstp;
>> -	resp->status = nfsd_readdir(rqstp, &resp->fh, (loff_t *)&argp->cookie,
> 
> Doesn't nfsd_readdir() update argp->cookie to point to the last offset?
> 
>> +	offset = argp->cookie;
>> +
>> +	resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
>> 				    &resp->common, nfs3svc_encode_entry);
>> 	memcpy(resp->verf, argp->verf, 8);
>> 	count = 0;
>> @@ -464,8 +467,6 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
>> 	}
>> 	resp->count = count >> 2;
>> 	if (resp->offset) {
>> -		loff_t offset = argp->cookie;
> 
> So, this shouldn't be equal to the initial cookie any more.
> 
> Am I missing something?

No, my mistake. This works as we expect. Thanks for the review!

However, I find it confusing that nfsd3_proc_readdir() is structured
differently than the other three readdir proc methods, and for no
documented reason.

Would you still be willing to consider this patch relabeled as a clean-up ?


> --b.
> 
>> -
>> 		if (unlikely(resp->offset1)) {
>> 			/* we ended up with offset on a page boundary */
>> 			*resp->offset = htonl(offset >> 32);
>> 

--
Chuck Lever




^ permalink raw reply	[flat|nested] 127+ messages in thread

* Re: [PATCH v2 001/118] NFSD: Fix returned READDIR offset cookie
  2020-11-21 16:15     ` Chuck Lever
@ 2020-11-21 16:32       ` Bruce Fields
  0 siblings, 0 replies; 127+ messages in thread
From: Bruce Fields @ 2020-11-21 16:32 UTC (permalink / raw)
  To: Chuck Lever; +Cc: Linux NFS Mailing List

On Sat, Nov 21, 2020 at 11:15:54AM -0500, Chuck Lever wrote:
> 
> 
> > On Nov 20, 2020, at 7:59 PM, bfields@fieldses.org wrote:
> > 
> > On Fri, Nov 20, 2020 at 03:33:51PM -0500, Chuck Lever wrote:
> >> Code inspection shows that the server's NFSv3 READDIR implementation
> >> returns the same offset cookie as the client sent, instead of the
> >> last cookie it returns in the reply's dirlist. This is unlike the
> >> NFSv2 READDIR, NFSv3 READDIRPLUS, and NFSv4 READDIR implementations,
> >> and it's been like this since the beginning of kernel git history.
> > 
> > Surely this should have caused actual failures in practice.
> > 
> >> I copied the logic from nfsd3_proc_readdirplus().
> >> 
> >> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> >> ---
> >> fs/nfsd/nfs3proc.c |    7 ++++---
> >> 1 file changed, 4 insertions(+), 3 deletions(-)
> >> 
> >> diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
> >> index d9be589fed15..e0ad18d6b5a8 100644
> >> --- a/fs/nfsd/nfs3proc.c
> >> +++ b/fs/nfsd/nfs3proc.c
> >> @@ -430,6 +430,7 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
> >> 	struct nfsd3_readdirargs *argp = rqstp->rq_argp;
> >> 	struct nfsd3_readdirres  *resp = rqstp->rq_resp;
> >> 	int		count = 0;
> >> +	loff_t		offset;
> >> 	struct page	**p;
> >> 	caddr_t		page_addr = NULL;
> >> 
> >> @@ -448,7 +449,9 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
> >> 	resp->common.err = nfs_ok;
> >> 	resp->buffer = argp->buffer;
> >> 	resp->rqstp = rqstp;
> >> -	resp->status = nfsd_readdir(rqstp, &resp->fh, (loff_t *)&argp->cookie,
> > 
> > Doesn't nfsd_readdir() update argp->cookie to point to the last offset?
> > 
> >> +	offset = argp->cookie;
> >> +
> >> +	resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
> >> 				    &resp->common, nfs3svc_encode_entry);
> >> 	memcpy(resp->verf, argp->verf, 8);
> >> 	count = 0;
> >> @@ -464,8 +467,6 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
> >> 	}
> >> 	resp->count = count >> 2;
> >> 	if (resp->offset) {
> >> -		loff_t offset = argp->cookie;
> > 
> > So, this shouldn't be equal to the initial cookie any more.
> > 
> > Am I missing something?
> 
> No, my mistake. This works as we expect. Thanks for the review!
> 
> However, I find it confusing that nfsd3_proc_readdir() is structured
> differently than the other three readdir proc methods, and for no
> documented reason.
> 
> Would you still be willing to consider this patch relabeled as a clean-up ?

Sure, seems fine, and if it confused you then it'd probably confuse
someone else.

--b.

^ permalink raw reply	[flat|nested] 127+ messages in thread

* Re: [PATCH v2 003/118] SUNRPC: Prepare for xdr_stream-style decoding on the server-side
  2020-11-20 20:34 ` [PATCH v2 003/118] SUNRPC: Prepare for xdr_stream-style decoding on the server-side Chuck Lever
@ 2020-11-23 18:49   ` J. Bruce Fields
  2020-11-23 18:52     ` Chuck Lever
  0 siblings, 1 reply; 127+ messages in thread
From: J. Bruce Fields @ 2020-11-23 18:49 UTC (permalink / raw)
  To: Chuck Lever; +Cc: linux-nfs

On Fri, Nov 20, 2020 at 03:34:02PM -0500, Chuck Lever wrote:
> 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.

I'm not sure how I feel about that part.  Do you plan to change this
everywhere?

Maybe it'd be simpler or clearer to make pc_decode return bool?

--b.

> 
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> ---
>  fs/nfsd/nfs4xdr.c          |    3 ++-
>  fs/nfsd/nfssvc.c           |    4 +++-
>  include/linux/sunrpc/svc.h |   16 ++++++++++++++++
>  include/linux/sunrpc/xdr.h |    5 +++++
>  net/sunrpc/svc.c           |    5 +++++
>  5 files changed, 31 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> index e3c6bea83bd6..66274ad05a9c 100644
> --- a/fs/nfsd/nfs4xdr.c
> +++ b/fs/nfsd/nfs4xdr.c
> @@ -5321,7 +5321,8 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p)
>  	args->ops = args->iops;
>  	args->rqstp = rqstp;
>  
> -	return !nfsd4_decode_compound(args);
> +	return nfsd4_decode_compound(args) == nfs_ok ?	XDR_DECODE_DONE :
> +							XDR_DECODE_FAILED;
>  }
>  
>  int
> diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
> index 27b1ad136150..daeab72975a3 100644
> --- a/fs/nfsd/nfssvc.c
> +++ b/fs/nfsd/nfssvc.c
> @@ -1020,7 +1020,9 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
>  	 * (necessary in the NFSv4.0 compound case)
>  	 */
>  	rqstp->rq_cachetype = proc->pc_cachetype;
> -	if (!proc->pc_decode(rqstp, argv->iov_base))
> +
> +	svcxdr_init_decode(rqstp, argv->iov_base);
> +	if (proc->pc_decode(rqstp, argv->iov_base) == XDR_DECODE_FAILED)
>  		goto out_decode_err;
>  
>  	switch (nfsd_cache_lookup(rqstp)) {
> diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
> index c220b734fa69..bb6c93283697 100644
> --- a/include/linux/sunrpc/svc.h
> +++ b/include/linux/sunrpc/svc.h
> @@ -248,6 +248,8 @@ struct svc_rqst {
>  	size_t			rq_xprt_hlen;	/* xprt header len */
>  	struct xdr_buf		rq_arg;
>  	struct xdr_buf		rq_res;
> +	struct xdr_stream	rq_xdr_stream;
> +	struct page		*rq_scratch_page;
>  	struct page		*rq_pages[RPCSVC_MAXPAGES + 1];
>  	struct page *		*rq_respages;	/* points into rq_pages */
>  	struct page *		*rq_next_page; /* next reply page to use */
> @@ -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
> + * @p: Starting position
> + *
> + */
> +static inline void svcxdr_init_decode(struct svc_rqst *rqstp, __be32 *p)
> +{
> +	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
> +
> +	xdr_init_decode(xdr, &rqstp->rq_arg, p, NULL);
> +	xdr_set_scratch_page(xdr, rqstp->rq_scratch_page);
> +}
> +
>  #endif /* SUNRPC_SVC_H */
> diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
> index 2729d2d6efce..abbb032de4e8 100644
> --- a/include/linux/sunrpc/xdr.h
> +++ b/include/linux/sunrpc/xdr.h
> @@ -19,6 +19,11 @@
>  struct bio_vec;
>  struct rpc_rqst;
>  
> +enum xdr_decode_result {
> +	XDR_DECODE_FAILED = 0,
> +	XDR_DECODE_DONE = 1,
> +};
> +
>  /*
>   * Buffer adjustment
>   */
> diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
> index b41500645c3f..4187745887f0 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);
> 

^ permalink raw reply	[flat|nested] 127+ messages in thread

* Re: [PATCH v2 003/118] SUNRPC: Prepare for xdr_stream-style decoding on the server-side
  2020-11-23 18:49   ` J. Bruce Fields
@ 2020-11-23 18:52     ` Chuck Lever
  0 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-23 18:52 UTC (permalink / raw)
  To: Bruce Fields; +Cc: Linux NFS Mailing List



> On Nov 23, 2020, at 1:49 PM, bfields@fieldses.org wrote:
> 
> On Fri, Nov 20, 2020 at 03:34:02PM -0500, Chuck Lever wrote:
>> 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.
> 
> I'm not sure how I feel about that part.  Do you plan to change this
> everywhere?

Yes. But, I agree it is a little wordy.


> Maybe it'd be simpler or clearer to make pc_decode return bool?

That was my first thought. But true/false is just as overloaded
and meaningless as "1" and "0".

However, I'm open to opinions and better ideas.


> --b.
> 
>> 
>> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
>> ---
>> fs/nfsd/nfs4xdr.c          |    3 ++-
>> fs/nfsd/nfssvc.c           |    4 +++-
>> include/linux/sunrpc/svc.h |   16 ++++++++++++++++
>> include/linux/sunrpc/xdr.h |    5 +++++
>> net/sunrpc/svc.c           |    5 +++++
>> 5 files changed, 31 insertions(+), 2 deletions(-)
>> 
>> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
>> index e3c6bea83bd6..66274ad05a9c 100644
>> --- a/fs/nfsd/nfs4xdr.c
>> +++ b/fs/nfsd/nfs4xdr.c
>> @@ -5321,7 +5321,8 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p)
>> 	args->ops = args->iops;
>> 	args->rqstp = rqstp;
>> 
>> -	return !nfsd4_decode_compound(args);
>> +	return nfsd4_decode_compound(args) == nfs_ok ?	XDR_DECODE_DONE :
>> +							XDR_DECODE_FAILED;
>> }
>> 
>> int
>> diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
>> index 27b1ad136150..daeab72975a3 100644
>> --- a/fs/nfsd/nfssvc.c
>> +++ b/fs/nfsd/nfssvc.c
>> @@ -1020,7 +1020,9 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
>> 	 * (necessary in the NFSv4.0 compound case)
>> 	 */
>> 	rqstp->rq_cachetype = proc->pc_cachetype;
>> -	if (!proc->pc_decode(rqstp, argv->iov_base))
>> +
>> +	svcxdr_init_decode(rqstp, argv->iov_base);
>> +	if (proc->pc_decode(rqstp, argv->iov_base) == XDR_DECODE_FAILED)
>> 		goto out_decode_err;
>> 
>> 	switch (nfsd_cache_lookup(rqstp)) {
>> diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
>> index c220b734fa69..bb6c93283697 100644
>> --- a/include/linux/sunrpc/svc.h
>> +++ b/include/linux/sunrpc/svc.h
>> @@ -248,6 +248,8 @@ struct svc_rqst {
>> 	size_t			rq_xprt_hlen;	/* xprt header len */
>> 	struct xdr_buf		rq_arg;
>> 	struct xdr_buf		rq_res;
>> +	struct xdr_stream	rq_xdr_stream;
>> +	struct page		*rq_scratch_page;
>> 	struct page		*rq_pages[RPCSVC_MAXPAGES + 1];
>> 	struct page *		*rq_respages;	/* points into rq_pages */
>> 	struct page *		*rq_next_page; /* next reply page to use */
>> @@ -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
>> + * @p: Starting position
>> + *
>> + */
>> +static inline void svcxdr_init_decode(struct svc_rqst *rqstp, __be32 *p)
>> +{
>> +	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
>> +
>> +	xdr_init_decode(xdr, &rqstp->rq_arg, p, NULL);
>> +	xdr_set_scratch_page(xdr, rqstp->rq_scratch_page);
>> +}
>> +
>> #endif /* SUNRPC_SVC_H */
>> diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
>> index 2729d2d6efce..abbb032de4e8 100644
>> --- a/include/linux/sunrpc/xdr.h
>> +++ b/include/linux/sunrpc/xdr.h
>> @@ -19,6 +19,11 @@
>> struct bio_vec;
>> struct rpc_rqst;
>> 
>> +enum xdr_decode_result {
>> +	XDR_DECODE_FAILED = 0,
>> +	XDR_DECODE_DONE = 1,
>> +};
>> +
>> /*
>>  * Buffer adjustment
>>  */
>> diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
>> index b41500645c3f..4187745887f0 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);

--
Chuck Lever




^ permalink raw reply	[flat|nested] 127+ messages in thread

* Re: [PATCH v2 005/118] NFSD: Replace the internals of the READ_BUF() macro
  2020-11-20 20:34 ` [PATCH v2 005/118] NFSD: Replace the internals of the READ_BUF() macro Chuck Lever
@ 2020-11-23 19:18   ` J. Bruce Fields
  2020-11-23 19:21     ` Chuck Lever
  0 siblings, 1 reply; 127+ messages in thread
From: J. Bruce Fields @ 2020-11-23 19:18 UTC (permalink / raw)
  To: Chuck Lever; +Cc: linux-nfs

On Fri, Nov 20, 2020 at 03:34:12PM -0500, Chuck Lever wrote:
> @@ -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))

Picky C question: is the compiler guaranteed to pack that struct in the
obvious way?

That aside, I'm not comfortable assuming the struct could never change
to, say, include something that's useful during processing but doesn't
appear on the wire.

Also, that change isn't actually logically related to the rest of the
patch, so it's the sort of thing I'd expect separated out.

--b.

^ permalink raw reply	[flat|nested] 127+ messages in thread

* Re: [PATCH v2 005/118] NFSD: Replace the internals of the READ_BUF() macro
  2020-11-23 19:18   ` J. Bruce Fields
@ 2020-11-23 19:21     ` Chuck Lever
  0 siblings, 0 replies; 127+ messages in thread
From: Chuck Lever @ 2020-11-23 19:21 UTC (permalink / raw)
  To: Bruce Fields; +Cc: Linux NFS Mailing List



> On Nov 23, 2020, at 2:18 PM, bfields@fieldses.org wrote:
> 
> On Fri, Nov 20, 2020 at 03:34:12PM -0500, Chuck Lever wrote:
>> @@ -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))
> 
> Picky C question: is the compiler guaranteed to pack that struct in the
> obvious way?
> 
> That aside, I'm not comfortable assuming the struct could never change
> to, say, include something that's useful during processing but doesn't
> appear on the wire.

OK, but you also don't like naked integers without documentation.
I can leave this as "xdr_stream_remaining() / 20" if you prefer.
Or we could define a macro somewhere that makes this code a little
more self-documenting.


> Also, that change isn't actually logically related to the rest of the
> patch, so it's the sort of thing I'd expect separated out.
> 
> --b.

--
Chuck Lever




^ permalink raw reply	[flat|nested] 127+ messages in thread

* Re: [PATCH v2 087/118] NFSD: Update READDIR3args decoders to use struct xdr_stream
  2020-11-20 20:41 ` [PATCH v2 087/118] NFSD: Update READDIR3args decoders to use struct xdr_stream Chuck Lever
@ 2020-11-23 20:55   ` J. Bruce Fields
  0 siblings, 0 replies; 127+ messages in thread
From: J. Bruce Fields @ 2020-11-23 20:55 UTC (permalink / raw)
  To: Chuck Lever; +Cc: linux-nfs

On Fri, Nov 20, 2020 at 03:41:29PM -0500, Chuck Lever wrote:
> As an additional clean up, neither nfsd3_proc_readdir() nor
> nfsd3_proc_readdirplus() make use of the dircount argument, so
> remove it.

Are we technically violating the protocol if we return more than
dircount entries?

https://tools.ietf.org/html/rfc1813#page-82 doesn't say it's optional.
I suppose we'd know by now if any client actually cared.  Seems like
it'd be easy to implement, though.

Anyway, for now:

>  int
>  nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p)
>  {
> +	struct xdr_stream *xdr = &rqstp->rq_xdr_stream;
>  	struct nfsd3_readdirargs *args = rqstp->rq_argp;

maybe just add "/* ignored */" to make it clear it's inentional we're
not actually using the value read into this variable?:

> +	u32 dircount;

--b.

>  
> -	p = decode_fh(p, &args->fh);
> -	if (!p)
> -		return 0;
> -	p = xdr_decode_hyper(p, &args->cookie);
> -	args->verf     = p; p += 2;
> -	args->dircount = ntohl(*p++);
> -	args->count    = ntohl(*p++);
> +	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
> +		return XDR_DECODE_FAILED;
> +	if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
> +		return XDR_DECODE_FAILED;
> +	args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
> +	if (!args->verf)
> +		return XDR_DECODE_FAILED;
> +	if (xdr_stream_decode_u32(xdr, &dircount) < 0)
> +		return XDR_DECODE_FAILED;
> +	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
> +		return XDR_DECODE_FAILED;
>  
> -	return xdr_argsize_check(rqstp, p);
> +	return XDR_DECODE_DONE;
>  }
>  
>  int
> diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
> index 789a364d5e69..64af5b01c5d7 100644
> --- a/fs/nfsd/xdr3.h
> +++ b/fs/nfsd/xdr3.h
> @@ -90,7 +90,6 @@ struct nfsd3_symlinkargs {
>  struct nfsd3_readdirargs {
>  	struct svc_fh		fh;
>  	__u64			cookie;
> -	__u32			dircount;
>  	__u32			count;
>  	__be32 *		verf;
>  };
> 

^ permalink raw reply	[flat|nested] 127+ messages in thread

end of thread, other threads:[~2020-11-23 20:55 UTC | newest]

Thread overview: 127+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-20 20:33 [PATCH v2 000/118] Update NFSD XDR functions Chuck Lever
2020-11-20 20:33 ` [PATCH v2 001/118] NFSD: Fix returned READDIR offset cookie Chuck Lever
2020-11-21  0:59   ` J. Bruce Fields
2020-11-21 16:15     ` Chuck Lever
2020-11-21 16:32       ` Bruce Fields
2020-11-20 20:33 ` [PATCH v2 002/118] SUNRPC: Add xdr_set_scratch_page() and xdr_reset_scratch_buffer() Chuck Lever
2020-11-20 20:34 ` [PATCH v2 003/118] SUNRPC: Prepare for xdr_stream-style decoding on the server-side Chuck Lever
2020-11-23 18:49   ` J. Bruce Fields
2020-11-23 18:52     ` Chuck Lever
2020-11-20 20:34 ` [PATCH v2 004/118] NFSD: Add common helpers to decode void args and encode void results Chuck Lever
2020-11-20 20:34 ` [PATCH v2 005/118] NFSD: Replace the internals of the READ_BUF() macro Chuck Lever
2020-11-23 19:18   ` J. Bruce Fields
2020-11-23 19:21     ` Chuck Lever
2020-11-20 20:34 ` [PATCH v2 006/118] NFSD: Replace READ* macros in nfsd4_decode_access() Chuck Lever
2020-11-20 20:34 ` [PATCH v2 007/118] NFSD: Replace READ* macros in nfsd4_decode_stateid() Chuck Lever
2020-11-20 20:34 ` [PATCH v2 008/118] NFSD: Replace READ* macros in nfsd4_decode_close() Chuck Lever
2020-11-20 20:34 ` [PATCH v2 009/118] NFSD: Replace READ* macros in nfsd4_decode_commit() Chuck Lever
2020-11-20 20:34 ` [PATCH v2 010/118] NFSD: Change the way the expected length of a fattr4 is checked Chuck Lever
2020-11-20 20:34 ` [PATCH v2 011/118] NFSD: Replace READ* macros that decode the fattr4 size attribute Chuck Lever
2020-11-20 20:34 ` [PATCH v2 012/118] NFSD: Replace READ* macros that decode the fattr4 acl attribute Chuck Lever
2020-11-20 20:34 ` [PATCH v2 013/118] NFSD: Replace READ* macros that decode the fattr4 mode attribute Chuck Lever
2020-11-20 20:35 ` [PATCH v2 014/118] NFSD: Replace READ* macros that decode the fattr4 owner attribute Chuck Lever
2020-11-20 20:35 ` [PATCH v2 015/118] NFSD: Replace READ* macros that decode the fattr4 owner_group attribute Chuck Lever
2020-11-20 20:35 ` [PATCH v2 016/118] NFSD: Replace READ* macros that decode the fattr4 time_set attributes Chuck Lever
2020-11-20 20:35 ` [PATCH v2 017/118] NFSD: Replace READ* macros that decode the fattr4 security label attribute Chuck Lever
2020-11-20 20:35 ` [PATCH v2 018/118] NFSD: Replace READ* macros that decode the fattr4 umask attribute Chuck Lever
2020-11-20 20:35 ` [PATCH v2 019/118] NFSD: Replace READ* macros in nfsd4_decode_fattr() Chuck Lever
2020-11-20 20:35 ` [PATCH v2 020/118] NFSD: Replace READ* macros in nfsd4_decode_create() Chuck Lever
2020-11-20 20:35 ` [PATCH v2 021/118] NFSD: Replace READ* macros in nfsd4_decode_getattr() Chuck Lever
2020-11-20 20:35 ` [PATCH v2 022/118] NFSD: Replace READ* macros in nfsd4_decode_link() Chuck Lever
2020-11-20 20:35 ` [PATCH v2 023/118] NFSD: Relocate nfsd4_decode_opaque() Chuck Lever
2020-11-20 20:35 ` [PATCH v2 024/118] NFSD: Add helpers to decode a clientid4 and an NFSv4 state owner Chuck Lever
2020-11-20 20:35 ` [PATCH v2 025/118] NFSD: Add helper for decoding locker4 Chuck Lever
2020-11-20 20:36 ` [PATCH v2 026/118] NFSD: Replace READ* macros in nfsd4_decode_lock() Chuck Lever
2020-11-20 20:36 ` [PATCH v2 027/118] NFSD: Replace READ* macros in nfsd4_decode_lockt() Chuck Lever
2020-11-20 20:36 ` [PATCH v2 028/118] NFSD: Replace READ* macros in nfsd4_decode_locku() Chuck Lever
2020-11-20 20:36 ` [PATCH v2 029/118] NFSD: Replace READ* macros in nfsd4_decode_lookup() Chuck Lever
2020-11-20 20:36 ` [PATCH v2 030/118] NFSD: Add helper to decode NFSv4 verifiers Chuck Lever
2020-11-20 20:36 ` [PATCH v2 031/118] NFSD: Add helper to decode OPEN's createhow4 argument Chuck Lever
2020-11-20 20:36 ` [PATCH v2 032/118] NFSD: Add helper to decode OPEN's openflag4 argument Chuck Lever
2020-11-20 20:36 ` [PATCH v2 033/118] NFSD: Replace READ* macros in nfsd4_decode_share_access() Chuck Lever
2020-11-20 20:36 ` [PATCH v2 034/118] NFSD: Replace READ* macros in nfsd4_decode_share_deny() Chuck Lever
2020-11-20 20:36 ` [PATCH v2 035/118] NFSD: Add helper to decode OPEN's open_claim4 argument Chuck Lever
2020-11-20 20:36 ` [PATCH v2 036/118] NFSD: Replace READ* macros in nfsd4_decode_open() Chuck Lever
2020-11-20 20:37 ` [PATCH v2 037/118] NFSD: Replace READ* macros in nfsd4_decode_open_confirm() Chuck Lever
2020-11-20 20:37 ` [PATCH v2 038/118] NFSD: Replace READ* macros in nfsd4_decode_open_downgrade() Chuck Lever
2020-11-20 20:37 ` [PATCH v2 039/118] NFSD: Replace READ* macros in nfsd4_decode_putfh() Chuck Lever
2020-11-20 20:37 ` [PATCH v2 040/118] NFSD: Replace READ* macros in nfsd4_decode_read() Chuck Lever
2020-11-20 20:37 ` [PATCH v2 041/118] NFSD: Replace READ* macros in nfsd4_decode_readdir() Chuck Lever
2020-11-20 20:37 ` [PATCH v2 042/118] NFSD: Replace READ* macros in nfsd4_decode_remove() Chuck Lever
2020-11-20 20:37 ` [PATCH v2 043/118] NFSD: Replace READ* macros in nfsd4_decode_rename() Chuck Lever
2020-11-20 20:37 ` [PATCH v2 044/118] NFSD: Replace READ* macros in nfsd4_decode_renew() Chuck Lever
2020-11-20 20:37 ` [PATCH v2 045/118] NFSD: Replace READ* macros in nfsd4_decode_secinfo() Chuck Lever
2020-11-20 20:37 ` [PATCH v2 046/118] NFSD: Replace READ* macros in nfsd4_decode_setclientid() Chuck Lever
2020-11-20 20:37 ` [PATCH v2 047/118] NFSD: Replace READ* macros in nfsd4_decode_setclientid_confirm() Chuck Lever
2020-11-20 20:38 ` [PATCH v2 048/118] NFSD: Replace READ* macros in nfsd4_decode_verify() Chuck Lever
2020-11-20 20:38 ` [PATCH v2 049/118] NFSD: Replace READ* macros in nfsd4_decode_write() Chuck Lever
2020-11-20 20:38 ` [PATCH v2 050/118] NFSD: Replace READ* macros in nfsd4_decode_release_lockowner() Chuck Lever
2020-11-20 20:38 ` [PATCH v2 051/118] NFSD: Replace READ* macros in nfsd4_decode_cb_sec() Chuck Lever
2020-11-20 20:38 ` [PATCH v2 052/118] NFSD: Replace READ* macros in nfsd4_decode_backchannel_ctl() Chuck Lever
2020-11-20 20:38 ` [PATCH v2 053/118] NFSD: Replace READ* macros in nfsd4_decode_bind_conn_to_session() Chuck Lever
2020-11-20 20:38 ` [PATCH v2 054/118] NFSD: Add a separate decoder to handle state_protect_ops Chuck Lever
2020-11-20 20:38 ` [PATCH v2 055/118] NFSD: Add a separate decoder for ssv_sp_parms Chuck Lever
2020-11-20 20:38 ` [PATCH v2 056/118] NFSD: Add a helper to decode state_protect4_a Chuck Lever
2020-11-20 20:38 ` [PATCH v2 057/118] NFSD: Add a helper to decode nfs_impl_id4 Chuck Lever
2020-11-20 20:38 ` [PATCH v2 058/118] NFSD: Add a helper to decode channel_attrs4 Chuck Lever
2020-11-20 20:38 ` [PATCH v2 059/118] NFSD: Replace READ* macros in nfsd4_decode_create_session() Chuck Lever
2020-11-20 20:39 ` [PATCH v2 060/118] NFSD: Replace READ* macros in nfsd4_decode_destroy_session() Chuck Lever
2020-11-20 20:39 ` [PATCH v2 061/118] NFSD: Replace READ* macros in nfsd4_decode_free_stateid() Chuck Lever
2020-11-20 20:39 ` [PATCH v2 062/118] NFSD: Replace READ* macros in nfsd4_decode_getdeviceinfo() Chuck Lever
2020-11-20 20:39 ` [PATCH v2 063/118] NFSD: Replace READ* macros in nfsd4_decode_layoutcommit() Chuck Lever
2020-11-20 20:39 ` [PATCH v2 064/118] NFSD: Replace READ* macros in nfsd4_decode_layoutget() Chuck Lever
2020-11-20 20:39 ` [PATCH v2 065/118] NFSD: Replace READ* macros in nfsd4_decode_layoutreturn() Chuck Lever
2020-11-20 20:39 ` [PATCH v2 066/118] NFSD: Replace READ* macros in nfsd4_decode_secinfo_no_name() Chuck Lever
2020-11-20 20:39 ` [PATCH v2 067/118] NFSD: Replace READ* macros in nfsd4_decode_sequence() Chuck Lever
2020-11-20 20:39 ` [PATCH v2 068/118] NFSD: Replace READ* macros in nfsd4_decode_test_stateid() Chuck Lever
2020-11-20 20:39 ` [PATCH v2 069/118] NFSD: Replace READ* macros in nfsd4_decode_destroy_clientid() Chuck Lever
2020-11-20 20:39 ` [PATCH v2 070/118] NFSD: Replace READ* macros in nfsd4_decode_reclaim_complete() Chuck Lever
2020-11-20 20:40 ` [PATCH v2 071/118] NFSD: Replace READ* macros in nfsd4_decode_fallocate() Chuck Lever
2020-11-20 20:40 ` [PATCH v2 072/118] NFSD: Replace READ* macros in nfsd4_decode_clone() Chuck Lever
2020-11-20 20:40 ` [PATCH v2 073/118] NFSD: Replace READ* macros in nfsd4_decode_nl4_server() Chuck Lever
2020-11-20 20:40 ` [PATCH v2 074/118] NFSD: Replace READ* macros in nfsd4_decode_copy() Chuck Lever
2020-11-20 20:40 ` [PATCH v2 075/118] NFSD: Replace READ* macros in nfsd4_decode_seek() Chuck Lever
2020-11-20 20:40 ` [PATCH v2 076/118] NFSD: Replace READ* macros in nfsd4_decode_xattr_name() Chuck Lever
2020-11-20 20:40 ` [PATCH v2 077/118] NFSD: Replace READ* macros in nfsd4_decode_setxattr() Chuck Lever
2020-11-20 20:40 ` [PATCH v2 078/118] NFSD: Replace READ* macros in nfsd4_decode_listxattrs() Chuck Lever
2020-11-20 20:40 ` [PATCH v2 079/118] NFSD: Replace READ* macros in nfsd4_decode_compound() Chuck Lever
2020-11-20 20:40 ` [PATCH v2 080/118] NFSD: Remove macros that are no longer used Chuck Lever
2020-11-20 20:40 ` [PATCH v2 081/118] NFSD: Update GETATTR3args decoder to use struct xdr_stream Chuck Lever
2020-11-20 20:41 ` [PATCH v2 082/118] NFSD: Update ACCESS3arg " Chuck Lever
2020-11-20 20:41 ` [PATCH v2 083/118] NFSD: Update READ3arg " Chuck Lever
2020-11-20 20:41 ` [PATCH v2 084/118] NFSD: Update WRITE3arg " Chuck Lever
2020-11-20 20:41 ` [PATCH v2 085/118] NFSD: Update READLINK3arg " Chuck Lever
2020-11-20 20:41 ` [PATCH v2 086/118] NFSD: Add helper to set up the pages where the dirlist is encoded Chuck Lever
2020-11-20 20:41 ` [PATCH v2 087/118] NFSD: Update READDIR3args decoders to use struct xdr_stream Chuck Lever
2020-11-23 20:55   ` J. Bruce Fields
2020-11-20 20:41 ` [PATCH v2 088/118] NFSD: Update COMMIT3arg decoder " Chuck Lever
2020-11-20 20:41 ` [PATCH v2 089/118] NFSD: Update the NFSv3 DIROPargs " Chuck Lever
2020-11-20 20:41 ` [PATCH v2 090/118] NFSD: Update the RENAME3args " Chuck Lever
2020-11-20 20:41 ` [PATCH v2 091/118] NFSD: Update the LINK3args " Chuck Lever
2020-11-20 20:41 ` [PATCH v2 092/118] NFSD: Update the SETATTR3args " Chuck Lever
2020-11-20 20:42 ` [PATCH v2 093/118] NFSD: Update the CREATE3args " Chuck Lever
2020-11-20 20:42 ` [PATCH v2 094/118] NFSD: Update the MKDIR3args " Chuck Lever
2020-11-20 20:42 ` [PATCH v2 095/118] NFSD: Update the SYMLINK3args " Chuck Lever
2020-11-20 20:42 ` [PATCH v2 096/118] NFSD: Update the MKNOD3args " Chuck Lever
2020-11-20 20:42 ` [PATCH v2 097/118] NFSD: Update the NFSv2 GETATTR argument " Chuck Lever
2020-11-20 20:42 ` [PATCH v2 098/118] NFSD: Update the NFSv2 READ " Chuck Lever
2020-11-20 20:42 ` [PATCH v2 099/118] NFSD: Update the NFSv2 WRITE " Chuck Lever
2020-11-20 20:42 ` [PATCH v2 100/118] NFSD: Update the NFSv2 READLINK " Chuck Lever
2020-11-20 20:42 ` [PATCH v2 101/118] NFSD: Add helper to set up the pages where the dirlist is encoded Chuck Lever
2020-11-20 20:42 ` [PATCH v2 102/118] NFSD: Update the NFSv2 READDIR argument decoder to use struct xdr_stream Chuck Lever
2020-11-20 20:42 ` [PATCH v2 103/118] NFSD: Update NFSv2 diropargs decoding " Chuck Lever
2020-11-20 20:42 ` [PATCH v2 104/118] NFSD: Update the NFSv2 RENAME argument decoder " Chuck Lever
2020-11-20 20:43 ` [PATCH v2 105/118] NFSD: Update the NFSv2 LINK " Chuck Lever
2020-11-20 20:43 ` [PATCH v2 106/118] NFSD: Update the NFSv2 SETATTR " Chuck Lever
2020-11-20 20:43 ` [PATCH v2 107/118] NFSD: Update the NFSv2 CREATE " Chuck Lever
2020-11-20 20:43 ` [PATCH v2 108/118] NFSD: Update the NFSv2 SYMLINK " Chuck Lever
2020-11-20 20:43 ` [PATCH v2 109/118] NFSD: Remove argument length checking in nfsd_dispatch() Chuck Lever
2020-11-20 20:43 ` [PATCH v2 110/118] NFSD: Update the NFSv2 GETACL argument decoder to use struct xdr_stream Chuck Lever
2020-11-20 20:43 ` [PATCH v2 111/118] NFSD: Add an xdr_stream-based decoder for NFSv2/3 ACLs Chuck Lever
2020-11-20 20:43 ` [PATCH v2 112/118] NFSD: Update the NFSv2 SETACL argument decoder to use struct xdr_stream Chuck Lever
2020-11-20 20:43 ` [PATCH v2 113/118] NFSD: Update the NFSv2 ACL GETATTR " Chuck Lever
2020-11-20 20:43 ` [PATCH v2 114/118] NFSD: Update the NFSv2 ACL ACCESS " Chuck Lever
2020-11-20 20:43 ` [PATCH v2 115/118] NFSD: Clean up after updating NFSv2 ACL decoders Chuck Lever
2020-11-20 20:44 ` [PATCH v2 116/118] NFSD: Update the NFSv3 GETACL argument decoder to use struct xdr_stream Chuck Lever
2020-11-20 20:44 ` [PATCH v2 117/118] NFSD: Update the NFSv2 SETACL " Chuck Lever
2020-11-20 20:44 ` [PATCH v2 118/118] NFSD: Clean up after updating NFSv3 ACL decoders Chuck Lever

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.