Print this page
4171 clean up spa_feature_*() interfaces
4172 implement extensible_dataset feature for use by other zpool features
Reviewed by: Max Grossman <max.grossman@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>

*** 281,296 **** spa_close(spa, FTAG); } static void ! feature_enable_sync(void *arg, dmu_tx_t *tx) { spa_t *spa = dmu_tx_pool(tx)->dp_spa; zfeature_info_t *feature = arg; ! spa_feature_enable(spa, feature, tx); spa_history_log_internal(spa, "zhack enable feature", tx, "guid=%s can_readonly=%u", feature->fi_guid, feature->fi_can_readonly); } --- 281,297 ---- spa_close(spa, FTAG); } static void ! zhack_feature_enable_sync(void *arg, dmu_tx_t *tx) { spa_t *spa = dmu_tx_pool(tx)->dp_spa; zfeature_info_t *feature = arg; ! feature_enable_sync(spa, feature, tx); ! spa_history_log_internal(spa, "zhack enable feature", tx, "guid=%s can_readonly=%u", feature->fi_guid, feature->fi_can_readonly); }
*** 300,310 **** char c; char *desc, *target; spa_t *spa; objset_t *mos; zfeature_info_t feature; ! zfeature_info_t *nodeps[] = { NULL }; /* * Features are not added to the pool's label until their refcounts * are incremented, so fi_mos can just be left as false for now. */ --- 301,311 ---- char c; char *desc, *target; spa_t *spa; objset_t *mos; zfeature_info_t feature; ! spa_feature_t nodeps[] = { SPA_FEATURE_NONE }; /* * Features are not added to the pool's label until their refcounts * are incremented, so fi_mos can just be left as false for now. */
*** 347,364 **** fatal(NULL, FTAG, "invalid feature guid: %s", feature.fi_guid); zhack_spa_open(target, B_FALSE, FTAG, &spa); mos = spa->spa_meta_objset; ! if (0 == zfeature_lookup_guid(feature.fi_guid, NULL)) fatal(spa, FTAG, "'%s' is a real feature, will not enable"); if (0 == zap_contains(mos, spa->spa_feat_desc_obj, feature.fi_guid)) fatal(spa, FTAG, "feature already enabled: %s", feature.fi_guid); VERIFY0(dsl_sync_task(spa_name(spa), NULL, ! feature_enable_sync, &feature, 5)); spa_close(spa, FTAG); free(desc); } --- 348,365 ---- fatal(NULL, FTAG, "invalid feature guid: %s", feature.fi_guid); zhack_spa_open(target, B_FALSE, FTAG, &spa); mos = spa->spa_meta_objset; ! if (zfeature_is_supported(feature.fi_guid)) fatal(spa, FTAG, "'%s' is a real feature, will not enable"); if (0 == zap_contains(mos, spa->spa_feat_desc_obj, feature.fi_guid)) fatal(spa, FTAG, "feature already enabled: %s", feature.fi_guid); VERIFY0(dsl_sync_task(spa_name(spa), NULL, ! zhack_feature_enable_sync, &feature, 5)); spa_close(spa, FTAG); free(desc); }
*** 366,388 **** static void feature_incr_sync(void *arg, dmu_tx_t *tx) { spa_t *spa = dmu_tx_pool(tx)->dp_spa; zfeature_info_t *feature = arg; ! spa_feature_incr(spa, feature, tx); spa_history_log_internal(spa, "zhack feature incr", tx, "guid=%s", feature->fi_guid); } static void feature_decr_sync(void *arg, dmu_tx_t *tx) { spa_t *spa = dmu_tx_pool(tx)->dp_spa; zfeature_info_t *feature = arg; ! spa_feature_decr(spa, feature, tx); spa_history_log_internal(spa, "zhack feature decr", tx, "guid=%s", feature->fi_guid); } static void --- 367,393 ---- static void feature_incr_sync(void *arg, dmu_tx_t *tx) { spa_t *spa = dmu_tx_pool(tx)->dp_spa; zfeature_info_t *feature = arg; + uint64_t refcount; ! VERIFY0(feature_get_refcount(spa, feature, &refcount)); ! feature_sync(spa, feature, refcount + 1, tx); spa_history_log_internal(spa, "zhack feature incr", tx, "guid=%s", feature->fi_guid); } static void feature_decr_sync(void *arg, dmu_tx_t *tx) { spa_t *spa = dmu_tx_pool(tx)->dp_spa; zfeature_info_t *feature = arg; + uint64_t refcount; ! VERIFY0(feature_get_refcount(spa, feature, &refcount)); ! feature_sync(spa, feature, refcount - 1, tx); spa_history_log_internal(spa, "zhack feature decr", tx, "guid=%s", feature->fi_guid); } static void
*** 392,402 **** char *target; boolean_t decr = B_FALSE; spa_t *spa; objset_t *mos; zfeature_info_t feature; ! zfeature_info_t *nodeps[] = { NULL }; /* * fi_desc does not matter here because it was written to disk * when the feature was enabled, but we need to properly set the * feature for read or write based on the information we read off --- 397,407 ---- char *target; boolean_t decr = B_FALSE; spa_t *spa; objset_t *mos; zfeature_info_t feature; ! spa_feature_t nodeps[] = { SPA_FEATURE_NONE }; /* * fi_desc does not matter here because it was written to disk * when the feature was enabled, but we need to properly set the * feature for read or write based on the information we read off
*** 435,447 **** fatal(NULL, FTAG, "invalid feature guid: %s", feature.fi_guid); zhack_spa_open(target, B_FALSE, FTAG, &spa); mos = spa->spa_meta_objset; ! if (0 == zfeature_lookup_guid(feature.fi_guid, NULL)) ! fatal(spa, FTAG, "'%s' is a real feature, will not change " ! "refcount"); if (0 == zap_contains(mos, spa->spa_feat_for_read_obj, feature.fi_guid)) { feature.fi_can_readonly = B_FALSE; } else if (0 == zap_contains(mos, spa->spa_feat_for_write_obj, --- 440,453 ---- fatal(NULL, FTAG, "invalid feature guid: %s", feature.fi_guid); zhack_spa_open(target, B_FALSE, FTAG, &spa); mos = spa->spa_meta_objset; ! if (zfeature_is_supported(feature.fi_guid)) { ! fatal(spa, FTAG, ! "'%s' is a real feature, will not change refcount"); ! } if (0 == zap_contains(mos, spa->spa_feat_for_read_obj, feature.fi_guid)) { feature.fi_can_readonly = B_FALSE; } else if (0 == zap_contains(mos, spa->spa_feat_for_write_obj,
*** 449,461 **** feature.fi_can_readonly = B_TRUE; } else { fatal(spa, FTAG, "feature is not enabled: %s", feature.fi_guid); } ! if (decr && !spa_feature_is_active(spa, &feature)) fatal(spa, FTAG, "feature refcount already 0: %s", feature.fi_guid); VERIFY0(dsl_sync_task(spa_name(spa), NULL, decr ? feature_decr_sync : feature_incr_sync, &feature, 5)); spa_close(spa, FTAG); --- 455,472 ---- feature.fi_can_readonly = B_TRUE; } else { fatal(spa, FTAG, "feature is not enabled: %s", feature.fi_guid); } ! if (decr) { ! uint64_t count; ! if (feature_get_refcount(spa, &feature, &count) == 0 && ! count != 0) { fatal(spa, FTAG, "feature refcount already 0: %s", feature.fi_guid); + } + } VERIFY0(dsl_sync_task(spa_name(spa), NULL, decr ? feature_decr_sync : feature_incr_sync, &feature, 5)); spa_close(spa, FTAG);