NFSv4.1/flexfiles: Fix a protocol error in layoutreturn
authorTrond Myklebust <trond.myklebust@primarydata.com>
Fri, 28 Aug 2015 00:37:39 +0000 (20:37 -0400)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Fri, 28 Aug 2015 00:42:20 +0000 (20:42 -0400)
According to the flexfiles protocol, the layoutreturn should specify an
array of errors in the following format:

struct ff_ioerr4 {
offset4        ffie_offset;
length4        ffie_length;
stateid4       ffie_stateid;
device_error4  ffie_errors<>;
};

This patch fixes up the code to ensure that our ffie_errors is indeed
encoded as an array (albeit with only a single entry).

Reported-by: Tom Haynes <thomas.haynes@primarydata.com>
Cc: stable@vger.kernel.org
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/flexfilelayout/flexfilelayoutdev.c

index f13e1969eedd911bf6a5d9be6af6e4ae403f6c1e..b28fa4cbea5261622c4dbeb9b3765d12a2abdf9a 100644 (file)
@@ -500,16 +500,19 @@ int ff_layout_encode_ds_ioerr(struct nfs4_flexfile_layout *flo,
                                           range->offset, range->length))
                        continue;
                /* offset(8) + length(8) + stateid(NFS4_STATEID_SIZE)
-                * + deviceid(NFS4_DEVICEID4_SIZE) + status(4) + opnum(4)
+                * + array length + deviceid(NFS4_DEVICEID4_SIZE)
+                * + status(4) + opnum(4)
                 */
                p = xdr_reserve_space(xdr,
-                               24 + NFS4_STATEID_SIZE + NFS4_DEVICEID4_SIZE);
+                               28 + NFS4_STATEID_SIZE + NFS4_DEVICEID4_SIZE);
                if (unlikely(!p))
                        return -ENOBUFS;
                p = xdr_encode_hyper(p, err->offset);
                p = xdr_encode_hyper(p, err->length);
                p = xdr_encode_opaque_fixed(p, &err->stateid,
                                            NFS4_STATEID_SIZE);
+               /* Encode 1 error */
+               *p++ = cpu_to_be32(1);
                p = xdr_encode_opaque_fixed(p, &err->deviceid,
                                            NFS4_DEVICEID4_SIZE);
                *p++ = cpu_to_be32(err->status);