344 spa->spa_feat_for_write_obj = zap_create_link(spa->spa_meta_objset,
345 DMU_OTN_ZAP_METADATA, DMU_POOL_DIRECTORY_OBJECT,
346 DMU_POOL_FEATURES_FOR_WRITE, tx);
347 spa->spa_feat_desc_obj = zap_create_link(spa->spa_meta_objset,
348 DMU_OTN_ZAP_METADATA, DMU_POOL_DIRECTORY_OBJECT,
349 DMU_POOL_FEATURE_DESCRIPTIONS, tx);
350 }
351
352 /*
353 * Enable any required dependencies, then enable the requested feature.
354 */
355 void
356 spa_feature_enable(spa_t *spa, zfeature_info_t *feature, dmu_tx_t *tx)
357 {
358 ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES);
359 VERIFY3U(0, ==, feature_do_action(spa->spa_meta_objset,
360 spa->spa_feat_for_read_obj, spa->spa_feat_for_write_obj,
361 spa->spa_feat_desc_obj, feature, FEATURE_ACTION_ENABLE, tx));
362 }
363
364 /*
365 * If the specified feature has not yet been enabled, this function returns
366 * ENOTSUP; otherwise, this function increments the feature's refcount (or
367 * returns EOVERFLOW if the refcount cannot be incremented). This function must
368 * be called from syncing context.
369 */
370 void
371 spa_feature_incr(spa_t *spa, zfeature_info_t *feature, dmu_tx_t *tx)
372 {
373 ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES);
374 VERIFY3U(0, ==, feature_do_action(spa->spa_meta_objset,
375 spa->spa_feat_for_read_obj, spa->spa_feat_for_write_obj,
376 spa->spa_feat_desc_obj, feature, FEATURE_ACTION_INCR, tx));
377 }
378
379 /*
380 * If the specified feature has not yet been enabled, this function returns
381 * ENOTSUP; otherwise, this function decrements the feature's refcount (or
382 * returns EOVERFLOW if the refcount is already 0). This function must
383 * be called from syncing context.
384 */
385 void
386 spa_feature_decr(spa_t *spa, zfeature_info_t *feature, dmu_tx_t *tx)
387 {
388 ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES);
389 VERIFY3U(0, ==, feature_do_action(spa->spa_meta_objset,
390 spa->spa_feat_for_read_obj, spa->spa_feat_for_write_obj,
391 spa->spa_feat_desc_obj, feature, FEATURE_ACTION_DECR, tx));
392 }
393
394 boolean_t
395 spa_feature_is_enabled(spa_t *spa, zfeature_info_t *feature)
396 {
397 int err;
398 uint64_t refcount;
399
400 if (spa_version(spa) < SPA_VERSION_FEATURES)
401 return (B_FALSE);
402
403 err = feature_get_refcount(spa->spa_meta_objset,
404 spa->spa_feat_for_read_obj, spa->spa_feat_for_write_obj,
405 feature, &refcount);
406 ASSERT(err == 0 || err == ENOTSUP);
407 return (err == 0);
408 }
409
410 boolean_t
411 spa_feature_is_active(spa_t *spa, zfeature_info_t *feature)
412 {
413 int err;
|
344 spa->spa_feat_for_write_obj = zap_create_link(spa->spa_meta_objset,
345 DMU_OTN_ZAP_METADATA, DMU_POOL_DIRECTORY_OBJECT,
346 DMU_POOL_FEATURES_FOR_WRITE, tx);
347 spa->spa_feat_desc_obj = zap_create_link(spa->spa_meta_objset,
348 DMU_OTN_ZAP_METADATA, DMU_POOL_DIRECTORY_OBJECT,
349 DMU_POOL_FEATURE_DESCRIPTIONS, tx);
350 }
351
352 /*
353 * Enable any required dependencies, then enable the requested feature.
354 */
355 void
356 spa_feature_enable(spa_t *spa, zfeature_info_t *feature, dmu_tx_t *tx)
357 {
358 ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES);
359 VERIFY3U(0, ==, feature_do_action(spa->spa_meta_objset,
360 spa->spa_feat_for_read_obj, spa->spa_feat_for_write_obj,
361 spa->spa_feat_desc_obj, feature, FEATURE_ACTION_ENABLE, tx));
362 }
363
364 void
365 spa_feature_incr(spa_t *spa, zfeature_info_t *feature, dmu_tx_t *tx)
366 {
367 ASSERT(dmu_tx_is_syncing(tx));
368 ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES);
369 VERIFY3U(0, ==, feature_do_action(spa->spa_meta_objset,
370 spa->spa_feat_for_read_obj, spa->spa_feat_for_write_obj,
371 spa->spa_feat_desc_obj, feature, FEATURE_ACTION_INCR, tx));
372 }
373
374 void
375 spa_feature_decr(spa_t *spa, zfeature_info_t *feature, dmu_tx_t *tx)
376 {
377 ASSERT(dmu_tx_is_syncing(tx));
378 ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES);
379 VERIFY3U(0, ==, feature_do_action(spa->spa_meta_objset,
380 spa->spa_feat_for_read_obj, spa->spa_feat_for_write_obj,
381 spa->spa_feat_desc_obj, feature, FEATURE_ACTION_DECR, tx));
382 }
383
384 /*
385 * This interface is for debugging only. Normal consumers should use
386 * spa_feature_is_enabled/spa_feature_is_active.
387 */
388 int
389 spa_feature_get_refcount(spa_t *spa, zfeature_info_t *feature)
390 {
391 int err;
392 uint64_t refcount;
393
394 if (spa_version(spa) < SPA_VERSION_FEATURES)
395 return (B_FALSE);
396
397 err = feature_get_refcount(spa->spa_meta_objset,
398 spa->spa_feat_for_read_obj, spa->spa_feat_for_write_obj,
399 feature, &refcount);
400 ASSERT(err == 0 || err == ENOTSUP);
401 return (err == 0 ? refcount : 0);
402 }
403
404 boolean_t
405 spa_feature_is_enabled(spa_t *spa, zfeature_info_t *feature)
406 {
407 int err;
408 uint64_t refcount;
409
410 if (spa_version(spa) < SPA_VERSION_FEATURES)
411 return (B_FALSE);
412
413 err = feature_get_refcount(spa->spa_meta_objset,
414 spa->spa_feat_for_read_obj, spa->spa_feat_for_write_obj,
415 feature, &refcount);
416 ASSERT(err == 0 || err == ENOTSUP);
417 return (err == 0);
418 }
419
420 boolean_t
421 spa_feature_is_active(spa_t *spa, zfeature_info_t *feature)
422 {
423 int err;
|