Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFSD: Rework encoding and decoding of nfsd4_deviceid

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>

authored by

Sergey Bashirov and committed by
Chuck Lever
832738e4 c97b737e

+39 -22
+2 -5
fs/nfsd/blocklayoutxdr.c
··· 29 29 *p++ = cpu_to_be32(len); 30 30 *p++ = cpu_to_be32(1); /* we always return a single extent */ 31 31 32 - p = xdr_encode_opaque_fixed(p, &b->vol_id, 33 - sizeof(struct nfsd4_deviceid)); 32 + p = svcxdr_encode_deviceid4(p, &b->vol_id); 34 33 p = xdr_encode_hyper(p, b->foff); 35 34 p = xdr_encode_hyper(p, b->len); 36 35 p = xdr_encode_hyper(p, b->soff); ··· 155 156 for (i = 0; i < nr_iomaps; i++) { 156 157 struct pnfs_block_extent bex; 157 158 158 - memcpy(&bex.vol_id, p, sizeof(struct nfsd4_deviceid)); 159 - p += XDR_QUADLEN(sizeof(struct nfsd4_deviceid)); 160 - 159 + p = svcxdr_decode_deviceid4(p, &bex.vol_id); 161 160 p = xdr_decode_hyper(p, &bex.foff); 162 161 if (bex.foff & (block_size - 1)) { 163 162 goto fail;
+1 -2
fs/nfsd/flexfilelayoutxdr.c
··· 54 54 *p++ = cpu_to_be32(1); /* single mirror */ 55 55 *p++ = cpu_to_be32(1); /* single data server */ 56 56 57 - p = xdr_encode_opaque_fixed(p, &fl->deviceid, 58 - sizeof(struct nfsd4_deviceid)); 57 + p = svcxdr_encode_deviceid4(p, &fl->deviceid); 59 58 60 59 *p++ = cpu_to_be32(1); /* efficiency */ 61 60
-1
fs/nfsd/nfs4layouts.c
··· 120 120 121 121 id->fsid_idx = fhp->fh_export->ex_devid_map->idx; 122 122 id->generation = device_generation; 123 - id->pad = 0; 124 123 return 0; 125 124 } 126 125
+1 -13
fs/nfsd/nfs4xdr.c
··· 587 587 } 588 588 589 589 #ifdef CONFIG_NFSD_PNFS 590 - static __be32 591 - nfsd4_decode_deviceid4(struct nfsd4_compoundargs *argp, 592 - struct nfsd4_deviceid *devid) 593 - { 594 - __be32 *p; 595 - 596 - p = xdr_inline_decode(argp->xdr, NFS4_DEVICEID4_SIZE); 597 - if (!p) 598 - return nfserr_bad_xdr; 599 - memcpy(devid, p, sizeof(*devid)); 600 - return nfs_ok; 601 - } 602 590 603 591 static __be32 604 592 nfsd4_decode_layoutupdate4(struct nfsd4_compoundargs *argp, ··· 1771 1783 __be32 status; 1772 1784 1773 1785 memset(gdev, 0, sizeof(*gdev)); 1774 - status = nfsd4_decode_deviceid4(argp, &gdev->gd_devid); 1786 + status = nfsd4_decode_deviceid4(argp->xdr, &gdev->gd_devid); 1775 1787 if (status) 1776 1788 return status; 1777 1789 if (xdr_stream_decode_u32(argp->xdr, &gdev->gd_layout_type) < 0)
+35 -1
fs/nfsd/xdr4.h
··· 595 595 struct nfsd4_deviceid { 596 596 u64 fsid_idx; 597 597 u32 generation; 598 - u32 pad; 599 598 }; 599 + 600 + static inline __be32 * 601 + svcxdr_encode_deviceid4(__be32 *p, const struct nfsd4_deviceid *devid) 602 + { 603 + __be64 *q = (__be64 *)p; 604 + 605 + *q = (__force __be64)devid->fsid_idx; 606 + p += 2; 607 + *p++ = (__force __be32)devid->generation; 608 + *p++ = xdr_zero; 609 + return p; 610 + } 611 + 612 + static inline __be32 * 613 + svcxdr_decode_deviceid4(__be32 *p, struct nfsd4_deviceid *devid) 614 + { 615 + __be64 *q = (__be64 *)p; 616 + 617 + devid->fsid_idx = (__force u64)(*q); 618 + p += 2; 619 + devid->generation = (__force u32)(*p++); 620 + p++; /* NFSD does not use the remaining octets */ 621 + return p; 622 + } 623 + 624 + static inline __be32 625 + nfsd4_decode_deviceid4(struct xdr_stream *xdr, struct nfsd4_deviceid *devid) 626 + { 627 + __be32 *p = xdr_inline_decode(xdr, NFS4_DEVICEID4_SIZE); 628 + 629 + if (unlikely(!p)) 630 + return nfserr_bad_xdr; 631 + svcxdr_decode_deviceid4(p, devid); 632 + return nfs_ok; 633 + } 600 634 601 635 struct nfsd4_layout_seg { 602 636 u32 iomode;