NFS: Add READ_PLUS hole segment decoding
authorAnna Schumaker <Anna.Schumaker@Netapp.com>
Thu, 28 Mar 2019 20:43:44 +0000 (16:43 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Wed, 7 Oct 2020 18:28:40 +0000 (14:28 -0400)
We keep things simple for now by only decoding a single hole or data
segment returned by the server, even if they returned more to us.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/nfs42xdr.c

index 930b4ca..9720fed 100644 (file)
@@ -53,7 +53,7 @@
 #define decode_read_plus_maxsz         (op_decode_hdr_maxsz + \
                                         1 /* rpr_eof */ + \
                                         1 /* rpr_contents count */ + \
-                                        NFS42_READ_PLUS_SEGMENT_SIZE)
+                                        2 * NFS42_READ_PLUS_SEGMENT_SIZE)
 #define encode_seek_maxsz              (op_encode_hdr_maxsz + \
                                         encode_stateid_maxsz + \
                                         2 /* offset */ + \
@@ -1045,6 +1045,28 @@ static int decode_read_plus_data(struct xdr_stream *xdr, struct nfs_pgio_res *re
        return 0;
 }
 
+static int decode_read_plus_hole(struct xdr_stream *xdr, struct nfs_pgio_res *res,
+                                uint32_t *eof)
+{
+       uint64_t offset, length, recvd;
+       __be32 *p;
+
+       p = xdr_inline_decode(xdr, 8 + 8);
+       if (unlikely(!p))
+               return -EIO;
+
+       p = xdr_decode_hyper(p, &offset);
+       p = xdr_decode_hyper(p, &length);
+       recvd = xdr_expand_hole(xdr, 0, length);
+       res->count += recvd;
+
+       if (recvd < length) {
+               *eof = 0;
+               return 1;
+       }
+       return 0;
+}
+
 static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
 {
        uint32_t eof, segments, type;
@@ -1071,6 +1093,8 @@ static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
        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;