linux-nfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1] NFSD: Fix zero NFSv4 READ results when RQ_SPLICE_OK is not set
@ 2023-09-27 17:16 Chuck Lever
  2023-09-28  6:47 ` Mantas Mikulėnas
  0 siblings, 1 reply; 2+ messages in thread
From: Chuck Lever @ 2023-09-27 17:16 UTC (permalink / raw)
  To: linux-nfs; +Cc: Mantas Mikulėnas, Chuck Lever, grawity

From: Chuck Lever <chuck.lever@oracle.com>

nfsd4_encode_readv() uses xdr->buf->page_len as a starting point for
the nfsd_iter_read() sink buffer -- page_len is going to be offset
by the parts of the COMPOUND that have already been encoded into
xdr->buf->pages.

However, that value must be captured /before/
xdr_reserve_space_vec() advances page_len by the expected size of
the read payload. Otherwise, the whole front part of the first
page of the payload in the reply will be uninitialized.

Mantas hit this because sec=krb5i forces RQ_SPLICE_OK off, which
invokes the readv part of the nfsd4_encode_read() path. Also,
older Linux NFS clients appear to send shorter READ requests
for files smaller than a page, whereas newer clients just send
page-sized requests and let the server send as many bytes as
are in the file.

Reported-by: Mantas Mikulėnas <grawity@gmail.com>
Closes: https://lore.kernel.org/linux-nfs/f1d0b234-e650-0f6e-0f5d-126b3d51d1eb@gmail.com/
Fixes: 703d75215555 ("NFSD: Hoist rq_vec preparation into nfsd_read() [step two]")
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs4xdr.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 2e40c74d2f72..92c7dde148a4 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -4113,6 +4113,7 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
 				 struct file *file, unsigned long maxcount)
 {
 	struct xdr_stream *xdr = resp->xdr;
+	unsigned int base = xdr->buf->page_len & ~PAGE_MASK;
 	unsigned int starting_len = xdr->buf->len;
 	__be32 zero = xdr_zero;
 	__be32 nfserr;
@@ -4121,8 +4122,7 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
 		return nfserr_resource;
 
 	nfserr = nfsd_iter_read(resp->rqstp, read->rd_fhp, file,
-				read->rd_offset, &maxcount,
-				xdr->buf->page_len & ~PAGE_MASK,
+				read->rd_offset, &maxcount, base,
 				&read->rd_eof);
 	read->rd_length = maxcount;
 	if (nfserr)



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

* Re: [PATCH v1] NFSD: Fix zero NFSv4 READ results when RQ_SPLICE_OK is not set
  2023-09-27 17:16 [PATCH v1] NFSD: Fix zero NFSv4 READ results when RQ_SPLICE_OK is not set Chuck Lever
@ 2023-09-28  6:47 ` Mantas Mikulėnas
  0 siblings, 0 replies; 2+ messages in thread
From: Mantas Mikulėnas @ 2023-09-28  6:47 UTC (permalink / raw)
  To: Chuck Lever, linux-nfs; +Cc: Chuck Lever

On 27/09/2023 20.16, Chuck Lever wrote:
> From: Chuck Lever <chuck.lever@oracle.com>
>
> nfsd4_encode_readv() uses xdr->buf->page_len as a starting point for
> the nfsd_iter_read() sink buffer -- page_len is going to be offset
> by the parts of the COMPOUND that have already been encoded into
> xdr->buf->pages.
>
> However, that value must be captured /before/
> xdr_reserve_space_vec() advances page_len by the expected size of
> the read payload. Otherwise, the whole front part of the first
> page of the payload in the reply will be uninitialized.
>
> Mantas hit this because sec=krb5i forces RQ_SPLICE_OK off, which
> invokes the readv part of the nfsd4_encode_read() path. Also,
> older Linux NFS clients appear to send shorter READ requests
> for files smaller than a page, whereas newer clients just send
> page-sized requests and let the server send as many bytes as
> are in the file.
>
> Reported-by: Mantas Mikulėnas <grawity@gmail.com>
> Closes: https://lore.kernel.org/linux-nfs/f1d0b234-e650-0f6e-0f5d-126b3d51d1eb@gmail.com/
> Fixes: 703d75215555 ("NFSD: Hoist rq_vec preparation into nfsd_read() [step two]")
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> ---
>   fs/nfsd/nfs4xdr.c |    4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> index 2e40c74d2f72..92c7dde148a4 100644
> --- a/fs/nfsd/nfs4xdr.c
> +++ b/fs/nfsd/nfs4xdr.c
> @@ -4113,6 +4113,7 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
>   				 struct file *file, unsigned long maxcount)
>   {
>   	struct xdr_stream *xdr = resp->xdr;
> +	unsigned int base = xdr->buf->page_len & ~PAGE_MASK;
>   	unsigned int starting_len = xdr->buf->len;
>   	__be32 zero = xdr_zero;
>   	__be32 nfserr;
> @@ -4121,8 +4122,7 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
>   		return nfserr_resource;
>   
>   	nfserr = nfsd_iter_read(resp->rqstp, read->rd_fhp, file,
> -				read->rd_offset, &maxcount,
> -				xdr->buf->page_len & ~PAGE_MASK,
> +				read->rd_offset, &maxcount, base,
>   				&read->rd_eof);
>   	read->rd_length = maxcount;
>   	if (nfserr)
>
Thanks, this seems to work for me.


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

end of thread, other threads:[~2023-09-28  6:47 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-27 17:16 [PATCH v1] NFSD: Fix zero NFSv4 READ results when RQ_SPLICE_OK is not set Chuck Lever
2023-09-28  6:47 ` Mantas Mikulėnas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).