diff options
author | loli10K <[email protected]> | 2019-10-11 01:39:41 +0200 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2019-10-10 16:39:41 -0700 |
commit | 715c996d3b5e45897ff165f2e6610e1b57da47e4 (patch) | |
tree | 4c600a53be1551d992a0ea222cb60e93f28234f3 /module | |
parent | 2516a8782158a1d420aa00ce5f470a33cc7ec2ca (diff) |
Fix pool creation with feature@allocation_classes disabled
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 <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: loli10K <[email protected]>
Closes #9427
Closes #9429
Diffstat (limited to 'module')
-rw-r--r-- | module/zcommon/zfs_comutil.c | 28 | ||||
-rw-r--r-- | module/zfs/spa.c | 10 |
2 files changed, 38 insertions, 0 deletions
diff --git a/module/zcommon/zfs_comutil.c b/module/zcommon/zfs_comutil.c index 5daa6907c..a3ff7d8e6 100644 --- a/module/zcommon/zfs_comutil.c +++ b/module/zcommon/zfs_comutil.c @@ -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); diff --git a/module/zfs/spa.c b/module/zfs/spa.c index 529ffc03d..facd5eda8 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -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) { |