@@ -201,11 +201,11 @@ static int decode_read_plus_data(struct xdr_stream *xdr, struct nfs_pgio_res *re
p = xdr_decode_hyper(p, &offset);
count = be32_to_cpup(p);
- recvd = xdr_read_pages(xdr, count);
+ recvd = xdr_align_data(xdr, res->count, count);
if (recvd < count)
res->eof = 0;
- res->count = recvd;
+ res->count += recvd;
return 0;
out_overflow:
print_overflow_msg(__func__, xdr);
@@ -225,11 +225,11 @@ static int decode_read_plus_hole(struct xdr_stream *xdr, struct nfs_pgio_res *re
p = xdr_decode_hyper(p, &offset);
p = xdr_decode_hyper(p, &length);
- recvd = xdr_expand_hole(xdr, 0, length);
+ recvd = xdr_expand_hole(xdr, res->count, length);
if (recvd < length)
res->eof = 0;
- res->count = recvd;
+ res->count += recvd;
return 0;
out_overflow:
print_overflow_msg(__func__, xdr);
@@ -240,7 +240,7 @@ static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
{
__be32 *p;
int status, type;
- uint32_t segments;
+ uint32_t i, segments;
status = decode_op_hdr(xdr, OP_READ_PLUS);
if (status)
@@ -253,20 +253,24 @@ static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
res->count = 0;
res->eof = be32_to_cpup(p++);
segments = be32_to_cpup(p++);
- if (segments == 0)
- return 0;
- p = xdr_inline_decode(xdr, 4);
- if (unlikely(!p))
- goto out_overflow;
-
- type = be32_to_cpup(p++);
- if (type == NFS4_CONTENT_DATA)
- status = decode_read_plus_data(xdr, res);
- else
- status = decode_read_plus_hole(xdr, res);
-
- if (segments > 1)
+ for (i = 0; i < segments; i++) {
+ p = xdr_inline_decode(xdr, 4);
+ if (unlikely(!p))
+ goto out_overflow;
+
+ type = be32_to_cpup(p);
+ if (type == NFS4_CONTENT_DATA)
+ status = decode_read_plus_data(xdr, res);
+ else
+ status = decode_read_plus_hole(xdr, res);
+ if (status)
+ break;
+ if (res->count == xdr->buf->page_len)
+ break;
+ }
+
+ if (i < segments)
res->eof = 0;
return status;
out_overflow:
We now have everything we need to read holes and then shift data to where it's supposed to be. Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com> --- fs/nfs/nfs42xdr.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-)