153089ab7Seschrock /* 253089ab7Seschrock * CDDL HEADER START 353089ab7Seschrock * 453089ab7Seschrock * The contents of this file are subject to the terms of the 553089ab7Seschrock * Common Development and Distribution License (the "License"). 653089ab7Seschrock * You may not use this file except in compliance with the License. 753089ab7Seschrock * 853089ab7Seschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 953089ab7Seschrock * or http://www.opensolaris.org/os/licensing. 1053089ab7Seschrock * See the License for the specific language governing permissions 1153089ab7Seschrock * and limitations under the License. 1253089ab7Seschrock * 1353089ab7Seschrock * When distributing Covered Code, include this CDDL HEADER in each 1453089ab7Seschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1553089ab7Seschrock * If applicable, add the following below this CDDL HEADER, with the 1653089ab7Seschrock * fields enclosed by brackets "[]" replaced with your own identifying 1753089ab7Seschrock * information: Portions Copyright [yyyy] [name of copyright owner] 1853089ab7Seschrock * 1953089ab7Seschrock * CDDL HEADER END 2053089ab7Seschrock */ 2153089ab7Seschrock 2253089ab7Seschrock /* 23ca0cc391SMatthew Ahrens * Copyright (c) 2011, 2015 by Delphix. All rights reserved. 2453089ab7Seschrock */ 2553089ab7Seschrock 2653089ab7Seschrock #include <sys/zfs_context.h> 2753089ab7Seschrock #include <sys/zfeature.h> 2853089ab7Seschrock #include <sys/dmu.h> 2953089ab7Seschrock #include <sys/nvpair.h> 3053089ab7Seschrock #include <sys/zap.h> 3153089ab7Seschrock #include <sys/dmu_tx.h> 3253089ab7Seschrock #include "zfeature_common.h" 3353089ab7Seschrock #include <sys/spa_impl.h> 3453089ab7Seschrock 3553089ab7Seschrock /* 3653089ab7Seschrock * ZFS Feature Flags 3753089ab7Seschrock * ----------------- 3853089ab7Seschrock * 3953089ab7Seschrock * ZFS feature flags are used to provide fine-grained versioning to the ZFS 4053089ab7Seschrock * on-disk format. Once enabled on a pool feature flags replace the old 4153089ab7Seschrock * spa_version() number. 4253089ab7Seschrock * 4353089ab7Seschrock * Each new on-disk format change will be given a uniquely identifying string 4453089ab7Seschrock * guid rather than a version number. This avoids the problem of different 4553089ab7Seschrock * organizations creating new on-disk formats with the same version number. To 4653089ab7Seschrock * keep feature guids unique they should consist of the reverse dns name of the 4753089ab7Seschrock * organization which implemented the feature and a short name for the feature, 4853089ab7Seschrock * separated by a colon (e.g. com.delphix:async_destroy). 4953089ab7Seschrock * 5053089ab7Seschrock * Reference Counts 5153089ab7Seschrock * ---------------- 5253089ab7Seschrock * 5353089ab7Seschrock * Within each pool features can be in one of three states: disabled, enabled, 5453089ab7Seschrock * or active. These states are differentiated by a reference count stored on 5553089ab7Seschrock * disk for each feature: 5653089ab7Seschrock * 5753089ab7Seschrock * 1) If there is no reference count stored on disk the feature is disabled. 5853089ab7Seschrock * 2) If the reference count is 0 a system administrator has enabled the 5953089ab7Seschrock * feature, but the feature has not been used yet, so no on-disk 6053089ab7Seschrock * format changes have been made. 6153089ab7Seschrock * 3) If the reference count is greater than 0 the feature is active. 6253089ab7Seschrock * The format changes required by the feature are currently on disk. 6353089ab7Seschrock * Note that if the feature's format changes are reversed the feature 6453089ab7Seschrock * may choose to set its reference count back to 0. 6553089ab7Seschrock * 6653089ab7Seschrock * Feature flags makes no differentiation between non-zero reference counts 6753089ab7Seschrock * for an active feature (e.g. a reference count of 1 means the same thing as a 6853089ab7Seschrock * reference count of 27834721), but feature implementations may choose to use 6953089ab7Seschrock * the reference count to store meaningful information. For example, a new RAID 7053089ab7Seschrock * implementation might set the reference count to the number of vdevs using 7153089ab7Seschrock * it. If all those disks are removed from the pool the feature goes back to 7253089ab7Seschrock * having a reference count of 0. 7353089ab7Seschrock * 7453089ab7Seschrock * It is the responsibility of the individual features to maintain a non-zero 7553089ab7Seschrock * reference count as long as the feature's format changes are present on disk. 7653089ab7Seschrock * 7753089ab7Seschrock * Dependencies 7853089ab7Seschrock * ------------ 7953089ab7Seschrock * 8053089ab7Seschrock * Each feature may depend on other features. The only effect of this 8153089ab7Seschrock * relationship is that when a feature is enabled all of its dependencies are 8253089ab7Seschrock * automatically enabled as well. Any future work to support disabling of 8353089ab7Seschrock * features would need to ensure that features cannot be disabled if other 8453089ab7Seschrock * enabled features depend on them. 8553089ab7Seschrock * 8653089ab7Seschrock * On-disk Format 8753089ab7Seschrock * -------------- 8853089ab7Seschrock * 8953089ab7Seschrock * When feature flags are enabled spa_version() is set to SPA_VERSION_FEATURES 9053089ab7Seschrock * (5000). In order for this to work the pool is automatically upgraded to 9153089ab7Seschrock * SPA_VERSION_BEFORE_FEATURES (28) first, so all pre-feature flags on disk 9253089ab7Seschrock * format changes will be in use. 9353089ab7Seschrock * 9453089ab7Seschrock * Information about features is stored in 3 ZAP objects in the pool's MOS. 9553089ab7Seschrock * These objects are linked to by the following names in the pool directory 9653089ab7Seschrock * object: 9753089ab7Seschrock * 9853089ab7Seschrock * 1) features_for_read: feature guid -> reference count 9953089ab7Seschrock * Features needed to open the pool for reading. 10053089ab7Seschrock * 2) features_for_write: feature guid -> reference count 10153089ab7Seschrock * Features needed to open the pool for writing. 10253089ab7Seschrock * 3) feature_descriptions: feature guid -> descriptive string 10353089ab7Seschrock * A human readable string. 10453089ab7Seschrock * 10553089ab7Seschrock * All enabled features appear in either features_for_read or 10653089ab7Seschrock * features_for_write, but not both. 10753089ab7Seschrock * 10853089ab7Seschrock * To open a pool in read-only mode only the features listed in 10953089ab7Seschrock * features_for_read need to be supported. 11053089ab7Seschrock * 11153089ab7Seschrock * To open the pool in read-write mode features in both features_for_read and 11253089ab7Seschrock * features_for_write need to be supported. 11353089ab7Seschrock * 11453089ab7Seschrock * Some features may be required to read the ZAP objects containing feature 11553089ab7Seschrock * information. To allow software to check for compatibility with these features 11653089ab7Seschrock * before the pool is opened their names must be stored in the label in a 11753089ab7Seschrock * new "features_for_read" entry (note that features that are only required 11853089ab7Seschrock * to write to a pool never need to be stored in the label since the 11953089ab7Seschrock * features_for_write ZAP object can be read before the pool is written to). 12053089ab7Seschrock * To save space in the label features must be explicitly marked as needing to 12153089ab7Seschrock * be written to the label. Also, reference counts are not stored in the label, 12253089ab7Seschrock * instead any feature whose reference count drops to 0 is removed from the 12353089ab7Seschrock * label. 12453089ab7Seschrock * 12553089ab7Seschrock * Adding New Features 12653089ab7Seschrock * ------------------- 12753089ab7Seschrock * 12853089ab7Seschrock * Features must be registered in zpool_feature_init() function in 12953089ab7Seschrock * zfeature_common.c using the zfeature_register() function. This function 13053089ab7Seschrock * has arguments to specify if the feature should be stored in the 13153089ab7Seschrock * features_for_read or features_for_write ZAP object and if it needs to be 13253089ab7Seschrock * written to the label when active. 13353089ab7Seschrock * 13453089ab7Seschrock * Once a feature is registered it will appear as a "feature@<feature name>" 13553089ab7Seschrock * property which can be set by an administrator. Feature implementors should 13653089ab7Seschrock * use the spa_feature_is_enabled() and spa_feature_is_active() functions to 13753089ab7Seschrock * query the state of a feature and the spa_feature_incr() and 13853089ab7Seschrock * spa_feature_decr() functions to change an enabled feature's reference count. 13953089ab7Seschrock * Reference counts may only be updated in the syncing context. 14053089ab7Seschrock * 14153089ab7Seschrock * Features may not perform enable-time initialization. Instead, any such 14253089ab7Seschrock * initialization should occur when the feature is first used. This design 14353089ab7Seschrock * enforces that on-disk changes be made only when features are used. Code 14453089ab7Seschrock * should only check if a feature is enabled using spa_feature_is_enabled(), 14553089ab7Seschrock * not by relying on any feature specific metadata existing. If a feature is 14653089ab7Seschrock * enabled, but the feature's metadata is not on disk yet then it should be 14753089ab7Seschrock * created as needed. 14853089ab7Seschrock * 14953089ab7Seschrock * As an example, consider the com.delphix:async_destroy feature. This feature 15053089ab7Seschrock * relies on the existence of a bptree in the MOS that store blocks for 15153089ab7Seschrock * asynchronous freeing. This bptree is not created when async_destroy is 15253089ab7Seschrock * enabled. Instead, when a dataset is destroyed spa_feature_is_enabled() is 15353089ab7Seschrock * called to check if async_destroy is enabled. If it is and the bptree object 15453089ab7Seschrock * does not exist yet, the bptree object is created as part of the dataset 15553089ab7Seschrock * destroy and async_destroy's reference count is incremented to indicate it 15653089ab7Seschrock * has made an on-disk format change. Later, after the destroyed dataset's 15753089ab7Seschrock * blocks have all been asynchronously freed there is no longer any use for the 15853089ab7Seschrock * bptree object, so it is destroyed and async_destroy's reference count is 15953089ab7Seschrock * decremented back to 0 to indicate that it has undone its on-disk format 16053089ab7Seschrock * changes. 16153089ab7Seschrock */ 16253089ab7Seschrock 16353089ab7Seschrock typedef enum { 16453089ab7Seschrock FEATURE_ACTION_INCR, 16553089ab7Seschrock FEATURE_ACTION_DECR, 16653089ab7Seschrock } feature_action_t; 16753089ab7Seschrock 16853089ab7Seschrock /* 1692acef22dSMatthew Ahrens * Checks that the active features in the pool are supported by 17053089ab7Seschrock * this software. Adds each unsupported feature (name -> description) to 17153089ab7Seschrock * the supplied nvlist. 17253089ab7Seschrock */ 17353089ab7Seschrock boolean_t 1742acef22dSMatthew Ahrens spa_features_check(spa_t *spa, boolean_t for_write, 17557221772SChristopher Siden nvlist_t *unsup_feat, nvlist_t *enabled_feat) 17653089ab7Seschrock { 1772acef22dSMatthew Ahrens objset_t *os = spa->spa_meta_objset; 17853089ab7Seschrock boolean_t supported; 17953089ab7Seschrock zap_cursor_t zc; 18053089ab7Seschrock zap_attribute_t za; 1812acef22dSMatthew Ahrens uint64_t obj = for_write ? 1822acef22dSMatthew Ahrens spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj; 18353089ab7Seschrock 18453089ab7Seschrock supported = B_TRUE; 18553089ab7Seschrock for (zap_cursor_init(&zc, os, obj); 18653089ab7Seschrock zap_cursor_retrieve(&zc, &za) == 0; 18753089ab7Seschrock zap_cursor_advance(&zc)) { 18853089ab7Seschrock ASSERT(za.za_integer_length == sizeof (uint64_t) && 18953089ab7Seschrock za.za_num_integers == 1); 19053089ab7Seschrock 19157221772SChristopher Siden if (NULL != enabled_feat) { 19257221772SChristopher Siden fnvlist_add_uint64(enabled_feat, za.za_name, 19357221772SChristopher Siden za.za_first_integer); 19457221772SChristopher Siden } 19557221772SChristopher Siden 19653089ab7Seschrock if (za.za_first_integer != 0 && 19753089ab7Seschrock !zfeature_is_supported(za.za_name)) { 19853089ab7Seschrock supported = B_FALSE; 19953089ab7Seschrock 20057221772SChristopher Siden if (NULL != unsup_feat) { 20153089ab7Seschrock char *desc = ""; 20253089ab7Seschrock char buf[MAXPATHLEN]; 20353089ab7Seschrock 2042acef22dSMatthew Ahrens if (zap_lookup(os, spa->spa_feat_desc_obj, 2052acef22dSMatthew Ahrens za.za_name, 1, sizeof (buf), buf) == 0) 20653089ab7Seschrock desc = buf; 20753089ab7Seschrock 20853089ab7Seschrock VERIFY(nvlist_add_string(unsup_feat, za.za_name, 20953089ab7Seschrock desc) == 0); 21053089ab7Seschrock } 21153089ab7Seschrock } 21253089ab7Seschrock } 21353089ab7Seschrock zap_cursor_fini(&zc); 21453089ab7Seschrock 21553089ab7Seschrock return (supported); 21653089ab7Seschrock } 21753089ab7Seschrock 2182acef22dSMatthew Ahrens /* 21943466aaeSMax Grossman * Use an in-memory cache of feature refcounts for quick retrieval. 22043466aaeSMax Grossman * 2212acef22dSMatthew Ahrens * Note: well-designed features will not need to use this; they should 2222acef22dSMatthew Ahrens * use spa_feature_is_enabled() and spa_feature_is_active() instead. 2232acef22dSMatthew Ahrens * However, this is non-static for zdb and zhack. 2242acef22dSMatthew Ahrens */ 2252acef22dSMatthew Ahrens int 2262acef22dSMatthew Ahrens feature_get_refcount(spa_t *spa, zfeature_info_t *feature, uint64_t *res) 22753089ab7Seschrock { 22843466aaeSMax Grossman ASSERT(VALID_FEATURE_FID(feature->fi_feature)); 22943466aaeSMax Grossman if (spa->spa_feat_refcount_cache[feature->fi_feature] == 23043466aaeSMax Grossman SPA_FEATURE_DISABLED) { 23143466aaeSMax Grossman return (SET_ERROR(ENOTSUP)); 23243466aaeSMax Grossman } 23343466aaeSMax Grossman *res = spa->spa_feat_refcount_cache[feature->fi_feature]; 23443466aaeSMax Grossman return (0); 23543466aaeSMax Grossman } 23643466aaeSMax Grossman 23743466aaeSMax Grossman /* 23843466aaeSMax Grossman * Note: well-designed features will not need to use this; they should 23943466aaeSMax Grossman * use spa_feature_is_enabled() and spa_feature_is_active() instead. 24043466aaeSMax Grossman * However, this is non-static for zdb and zhack. 24143466aaeSMax Grossman */ 24243466aaeSMax Grossman int 24343466aaeSMax Grossman feature_get_refcount_from_disk(spa_t *spa, zfeature_info_t *feature, 24443466aaeSMax Grossman uint64_t *res) 24543466aaeSMax Grossman { 24653089ab7Seschrock int err; 24753089ab7Seschrock uint64_t refcount; 248ca0cc391SMatthew Ahrens uint64_t zapobj = (feature->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 2492acef22dSMatthew Ahrens spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj; 25053089ab7Seschrock 251f1745736SMatthew Ahrens /* 252f1745736SMatthew Ahrens * If the pool is currently being created, the feature objects may not 253f1745736SMatthew Ahrens * have been allocated yet. Act as though all features are disabled. 254f1745736SMatthew Ahrens */ 255f1745736SMatthew Ahrens if (zapobj == 0) 256be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 25753089ab7Seschrock 2582acef22dSMatthew Ahrens err = zap_lookup(spa->spa_meta_objset, zapobj, 2592acef22dSMatthew Ahrens feature->fi_guid, sizeof (uint64_t), 1, &refcount); 26053089ab7Seschrock if (err != 0) { 26153089ab7Seschrock if (err == ENOENT) 262be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 26353089ab7Seschrock else 26453089ab7Seschrock return (err); 26553089ab7Seschrock } 26653089ab7Seschrock *res = refcount; 26753089ab7Seschrock return (0); 26853089ab7Seschrock } 26953089ab7Seschrock 27043466aaeSMax Grossman 27143466aaeSMax Grossman static int 272*9a686fbcSPaul Dagnelie feature_get_enabled_txg(spa_t *spa, zfeature_info_t *feature, uint64_t *res) 273*9a686fbcSPaul Dagnelie { 27443466aaeSMax Grossman uint64_t enabled_txg_obj = spa->spa_feat_enabled_txg_obj; 27543466aaeSMax Grossman 27643466aaeSMax Grossman ASSERT(zfeature_depends_on(feature->fi_feature, 27743466aaeSMax Grossman SPA_FEATURE_ENABLED_TXG)); 27843466aaeSMax Grossman 27943466aaeSMax Grossman if (!spa_feature_is_enabled(spa, feature->fi_feature)) { 28043466aaeSMax Grossman return (SET_ERROR(ENOTSUP)); 28143466aaeSMax Grossman } 28243466aaeSMax Grossman 28343466aaeSMax Grossman ASSERT(enabled_txg_obj != 0); 28443466aaeSMax Grossman 28543466aaeSMax Grossman VERIFY0(zap_lookup(spa->spa_meta_objset, spa->spa_feat_enabled_txg_obj, 28643466aaeSMax Grossman feature->fi_guid, sizeof (uint64_t), 1, res)); 28743466aaeSMax Grossman 28843466aaeSMax Grossman return (0); 28943466aaeSMax Grossman } 29043466aaeSMax Grossman 2912acef22dSMatthew Ahrens /* 2922acef22dSMatthew Ahrens * This function is non-static for zhack; it should otherwise not be used 2932acef22dSMatthew Ahrens * outside this file. 2942acef22dSMatthew Ahrens */ 2952acef22dSMatthew Ahrens void 2962acef22dSMatthew Ahrens feature_sync(spa_t *spa, zfeature_info_t *feature, uint64_t refcount, 29753089ab7Seschrock dmu_tx_t *tx) 29853089ab7Seschrock { 29943466aaeSMax Grossman ASSERT(VALID_FEATURE_OR_NONE(feature->fi_feature)); 300ca0cc391SMatthew Ahrens uint64_t zapobj = (feature->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 3012acef22dSMatthew Ahrens spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj; 3022acef22dSMatthew Ahrens 3032acef22dSMatthew Ahrens VERIFY0(zap_update(spa->spa_meta_objset, zapobj, feature->fi_guid, 3042acef22dSMatthew Ahrens sizeof (uint64_t), 1, &refcount, tx)); 3052acef22dSMatthew Ahrens 30643466aaeSMax Grossman /* 30743466aaeSMax Grossman * feature_sync is called directly from zhack, allowing the 30843466aaeSMax Grossman * creation of arbitrary features whose fi_feature field may 30943466aaeSMax Grossman * be greater than SPA_FEATURES. When called from zhack, the 31043466aaeSMax Grossman * zfeature_info_t object's fi_feature field will be set to 31143466aaeSMax Grossman * SPA_FEATURE_NONE. 31243466aaeSMax Grossman */ 31343466aaeSMax Grossman if (feature->fi_feature != SPA_FEATURE_NONE) { 31443466aaeSMax Grossman uint64_t *refcount_cache = 31543466aaeSMax Grossman &spa->spa_feat_refcount_cache[feature->fi_feature]; 31643466aaeSMax Grossman VERIFY3U(*refcount_cache, ==, 31743466aaeSMax Grossman atomic_swap_64(refcount_cache, refcount)); 31843466aaeSMax Grossman } 31943466aaeSMax Grossman 3202acef22dSMatthew Ahrens if (refcount == 0) 3212acef22dSMatthew Ahrens spa_deactivate_mos_feature(spa, feature->fi_guid); 322ca0cc391SMatthew Ahrens else if (feature->fi_flags & ZFEATURE_FLAG_MOS) 32343466aaeSMax Grossman spa_activate_mos_feature(spa, feature->fi_guid, tx); 3242acef22dSMatthew Ahrens } 3252acef22dSMatthew Ahrens 3262acef22dSMatthew Ahrens /* 3272acef22dSMatthew Ahrens * This function is non-static for zhack; it should otherwise not be used 3282acef22dSMatthew Ahrens * outside this file. 3292acef22dSMatthew Ahrens */ 3302acef22dSMatthew Ahrens void 3312acef22dSMatthew Ahrens feature_enable_sync(spa_t *spa, zfeature_info_t *feature, dmu_tx_t *tx) 3322acef22dSMatthew Ahrens { 333ca0cc391SMatthew Ahrens uint64_t initial_refcount = 334ca0cc391SMatthew Ahrens (feature->fi_flags & ZFEATURE_FLAG_ACTIVATE_ON_ENABLE) ? 1 : 0; 335ca0cc391SMatthew Ahrens uint64_t zapobj = (feature->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 3362acef22dSMatthew Ahrens spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj; 33753089ab7Seschrock 33853089ab7Seschrock ASSERT(0 != zapobj); 33953089ab7Seschrock ASSERT(zfeature_is_valid_guid(feature->fi_guid)); 3402acef22dSMatthew Ahrens ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES); 34153089ab7Seschrock 34253089ab7Seschrock /* 34353089ab7Seschrock * If the feature is already enabled, ignore the request. 34453089ab7Seschrock */ 3452acef22dSMatthew Ahrens if (zap_contains(spa->spa_meta_objset, zapobj, feature->fi_guid) == 0) 3462acef22dSMatthew Ahrens return; 3472acef22dSMatthew Ahrens 3482acef22dSMatthew Ahrens for (int i = 0; feature->fi_depends[i] != SPA_FEATURE_NONE; i++) 3492acef22dSMatthew Ahrens spa_feature_enable(spa, feature->fi_depends[i], tx); 3502acef22dSMatthew Ahrens 3512acef22dSMatthew Ahrens VERIFY0(zap_update(spa->spa_meta_objset, spa->spa_feat_desc_obj, 3522acef22dSMatthew Ahrens feature->fi_guid, 1, strlen(feature->fi_desc) + 1, 3532acef22dSMatthew Ahrens feature->fi_desc, tx)); 35443466aaeSMax Grossman 35543466aaeSMax Grossman feature_sync(spa, feature, initial_refcount, tx); 35643466aaeSMax Grossman 35743466aaeSMax Grossman if (spa_feature_is_enabled(spa, SPA_FEATURE_ENABLED_TXG)) { 35843466aaeSMax Grossman uint64_t enabling_txg = dmu_tx_get_txg(tx); 35943466aaeSMax Grossman 36043466aaeSMax Grossman if (spa->spa_feat_enabled_txg_obj == 0ULL) { 36143466aaeSMax Grossman spa->spa_feat_enabled_txg_obj = 36243466aaeSMax Grossman zap_create_link(spa->spa_meta_objset, 36343466aaeSMax Grossman DMU_OTN_ZAP_METADATA, DMU_POOL_DIRECTORY_OBJECT, 36443466aaeSMax Grossman DMU_POOL_FEATURE_ENABLED_TXG, tx); 36543466aaeSMax Grossman } 36643466aaeSMax Grossman spa_feature_incr(spa, SPA_FEATURE_ENABLED_TXG, tx); 36743466aaeSMax Grossman 36843466aaeSMax Grossman VERIFY0(zap_add(spa->spa_meta_objset, 36943466aaeSMax Grossman spa->spa_feat_enabled_txg_obj, feature->fi_guid, 37043466aaeSMax Grossman sizeof (uint64_t), 1, &enabling_txg, tx)); 37143466aaeSMax Grossman } 3722acef22dSMatthew Ahrens } 3732acef22dSMatthew Ahrens 3742acef22dSMatthew Ahrens static void 3752acef22dSMatthew Ahrens feature_do_action(spa_t *spa, spa_feature_t fid, feature_action_t action, 3762acef22dSMatthew Ahrens dmu_tx_t *tx) 3772acef22dSMatthew Ahrens { 3782acef22dSMatthew Ahrens uint64_t refcount; 3792acef22dSMatthew Ahrens zfeature_info_t *feature = &spa_feature_table[fid]; 380ca0cc391SMatthew Ahrens uint64_t zapobj = (feature->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 3812acef22dSMatthew Ahrens spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj; 3822acef22dSMatthew Ahrens 38343466aaeSMax Grossman ASSERT(VALID_FEATURE_FID(fid)); 3842acef22dSMatthew Ahrens ASSERT(0 != zapobj); 3852acef22dSMatthew Ahrens ASSERT(zfeature_is_valid_guid(feature->fi_guid)); 3862acef22dSMatthew Ahrens 3872acef22dSMatthew Ahrens ASSERT(dmu_tx_is_syncing(tx)); 3882acef22dSMatthew Ahrens ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES); 3892acef22dSMatthew Ahrens 39043466aaeSMax Grossman VERIFY3U(feature_get_refcount(spa, feature, &refcount), !=, ENOTSUP); 3912acef22dSMatthew Ahrens 3922acef22dSMatthew Ahrens switch (action) { 39353089ab7Seschrock case FEATURE_ACTION_INCR: 3942acef22dSMatthew Ahrens VERIFY3U(refcount, !=, UINT64_MAX); 39553089ab7Seschrock refcount++; 39653089ab7Seschrock break; 39753089ab7Seschrock case FEATURE_ACTION_DECR: 3982acef22dSMatthew Ahrens VERIFY3U(refcount, !=, 0); 39953089ab7Seschrock refcount--; 40053089ab7Seschrock break; 40153089ab7Seschrock default: 40253089ab7Seschrock ASSERT(0); 40353089ab7Seschrock break; 40453089ab7Seschrock } 40553089ab7Seschrock 4062acef22dSMatthew Ahrens feature_sync(spa, feature, refcount, tx); 40753089ab7Seschrock } 40853089ab7Seschrock 40953089ab7Seschrock void 41053089ab7Seschrock spa_feature_create_zap_objects(spa_t *spa, dmu_tx_t *tx) 41153089ab7Seschrock { 41253089ab7Seschrock /* 41353089ab7Seschrock * We create feature flags ZAP objects in two instances: during pool 41453089ab7Seschrock * creation and during pool upgrade. 41553089ab7Seschrock */ 41653089ab7Seschrock ASSERT(dsl_pool_sync_context(spa_get_dsl(spa)) || (!spa->spa_sync_on && 41753089ab7Seschrock tx->tx_txg == TXG_INITIAL)); 41853089ab7Seschrock 41953089ab7Seschrock spa->spa_feat_for_read_obj = zap_create_link(spa->spa_meta_objset, 42053089ab7Seschrock DMU_OTN_ZAP_METADATA, DMU_POOL_DIRECTORY_OBJECT, 42153089ab7Seschrock DMU_POOL_FEATURES_FOR_READ, tx); 42253089ab7Seschrock spa->spa_feat_for_write_obj = zap_create_link(spa->spa_meta_objset, 42353089ab7Seschrock DMU_OTN_ZAP_METADATA, DMU_POOL_DIRECTORY_OBJECT, 42453089ab7Seschrock DMU_POOL_FEATURES_FOR_WRITE, tx); 42553089ab7Seschrock spa->spa_feat_desc_obj = zap_create_link(spa->spa_meta_objset, 42653089ab7Seschrock DMU_OTN_ZAP_METADATA, DMU_POOL_DIRECTORY_OBJECT, 42753089ab7Seschrock DMU_POOL_FEATURE_DESCRIPTIONS, tx); 42853089ab7Seschrock } 42953089ab7Seschrock 43053089ab7Seschrock /* 43153089ab7Seschrock * Enable any required dependencies, then enable the requested feature. 43253089ab7Seschrock */ 43353089ab7Seschrock void 4342acef22dSMatthew Ahrens spa_feature_enable(spa_t *spa, spa_feature_t fid, dmu_tx_t *tx) 43553089ab7Seschrock { 43653089ab7Seschrock ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES); 43743466aaeSMax Grossman ASSERT(VALID_FEATURE_FID(fid)); 4382acef22dSMatthew Ahrens feature_enable_sync(spa, &spa_feature_table[fid], tx); 43953089ab7Seschrock } 44053089ab7Seschrock 44153089ab7Seschrock void 4422acef22dSMatthew Ahrens spa_feature_incr(spa_t *spa, spa_feature_t fid, dmu_tx_t *tx) 44353089ab7Seschrock { 4442acef22dSMatthew Ahrens feature_do_action(spa, fid, FEATURE_ACTION_INCR, tx); 44553089ab7Seschrock } 44653089ab7Seschrock 44753089ab7Seschrock void 4482acef22dSMatthew Ahrens spa_feature_decr(spa_t *spa, spa_feature_t fid, dmu_tx_t *tx) 44953089ab7Seschrock { 4502acef22dSMatthew Ahrens feature_do_action(spa, fid, FEATURE_ACTION_DECR, tx); 4510713e232SGeorge Wilson } 4520713e232SGeorge Wilson 45353089ab7Seschrock boolean_t 4542acef22dSMatthew Ahrens spa_feature_is_enabled(spa_t *spa, spa_feature_t fid) 45553089ab7Seschrock { 45653089ab7Seschrock int err; 45753089ab7Seschrock uint64_t refcount; 45853089ab7Seschrock 45943466aaeSMax Grossman ASSERT(VALID_FEATURE_FID(fid)); 46053089ab7Seschrock if (spa_version(spa) < SPA_VERSION_FEATURES) 46153089ab7Seschrock return (B_FALSE); 46253089ab7Seschrock 4632acef22dSMatthew Ahrens err = feature_get_refcount(spa, &spa_feature_table[fid], &refcount); 46453089ab7Seschrock ASSERT(err == 0 || err == ENOTSUP); 46553089ab7Seschrock return (err == 0); 46653089ab7Seschrock } 46753089ab7Seschrock 46853089ab7Seschrock boolean_t 4692acef22dSMatthew Ahrens spa_feature_is_active(spa_t *spa, spa_feature_t fid) 47053089ab7Seschrock { 47153089ab7Seschrock int err; 47253089ab7Seschrock uint64_t refcount; 47353089ab7Seschrock 47443466aaeSMax Grossman ASSERT(VALID_FEATURE_FID(fid)); 47553089ab7Seschrock if (spa_version(spa) < SPA_VERSION_FEATURES) 47653089ab7Seschrock return (B_FALSE); 47753089ab7Seschrock 4782acef22dSMatthew Ahrens err = feature_get_refcount(spa, &spa_feature_table[fid], &refcount); 47953089ab7Seschrock ASSERT(err == 0 || err == ENOTSUP); 48053089ab7Seschrock return (err == 0 && refcount > 0); 48153089ab7Seschrock } 48243466aaeSMax Grossman 48343466aaeSMax Grossman /* 48443466aaeSMax Grossman * For the feature specified by fid (which must depend on 48543466aaeSMax Grossman * SPA_FEATURE_ENABLED_TXG), return the TXG at which it was enabled in the 48643466aaeSMax Grossman * OUT txg argument. 48743466aaeSMax Grossman * 48843466aaeSMax Grossman * Returns B_TRUE if the feature is enabled, in which case txg will be filled 48943466aaeSMax Grossman * with the transaction group in which the specified feature was enabled. 49043466aaeSMax Grossman * Returns B_FALSE otherwise (i.e. if the feature is not enabled). 49143466aaeSMax Grossman */ 49243466aaeSMax Grossman boolean_t 493*9a686fbcSPaul Dagnelie spa_feature_enabled_txg(spa_t *spa, spa_feature_t fid, uint64_t *txg) 494*9a686fbcSPaul Dagnelie { 49543466aaeSMax Grossman int err; 49643466aaeSMax Grossman 49743466aaeSMax Grossman ASSERT(VALID_FEATURE_FID(fid)); 49843466aaeSMax Grossman if (spa_version(spa) < SPA_VERSION_FEATURES) 49943466aaeSMax Grossman return (B_FALSE); 50043466aaeSMax Grossman 50143466aaeSMax Grossman err = feature_get_enabled_txg(spa, &spa_feature_table[fid], txg); 50243466aaeSMax Grossman ASSERT(err == 0 || err == ENOTSUP); 50343466aaeSMax Grossman 50443466aaeSMax Grossman return (err == 0); 50543466aaeSMax Grossman } 506