Linux-NFS Archive on lore.kernel.org
 help / color / Atom feed
From: Chuck Lever <chuck.lever@oracle.com>
To: anna.schumaker@netapp.com
Cc: linux-rdma@vger.kernel.org, linux-nfs@vger.kernel.org
Subject: [PATCH v1 20/23] NFS: Account for XDR pad of buf->pages
Date: Mon, 11 Feb 2019 11:25:25 -0500
Message-ID: <20190211162525.2817.60645.stgit@manet.1015granger.net> (raw)
In-Reply-To: <20190211161920.2817.20881.stgit@manet.1015granger.net>

Certain NFS results (eg. READLINK) might expect a data payload that
is not an exact multiple of 4 bytes. In this case, XDR encoding
is required to pad that payload so its length on the wire is a
multiple of 4 bytes. The constants that define the maximum size of
each NFS result do not appear to account for this extra word.

In each case where the data payload is to be received into pages:

- 1 word is added to the size of the receive buffer allocated by
  call_allocate

- rpc_inline_rcv_pages subtracts 1 word from @hdrsize so that the
  extra buffer space falls into the rcv_buf's tail iovec

- If buf->pagelen is word-aligned, an XDR pad is not needed and
  is thus removed from the tail

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfs/nfs2xdr.c  |    6 +++---
 fs/nfs/nfs3xdr.c  |   10 +++++-----
 fs/nfs/nfs4xdr.c  |   15 ++++++++-------
 net/sunrpc/clnt.c |    6 +++++-
 net/sunrpc/xdr.c  |    2 ++
 5 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 1dcd0fe..a7ed29d 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -56,11 +56,11 @@
 
 #define NFS_attrstat_sz		(1+NFS_fattr_sz)
 #define NFS_diropres_sz		(1+NFS_fhandle_sz+NFS_fattr_sz)
-#define NFS_readlinkres_sz	(2)
-#define NFS_readres_sz		(1+NFS_fattr_sz+1)
+#define NFS_readlinkres_sz	(2+1)
+#define NFS_readres_sz		(1+NFS_fattr_sz+1+1)
 #define NFS_writeres_sz         (NFS_attrstat_sz)
 #define NFS_stat_sz		(1)
-#define NFS_readdirres_sz	(1)
+#define NFS_readdirres_sz	(1+1)
 #define NFS_statfsres_sz	(1+NFS_info_sz)
 
 static int nfs_stat_to_errno(enum nfs_stat);
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index a54dcf4..110358f 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -69,13 +69,13 @@
 #define NFS3_removeres_sz	(NFS3_setattrres_sz)
 #define NFS3_lookupres_sz	(1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
 #define NFS3_accessres_sz	(1+NFS3_post_op_attr_sz+1)
-#define NFS3_readlinkres_sz	(1+NFS3_post_op_attr_sz+1)
-#define NFS3_readres_sz		(1+NFS3_post_op_attr_sz+3)
+#define NFS3_readlinkres_sz	(1+NFS3_post_op_attr_sz+1+1)
+#define NFS3_readres_sz		(1+NFS3_post_op_attr_sz+3+1)
 #define NFS3_writeres_sz	(1+NFS3_wcc_data_sz+4)
 #define NFS3_createres_sz	(1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
 #define NFS3_renameres_sz	(1+(2 * NFS3_wcc_data_sz))
 #define NFS3_linkres_sz		(1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
-#define NFS3_readdirres_sz	(1+NFS3_post_op_attr_sz+2)
+#define NFS3_readdirres_sz	(1+NFS3_post_op_attr_sz+2+1)
 #define NFS3_fsstatres_sz	(1+NFS3_post_op_attr_sz+13)
 #define NFS3_fsinfores_sz	(1+NFS3_post_op_attr_sz+12)
 #define NFS3_pathconfres_sz	(1+NFS3_post_op_attr_sz+6)
@@ -85,7 +85,7 @@
 #define ACL3_setaclargs_sz	(NFS3_fh_sz+1+ \
 				XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
 #define ACL3_getaclres_sz	(1+NFS3_post_op_attr_sz+1+ \
-				XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
+				XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE)+1)
 #define ACL3_setaclres_sz	(1+NFS3_post_op_attr_sz)
 
 static int nfs3_stat_to_errno(enum nfs_stat);
@@ -1629,7 +1629,7 @@ static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
 	result->op_status = status;
 	if (status != NFS3_OK)
 		goto out_status;
-	result->replen = 3 + ((xdr_stream_pos(xdr) - pos) >> 2);
+	result->replen = 4 + ((xdr_stream_pos(xdr) - pos) >> 2);
 	error = decode_read3resok(xdr, result);
 out:
 	return error;
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index d0fa18d..6d9d5e2 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -215,14 +215,14 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
 				 nfs4_fattr_bitmap_maxsz)
 #define encode_read_maxsz	(op_encode_hdr_maxsz + \
 				 encode_stateid_maxsz + 3)
-#define decode_read_maxsz	(op_decode_hdr_maxsz + 2)
+#define decode_read_maxsz	(op_decode_hdr_maxsz + 2 + 1)
 #define encode_readdir_maxsz	(op_encode_hdr_maxsz + \
 				 2 + encode_verifier_maxsz + 5 + \
 				nfs4_label_maxsz)
 #define decode_readdir_maxsz	(op_decode_hdr_maxsz + \
-				 decode_verifier_maxsz)
+				 decode_verifier_maxsz + 1)
 #define encode_readlink_maxsz	(op_encode_hdr_maxsz)
-#define decode_readlink_maxsz	(op_decode_hdr_maxsz + 1)
+#define decode_readlink_maxsz	(op_decode_hdr_maxsz + 1 + 1)
 #define encode_write_maxsz	(op_encode_hdr_maxsz + \
 				 encode_stateid_maxsz + 4)
 #define decode_write_maxsz	(op_decode_hdr_maxsz + \
@@ -284,14 +284,14 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
 #define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
 #define encode_getacl_maxsz	(encode_getattr_maxsz)
 #define decode_getacl_maxsz	(op_decode_hdr_maxsz + \
-				 nfs4_fattr_bitmap_maxsz + 1)
+				 nfs4_fattr_bitmap_maxsz + 1 + 1)
 #define encode_setacl_maxsz	(op_encode_hdr_maxsz + \
 				 encode_stateid_maxsz + 3)
 #define decode_setacl_maxsz	(decode_setattr_maxsz)
 #define encode_fs_locations_maxsz \
 				(encode_getattr_maxsz)
 #define decode_fs_locations_maxsz \
-				(0)
+				(1)
 #define encode_secinfo_maxsz	(op_encode_hdr_maxsz + nfs4_name_maxsz)
 #define decode_secinfo_maxsz	(op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4))
 
@@ -392,12 +392,13 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
 				1 /* opaque devaddr4 length */ + \
 				  /* devaddr4 payload is read into page */ \
 				1 /* notification bitmap length */ + \
-				1 /* notification bitmap, word 0 */)
+				1 /* notification bitmap, word 0 */ + \
+				1 /* possible XDR padding */)
 #define encode_layoutget_maxsz	(op_encode_hdr_maxsz + 10 + \
 				encode_stateid_maxsz)
 #define decode_layoutget_maxsz	(op_decode_hdr_maxsz + 8 + \
 				decode_stateid_maxsz + \
-				XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE))
+				XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE) + 1)
 #define encode_layoutcommit_maxsz (op_encode_hdr_maxsz +          \
 				2 /* offset */ + \
 				2 /* length */ + \
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index f780605..4ea38b0 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1177,7 +1177,11 @@ void rpc_prepare_reply_pages(struct rpc_rqst *req, struct page **pages,
 			     unsigned int base, unsigned int len,
 			     unsigned int hdrsize)
 {
-	hdrsize += RPC_REPHDRSIZE + req->rq_cred->cr_auth->au_rslack;
+	/* Subtract one to force an extra word of buffer space for the
+	 * payload's XDR pad to fall into the rcv_buf's tail iovec.
+	 */
+	hdrsize += RPC_REPHDRSIZE + req->rq_cred->cr_auth->au_rslack - 1;
+
 	xdr_inline_pages(&req->rq_rcv_buf, hdrsize << 2, pages, base, len);
 	trace_rpc_reply_pages(req);
 }
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index 7cca515..aa8177d 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -189,6 +189,8 @@ __be32 *xdr_encode_opaque(__be32 *p, const void *ptr, unsigned int nbytes)
 
 	tail->iov_base = buf + offset;
 	tail->iov_len = buflen - offset;
+	if ((xdr->page_len & 3) == 0)
+		tail->iov_len -= sizeof(__be32);
 
 	xdr->buflen += len;
 }


  parent reply index

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-11 16:23 [PATCH v1 00/23] NFS client patches for v5.1 (complete) Chuck Lever
2019-02-11 16:23 ` [PATCH v1 01/23] xprtrdma: Fix sparse warnings Chuck Lever
2019-02-11 16:23 ` [PATCH v1 02/23] xprtrdma: Check inline size before providing a Write chunk Chuck Lever
2019-02-11 16:23 ` [PATCH v1 03/23] xprtrdma: Reduce the doorbell rate (Receive) Chuck Lever
2019-02-11 16:24 ` [PATCH v1 04/23] SUNRPC: Display symbolic flag names in RPC trace events Chuck Lever
2019-02-11 16:24 ` [PATCH v1 05/23] SUNRPC: Add xdr_stream::rqst field Chuck Lever
2019-02-11 16:24 ` [PATCH v1 06/23] SUNRPC: Add XDR overflow trace event Chuck Lever
2019-02-11 16:24 ` [PATCH v1 07/23] SUNRPC: Add trace event that reports reply page vector alignment Chuck Lever
2019-02-11 16:24 ` [PATCH v1 08/23] NFS: Remove print_overflow_msg() Chuck Lever
2019-02-11 16:24 ` [PATCH v1 09/23] NFS: Add trace events to report non-zero NFS status codes Chuck Lever
2019-02-11 16:24 ` [PATCH v1 10/23] SUNRPC: Remove some dprintk() call sites from auth functions Chuck Lever
2019-02-11 16:24 ` [PATCH v1 11/23] SUNRPC: Remove rpc_xprt::tsh_size Chuck Lever
2019-02-11 16:24 ` [PATCH v1 12/23] SUNRPC: Add build option to disable support for insecure enctypes Chuck Lever
2019-02-11 16:24 ` [PATCH v1 13/23] SUNRPC: Use struct xdr_stream when constructing RPC Call header Chuck Lever
2019-02-11 16:24 ` [PATCH v1 14/23] SUNRPC: Clean up rpc_verify_header() Chuck Lever
2019-02-11 16:24 ` [PATCH v1 15/23] SUNRPC: Use struct xdr_stream when decoding RPC Reply header Chuck Lever
2019-02-11 16:25 ` [PATCH v1 16/23] SUNRPC: Introduce trace points in rpc_auth_gss.ko Chuck Lever
2019-02-11 16:25 ` [PATCH v1 17/23] SUNRPC: Remove xdr_buf_trim() Chuck Lever
2019-02-11 16:25 ` [PATCH v1 18/23] SUNRPC: Add SPDX IDs to some net/sunrpc/auth_gss/ files Chuck Lever
2019-02-11 16:25 ` [PATCH v1 19/23] SUNRPC: Introduce rpc_prepare_reply_pages() Chuck Lever
2019-02-11 16:25 ` Chuck Lever [this message]
2019-04-05 17:36   ` [PATCH v1 20/23] NFS: Account for XDR pad of buf->pages Olga Kornievskaia
2019-04-05 17:51     ` Chuck Lever
2019-04-05 19:17       ` Olga Kornievskaia
2019-04-05 19:23         ` Chuck Lever
2019-04-05 19:27           ` Olga Kornievskaia
2019-04-05 19:42             ` Chuck Lever
2019-04-08 14:36               ` Olga Kornievskaia
2019-04-08 14:43                 ` Chuck Lever
2019-04-08 15:21                   ` Olga Kornievskaia
2019-04-08 15:26                     ` Olga Kornievskaia
2019-04-08 15:50                       ` Olga Kornievskaia
2019-04-08 16:02                         ` Olga Kornievskaia
2019-04-08 16:29                         ` Chuck Lever
2019-02-11 16:25 ` [PATCH v1 21/23] SUNRPC: Make AUTH_SYS and AUTH_NULL set au_verfsize Chuck Lever
2019-02-11 16:25 ` [PATCH v1 22/23] SUNRPC: Add rpc_auth::au_ralign field Chuck Lever
2019-02-11 16:25 ` [PATCH v1 23/23] SUNRPC: Use au_rslack when computing reply buffer size Chuck Lever

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190211162525.2817.60645.stgit@manet.1015granger.net \
    --to=chuck.lever@oracle.com \
    --cc=anna.schumaker@netapp.com \
    --cc=linux-nfs@vger.kernel.org \
    --cc=linux-rdma@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Linux-NFS Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-nfs/0 linux-nfs/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-nfs linux-nfs/ https://lore.kernel.org/linux-nfs \
		linux-nfs@vger.kernel.org linux-nfs@archiver.kernel.org
	public-inbox-index linux-nfs


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-nfs


AGPL code for this site: git clone https://public-inbox.org/ public-inbox