aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
authorPaul Dagnelie <[email protected]>2018-10-16 11:15:04 -0700
committerMatthew Ahrens <[email protected]>2018-10-16 11:15:04 -0700
commitd52d80b700229e879fe757c989c3bcd3a3a42f2a (patch)
treebaa4fde58282a0a23eb038f163e1a6505fe60665 /module/zfs
parent779a6c0bf6df76e0dd92c1ccf81f48512b835bb0 (diff)
Add types to featureflags in zfs
The boolean featureflags in use thus far in ZFS are extremely useful, but because they take advantage of the zap layer, more interesting data than just a true/false value can be stored in a featureflag. In redacted send/receive, this is used to store the list of redaction snapshots for a redacted dataset. This change adds the ability for ZFS to store types other than a boolean in a featureflag. The only other implemented type is a uint64_t array. It also modifies the interfaces around dataset features to accomodate the new capabilities, and adds a few new functions to increase encapsulation. This functionality will be used by the Redacted Send/Receive feature. Reviewed-by: Matthew Ahrens <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Paul Dagnelie <[email protected]> Closes #7981
Diffstat (limited to 'module/zfs')
-rw-r--r--module/zfs/dmu_object.c3
-rw-r--r--module/zfs/dmu_objset.c18
-rw-r--r--module/zfs/dmu_send.c4
-rw-r--r--module/zfs/dnode_sync.c4
-rw-r--r--module/zfs/dsl_crypt.c8
-rw-r--r--module/zfs/dsl_dataset.c231
-rw-r--r--module/zfs/dsl_destroy.c14
7 files changed, 213 insertions, 69 deletions
diff --git a/module/zfs/dmu_object.c b/module/zfs/dmu_object.c
index afee869b6..9b5cf125f 100644
--- a/module/zfs/dmu_object.c
+++ b/module/zfs/dmu_object.c
@@ -337,7 +337,8 @@ dmu_object_next(objset_t *os, uint64_t *objectp, boolean_t hole, uint64_t txg)
if (*objectp == 0) {
start_obj = 1;
- } else if (ds && ds->ds_feature_inuse[SPA_FEATURE_LARGE_DNODE]) {
+ } else if (ds && dsl_dataset_feature_is_active(ds,
+ SPA_FEATURE_LARGE_DNODE)) {
uint64_t i = *objectp + 1;
uint64_t last_obj = *objectp | (DNODES_PER_BLOCK - 1);
dmu_object_info_t doi;
diff --git a/module/zfs/dmu_objset.c b/module/zfs/dmu_objset.c
index 7ad1d618a..a8304c18d 100644
--- a/module/zfs/dmu_objset.c
+++ b/module/zfs/dmu_objset.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2017 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
@@ -1073,14 +1073,14 @@ dmu_objset_create_impl_dnstats(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
(!os->os_encrypted || !dmu_objset_is_receiving(os))) {
os->os_phys->os_flags |= OBJSET_FLAG_USERACCOUNTING_COMPLETE;
if (dmu_objset_userobjused_enabled(os)) {
- ds->ds_feature_activation_needed[
- SPA_FEATURE_USEROBJ_ACCOUNTING] = B_TRUE;
+ ds->ds_feature_activation[
+ SPA_FEATURE_USEROBJ_ACCOUNTING] = (void *)B_TRUE;
os->os_phys->os_flags |=
OBJSET_FLAG_USEROBJACCOUNTING_COMPLETE;
}
if (dmu_objset_projectquota_enabled(os)) {
- ds->ds_feature_activation_needed[
- SPA_FEATURE_PROJECT_QUOTA] = B_TRUE;
+ ds->ds_feature_activation[
+ SPA_FEATURE_PROJECT_QUOTA] = (void *)B_TRUE;
os->os_phys->os_flags |=
OBJSET_FLAG_PROJECTQUOTA_COMPLETE;
}
@@ -2377,11 +2377,11 @@ dmu_objset_id_quota_upgrade_cb(objset_t *os)
dmu_objset_userobjspace_present(os))
return (SET_ERROR(ENOTSUP));
- dmu_objset_ds(os)->ds_feature_activation_needed[
- SPA_FEATURE_USEROBJ_ACCOUNTING] = B_TRUE;
+ dmu_objset_ds(os)->ds_feature_activation[
+ SPA_FEATURE_USEROBJ_ACCOUNTING] = (void *)B_TRUE;
if (dmu_objset_projectquota_enabled(os))
- dmu_objset_ds(os)->ds_feature_activation_needed[
- SPA_FEATURE_PROJECT_QUOTA] = B_TRUE;
+ dmu_objset_ds(os)->ds_feature_activation[
+ SPA_FEATURE_PROJECT_QUOTA] = (void *)B_TRUE;
err = dmu_objset_space_upgrade(os);
if (err)
diff --git a/module/zfs/dmu_send.c b/module/zfs/dmu_send.c
index 24f663d3f..9c0ad406b 100644
--- a/module/zfs/dmu_send.c
+++ b/module/zfs/dmu_send.c
@@ -1022,9 +1022,9 @@ dmu_send_impl(void *tag, dsl_pool_t *dp, dsl_dataset_t *to_ds,
/* raw sends imply large_block_ok */
if ((large_block_ok || rawok) &&
- to_ds->ds_feature_inuse[SPA_FEATURE_LARGE_BLOCKS])
+ dsl_dataset_feature_is_active(to_ds, SPA_FEATURE_LARGE_BLOCKS))
featureflags |= DMU_BACKUP_FEATURE_LARGE_BLOCKS;
- if (to_ds->ds_feature_inuse[SPA_FEATURE_LARGE_DNODE])
+ if (dsl_dataset_feature_is_active(to_ds, SPA_FEATURE_LARGE_DNODE))
featureflags |= DMU_BACKUP_FEATURE_LARGE_DNODE;
/* encrypted datasets will not have embedded blocks */
diff --git a/module/zfs/dnode_sync.c b/module/zfs/dnode_sync.c
index e42f337ed..c4062beb3 100644
--- a/module/zfs/dnode_sync.c
+++ b/module/zfs/dnode_sync.c
@@ -753,8 +753,8 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
if (dn->dn_num_slots > DNODE_MIN_SLOTS) {
dsl_dataset_t *ds = dn->dn_objset->os_dsl_dataset;
mutex_enter(&ds->ds_lock);
- ds->ds_feature_activation_needed[SPA_FEATURE_LARGE_DNODE] =
- B_TRUE;
+ ds->ds_feature_activation[SPA_FEATURE_LARGE_DNODE] =
+ (void *)B_TRUE;
mutex_exit(&ds->ds_lock);
}
diff --git a/module/zfs/dsl_crypt.c b/module/zfs/dsl_crypt.c
index 0eeb260c3..d2545c6fa 100644
--- a/module/zfs/dsl_crypt.c
+++ b/module/zfs/dsl_crypt.c
@@ -15,6 +15,7 @@
/*
* Copyright (c) 2017, Datto, Inc. All rights reserved.
+ * Copyright (c) 2018 by Delphix. All rights reserved.
*/
#include <sys/dsl_crypt.h>
@@ -1938,7 +1939,8 @@ dsl_dataset_create_crypt_sync(uint64_t dsobj, dsl_dir_t *dd,
VERIFY0(zap_add(dp->dp_meta_objset, dd->dd_object,
DD_FIELD_CRYPTO_KEY_OBJ, sizeof (uint64_t), 1, &dd->dd_crypto_obj,
tx));
- dsl_dataset_activate_feature(dsobj, SPA_FEATURE_ENCRYPTION, tx);
+ dsl_dataset_activate_feature(dsobj, SPA_FEATURE_ENCRYPTION,
+ (void *)B_TRUE, tx);
/*
* If we inherited the wrapping key we release our reference now.
@@ -2249,8 +2251,8 @@ dsl_crypto_recv_raw_key_sync(dsl_dataset_t *ds, nvlist_t *nvl, dmu_tx_t *tx)
sizeof (uint64_t), 1, &version, tx));
dsl_dataset_activate_feature(ds->ds_object,
- SPA_FEATURE_ENCRYPTION, tx);
- ds->ds_feature_inuse[SPA_FEATURE_ENCRYPTION] = B_TRUE;
+ SPA_FEATURE_ENCRYPTION, (void *)B_TRUE, tx);
+ ds->ds_feature[SPA_FEATURE_ENCRYPTION] = (void *)B_TRUE;
/* save the dd_crypto_obj on disk */
VERIFY0(zap_add(mos, dd->dd_object, DD_FIELD_CRYPTO_KEY_OBJ,
diff --git a/module/zfs/dsl_dataset.c b/module/zfs/dsl_dataset.c
index 5d98f460a..168aea861 100644
--- a/module/zfs/dsl_dataset.c
+++ b/module/zfs/dsl_dataset.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
* Copyright (c) 2014, Joyent, Inc. All rights reserved.
* Copyright (c) 2014 RackTop Systems.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
@@ -89,6 +89,8 @@ static void dsl_dataset_set_remap_deadlist_object(dsl_dataset_t *ds,
static void dsl_dataset_unset_remap_deadlist_object(dsl_dataset_t *ds,
dmu_tx_t *tx);
+static void unload_zfeature(dsl_dataset_t *ds, spa_feature_t f);
+
extern int spa_asize_inflation;
static zil_header_t zero_zil;
@@ -149,13 +151,16 @@ dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
dsl_dataset_phys(ds)->ds_unique_bytes += used;
if (BP_GET_LSIZE(bp) > SPA_OLD_MAXBLOCKSIZE) {
- ds->ds_feature_activation_needed[SPA_FEATURE_LARGE_BLOCKS] =
- B_TRUE;
+ ds->ds_feature_activation[SPA_FEATURE_LARGE_BLOCKS] =
+ (void *)B_TRUE;
}
spa_feature_t f = zio_checksum_to_feature(BP_GET_CHECKSUM(bp));
- if (f != SPA_FEATURE_NONE)
- ds->ds_feature_activation_needed[f] = B_TRUE;
+ if (f != SPA_FEATURE_NONE) {
+ ASSERT3S(spa_feature_table[f].fi_type, ==,
+ ZFEATURE_TYPE_BOOLEAN);
+ ds->ds_feature_activation[f] = (void *)B_TRUE;
+ }
mutex_exit(&ds->ds_lock);
dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD, delta,
@@ -291,6 +296,72 @@ dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
return (used);
}
+struct feature_type_uint64_array_arg {
+ uint64_t length;
+ uint64_t *array;
+};
+
+static void
+unload_zfeature(dsl_dataset_t *ds, spa_feature_t f)
+{
+ switch (spa_feature_table[f].fi_type) {
+ case ZFEATURE_TYPE_BOOLEAN:
+ break;
+ case ZFEATURE_TYPE_UINT64_ARRAY:
+ {
+ struct feature_type_uint64_array_arg *ftuaa = ds->ds_feature[f];
+ kmem_free(ftuaa->array, ftuaa->length * sizeof (uint64_t));
+ kmem_free(ftuaa, sizeof (*ftuaa));
+ break;
+ }
+ default:
+ panic("Invalid zfeature type %d", spa_feature_table[f].fi_type);
+ }
+}
+
+static int
+load_zfeature(objset_t *mos, dsl_dataset_t *ds, spa_feature_t f)
+{
+ int err = 0;
+ switch (spa_feature_table[f].fi_type) {
+ case ZFEATURE_TYPE_BOOLEAN:
+ err = zap_contains(mos, ds->ds_object,
+ spa_feature_table[f].fi_guid);
+ if (err == 0) {
+ ds->ds_feature[f] = (void *)B_TRUE;
+ } else {
+ ASSERT3U(err, ==, ENOENT);
+ err = 0;
+ }
+ break;
+ case ZFEATURE_TYPE_UINT64_ARRAY:
+ {
+ uint64_t int_size, num_int;
+ uint64_t *data;
+ err = zap_length(mos, ds->ds_object,
+ spa_feature_table[f].fi_guid, &int_size, &num_int);
+ if (err != 0) {
+ ASSERT3U(err, ==, ENOENT);
+ err = 0;
+ break;
+ }
+ ASSERT3U(int_size, ==, sizeof (uint64_t));
+ data = kmem_alloc(int_size * num_int, KM_SLEEP);
+ VERIFY0(zap_lookup(mos, ds->ds_object,
+ spa_feature_table[f].fi_guid, int_size, num_int, data));
+ struct feature_type_uint64_array_arg *ftuaa =
+ kmem_alloc(sizeof (*ftuaa), KM_SLEEP);
+ ftuaa->length = num_int;
+ ftuaa->array = data;
+ ds->ds_feature[f] = ftuaa;
+ break;
+ }
+ default:
+ panic("Invalid zfeature type %d", spa_feature_table[f].fi_type);
+ }
+ return (err);
+}
+
/*
* We have to release the fsid syncronously or we risk that a subsequent
* mount of the same dataset will fail to unique_insert the fsid. This
@@ -334,6 +405,11 @@ dsl_dataset_evict_async(void *dbu)
ASSERT(!list_link_active(&ds->ds_synced_link));
+ for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
+ if (dsl_dataset_feature_is_active(ds, f))
+ unload_zfeature(ds, f);
+ }
+
list_destroy(&ds->ds_prop_cbs);
mutex_destroy(&ds->ds_lock);
mutex_destroy(&ds->ds_opening_lock);
@@ -501,14 +577,7 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
if (!(spa_feature_table[f].fi_flags &
ZFEATURE_FLAG_PER_DATASET))
continue;
- err = zap_contains(mos, dsobj,
- spa_feature_table[f].fi_guid);
- if (err == 0) {
- ds->ds_feature_inuse[f] = B_TRUE;
- } else {
- ASSERT3U(err, ==, ENOENT);
- err = 0;
- }
+ err = load_zfeature(mos, ds, f);
}
}
@@ -872,8 +941,55 @@ dsl_dataset_has_owner(dsl_dataset_t *ds)
return (rv);
}
+static boolean_t
+zfeature_active(spa_feature_t f, void *arg)
+{
+ switch (spa_feature_table[f].fi_type) {
+ case ZFEATURE_TYPE_BOOLEAN: {
+ boolean_t val = (boolean_t)arg;
+ ASSERT(val == B_FALSE || val == B_TRUE);
+ return (val);
+ }
+ case ZFEATURE_TYPE_UINT64_ARRAY:
+ /*
+ * In this case, arg is a uint64_t array. The feature is active
+ * if the array is non-null.
+ */
+ return (arg != NULL);
+ default:
+ panic("Invalid zfeature type %d", spa_feature_table[f].fi_type);
+ return (B_FALSE);
+ }
+}
+
+boolean_t
+dsl_dataset_feature_is_active(dsl_dataset_t *ds, spa_feature_t f)
+{
+ return (zfeature_active(f, ds->ds_feature[f]));
+}
+
+/*
+ * The buffers passed out by this function are references to internal buffers;
+ * they should not be freed by callers of this function, and they should not be
+ * used after the dataset has been released.
+ */
+boolean_t
+dsl_dataset_get_uint64_array_feature(dsl_dataset_t *ds, spa_feature_t f,
+ uint64_t *outlength, uint64_t **outp)
+{
+ VERIFY(spa_feature_table[f].fi_type & ZFEATURE_TYPE_UINT64_ARRAY);
+ if (!dsl_dataset_feature_is_active(ds, f)) {
+ return (B_FALSE);
+ }
+ struct feature_type_uint64_array_arg *ftuaa = ds->ds_feature[f];
+ *outp = ftuaa->array;
+ *outlength = ftuaa->length;
+ return (B_TRUE);
+}
+
void
-dsl_dataset_activate_feature(uint64_t dsobj, spa_feature_t f, dmu_tx_t *tx)
+dsl_dataset_activate_feature(uint64_t dsobj, spa_feature_t f, void *arg,
+ dmu_tx_t *tx)
{
spa_t *spa = dmu_tx_pool(tx)->dp_spa;
objset_t *mos = dmu_tx_pool(tx)->dp_meta_objset;
@@ -884,20 +1000,44 @@ dsl_dataset_activate_feature(uint64_t dsobj, spa_feature_t f, dmu_tx_t *tx)
spa_feature_incr(spa, f, tx);
dmu_object_zapify(mos, dsobj, DMU_OT_DSL_DATASET, tx);
- VERIFY0(zap_add(mos, dsobj, spa_feature_table[f].fi_guid,
- sizeof (zero), 1, &zero, tx));
+ switch (spa_feature_table[f].fi_type) {
+ case ZFEATURE_TYPE_BOOLEAN:
+ ASSERT3S((boolean_t)arg, ==, B_TRUE);
+ VERIFY0(zap_add(mos, dsobj, spa_feature_table[f].fi_guid,
+ sizeof (zero), 1, &zero, tx));
+ break;
+ case ZFEATURE_TYPE_UINT64_ARRAY:
+ {
+ struct feature_type_uint64_array_arg *ftuaa = arg;
+ VERIFY0(zap_add(mos, dsobj, spa_feature_table[f].fi_guid,
+ sizeof (uint64_t), ftuaa->length, ftuaa->array, tx));
+ break;
+ }
+ default:
+ panic("Invalid zfeature type %d", spa_feature_table[f].fi_type);
+ }
}
void
-dsl_dataset_deactivate_feature(uint64_t dsobj, spa_feature_t f, dmu_tx_t *tx)
+dsl_dataset_deactivate_feature_impl(dsl_dataset_t *ds, spa_feature_t f,
+ dmu_tx_t *tx)
{
spa_t *spa = dmu_tx_pool(tx)->dp_spa;
objset_t *mos = dmu_tx_pool(tx)->dp_meta_objset;
+ uint64_t dsobj = ds->ds_object;
VERIFY(spa_feature_table[f].fi_flags & ZFEATURE_FLAG_PER_DATASET);
VERIFY0(zap_remove(mos, dsobj, spa_feature_table[f].fi_guid, tx));
spa_feature_decr(spa, f, tx);
+ ds->ds_feature[f] = NULL;
+}
+
+void
+dsl_dataset_deactivate_feature(dsl_dataset_t *ds, spa_feature_t f, dmu_tx_t *tx)
+{
+ unload_zfeature(ds, f);
+ dsl_dataset_deactivate_feature_impl(ds, f, tx);
}
uint64_t
@@ -961,8 +1101,10 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
(DS_FLAG_INCONSISTENT | DS_FLAG_CI_DATASET);
for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
- if (origin->ds_feature_inuse[f])
- dsl_dataset_activate_feature(dsobj, f, tx);
+ if (zfeature_active(f, origin->ds_feature[f])) {
+ dsl_dataset_activate_feature(dsobj, f,
+ origin->ds_feature[f], tx);
+ }
}
dmu_buf_will_dirty(origin->ds_dbuf, tx);
@@ -1492,8 +1634,10 @@ dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
dmu_buf_rele(dbuf, FTAG);
for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
- if (ds->ds_feature_inuse[f])
- dsl_dataset_activate_feature(dsobj, f, tx);
+ if (zfeature_active(f, ds->ds_feature[f])) {
+ dsl_dataset_activate_feature(dsobj, f,
+ ds->ds_feature[f], tx);
+ }
}
ASSERT3U(ds->ds_prev != 0, ==,
@@ -1808,11 +1952,12 @@ dsl_dataset_sync(dsl_dataset_t *ds, zio_t *zio, dmu_tx_t *tx)
dmu_objset_sync(ds->ds_objset, zio, tx);
for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
- if (ds->ds_feature_activation_needed[f]) {
- if (ds->ds_feature_inuse[f])
+ if (zfeature_active(f, ds->ds_feature_activation[f])) {
+ if (zfeature_active(f, ds->ds_feature[f]))
continue;
- dsl_dataset_activate_feature(ds->ds_object, f, tx);
- ds->ds_feature_inuse[f] = B_TRUE;
+ dsl_dataset_activate_feature(ds->ds_object, f,
+ ds->ds_feature_activation[f], tx);
+ ds->ds_feature[f] = ds->ds_feature_activation[f];
}
}
}
@@ -3530,31 +3675,31 @@ dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
if (!(spa_feature_table[f].fi_flags &
ZFEATURE_FLAG_PER_DATASET)) {
- ASSERT(!clone->ds_feature_inuse[f]);
- ASSERT(!origin_head->ds_feature_inuse[f]);
+ ASSERT(!dsl_dataset_feature_is_active(clone, f));
+ ASSERT(!dsl_dataset_feature_is_active(origin_head, f));
continue;
}
- boolean_t clone_inuse = clone->ds_feature_inuse[f];
- boolean_t origin_head_inuse = origin_head->ds_feature_inuse[f];
+ boolean_t clone_inuse = dsl_dataset_feature_is_active(clone, f);
+ void *clone_feature = clone->ds_feature[f];
+ boolean_t origin_head_inuse =
+ dsl_dataset_feature_is_active(origin_head, f);
+ void *origin_head_feature = origin_head->ds_feature[f];
+
+ if (clone_inuse)
+ dsl_dataset_deactivate_feature_impl(clone, f, tx);
+ if (origin_head_inuse)
+ dsl_dataset_deactivate_feature_impl(origin_head, f, tx);
if (clone_inuse) {
- dsl_dataset_deactivate_feature(clone->ds_object, f, tx);
- clone->ds_feature_inuse[f] = B_FALSE;
- }
- if (origin_head_inuse) {
- dsl_dataset_deactivate_feature(origin_head->ds_object,
- f, tx);
- origin_head->ds_feature_inuse[f] = B_FALSE;
- }
- if (clone_inuse) {
- dsl_dataset_activate_feature(origin_head->ds_object,
- f, tx);
- origin_head->ds_feature_inuse[f] = B_TRUE;
+ dsl_dataset_activate_feature(origin_head->ds_object, f,
+ clone_feature, tx);
+ origin_head->ds_feature[f] = clone_feature;
}
if (origin_head_inuse) {
- dsl_dataset_activate_feature(clone->ds_object, f, tx);
- clone->ds_feature_inuse[f] = B_TRUE;
+ dsl_dataset_activate_feature(clone->ds_object, f,
+ origin_head_feature, tx);
+ clone->ds_feature[f] = origin_head_feature;
}
}
diff --git a/module/zfs/dsl_destroy.c b/module/zfs/dsl_destroy.c
index b80d34672..97d7befbd 100644
--- a/module/zfs/dsl_destroy.c
+++ b/module/zfs/dsl_destroy.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2017 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2013 by Joyent, Inc. All rights reserved.
* Copyright (c) 2016 Actifio, Inc. All rights reserved.
@@ -315,10 +315,8 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx)
obj = ds->ds_object;
for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
- if (ds->ds_feature_inuse[f]) {
- dsl_dataset_deactivate_feature(obj, f, tx);
- ds->ds_feature_inuse[f] = B_FALSE;
- }
+ if (dsl_dataset_feature_is_active(ds, f))
+ dsl_dataset_deactivate_feature(ds, f, tx);
}
if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) {
ASSERT3P(ds->ds_prev, ==, NULL);
@@ -869,10 +867,8 @@ dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx)
obj = ds->ds_object;
for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
- if (ds->ds_feature_inuse[f]) {
- dsl_dataset_deactivate_feature(obj, f, tx);
- ds->ds_feature_inuse[f] = B_FALSE;
- }
+ if (dsl_dataset_feature_is_active(ds, f))
+ dsl_dataset_deactivate_feature(ds, f, tx);
}
dsl_scan_ds_destroyed(ds, tx);