NFSv4.2: Fix READ_PLUS size calculations
authorAnna Schumaker <Anna.Schumaker@Netapp.com>
Wed, 31 May 2023 21:02:54 +0000 (17:02 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Wed, 23 Aug 2023 19:58:47 +0000 (15:58 -0400)
I bump the decode_read_plus_maxsz to account for hole segments, but I
need to subtract out this increase when calling
rpc_prepare_reply_pages() so the common case of single data segment
replies can be directly placed into the xdr pages without needing to be
shifted around.

Reported-by: Chuck Lever <chuck.lever@oracle.com>
Fixes: d3b00a802c845 ("NFS: Replace the READ_PLUS decoding code")
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/nfs42xdr.c

index d0919c5bf61c7a6877fd1f5dfa7a4127552cf890..78193f04d8928c428590db4fd96a627d2901008f 100644 (file)
                                        (1 /* data_content4 */ + \
                                         2 /* data_info4.di_offset */ + \
                                         1 /* data_info4.di_length */)
+#define NFS42_READ_PLUS_HOLE_SEGMENT_SIZE \
+                                       (1 /* data_content4 */ + \
+                                        2 /* data_info4.di_offset */ + \
+                                        2 /* data_info4.di_length */)
+#define READ_PLUS_SEGMENT_SIZE_DIFF    (NFS42_READ_PLUS_HOLE_SEGMENT_SIZE - \
+                                        NFS42_READ_PLUS_DATA_SEGMENT_SIZE)
 #define decode_read_plus_maxsz         (op_decode_hdr_maxsz + \
                                         1 /* rpr_eof */ + \
                                         1 /* rpr_contents count */ + \
-                                        NFS42_READ_PLUS_DATA_SEGMENT_SIZE)
+                                        NFS42_READ_PLUS_HOLE_SEGMENT_SIZE)
 #define encode_seek_maxsz              (op_encode_hdr_maxsz + \
                                         encode_stateid_maxsz + \
                                         2 /* offset */ + \
@@ -617,8 +623,8 @@ static void nfs4_xdr_enc_read_plus(struct rpc_rqst *req,
        encode_putfh(xdr, args->fh, &hdr);
        encode_read_plus(xdr, args, &hdr);
 
-       rpc_prepare_reply_pages(req, args->pages, args->pgbase,
-                               args->count, hdr.replen);
+       rpc_prepare_reply_pages(req, args->pages, args->pgbase, args->count,
+                               hdr.replen - READ_PLUS_SEGMENT_SIZE_DIFF);
        encode_nops(&hdr);
 }