Skip to content

Commit

Permalink
Fix pool creation with feature@allocation_classes disabled
Browse files Browse the repository at this point in the history
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.

Signed-off-by: loli10K <[email protected]>
  • Loading branch information
loli10K committed Oct 8, 2019
1 parent 7b50929 commit 07c541a
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 1 deletion.
1 change: 1 addition & 0 deletions include/zfs_comutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
28 changes: 28 additions & 0 deletions module/zcommon/zfs_comutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions module/zfs/spa.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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))) {
Expand All @@ -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;
}
}

Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down

0 comments on commit 07c541a

Please sign in to comment.