NFS: Decode a full READ_PLUS reply

Decode multiple hole and data segments sent by the server, placing
everything directly where they need to go in the xdr pages.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
Anna Schumaker 2020-04-01 16:28:51 -04:00
parent e6ac0accb2
commit bff049a3b5
1 changed files with 19 additions and 17 deletions

View File

@ -1032,7 +1032,7 @@ 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);
res->count += recvd;
if (count > recvd) {
@ -1057,7 +1057,7 @@ 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);
res->count += recvd;
if (recvd < length) {
@ -1070,7 +1070,7 @@ static int decode_read_plus_hole(struct xdr_stream *xdr, struct nfs_pgio_res *re
static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
{
uint32_t eof, segments, type;
int status;
int status, i;
__be32 *p;
status = decode_op_hdr(xdr, OP_READ_PLUS);
@ -1086,22 +1086,24 @@ static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
if (segments == 0)
goto out;
p = xdr_inline_decode(xdr, 4);
if (unlikely(!p))
return -EIO;
for (i = 0; i < segments; i++) {
p = xdr_inline_decode(xdr, 4);
if (unlikely(!p))
return -EIO;
type = be32_to_cpup(p++);
if (type == NFS4_CONTENT_DATA)
status = decode_read_plus_data(xdr, res, &eof);
else if (type == NFS4_CONTENT_HOLE)
status = decode_read_plus_hole(xdr, res, &eof);
else
return -EINVAL;
type = be32_to_cpup(p++);
if (type == NFS4_CONTENT_DATA)
status = decode_read_plus_data(xdr, res, &eof);
else if (type == NFS4_CONTENT_HOLE)
status = decode_read_plus_hole(xdr, res, &eof);
else
return -EINVAL;
if (status)
return status;
if (segments > 1)
eof = 0;
if (status < 0)
return status;
if (status > 0)
break;
}
out:
res->eof = eof;