[v2,1/4] NFSD: Return eof and maxcount to nfsd4_encode_read()
diff mbox series

Message ID 20200214211206.407725-2-Anna.Schumaker@Netapp.com
State New
Headers show
Series
  • NFSD: Add support for the v4.2 READ_PLUS operation
Related show

Commit Message

Anna Schumaker Feb. 14, 2020, 9:12 p.m. UTC
From: Anna Schumaker <Anna.Schumaker@Netapp.com>

I want to reuse nfsd4_encode_readv() and nfsd4_encode_splice_read() in
READ_PLUS rather than reimplementing them. READ_PLUS returns a single
eof flag for the entire call and a separate maxcount for each data
segment, so we need to have the READ call encode these values in a
different place.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
---
 fs/nfsd/nfs4xdr.c | 60 ++++++++++++++++++++---------------------------
 1 file changed, 26 insertions(+), 34 deletions(-)

Comments

Chuck Lever Feb. 14, 2020, 10:20 p.m. UTC | #1
> On Feb 14, 2020, at 4:12 PM, schumaker.anna@gmail.com wrote:
> 
> From: Anna Schumaker <Anna.Schumaker@Netapp.com>
> 
> I want to reuse nfsd4_encode_readv() and nfsd4_encode_splice_read() in
> READ_PLUS rather than reimplementing them. READ_PLUS returns a single
> eof flag for the entire call and a separate maxcount for each data
> segment, so we need to have the READ call encode these values in a
> different place.

This probably collides pretty nastily with the fix I posted today for
https://bugzilla.kernel.org/show_bug.cgi?id=198053 .

Can my fix go in first so that there is still opportunity to backport it?


> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
> ---
> fs/nfsd/nfs4xdr.c | 60 ++++++++++++++++++++---------------------------
> 1 file changed, 26 insertions(+), 34 deletions(-)
> 
> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> index 9761512674a0..45f0623f6488 100644
> --- a/fs/nfsd/nfs4xdr.c
> +++ b/fs/nfsd/nfs4xdr.c
> @@ -3521,23 +3521,22 @@ nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struc
> 
> static __be32 nfsd4_encode_splice_read(
> 				struct nfsd4_compoundres *resp,
> -				struct nfsd4_read *read,
> -				struct file *file, unsigned long maxcount)
> +				struct nfsd4_read *read, struct file *file,
> +				unsigned long *maxcount, u32 *eof)
> {
> 	struct xdr_stream *xdr = &resp->xdr;
> 	struct xdr_buf *buf = xdr->buf;
> -	u32 eof;
> +	long len;
> 	int space_left;
> 	__be32 nfserr;
> -	__be32 *p = xdr->p - 2;
> 
> 	/* Make sure there will be room for padding if needed */
> 	if (xdr->end - xdr->p < 1)
> 		return nfserr_resource;
> 
> +	len = *maxcount;
> 	nfserr = nfsd_splice_read(read->rd_rqstp, read->rd_fhp,
> -				  file, read->rd_offset, &maxcount, &eof);
> -	read->rd_length = maxcount;
> +				  file, read->rd_offset, maxcount, eof);
> 	if (nfserr) {
> 		/*
> 		 * nfsd_splice_actor may have already messed with the
> @@ -3548,24 +3547,21 @@ static __be32 nfsd4_encode_splice_read(
> 		return nfserr;
> 	}
> 
> -	*(p++) = htonl(eof);
> -	*(p++) = htonl(maxcount);
> -
> -	buf->page_len = maxcount;
> -	buf->len += maxcount;
> -	xdr->page_ptr += (buf->page_base + maxcount + PAGE_SIZE - 1)
> +	buf->page_len = *maxcount;
> +	buf->len += *maxcount;
> +	xdr->page_ptr += (buf->page_base + *maxcount + PAGE_SIZE - 1)
> 							/ PAGE_SIZE;
> 
> 	/* Use rest of head for padding and remaining ops: */
> 	buf->tail[0].iov_base = xdr->p;
> 	buf->tail[0].iov_len = 0;
> 	xdr->iov = buf->tail;
> -	if (maxcount&3) {
> -		int pad = 4 - (maxcount&3);
> +	if (*maxcount&3) {
> +		int pad = 4 - (*maxcount&3);
> 
> 		*(xdr->p++) = 0;
> 
> -		buf->tail[0].iov_base += maxcount&3;
> +		buf->tail[0].iov_base += *maxcount&3;
> 		buf->tail[0].iov_len = pad;
> 		buf->len += pad;
> 	}
> @@ -3579,22 +3575,20 @@ static __be32 nfsd4_encode_splice_read(
> }
> 
> static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
> -				 struct nfsd4_read *read,
> -				 struct file *file, unsigned long maxcount)
> +				 struct nfsd4_read *read, struct file *file,
> +				 unsigned long *maxcount, u32 *eof)
> {
> 	struct xdr_stream *xdr = &resp->xdr;
> -	u32 eof;
> 	int v;
> 	int starting_len = xdr->buf->len - 8;
> 	long len;
> 	int thislen;
> 	__be32 nfserr;
> -	__be32 tmp;
> 	__be32 *p;
> 	u32 zzz = 0;
> 	int pad;
> 
> -	len = maxcount;
> +	len = *maxcount;
> 	v = 0;
> 
> 	thislen = min_t(long, len, ((void *)xdr->end - (void *)xdr->p));
> @@ -3616,22 +3610,15 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
> 	}
> 	read->rd_vlen = v;
> 
> -	len = maxcount;
> +	len = *maxcount;
> 	nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset,
> -			    resp->rqstp->rq_vec, read->rd_vlen, &maxcount,
> -			    &eof);
> -	read->rd_length = maxcount;
> +			    resp->rqstp->rq_vec, read->rd_vlen, maxcount, eof);
> 	if (nfserr)
> 		return nfserr;
> -	xdr_truncate_encode(xdr, starting_len + 8 + ((maxcount+3)&~3));
> +	xdr_truncate_encode(xdr, starting_len + 8 + ((*maxcount+3)&~3));
> 
> -	tmp = htonl(eof);
> -	write_bytes_to_xdr_buf(xdr->buf, starting_len    , &tmp, 4);
> -	tmp = htonl(maxcount);
> -	write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4);
> -
> -	pad = (maxcount&3) ? 4 - (maxcount&3) : 0;
> -	write_bytes_to_xdr_buf(xdr->buf, starting_len + 8 + maxcount,
> +	pad = (*maxcount&3) ? 4 - (*maxcount&3) : 0;
> +	write_bytes_to_xdr_buf(xdr->buf, starting_len + 8 + *maxcount,
> 								&zzz, pad);
> 	return 0;
> 
> @@ -3642,6 +3629,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
> 		  struct nfsd4_read *read)
> {
> 	unsigned long maxcount;
> +	u32 eof;
> 	struct xdr_stream *xdr = &resp->xdr;
> 	struct file *file;
> 	int starting_len = xdr->buf->len;
> @@ -3670,13 +3658,17 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
> 
> 	if (file->f_op->splice_read &&
> 	    test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags))
> -		nfserr = nfsd4_encode_splice_read(resp, read, file, maxcount);
> +		nfserr = nfsd4_encode_splice_read(resp, read, file, &maxcount, &eof);
> 	else
> -		nfserr = nfsd4_encode_readv(resp, read, file, maxcount);
> +		nfserr = nfsd4_encode_readv(resp, read, file, &maxcount, &eof);
> 
> 	if (nfserr)
> 		xdr_truncate_encode(xdr, starting_len);
> 
> +	read->rd_length = maxcount;
> +	*p++ = htonl(eof);
> +	*p++ = htonl(maxcount);
> +
> 	return nfserr;
> }
> 
> -- 
> 2.25.0
> 

--
Chuck Lever
J. Bruce Fields Feb. 17, 2020, 7:52 p.m. UTC | #2
On Fri, Feb 14, 2020 at 05:20:37PM -0500, Chuck Lever wrote:
> 
> 
> > On Feb 14, 2020, at 4:12 PM, schumaker.anna@gmail.com wrote:
> > 
> > From: Anna Schumaker <Anna.Schumaker@Netapp.com>
> > 
> > I want to reuse nfsd4_encode_readv() and nfsd4_encode_splice_read() in
> > READ_PLUS rather than reimplementing them. READ_PLUS returns a single
> > eof flag for the entire call and a separate maxcount for each data
> > segment, so we need to have the READ call encode these values in a
> > different place.
> 
> This probably collides pretty nastily with the fix I posted today for
> https://bugzilla.kernel.org/show_bug.cgi?id=198053 .
> 
> Can my fix go in first so that there is still opportunity to backport it?

Sure, makes sense.--b.

> 
> 
> > Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
> > ---
> > fs/nfsd/nfs4xdr.c | 60 ++++++++++++++++++++---------------------------
> > 1 file changed, 26 insertions(+), 34 deletions(-)
> > 
> > diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> > index 9761512674a0..45f0623f6488 100644
> > --- a/fs/nfsd/nfs4xdr.c
> > +++ b/fs/nfsd/nfs4xdr.c
> > @@ -3521,23 +3521,22 @@ nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struc
> > 
> > static __be32 nfsd4_encode_splice_read(
> > 				struct nfsd4_compoundres *resp,
> > -				struct nfsd4_read *read,
> > -				struct file *file, unsigned long maxcount)
> > +				struct nfsd4_read *read, struct file *file,
> > +				unsigned long *maxcount, u32 *eof)
> > {
> > 	struct xdr_stream *xdr = &resp->xdr;
> > 	struct xdr_buf *buf = xdr->buf;
> > -	u32 eof;
> > +	long len;
> > 	int space_left;
> > 	__be32 nfserr;
> > -	__be32 *p = xdr->p - 2;
> > 
> > 	/* Make sure there will be room for padding if needed */
> > 	if (xdr->end - xdr->p < 1)
> > 		return nfserr_resource;
> > 
> > +	len = *maxcount;
> > 	nfserr = nfsd_splice_read(read->rd_rqstp, read->rd_fhp,
> > -				  file, read->rd_offset, &maxcount, &eof);
> > -	read->rd_length = maxcount;
> > +				  file, read->rd_offset, maxcount, eof);
> > 	if (nfserr) {
> > 		/*
> > 		 * nfsd_splice_actor may have already messed with the
> > @@ -3548,24 +3547,21 @@ static __be32 nfsd4_encode_splice_read(
> > 		return nfserr;
> > 	}
> > 
> > -	*(p++) = htonl(eof);
> > -	*(p++) = htonl(maxcount);
> > -
> > -	buf->page_len = maxcount;
> > -	buf->len += maxcount;
> > -	xdr->page_ptr += (buf->page_base + maxcount + PAGE_SIZE - 1)
> > +	buf->page_len = *maxcount;
> > +	buf->len += *maxcount;
> > +	xdr->page_ptr += (buf->page_base + *maxcount + PAGE_SIZE - 1)
> > 							/ PAGE_SIZE;
> > 
> > 	/* Use rest of head for padding and remaining ops: */
> > 	buf->tail[0].iov_base = xdr->p;
> > 	buf->tail[0].iov_len = 0;
> > 	xdr->iov = buf->tail;
> > -	if (maxcount&3) {
> > -		int pad = 4 - (maxcount&3);
> > +	if (*maxcount&3) {
> > +		int pad = 4 - (*maxcount&3);
> > 
> > 		*(xdr->p++) = 0;
> > 
> > -		buf->tail[0].iov_base += maxcount&3;
> > +		buf->tail[0].iov_base += *maxcount&3;
> > 		buf->tail[0].iov_len = pad;
> > 		buf->len += pad;
> > 	}
> > @@ -3579,22 +3575,20 @@ static __be32 nfsd4_encode_splice_read(
> > }
> > 
> > static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
> > -				 struct nfsd4_read *read,
> > -				 struct file *file, unsigned long maxcount)
> > +				 struct nfsd4_read *read, struct file *file,
> > +				 unsigned long *maxcount, u32 *eof)
> > {
> > 	struct xdr_stream *xdr = &resp->xdr;
> > -	u32 eof;
> > 	int v;
> > 	int starting_len = xdr->buf->len - 8;
> > 	long len;
> > 	int thislen;
> > 	__be32 nfserr;
> > -	__be32 tmp;
> > 	__be32 *p;
> > 	u32 zzz = 0;
> > 	int pad;
> > 
> > -	len = maxcount;
> > +	len = *maxcount;
> > 	v = 0;
> > 
> > 	thislen = min_t(long, len, ((void *)xdr->end - (void *)xdr->p));
> > @@ -3616,22 +3610,15 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
> > 	}
> > 	read->rd_vlen = v;
> > 
> > -	len = maxcount;
> > +	len = *maxcount;
> > 	nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset,
> > -			    resp->rqstp->rq_vec, read->rd_vlen, &maxcount,
> > -			    &eof);
> > -	read->rd_length = maxcount;
> > +			    resp->rqstp->rq_vec, read->rd_vlen, maxcount, eof);
> > 	if (nfserr)
> > 		return nfserr;
> > -	xdr_truncate_encode(xdr, starting_len + 8 + ((maxcount+3)&~3));
> > +	xdr_truncate_encode(xdr, starting_len + 8 + ((*maxcount+3)&~3));
> > 
> > -	tmp = htonl(eof);
> > -	write_bytes_to_xdr_buf(xdr->buf, starting_len    , &tmp, 4);
> > -	tmp = htonl(maxcount);
> > -	write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4);
> > -
> > -	pad = (maxcount&3) ? 4 - (maxcount&3) : 0;
> > -	write_bytes_to_xdr_buf(xdr->buf, starting_len + 8 + maxcount,
> > +	pad = (*maxcount&3) ? 4 - (*maxcount&3) : 0;
> > +	write_bytes_to_xdr_buf(xdr->buf, starting_len + 8 + *maxcount,
> > 								&zzz, pad);
> > 	return 0;
> > 
> > @@ -3642,6 +3629,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
> > 		  struct nfsd4_read *read)
> > {
> > 	unsigned long maxcount;
> > +	u32 eof;
> > 	struct xdr_stream *xdr = &resp->xdr;
> > 	struct file *file;
> > 	int starting_len = xdr->buf->len;
> > @@ -3670,13 +3658,17 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
> > 
> > 	if (file->f_op->splice_read &&
> > 	    test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags))
> > -		nfserr = nfsd4_encode_splice_read(resp, read, file, maxcount);
> > +		nfserr = nfsd4_encode_splice_read(resp, read, file, &maxcount, &eof);
> > 	else
> > -		nfserr = nfsd4_encode_readv(resp, read, file, maxcount);
> > +		nfserr = nfsd4_encode_readv(resp, read, file, &maxcount, &eof);
> > 
> > 	if (nfserr)
> > 		xdr_truncate_encode(xdr, starting_len);
> > 
> > +	read->rd_length = maxcount;
> > +	*p++ = htonl(eof);
> > +	*p++ = htonl(maxcount);
> > +
> > 	return nfserr;
> > }
> > 
> > -- 
> > 2.25.0
> > 
> 
> --
> Chuck Lever
> 
> 
>

Patch
diff mbox series

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 9761512674a0..45f0623f6488 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -3521,23 +3521,22 @@  nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struc
 
 static __be32 nfsd4_encode_splice_read(
 				struct nfsd4_compoundres *resp,
-				struct nfsd4_read *read,
-				struct file *file, unsigned long maxcount)
+				struct nfsd4_read *read, struct file *file,
+				unsigned long *maxcount, u32 *eof)
 {
 	struct xdr_stream *xdr = &resp->xdr;
 	struct xdr_buf *buf = xdr->buf;
-	u32 eof;
+	long len;
 	int space_left;
 	__be32 nfserr;
-	__be32 *p = xdr->p - 2;
 
 	/* Make sure there will be room for padding if needed */
 	if (xdr->end - xdr->p < 1)
 		return nfserr_resource;
 
+	len = *maxcount;
 	nfserr = nfsd_splice_read(read->rd_rqstp, read->rd_fhp,
-				  file, read->rd_offset, &maxcount, &eof);
-	read->rd_length = maxcount;
+				  file, read->rd_offset, maxcount, eof);
 	if (nfserr) {
 		/*
 		 * nfsd_splice_actor may have already messed with the
@@ -3548,24 +3547,21 @@  static __be32 nfsd4_encode_splice_read(
 		return nfserr;
 	}
 
-	*(p++) = htonl(eof);
-	*(p++) = htonl(maxcount);
-
-	buf->page_len = maxcount;
-	buf->len += maxcount;
-	xdr->page_ptr += (buf->page_base + maxcount + PAGE_SIZE - 1)
+	buf->page_len = *maxcount;
+	buf->len += *maxcount;
+	xdr->page_ptr += (buf->page_base + *maxcount + PAGE_SIZE - 1)
 							/ PAGE_SIZE;
 
 	/* Use rest of head for padding and remaining ops: */
 	buf->tail[0].iov_base = xdr->p;
 	buf->tail[0].iov_len = 0;
 	xdr->iov = buf->tail;
-	if (maxcount&3) {
-		int pad = 4 - (maxcount&3);
+	if (*maxcount&3) {
+		int pad = 4 - (*maxcount&3);
 
 		*(xdr->p++) = 0;
 
-		buf->tail[0].iov_base += maxcount&3;
+		buf->tail[0].iov_base += *maxcount&3;
 		buf->tail[0].iov_len = pad;
 		buf->len += pad;
 	}
@@ -3579,22 +3575,20 @@  static __be32 nfsd4_encode_splice_read(
 }
 
 static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
-				 struct nfsd4_read *read,
-				 struct file *file, unsigned long maxcount)
+				 struct nfsd4_read *read, struct file *file,
+				 unsigned long *maxcount, u32 *eof)
 {
 	struct xdr_stream *xdr = &resp->xdr;
-	u32 eof;
 	int v;
 	int starting_len = xdr->buf->len - 8;
 	long len;
 	int thislen;
 	__be32 nfserr;
-	__be32 tmp;
 	__be32 *p;
 	u32 zzz = 0;
 	int pad;
 
-	len = maxcount;
+	len = *maxcount;
 	v = 0;
 
 	thislen = min_t(long, len, ((void *)xdr->end - (void *)xdr->p));
@@ -3616,22 +3610,15 @@  static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
 	}
 	read->rd_vlen = v;
 
-	len = maxcount;
+	len = *maxcount;
 	nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset,
-			    resp->rqstp->rq_vec, read->rd_vlen, &maxcount,
-			    &eof);
-	read->rd_length = maxcount;
+			    resp->rqstp->rq_vec, read->rd_vlen, maxcount, eof);
 	if (nfserr)
 		return nfserr;
-	xdr_truncate_encode(xdr, starting_len + 8 + ((maxcount+3)&~3));
+	xdr_truncate_encode(xdr, starting_len + 8 + ((*maxcount+3)&~3));
 
-	tmp = htonl(eof);
-	write_bytes_to_xdr_buf(xdr->buf, starting_len    , &tmp, 4);
-	tmp = htonl(maxcount);
-	write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4);
-
-	pad = (maxcount&3) ? 4 - (maxcount&3) : 0;
-	write_bytes_to_xdr_buf(xdr->buf, starting_len + 8 + maxcount,
+	pad = (*maxcount&3) ? 4 - (*maxcount&3) : 0;
+	write_bytes_to_xdr_buf(xdr->buf, starting_len + 8 + *maxcount,
 								&zzz, pad);
 	return 0;
 
@@ -3642,6 +3629,7 @@  nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
 		  struct nfsd4_read *read)
 {
 	unsigned long maxcount;
+	u32 eof;
 	struct xdr_stream *xdr = &resp->xdr;
 	struct file *file;
 	int starting_len = xdr->buf->len;
@@ -3670,13 +3658,17 @@  nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
 
 	if (file->f_op->splice_read &&
 	    test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags))
-		nfserr = nfsd4_encode_splice_read(resp, read, file, maxcount);
+		nfserr = nfsd4_encode_splice_read(resp, read, file, &maxcount, &eof);
 	else
-		nfserr = nfsd4_encode_readv(resp, read, file, maxcount);
+		nfserr = nfsd4_encode_readv(resp, read, file, &maxcount, &eof);
 
 	if (nfserr)
 		xdr_truncate_encode(xdr, starting_len);
 
+	read->rd_length = maxcount;
+	*p++ = htonl(eof);
+	*p++ = htonl(maxcount);
+
 	return nfserr;
 }