]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - fs/nfsd/nfs4xdr.c
nfsd: allow nfsd to advertise multiple layout types
[karo-tx-linux.git] / fs / nfsd / nfs4xdr.c
index 9df898ba648f73a14b1e42be47dbfddf189ec0a6..0aa0236a142904c6de5123b87ef96c55043c7f7d 100644 (file)
@@ -1299,16 +1299,14 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
                break;
        case SP4_MACH_CRED:
                /* spo_must_enforce */
-               READ_BUF(4);
-               dummy = be32_to_cpup(p++);
-               READ_BUF(dummy * 4);
-               p += dummy;
-
+               status = nfsd4_decode_bitmap(argp,
+                                       exid->spo_must_enforce);
+               if (status)
+                       goto out;
                /* spo_must_allow */
-               READ_BUF(4);
-               dummy = be32_to_cpup(p++);
-               READ_BUF(dummy * 4);
-               p += dummy;
+               status = nfsd4_decode_bitmap(argp, exid->spo_must_allow);
+               if (status)
+                       goto out;
                break;
        case SP4_SSV:
                /* ssp_ops */
@@ -2164,22 +2162,20 @@ nfsd4_encode_aclname(struct xdr_stream *xdr, struct svc_rqst *rqstp,
 }
 
 static inline __be32
-nfsd4_encode_layout_type(struct xdr_stream *xdr, enum pnfs_layouttype layout_type)
+nfsd4_encode_layout_types(struct xdr_stream *xdr, u32 layout_types)
 {
-       __be32 *p;
+       __be32          *p;
+       unsigned long   i = hweight_long(layout_types);
 
-       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);
-       }
+       p = xdr_reserve_space(xdr, 4 + 4 * i);
+       if (!p)
+               return nfserr_resource;
+
+       *p++ = cpu_to_be32(i);
+
+       for (i = LAYOUT_NFSV4_1_FILES; i < LAYOUT_TYPE_MAX; ++i)
+               if (layout_types & (1 << i))
+                       *p++ = cpu_to_be32(i);
 
        return 0;
 }
@@ -2754,13 +2750,13 @@ out_acl:
        }
 #ifdef CONFIG_NFSD_PNFS
        if (bmval1 & FATTR4_WORD1_FS_LAYOUT_TYPES) {
-               status = nfsd4_encode_layout_type(xdr, exp->ex_layout_type);
+               status = nfsd4_encode_layout_types(xdr, exp->ex_layout_types);
                if (status)
                        goto out;
        }
 
        if (bmval2 & FATTR4_WORD2_LAYOUT_TYPES) {
-               status = nfsd4_encode_layout_type(xdr, exp->ex_layout_type);
+               status = nfsd4_encode_layout_types(xdr, exp->ex_layout_types);
                if (status)
                        goto out;
        }
@@ -3867,14 +3863,6 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_w
        return nfserr;
 }
 
-static const u32 nfs4_minimal_spo_must_enforce[2] = {
-       [1] = 1 << (OP_BIND_CONN_TO_SESSION - 32) |
-             1 << (OP_EXCHANGE_ID - 32) |
-             1 << (OP_CREATE_SESSION - 32) |
-             1 << (OP_DESTROY_SESSION - 32) |
-             1 << (OP_DESTROY_CLIENTID - 32)
-};
-
 static __be32
 nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
                         struct nfsd4_exchange_id *exid)
@@ -3885,6 +3873,7 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
        char *server_scope;
        int major_id_sz;
        int server_scope_sz;
+       int status = 0;
        uint64_t minor_id = 0;
 
        if (nfserr)
@@ -3913,18 +3902,20 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
        case SP4_NONE:
                break;
        case SP4_MACH_CRED:
-               /* spo_must_enforce, spo_must_allow */
-               p = xdr_reserve_space(xdr, 16);
-               if (!p)
-                       return nfserr_resource;
-
                /* spo_must_enforce bitmap: */
-               *p++ = cpu_to_be32(2);
-               *p++ = cpu_to_be32(nfs4_minimal_spo_must_enforce[0]);
-               *p++ = cpu_to_be32(nfs4_minimal_spo_must_enforce[1]);
-               /* empty spo_must_allow bitmap: */
-               *p++ = cpu_to_be32(0);
-
+               status = nfsd4_encode_bitmap(xdr,
+                                       exid->spo_must_enforce[0],
+                                       exid->spo_must_enforce[1],
+                                       exid->spo_must_enforce[2]);
+               if (status)
+                       goto out;
+               /* spo_must_allow bitmap: */
+               status = nfsd4_encode_bitmap(xdr,
+                                       exid->spo_must_allow[0],
+                                       exid->spo_must_allow[1],
+                                       exid->spo_must_allow[2]);
+               if (status)
+                       goto out;
                break;
        default:
                WARN_ON_ONCE(1);
@@ -3951,6 +3942,8 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
        /* Implementation id */
        *p++ = cpu_to_be32(0);  /* zero length nfs_impl_id4 array */
        return 0;
+out:
+       return status;
 }
 
 static __be32