]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
NFSD: Rework encoding and decoding of nfsd4_deviceid
authorSergey Bashirov <sergeybashirov@gmail.com>
Mon, 20 Oct 2025 12:56:00 +0000 (08:56 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 29 Oct 2025 13:03:13 +0000 (14:03 +0100)
[ Upstream commit 832738e4b325b742940761e10487403f9aad13e8 ]

Compilers may optimize the layout of C structures, so we should not rely
on sizeof struct and memcpy to encode and decode XDR structures. The byte
order of the fields should also be taken into account.

This patch adds the correct functions to handle the deviceid4 structure
and removes the pad field, which is currently not used by NFSD, from the
runtime state. The server's byte order is preserved because the deviceid4
blob on the wire is only used as a cookie by the client.

Signed-off-by: Sergey Bashirov <sergeybashirov@gmail.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Stable-dep-of: d68886bae76a ("NFSD: Fix last write offset handling in layoutcommit")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/nfsd/blocklayoutxdr.c
fs/nfsd/flexfilelayoutxdr.c
fs/nfsd/nfs4layouts.c
fs/nfsd/nfs4xdr.c
fs/nfsd/xdr4.h

index 1ed2f691ebb908670387c05da0968249a89041af..dd35c472eb37deb6d0ec2440de7a0dbd7a00d2fa 100644 (file)
@@ -29,8 +29,7 @@ nfsd4_block_encode_layoutget(struct xdr_stream *xdr,
        *p++ = cpu_to_be32(len);
        *p++ = cpu_to_be32(1);          /* we always return a single extent */
 
-       p = xdr_encode_opaque_fixed(p, &b->vol_id,
-                       sizeof(struct nfsd4_deviceid));
+       p = svcxdr_encode_deviceid4(p, &b->vol_id);
        p = xdr_encode_hyper(p, b->foff);
        p = xdr_encode_hyper(p, b->len);
        p = xdr_encode_hyper(p, b->soff);
@@ -145,9 +144,7 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
        for (i = 0; i < nr_iomaps; i++) {
                struct pnfs_block_extent bex;
 
-               memcpy(&bex.vol_id, p, sizeof(struct nfsd4_deviceid));
-               p += XDR_QUADLEN(sizeof(struct nfsd4_deviceid));
-
+               p = svcxdr_decode_deviceid4(p, &bex.vol_id);
                p = xdr_decode_hyper(p, &bex.foff);
                if (bex.foff & (block_size - 1)) {
                        dprintk("%s: unaligned offset 0x%llx\n",
index bb205328e043dafee5b2daa7d9f5023a576d8e32..223a10f37898ef1531085be802e760a3a26fe3ea 100644 (file)
@@ -54,8 +54,7 @@ nfsd4_ff_encode_layoutget(struct xdr_stream *xdr,
        *p++ = cpu_to_be32(1);                  /* single mirror */
        *p++ = cpu_to_be32(1);                  /* single data server */
 
-       p = xdr_encode_opaque_fixed(p, &fl->deviceid,
-                       sizeof(struct nfsd4_deviceid));
+       p = svcxdr_encode_deviceid4(p, &fl->deviceid);
 
        *p++ = cpu_to_be32(1);                  /* efficiency */
 
index e4e23b2a3e6552d1bef590d1f1ca42a78cf864c4..d0fbbd34db689cd2c73c6251f2c68e49a02f3fc8 100644 (file)
@@ -120,7 +120,6 @@ nfsd4_set_deviceid(struct nfsd4_deviceid *id, const struct svc_fh *fhp,
 
        id->fsid_idx = fhp->fh_export->ex_devid_map->idx;
        id->generation = device_generation;
-       id->pad = 0;
        return 0;
 }
 
index 0fb48e0c179dae2b1ca34acc3fcf4c6d3976bc24..3a9f929cdb31e24b5363e8f668e61c1291793cd4 100644 (file)
@@ -566,18 +566,6 @@ nfsd4_decode_state_owner4(struct nfsd4_compoundargs *argp,
 }
 
 #ifdef CONFIG_NFSD_PNFS
-static __be32
-nfsd4_decode_deviceid4(struct nfsd4_compoundargs *argp,
-                      struct nfsd4_deviceid *devid)
-{
-       __be32 *p;
-
-       p = xdr_inline_decode(argp->xdr, NFS4_DEVICEID4_SIZE);
-       if (!p)
-               return nfserr_bad_xdr;
-       memcpy(devid, p, sizeof(*devid));
-       return nfs_ok;
-}
 
 static __be32
 nfsd4_decode_layoutupdate4(struct nfsd4_compoundargs *argp,
@@ -1733,7 +1721,7 @@ nfsd4_decode_getdeviceinfo(struct nfsd4_compoundargs *argp,
        __be32 status;
 
        memset(gdev, 0, sizeof(*gdev));
-       status = nfsd4_decode_deviceid4(argp, &gdev->gd_devid);
+       status = nfsd4_decode_deviceid4(argp->xdr, &gdev->gd_devid);
        if (status)
                return status;
        if (xdr_stream_decode_u32(argp->xdr, &gdev->gd_layout_type) < 0)
index 9bd1ade6ba54f94f3fa6a466205140447d1769f2..c2765619edd4eadced9d978b9c8ebd7d9ace4d17 100644 (file)
@@ -459,9 +459,43 @@ struct nfsd4_reclaim_complete {
 struct nfsd4_deviceid {
        u64                     fsid_idx;
        u32                     generation;
-       u32                     pad;
 };
 
+static inline __be32 *
+svcxdr_encode_deviceid4(__be32 *p, const struct nfsd4_deviceid *devid)
+{
+       __be64 *q = (__be64 *)p;
+
+       *q = (__force __be64)devid->fsid_idx;
+       p += 2;
+       *p++ = (__force __be32)devid->generation;
+       *p++ = xdr_zero;
+       return p;
+}
+
+static inline __be32 *
+svcxdr_decode_deviceid4(__be32 *p, struct nfsd4_deviceid *devid)
+{
+       __be64 *q = (__be64 *)p;
+
+       devid->fsid_idx = (__force u64)(*q);
+       p += 2;
+       devid->generation = (__force u32)(*p++);
+       p++; /* NFSD does not use the remaining octets */
+       return p;
+}
+
+static inline __be32
+nfsd4_decode_deviceid4(struct xdr_stream *xdr, struct nfsd4_deviceid *devid)
+{
+       __be32 *p = xdr_inline_decode(xdr, NFS4_DEVICEID4_SIZE);
+
+       if (unlikely(!p))
+               return nfserr_bad_xdr;
+       svcxdr_decode_deviceid4(p, devid);
+       return nfs_ok;
+}
+
 struct nfsd4_layout_seg {
        u32                     iomode;
        u64                     offset;