nfsd: Fix an FS_LAYOUT_TYPES/LAYOUT_TYPES encode bug
authorKinglong Mee <kinglongmee@gmail.com>
Thu, 30 Jul 2015 13:52:44 +0000 (21:52 +0800)
committerJ. Bruce Fields <bfields@redhat.com>
Mon, 31 Aug 2015 20:12:39 +0000 (16:12 -0400)
Currently we'll respond correctly to a request for either
FS_LAYOUT_TYPES or LAYOUT_TYPES, but not to a request for both
attributes simultaneously.

Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Cc: stable@vger.kernel.org
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfs4xdr.c

index 1aa0dc38ed5840a4af573ca3bc296cdc8506ba47..ea05dfb132495b7e87e5edcf777b75afc32bcdbc 100644 (file)
@@ -2140,6 +2140,27 @@ nfsd4_encode_aclname(struct xdr_stream *xdr, struct svc_rqst *rqstp,
                return nfsd4_encode_user(xdr, rqstp, ace->who_uid);
 }
 
+static inline __be32
+nfsd4_encode_layout_type(struct xdr_stream *xdr, enum pnfs_layouttype layout_type)
+{
+       __be32 *p;
+
+       if (layout_type) {
+               p = xdr_reserve_space(xdr, 8);
+               if (!p)
+                       return nfserr_resource;
+               *p++ = cpu_to_be32(1);
+               *p++ = cpu_to_be32(layout_type);
+       } else {
+               p = xdr_reserve_space(xdr, 4);
+               if (!p)
+                       return nfserr_resource;
+               *p++ = cpu_to_be32(0);
+       }
+
+       return 0;
+}
+
 #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
                              FATTR4_WORD0_RDATTR_ERROR)
 #define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
@@ -2695,20 +2716,16 @@ out_acl:
                p = xdr_encode_hyper(p, ino);
        }
 #ifdef CONFIG_NFSD_PNFS
-       if ((bmval1 & FATTR4_WORD1_FS_LAYOUT_TYPES) ||
-           (bmval2 & FATTR4_WORD2_LAYOUT_TYPES)) {
-               if (exp->ex_layout_type) {
-                       p = xdr_reserve_space(xdr, 8);
-                       if (!p)
-                               goto out_resource;
-                       *p++ = cpu_to_be32(1);
-                       *p++ = cpu_to_be32(exp->ex_layout_type);
-               } else {
-                       p = xdr_reserve_space(xdr, 4);
-                       if (!p)
-                               goto out_resource;
-                       *p++ = cpu_to_be32(0);
-               }
+       if (bmval1 & FATTR4_WORD1_FS_LAYOUT_TYPES) {
+               status = nfsd4_encode_layout_type(xdr, exp->ex_layout_type);
+               if (status)
+                       goto out;
+       }
+
+       if (bmval2 & FATTR4_WORD2_LAYOUT_TYPES) {
+               status = nfsd4_encode_layout_type(xdr, exp->ex_layout_type);
+               if (status)
+                       goto out;
        }
 
        if (bmval2 & FATTR4_WORD2_LAYOUT_BLKSIZE) {