mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
Illumos 5959 - clean up per-dataset feature count code
5959 clean up per-dataset feature count code Reviewed by: Toomas Soome <tsoome@me.com> Reviewed by: George Wilson <george@delphix.com> Reviewed by: Alex Reece <alex@delphix.com> Approved by: Richard Lowe <richlowe@richlowe.net> References: https://www.illumos.org/issues/5959 https://github.com/illumos/illumos-gate/commit/ca0cc39 Porting notes: illumos code doesn't check for feature_get_refcount() returning ENOTSUP (which means feature is disabled) in zdb. zfsonlinux added a check in https://github.com/zfsonlinux/zfs/commit/784652c due to #3468. The check was reintroduced here. Ported-by: Witaut Bajaryn <vitaut.bayaryn@gmail.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #3965
This commit is contained in:
committed by
Brian Behlendorf
parent
072484504f
commit
241b541574
@@ -1615,6 +1615,11 @@ dmu_buf_write_embedded(dmu_buf_t *dbuf, void *data,
|
||||
struct dirty_leaf *dl;
|
||||
dmu_object_type_t type;
|
||||
|
||||
if (etype == BP_EMBEDDED_TYPE_DATA) {
|
||||
ASSERT(spa_feature_is_active(dmu_objset_spa(db->db_objset),
|
||||
SPA_FEATURE_EMBEDDED_DATA));
|
||||
}
|
||||
|
||||
DB_DNODE_ENTER(db);
|
||||
type = DB_DNODE(db)->dn_type;
|
||||
DB_DNODE_EXIT(db);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
|
||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2014, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
|
||||
@@ -611,7 +611,7 @@ dmu_send_impl(void *tag, dsl_pool_t *dp, dsl_dataset_t *ds,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (large_block_ok && ds->ds_large_blocks)
|
||||
if (large_block_ok && ds->ds_feature_inuse[SPA_FEATURE_LARGE_BLOCKS])
|
||||
featureflags |= DMU_BACKUP_FEATURE_LARGE_BLOCKS;
|
||||
if (embedok &&
|
||||
spa_feature_is_active(dp->dp_spa, SPA_FEATURE_EMBEDDED_DATA)) {
|
||||
@@ -1226,13 +1226,6 @@ dmu_recv_begin_sync(void *arg, dmu_tx_t *tx)
|
||||
}
|
||||
VERIFY0(dsl_dataset_own_obj(dp, dsobj, dmu_recv_tag, &newds));
|
||||
|
||||
if ((DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
|
||||
DMU_BACKUP_FEATURE_LARGE_BLOCKS) &&
|
||||
!newds->ds_large_blocks) {
|
||||
dsl_dataset_activate_large_blocks_sync_impl(dsobj, tx);
|
||||
newds->ds_large_blocks = B_TRUE;
|
||||
}
|
||||
|
||||
dmu_buf_will_dirty(newds->ds_dbuf, tx);
|
||||
dsl_dataset_phys(newds)->ds_flags |= DS_FLAG_INCONSISTENT;
|
||||
|
||||
|
||||
+106
-92
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2015 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.
|
||||
@@ -126,8 +126,10 @@ dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
|
||||
dsl_dataset_phys(ds)->ds_compressed_bytes += compressed;
|
||||
dsl_dataset_phys(ds)->ds_uncompressed_bytes += uncompressed;
|
||||
dsl_dataset_phys(ds)->ds_unique_bytes += used;
|
||||
if (BP_GET_LSIZE(bp) > SPA_OLD_MAXBLOCKSIZE)
|
||||
ds->ds_need_large_blocks = B_TRUE;
|
||||
if (BP_GET_LSIZE(bp) > SPA_OLD_MAXBLOCKSIZE) {
|
||||
ds->ds_feature_activation_needed[SPA_FEATURE_LARGE_BLOCKS] =
|
||||
B_TRUE;
|
||||
}
|
||||
mutex_exit(&ds->ds_lock);
|
||||
dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD, delta,
|
||||
compressed, uncompressed, tx);
|
||||
@@ -432,19 +434,25 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
|
||||
offsetof(dmu_sendarg_t, dsa_link));
|
||||
|
||||
if (doi.doi_type == DMU_OTN_ZAP_METADATA) {
|
||||
int zaperr = zap_contains(mos, dsobj,
|
||||
DS_FIELD_LARGE_BLOCKS);
|
||||
if (zaperr != ENOENT) {
|
||||
VERIFY0(zaperr);
|
||||
ds->ds_large_blocks = B_TRUE;
|
||||
spa_feature_t f;
|
||||
|
||||
for (f = 0; f < SPA_FEATURES; f++) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
err = dsl_dir_hold_obj(dp,
|
||||
dsl_dataset_phys(ds)->ds_dir_obj, NULL, ds,
|
||||
&ds->ds_dir);
|
||||
}
|
||||
err = dsl_dir_hold_obj(dp,
|
||||
dsl_dataset_phys(ds)->ds_dir_obj, NULL, ds, &ds->ds_dir);
|
||||
if (err != 0) {
|
||||
mutex_destroy(&ds->ds_lock);
|
||||
mutex_destroy(&ds->ds_opening_lock);
|
||||
@@ -698,6 +706,34 @@ dsl_dataset_tryown(dsl_dataset_t *ds, void *tag)
|
||||
return (gotit);
|
||||
}
|
||||
|
||||
static void
|
||||
dsl_dataset_activate_feature(uint64_t dsobj, 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 zero = 0;
|
||||
|
||||
VERIFY(spa_feature_table[f].fi_flags & ZFEATURE_FLAG_PER_DATASET);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void
|
||||
dsl_dataset_deactivate_feature(uint64_t dsobj, 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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
|
||||
uint64_t flags, dmu_tx_t *tx)
|
||||
@@ -736,6 +772,7 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
|
||||
if (origin == NULL) {
|
||||
dsphys->ds_deadlist_obj = dsl_deadlist_alloc(mos, tx);
|
||||
} else {
|
||||
spa_feature_t f;
|
||||
dsl_dataset_t *ohds; /* head of the origin snapshot */
|
||||
|
||||
dsphys->ds_prev_snap_obj = origin->ds_object;
|
||||
@@ -756,8 +793,10 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
|
||||
dsphys->ds_flags |= dsl_dataset_phys(origin)->ds_flags &
|
||||
(DS_FLAG_INCONSISTENT | DS_FLAG_CI_DATASET);
|
||||
|
||||
if (origin->ds_large_blocks)
|
||||
dsl_dataset_activate_large_blocks_sync_impl(dsobj, tx);
|
||||
for (f = 0; f < SPA_FEATURES; f++) {
|
||||
if (origin->ds_feature_inuse[f])
|
||||
dsl_dataset_activate_feature(dsobj, f, tx);
|
||||
}
|
||||
|
||||
dmu_buf_will_dirty(origin->ds_dbuf, tx);
|
||||
dsl_dataset_phys(origin)->ds_num_children++;
|
||||
@@ -1233,6 +1272,7 @@ dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
|
||||
dsl_dataset_phys_t *dsphys;
|
||||
uint64_t dsobj, crtxg;
|
||||
objset_t *mos = dp->dp_meta_objset;
|
||||
spa_feature_t f;
|
||||
ASSERTV(static zil_header_t zero_zil);
|
||||
ASSERTV(objset_t *os);
|
||||
|
||||
@@ -1282,8 +1322,10 @@ dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
|
||||
dsphys->ds_bp = dsl_dataset_phys(ds)->ds_bp;
|
||||
dmu_buf_rele(dbuf, FTAG);
|
||||
|
||||
if (ds->ds_large_blocks)
|
||||
dsl_dataset_activate_large_blocks_sync_impl(dsobj, tx);
|
||||
for (f = 0; f < SPA_FEATURES; f++) {
|
||||
if (ds->ds_feature_inuse[f])
|
||||
dsl_dataset_activate_feature(dsobj, f, tx);
|
||||
}
|
||||
|
||||
ASSERT3U(ds->ds_prev != 0, ==,
|
||||
dsl_dataset_phys(ds)->ds_prev_snap_obj != 0);
|
||||
@@ -1561,6 +1603,8 @@ dsl_dataset_snapshot_tmp(const char *fsname, const char *snapname,
|
||||
void
|
||||
dsl_dataset_sync(dsl_dataset_t *ds, zio_t *zio, dmu_tx_t *tx)
|
||||
{
|
||||
spa_feature_t f;
|
||||
|
||||
ASSERT(dmu_tx_is_syncing(tx));
|
||||
ASSERT(ds->ds_objset != NULL);
|
||||
ASSERT(dsl_dataset_phys(ds)->ds_next_snap_obj == 0);
|
||||
@@ -1574,9 +1618,13 @@ dsl_dataset_sync(dsl_dataset_t *ds, zio_t *zio, dmu_tx_t *tx)
|
||||
|
||||
dmu_objset_sync(ds->ds_objset, zio, tx);
|
||||
|
||||
if (ds->ds_need_large_blocks && !ds->ds_large_blocks) {
|
||||
dsl_dataset_activate_large_blocks_sync_impl(ds->ds_object, tx);
|
||||
ds->ds_large_blocks = B_TRUE;
|
||||
for (f = 0; f < SPA_FEATURES; f++) {
|
||||
if (ds->ds_feature_activation_needed[f]) {
|
||||
if (ds->ds_feature_inuse[f])
|
||||
continue;
|
||||
dsl_dataset_activate_feature(ds->ds_object, f, tx);
|
||||
ds->ds_feature_inuse[f] = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2703,6 +2751,7 @@ void
|
||||
dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
|
||||
dsl_dataset_t *origin_head, dmu_tx_t *tx)
|
||||
{
|
||||
spa_feature_t f;
|
||||
dsl_pool_t *dp = dmu_tx_pool(tx);
|
||||
int64_t unused_refres_delta;
|
||||
|
||||
@@ -2711,6 +2760,43 @@ dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
|
||||
dsl_dataset_phys(clone)->ds_unique_bytes <= origin_head->ds_quota);
|
||||
ASSERT3P(clone->ds_prev, ==, origin_head->ds_prev);
|
||||
|
||||
/*
|
||||
* Swap per-dataset feature flags.
|
||||
*/
|
||||
for (f = 0; f < SPA_FEATURES; f++) {
|
||||
boolean_t clone_inuse;
|
||||
boolean_t origin_head_inuse;
|
||||
|
||||
if (!(spa_feature_table[f].fi_flags &
|
||||
ZFEATURE_FLAG_PER_DATASET)) {
|
||||
ASSERT(!clone->ds_feature_inuse[f]);
|
||||
ASSERT(!origin_head->ds_feature_inuse[f]);
|
||||
continue;
|
||||
}
|
||||
|
||||
clone_inuse = clone->ds_feature_inuse[f];
|
||||
origin_head_inuse = origin_head->ds_feature_inuse[f];
|
||||
|
||||
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;
|
||||
}
|
||||
if (origin_head_inuse) {
|
||||
dsl_dataset_activate_feature(clone->ds_object, f, tx);
|
||||
clone->ds_feature_inuse[f] = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
dmu_buf_will_dirty(clone->ds_dbuf, tx);
|
||||
dmu_buf_will_dirty(origin_head->ds_dbuf, tx);
|
||||
|
||||
@@ -3265,77 +3351,6 @@ dsl_dataset_space_wouldfree(dsl_dataset_t *firstsnap,
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
dsl_dataset_activate_large_blocks_check(void *arg, dmu_tx_t *tx)
|
||||
{
|
||||
const char *dsname = arg;
|
||||
dsl_dataset_t *ds;
|
||||
dsl_pool_t *dp = dmu_tx_pool(tx);
|
||||
int error = 0;
|
||||
|
||||
if (!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_LARGE_BLOCKS))
|
||||
return (SET_ERROR(ENOTSUP));
|
||||
|
||||
ASSERT(spa_feature_is_enabled(dp->dp_spa,
|
||||
SPA_FEATURE_EXTENSIBLE_DATASET));
|
||||
|
||||
error = dsl_dataset_hold(dp, dsname, FTAG, &ds);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
if (ds->ds_large_blocks)
|
||||
error = EALREADY;
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
void
|
||||
dsl_dataset_activate_large_blocks_sync_impl(uint64_t dsobj, 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 zero = 0;
|
||||
|
||||
spa_feature_incr(spa, SPA_FEATURE_LARGE_BLOCKS, tx);
|
||||
dmu_object_zapify(mos, dsobj, DMU_OT_DSL_DATASET, tx);
|
||||
|
||||
VERIFY0(zap_add(mos, dsobj, DS_FIELD_LARGE_BLOCKS,
|
||||
sizeof (zero), 1, &zero, tx));
|
||||
}
|
||||
|
||||
static void
|
||||
dsl_dataset_activate_large_blocks_sync(void *arg, dmu_tx_t *tx)
|
||||
{
|
||||
const char *dsname = arg;
|
||||
dsl_dataset_t *ds;
|
||||
|
||||
VERIFY0(dsl_dataset_hold(dmu_tx_pool(tx), dsname, FTAG, &ds));
|
||||
|
||||
dsl_dataset_activate_large_blocks_sync_impl(ds->ds_object, tx);
|
||||
ASSERT(!ds->ds_large_blocks);
|
||||
ds->ds_large_blocks = B_TRUE;
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
}
|
||||
|
||||
int
|
||||
dsl_dataset_activate_large_blocks(const char *dsname)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = dsl_sync_task(dsname,
|
||||
dsl_dataset_activate_large_blocks_check,
|
||||
dsl_dataset_activate_large_blocks_sync, (void *)dsname,
|
||||
1, ZFS_SPACE_CHECK_RESERVED);
|
||||
|
||||
/*
|
||||
* EALREADY indicates that this dataset already supports large blocks.
|
||||
*/
|
||||
if (error == EALREADY)
|
||||
error = 0;
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if 'earlier' is an earlier snapshot in 'later's timeline.
|
||||
* For example, they could both be snapshots of the same filesystem, and
|
||||
@@ -3380,7 +3395,6 @@ dsl_dataset_is_before(dsl_dataset_t *later, dsl_dataset_t *earlier,
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dsl_dataset_zapify(dsl_dataset_t *ds, dmu_tx_t *tx)
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||
* Copyright (c) 2013 by Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
@@ -246,6 +246,7 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx)
|
||||
#ifdef ZFS_DEBUG
|
||||
int err;
|
||||
#endif
|
||||
spa_feature_t f;
|
||||
int after_branch_point = FALSE;
|
||||
dsl_pool_t *dp = ds->ds_dir->dd_pool;
|
||||
objset_t *mos = dp->dp_meta_objset;
|
||||
@@ -277,9 +278,11 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx)
|
||||
|
||||
obj = ds->ds_object;
|
||||
|
||||
if (ds->ds_large_blocks) {
|
||||
ASSERT0(zap_contains(mos, obj, DS_FIELD_LARGE_BLOCKS));
|
||||
spa_feature_decr(dp->dp_spa, SPA_FEATURE_LARGE_BLOCKS, tx);
|
||||
for (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_phys(ds)->ds_prev_snap_obj != 0) {
|
||||
ASSERT3P(ds->ds_prev, ==, NULL);
|
||||
@@ -715,6 +718,7 @@ void
|
||||
dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx)
|
||||
{
|
||||
dsl_pool_t *dp = dmu_tx_pool(tx);
|
||||
spa_feature_t f;
|
||||
objset_t *mos = dp->dp_meta_objset;
|
||||
uint64_t obj, ddobj, prevobj = 0;
|
||||
boolean_t rmorigin;
|
||||
@@ -742,13 +746,17 @@ dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx)
|
||||
ASSERT0(ds->ds_reserved);
|
||||
}
|
||||
|
||||
if (ds->ds_large_blocks)
|
||||
spa_feature_decr(dp->dp_spa, SPA_FEATURE_LARGE_BLOCKS, tx);
|
||||
obj = ds->ds_object;
|
||||
|
||||
for (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;
|
||||
}
|
||||
}
|
||||
|
||||
dsl_scan_ds_destroyed(ds, tx);
|
||||
|
||||
obj = ds->ds_object;
|
||||
|
||||
if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) {
|
||||
/* This is a clone */
|
||||
ASSERT(ds->ds_prev != NULL);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/zfs_context.h>
|
||||
@@ -253,7 +253,7 @@ feature_get_refcount_from_disk(spa_t *spa, zfeature_info_t *feature,
|
||||
{
|
||||
int err;
|
||||
uint64_t refcount;
|
||||
uint64_t zapobj = feature->fi_can_readonly ?
|
||||
uint64_t zapobj = (feature->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
|
||||
spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj;
|
||||
|
||||
/*
|
||||
@@ -306,7 +306,7 @@ feature_sync(spa_t *spa, zfeature_info_t *feature, uint64_t refcount,
|
||||
uint64_t zapobj;
|
||||
|
||||
ASSERT(VALID_FEATURE_OR_NONE(feature->fi_feature));
|
||||
zapobj = feature->fi_can_readonly ?
|
||||
zapobj = (feature->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
|
||||
spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj;
|
||||
VERIFY0(zap_update(spa->spa_meta_objset, zapobj, feature->fi_guid,
|
||||
sizeof (uint64_t), 1, &refcount, tx));
|
||||
@@ -327,7 +327,7 @@ feature_sync(spa_t *spa, zfeature_info_t *feature, uint64_t refcount,
|
||||
|
||||
if (refcount == 0)
|
||||
spa_deactivate_mos_feature(spa, feature->fi_guid);
|
||||
else if (feature->fi_mos)
|
||||
else if (feature->fi_flags & ZFEATURE_FLAG_MOS)
|
||||
spa_activate_mos_feature(spa, feature->fi_guid, tx);
|
||||
}
|
||||
|
||||
@@ -338,8 +338,9 @@ feature_sync(spa_t *spa, zfeature_info_t *feature, uint64_t refcount,
|
||||
void
|
||||
feature_enable_sync(spa_t *spa, zfeature_info_t *feature, dmu_tx_t *tx)
|
||||
{
|
||||
uint64_t initial_refcount = feature->fi_activate_on_enable ? 1 : 0;
|
||||
uint64_t zapobj = feature->fi_can_readonly ?
|
||||
uint64_t initial_refcount =
|
||||
(feature->fi_flags & ZFEATURE_FLAG_ACTIVATE_ON_ENABLE) ? 1 : 0;
|
||||
uint64_t zapobj = (feature->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
|
||||
spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj;
|
||||
int i;
|
||||
|
||||
@@ -385,7 +386,8 @@ feature_do_action(spa_t *spa, spa_feature_t fid, feature_action_t action,
|
||||
{
|
||||
uint64_t refcount = 0;
|
||||
zfeature_info_t *feature = &spa_feature_table[fid];
|
||||
ASSERTV(uint64_t zapobj = feature->fi_can_readonly ?
|
||||
ASSERTV(uint64_t zapobj =
|
||||
(feature->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
|
||||
spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj);
|
||||
|
||||
ASSERT(VALID_FEATURE_FID(fid));
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
||||
* Copyright (c) 2014, Nexenta Systems, Inc. All rights reserved.
|
||||
*/
|
||||
@@ -135,15 +135,15 @@ zfeature_depends_on(spa_feature_t fid, spa_feature_t check) {
|
||||
|
||||
static void
|
||||
zfeature_register(spa_feature_t fid, const char *guid, const char *name,
|
||||
const char *desc, boolean_t readonly, boolean_t mos,
|
||||
boolean_t activate_on_enable, const spa_feature_t *deps)
|
||||
const char *desc, zfeature_flags_t flags, const spa_feature_t *deps)
|
||||
{
|
||||
zfeature_info_t *feature = &spa_feature_table[fid];
|
||||
static spa_feature_t nodeps[] = { SPA_FEATURE_NONE };
|
||||
|
||||
ASSERT(name != NULL);
|
||||
ASSERT(desc != NULL);
|
||||
ASSERT(!readonly || !mos);
|
||||
ASSERT((flags & ZFEATURE_FLAG_READONLY_COMPAT) == 0 ||
|
||||
(flags & ZFEATURE_FLAG_MOS) == 0);
|
||||
ASSERT3U(fid, <, SPA_FEATURES);
|
||||
ASSERT(zfeature_is_valid_guid(guid));
|
||||
|
||||
@@ -154,9 +154,7 @@ zfeature_register(spa_feature_t fid, const char *guid, const char *name,
|
||||
feature->fi_guid = guid;
|
||||
feature->fi_uname = name;
|
||||
feature->fi_desc = desc;
|
||||
feature->fi_can_readonly = readonly;
|
||||
feature->fi_mos = mos;
|
||||
feature->fi_activate_on_enable = activate_on_enable;
|
||||
feature->fi_flags = flags;
|
||||
feature->fi_depends = deps;
|
||||
}
|
||||
|
||||
@@ -165,28 +163,28 @@ zpool_feature_init(void)
|
||||
{
|
||||
zfeature_register(SPA_FEATURE_ASYNC_DESTROY,
|
||||
"com.delphix:async_destroy", "async_destroy",
|
||||
"Destroy filesystems asynchronously.", B_TRUE, B_FALSE,
|
||||
B_FALSE, NULL);
|
||||
"Destroy filesystems asynchronously.",
|
||||
ZFEATURE_FLAG_READONLY_COMPAT, NULL);
|
||||
|
||||
zfeature_register(SPA_FEATURE_EMPTY_BPOBJ,
|
||||
"com.delphix:empty_bpobj", "empty_bpobj",
|
||||
"Snapshots use less space.", B_TRUE, B_FALSE,
|
||||
B_FALSE, NULL);
|
||||
"Snapshots use less space.",
|
||||
ZFEATURE_FLAG_READONLY_COMPAT, NULL);
|
||||
|
||||
zfeature_register(SPA_FEATURE_LZ4_COMPRESS,
|
||||
"org.illumos:lz4_compress", "lz4_compress",
|
||||
"LZ4 compression algorithm support.", B_FALSE, B_FALSE,
|
||||
B_TRUE, NULL);
|
||||
"LZ4 compression algorithm support.",
|
||||
ZFEATURE_FLAG_ACTIVATE_ON_ENABLE, NULL);
|
||||
|
||||
zfeature_register(SPA_FEATURE_SPACEMAP_HISTOGRAM,
|
||||
"com.delphix:spacemap_histogram", "spacemap_histogram",
|
||||
"Spacemaps maintain space histograms.", B_TRUE, B_FALSE,
|
||||
B_FALSE, NULL);
|
||||
"Spacemaps maintain space histograms.",
|
||||
ZFEATURE_FLAG_READONLY_COMPAT, NULL);
|
||||
|
||||
zfeature_register(SPA_FEATURE_ENABLED_TXG,
|
||||
"com.delphix:enabled_txg", "enabled_txg",
|
||||
"Record txg at which a feature is enabled", B_TRUE, B_FALSE,
|
||||
B_FALSE, NULL);
|
||||
"Record txg at which a feature is enabled",
|
||||
ZFEATURE_FLAG_READONLY_COMPAT, NULL);
|
||||
|
||||
{
|
||||
static const spa_feature_t hole_birth_deps[] = {
|
||||
@@ -196,13 +194,14 @@ zpool_feature_init(void)
|
||||
zfeature_register(SPA_FEATURE_HOLE_BIRTH,
|
||||
"com.delphix:hole_birth", "hole_birth",
|
||||
"Retain hole birth txg for more precise zfs send",
|
||||
B_FALSE, B_TRUE, B_TRUE, hole_birth_deps);
|
||||
ZFEATURE_FLAG_MOS | ZFEATURE_FLAG_ACTIVATE_ON_ENABLE,
|
||||
hole_birth_deps);
|
||||
}
|
||||
|
||||
zfeature_register(SPA_FEATURE_EXTENSIBLE_DATASET,
|
||||
"com.delphix:extensible_dataset", "extensible_dataset",
|
||||
"Enhanced dataset functionality, used by other features.",
|
||||
B_FALSE, B_FALSE, B_FALSE, NULL);
|
||||
0, NULL);
|
||||
|
||||
{
|
||||
static const spa_feature_t bookmarks_deps[] = {
|
||||
@@ -213,7 +212,7 @@ zpool_feature_init(void)
|
||||
zfeature_register(SPA_FEATURE_BOOKMARKS,
|
||||
"com.delphix:bookmarks", "bookmarks",
|
||||
"\"zfs bookmark\" command",
|
||||
B_TRUE, B_FALSE, B_FALSE, bookmarks_deps);
|
||||
ZFEATURE_FLAG_READONLY_COMPAT, bookmarks_deps);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -223,14 +222,15 @@ zpool_feature_init(void)
|
||||
};
|
||||
zfeature_register(SPA_FEATURE_FS_SS_LIMIT,
|
||||
"com.joyent:filesystem_limits", "filesystem_limits",
|
||||
"Filesystem and snapshot limits.", B_TRUE, B_FALSE, B_FALSE,
|
||||
filesystem_limits_deps);
|
||||
"Filesystem and snapshot limits.",
|
||||
ZFEATURE_FLAG_READONLY_COMPAT, filesystem_limits_deps);
|
||||
}
|
||||
|
||||
zfeature_register(SPA_FEATURE_EMBEDDED_DATA,
|
||||
"com.delphix:embedded_data", "embedded_data",
|
||||
"Blocks which compress very well use even less space.",
|
||||
B_FALSE, B_TRUE, B_TRUE, NULL);
|
||||
ZFEATURE_FLAG_MOS | ZFEATURE_FLAG_ACTIVATE_ON_ENABLE,
|
||||
NULL);
|
||||
|
||||
{
|
||||
static const spa_feature_t large_blocks_deps[] = {
|
||||
@@ -239,7 +239,7 @@ zpool_feature_init(void)
|
||||
};
|
||||
zfeature_register(SPA_FEATURE_LARGE_BLOCKS,
|
||||
"org.open-zfs:large_blocks", "large_blocks",
|
||||
"Support for blocks larger than 128KB.", B_FALSE, B_FALSE, B_FALSE,
|
||||
large_blocks_deps);
|
||||
"Support for blocks larger than 128KB.",
|
||||
ZFEATURE_FLAG_PER_DATASET, large_blocks_deps);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user