nfsd: allow nfsd to advertise multiple layout types
authorJeff Layton <jlayton@poochiereds.net>
Sun, 10 Jul 2016 19:55:58 +0000 (15:55 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Fri, 15 Jul 2016 19:31:32 +0000 (15:31 -0400)
If the underlying filesystem supports multiple layout types, then there
is little reason not to advertise that fact to clients and let them
choose what type to use.

Turn the ex_layout_type field into a bitfield. For each supported
layout type, we set a bit in that field. When the client requests a
layout, ensure that the bit for that layout type is set. When the
client requests attributes, send back a list of supported types.

Signed-off-by: Jeff Layton <jlayton@poochiereds.net>
Reviewed-by: Weston Andros Adamson <dros@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/export.c
fs/nfsd/export.h
fs/nfsd/nfs4layouts.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4xdr.c

index 79de2f38dd63f685351381a637289c8097617ebf..43e109cc0ccc39e8293a7c8926bcb1c105951714 100644 (file)
@@ -706,7 +706,7 @@ static void svc_export_init(struct cache_head *cnew, struct cache_head *citem)
        new->ex_fslocs.locations = NULL;
        new->ex_fslocs.locations_count = 0;
        new->ex_fslocs.migrated = 0;
-       new->ex_layout_type = 0;
+       new->ex_layout_types = 0;
        new->ex_uuid = NULL;
        new->cd = item->cd;
 }
@@ -731,7 +731,7 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem)
        item->ex_fslocs.locations_count = 0;
        new->ex_fslocs.migrated = item->ex_fslocs.migrated;
        item->ex_fslocs.migrated = 0;
-       new->ex_layout_type = item->ex_layout_type;
+       new->ex_layout_types = item->ex_layout_types;
        new->ex_nflavors = item->ex_nflavors;
        for (i = 0; i < MAX_SECINFO_LIST; i++) {
                new->ex_flavors[i] = item->ex_flavors[i];
index 2e315072bf3fb83e62d0c469a2d43b2d3683392f..730f15eeb7ed561fb50b5485af00f2a5a8aca2f7 100644 (file)
@@ -57,7 +57,7 @@ struct svc_export {
        struct nfsd4_fs_locations ex_fslocs;
        uint32_t                ex_nflavors;
        struct exp_flavor_info  ex_flavors[MAX_SECINFO_LIST];
-       enum pnfs_layouttype    ex_layout_type;
+       u32                     ex_layout_types;
        struct nfsd4_deviceid_map *ex_devid_map;
        struct cache_detail     *cd;
 };
index 6d98d16b3354fb93c3c660c29b1d3b29f77513af..2be9602b0221bd19f7492dad6266f3fd78c4e050 100644 (file)
@@ -139,21 +139,21 @@ void nfsd4_setup_layout_type(struct svc_export *exp)
         * otherwise advertise the block layout.
         */
 #ifdef CONFIG_NFSD_FLEXFILELAYOUT
-       exp->ex_layout_type = LAYOUT_FLEX_FILES;
+       exp->ex_layout_types |= 1 << LAYOUT_FLEX_FILES;
 #endif
 #ifdef CONFIG_NFSD_BLOCKLAYOUT
        /* overwrite flex file layout selection if needed */
        if (sb->s_export_op->get_uuid &&
            sb->s_export_op->map_blocks &&
            sb->s_export_op->commit_blocks)
-               exp->ex_layout_type = LAYOUT_BLOCK_VOLUME;
+               exp->ex_layout_types |= 1 << LAYOUT_BLOCK_VOLUME;
 #endif
 #ifdef CONFIG_NFSD_SCSILAYOUT
        /* overwrite block layout selection if needed */
        if (sb->s_export_op->map_blocks &&
            sb->s_export_op->commit_blocks &&
            sb->s_bdev && sb->s_bdev->bd_disk->fops->pr_ops)
-               exp->ex_layout_type = LAYOUT_SCSI;
+               exp->ex_layout_types |= 1 << LAYOUT_SCSI;
 #endif
 }
 
index 89fad8aeffe201219f9c0a9b060088cafe706233..e0c15f879d8953f895fb5728cd404940659d49a5 100644 (file)
@@ -1219,12 +1219,12 @@ nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 static const struct nfsd4_layout_ops *
 nfsd4_layout_verify(struct svc_export *exp, unsigned int layout_type)
 {
-       if (!exp->ex_layout_type) {
+       if (!exp->ex_layout_types) {
                dprintk("%s: export does not support pNFS\n", __func__);
                return NULL;
        }
 
-       if (exp->ex_layout_type != layout_type) {
+       if (!(exp->ex_layout_types & (1 << layout_type))) {
                dprintk("%s: layout type %d not supported\n",
                        __func__, layout_type);
                return NULL;
index 84ef94794496dba8382d36badbb79dadd302e2a4..0aa0236a142904c6de5123b87ef96c55043c7f7d 100644 (file)
@@ -2162,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;
 }
@@ -2752,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;
        }