mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 03:09:34 +03:00
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 <pavel.zakharov@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: loli10K <ezomori.nozomu@gmail.com> Closes #9427 Closes #9429
This commit is contained in:
parent
90bc5ca5e1
commit
f1ba5478a3
@ -34,6 +34,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern boolean_t zfs_allocatable_devs(nvlist_t *);
|
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 void zpool_get_load_policy(nvlist_t *, zpool_load_policy_t *);
|
||||||
|
|
||||||
extern int zfs_zpl_version_map(int spa_version);
|
extern int zfs_zpl_version_map(int spa_version);
|
||||||
|
@ -64,6 +64,33 @@ zfs_allocatable_devs(nvlist_t *nv)
|
|||||||
return (B_FALSE);
|
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
|
void
|
||||||
zpool_get_load_policy(nvlist_t *nvl, zpool_load_policy_t *zlpp)
|
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)
|
#if defined(_KERNEL)
|
||||||
EXPORT_SYMBOL(zfs_allocatable_devs);
|
EXPORT_SYMBOL(zfs_allocatable_devs);
|
||||||
|
EXPORT_SYMBOL(zfs_special_devs);
|
||||||
EXPORT_SYMBOL(zpool_get_load_policy);
|
EXPORT_SYMBOL(zpool_get_load_policy);
|
||||||
EXPORT_SYMBOL(zfs_zpl_version_map);
|
EXPORT_SYMBOL(zfs_zpl_version_map);
|
||||||
EXPORT_SYMBOL(zfs_spa_version_map);
|
EXPORT_SYMBOL(zfs_spa_version_map);
|
||||||
|
@ -5134,6 +5134,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
|
|||||||
uint64_t version, obj;
|
uint64_t version, obj;
|
||||||
boolean_t has_features;
|
boolean_t has_features;
|
||||||
boolean_t has_encryption;
|
boolean_t has_encryption;
|
||||||
|
boolean_t has_allocclass;
|
||||||
spa_feature_t feat;
|
spa_feature_t feat;
|
||||||
char *feat_name;
|
char *feat_name;
|
||||||
char *poolname;
|
char *poolname;
|
||||||
@ -5178,6 +5179,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
|
|||||||
|
|
||||||
has_features = B_FALSE;
|
has_features = B_FALSE;
|
||||||
has_encryption = B_FALSE;
|
has_encryption = B_FALSE;
|
||||||
|
has_allocclass = B_FALSE;
|
||||||
for (nvpair_t *elem = nvlist_next_nvpair(props, NULL);
|
for (nvpair_t *elem = nvlist_next_nvpair(props, NULL);
|
||||||
elem != NULL; elem = nvlist_next_nvpair(props, elem)) {
|
elem != NULL; elem = nvlist_next_nvpair(props, elem)) {
|
||||||
if (zpool_prop_feature(nvpair_name(elem))) {
|
if (zpool_prop_feature(nvpair_name(elem))) {
|
||||||
@ -5187,6 +5189,8 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
|
|||||||
VERIFY0(zfeature_lookup_name(feat_name, &feat));
|
VERIFY0(zfeature_lookup_name(feat_name, &feat));
|
||||||
if (feat == SPA_FEATURE_ENCRYPTION)
|
if (feat == SPA_FEATURE_ENCRYPTION)
|
||||||
has_encryption = B_TRUE;
|
has_encryption = B_TRUE;
|
||||||
|
if (feat == SPA_FEATURE_ALLOCATION_CLASSES)
|
||||||
|
has_allocclass = B_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5200,6 +5204,12 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
|
|||||||
return (error);
|
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,
|
if (has_features || nvlist_lookup_uint64(props,
|
||||||
zpool_prop_to_name(ZPOOL_PROP_VERSION), &version) != 0) {
|
zpool_prop_to_name(ZPOOL_PROP_VERSION), &version) != 0) {
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
|
|
||||||
#
|
#
|
||||||
# DESCRIPTION:
|
# 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"
|
verify_runnable "global"
|
||||||
@ -31,6 +32,9 @@ log_assert $claim
|
|||||||
log_onexit cleanup
|
log_onexit cleanup
|
||||||
|
|
||||||
log_must disk_setup
|
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 \
|
log_must zpool create $TESTPOOL raidz $ZPOOL_DISKS special mirror \
|
||||||
$CLASS_DISK0 $CLASS_DISK1
|
$CLASS_DISK0 $CLASS_DISK1
|
||||||
log_must display_status "$TESTPOOL"
|
log_must display_status "$TESTPOOL"
|
||||||
|
Loading…
Reference in New Issue
Block a user