]> granicus.if.org Git - zfs/commitdiff
Fix pool creation with feature@allocation_classes disabled
authorloli10K <loli10K@users.noreply.github.com>
Thu, 10 Oct 2019 23:39:41 +0000 (01:39 +0200)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 10 Oct 2019 23:39:41 +0000 (16:39 -0700)
When "feature@allocation_classes" is not enabled on the pool no vdev
with "special" or "dedup" allocation type should be allowed to exist in
the vdev tree.

Reviewed-by: Pavel Zakharov <pavel.zakharov@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: loli10K <ezomori.nozomu@gmail.com>
Closes #9427
Closes #9429

include/zfs_comutil.h
module/zcommon/zfs_comutil.c
module/zfs/spa.c
tests/zfs-tests/tests/functional/alloc_class/alloc_class_001_pos.ksh

index 1360d6e1c17131829a9ff1cdb197b82f62434a3f..7cdc6d6938aeb49f7b2e283989e293337990aff6 100644 (file)
@@ -34,6 +34,7 @@ extern "C" {
 #endif
 
 extern boolean_t zfs_allocatable_devs(nvlist_t *);
+extern boolean_t zfs_special_devs(nvlist_t *);
 extern void zpool_get_load_policy(nvlist_t *, zpool_load_policy_t *);
 
 extern int zfs_zpl_version_map(int spa_version);
index 5daa6907c5d0ada506f53e0697018f84ca1dad2d..a3ff7d8e6991e3e1eb0b64f071fa9747269e9963 100644 (file)
@@ -64,6 +64,33 @@ zfs_allocatable_devs(nvlist_t *nv)
        return (B_FALSE);
 }
 
+/*
+ * Are there special vdevs?
+ */
+boolean_t
+zfs_special_devs(nvlist_t *nv)
+{
+       char *bias;
+       uint_t c;
+       nvlist_t **child;
+       uint_t children;
+
+       if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
+           &child, &children) != 0) {
+               return (B_FALSE);
+       }
+       for (c = 0; c < children; c++) {
+               if (nvlist_lookup_string(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS,
+                   &bias) == 0) {
+                       if (strcmp(bias, VDEV_ALLOC_BIAS_SPECIAL) == 0 ||
+                           strcmp(bias, VDEV_ALLOC_BIAS_DEDUP) == 0) {
+                               return (B_TRUE);
+                       }
+               }
+       }
+       return (B_FALSE);
+}
+
 void
 zpool_get_load_policy(nvlist_t *nvl, zpool_load_policy_t *zlpp)
 {
@@ -223,6 +250,7 @@ zfs_dataset_name_hidden(const char *name)
 
 #if defined(_KERNEL)
 EXPORT_SYMBOL(zfs_allocatable_devs);
+EXPORT_SYMBOL(zfs_special_devs);
 EXPORT_SYMBOL(zpool_get_load_policy);
 EXPORT_SYMBOL(zfs_zpl_version_map);
 EXPORT_SYMBOL(zfs_spa_version_map);
index 529ffc03ddb3c85a22130202fe61ecbdbb7be0f6..facd5eda80fa241e66c286bc929b99ceb6ba88be 100644 (file)
@@ -5620,6 +5620,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
        uint64_t version, obj;
        boolean_t has_features;
        boolean_t has_encryption;
+       boolean_t has_allocclass;
        spa_feature_t feat;
        char *feat_name;
        char *poolname;
@@ -5664,6 +5665,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
 
        has_features = B_FALSE;
        has_encryption = B_FALSE;
+       has_allocclass = B_FALSE;
        for (nvpair_t *elem = nvlist_next_nvpair(props, NULL);
            elem != NULL; elem = nvlist_next_nvpair(props, elem)) {
                if (zpool_prop_feature(nvpair_name(elem))) {
@@ -5673,6 +5675,8 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
                        VERIFY0(zfeature_lookup_name(feat_name, &feat));
                        if (feat == SPA_FEATURE_ENCRYPTION)
                                has_encryption = B_TRUE;
+                       if (feat == SPA_FEATURE_ALLOCATION_CLASSES)
+                               has_allocclass = B_TRUE;
                }
        }
 
@@ -5686,6 +5690,12 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
                        return (error);
                }
        }
+       if (!has_allocclass && zfs_special_devs(nvroot)) {
+               spa_deactivate(spa);
+               spa_remove(spa);
+               mutex_exit(&spa_namespace_lock);
+               return (ENOTSUP);
+       }
 
        if (has_features || nvlist_lookup_uint64(props,
            zpool_prop_to_name(ZPOOL_PROP_VERSION), &version) != 0) {
index 441df82967186b5e21545a53c90b9b655806c0f5..3237d7cb784f7a2967212e35021d7bc65c5bdf80 100755 (executable)
@@ -20,7 +20,8 @@
 
 #
 # DESCRIPTION:
-#      Creating a pool with a special device succeeds.
+#      Creating a pool with a special device succeeds, but only if
+#      "feature@allocation_classes" is enabled.
 #
 
 verify_runnable "global"
@@ -31,6 +32,9 @@ log_assert $claim
 log_onexit cleanup
 
 log_must disk_setup
+for type in special dedup; do
+       log_mustnot zpool create -d $TESTPOOL $CLASS_DISK0 $type $CLASS_DISK1
+done
 log_must zpool create $TESTPOOL raidz $ZPOOL_DISKS special mirror \
     $CLASS_DISK0 $CLASS_DISK1
 log_must display_status "$TESTPOOL"