1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9eda14cbcSMatt Macy * or http://www.opensolaris.org/os/licensing. 10eda14cbcSMatt Macy * See the License for the specific language governing permissions 11eda14cbcSMatt Macy * and limitations under the License. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy * 19eda14cbcSMatt Macy * CDDL HEADER END 20eda14cbcSMatt Macy */ 21eda14cbcSMatt Macy 22eda14cbcSMatt Macy /* 23eda14cbcSMatt Macy * Copyright (c) 2011, 2015 by Delphix. All rights reserved. 24eda14cbcSMatt Macy */ 25eda14cbcSMatt Macy 26eda14cbcSMatt Macy #include <sys/zfs_context.h> 27eda14cbcSMatt Macy #include <sys/zfeature.h> 28eda14cbcSMatt Macy #include <sys/dmu.h> 29eda14cbcSMatt Macy #include <sys/nvpair.h> 30eda14cbcSMatt Macy #include <sys/zap.h> 31eda14cbcSMatt Macy #include <sys/dmu_tx.h> 32eda14cbcSMatt Macy #include "zfeature_common.h" 33eda14cbcSMatt Macy #include <sys/spa_impl.h> 34eda14cbcSMatt Macy 35eda14cbcSMatt Macy /* 36eda14cbcSMatt Macy * ZFS Feature Flags 37eda14cbcSMatt Macy * ----------------- 38eda14cbcSMatt Macy * 39eda14cbcSMatt Macy * ZFS feature flags are used to provide fine-grained versioning to the ZFS 40eda14cbcSMatt Macy * on-disk format. Once enabled on a pool feature flags replace the old 41eda14cbcSMatt Macy * spa_version() number. 42eda14cbcSMatt Macy * 43eda14cbcSMatt Macy * Each new on-disk format change will be given a uniquely identifying string 44eda14cbcSMatt Macy * GUID rather than a version number. This avoids the problem of different 45eda14cbcSMatt Macy * organizations creating new on-disk formats with the same version number. To 46eda14cbcSMatt Macy * keep feature GUIDs unique they should consist of the reverse dns name of the 47eda14cbcSMatt Macy * organization which implemented the feature and a short name for the feature, 48eda14cbcSMatt Macy * separated by a colon (e.g. com.delphix:async_destroy). 49eda14cbcSMatt Macy * 50eda14cbcSMatt Macy * Reference Counts 51eda14cbcSMatt Macy * ---------------- 52eda14cbcSMatt Macy * 53eda14cbcSMatt Macy * Within each pool features can be in one of three states: disabled, enabled, 54eda14cbcSMatt Macy * or active. These states are differentiated by a reference count stored on 55eda14cbcSMatt Macy * disk for each feature: 56eda14cbcSMatt Macy * 57eda14cbcSMatt Macy * 1) If there is no reference count stored on disk the feature is disabled. 58eda14cbcSMatt Macy * 2) If the reference count is 0 a system administrator has enabled the 59eda14cbcSMatt Macy * feature, but the feature has not been used yet, so no on-disk 60eda14cbcSMatt Macy * format changes have been made. 61eda14cbcSMatt Macy * 3) If the reference count is greater than 0 the feature is active. 62eda14cbcSMatt Macy * The format changes required by the feature are currently on disk. 63eda14cbcSMatt Macy * Note that if the feature's format changes are reversed the feature 64eda14cbcSMatt Macy * may choose to set its reference count back to 0. 65eda14cbcSMatt Macy * 66eda14cbcSMatt Macy * Feature flags makes no differentiation between non-zero reference counts 67eda14cbcSMatt Macy * for an active feature (e.g. a reference count of 1 means the same thing as a 68eda14cbcSMatt Macy * reference count of 27834721), but feature implementations may choose to use 69eda14cbcSMatt Macy * the reference count to store meaningful information. For example, a new RAID 70eda14cbcSMatt Macy * implementation might set the reference count to the number of vdevs using 71eda14cbcSMatt Macy * it. If all those disks are removed from the pool the feature goes back to 72eda14cbcSMatt Macy * having a reference count of 0. 73eda14cbcSMatt Macy * 74eda14cbcSMatt Macy * It is the responsibility of the individual features to maintain a non-zero 75eda14cbcSMatt Macy * reference count as long as the feature's format changes are present on disk. 76eda14cbcSMatt Macy * 77eda14cbcSMatt Macy * Dependencies 78eda14cbcSMatt Macy * ------------ 79eda14cbcSMatt Macy * 80eda14cbcSMatt Macy * Each feature may depend on other features. The only effect of this 81eda14cbcSMatt Macy * relationship is that when a feature is enabled all of its dependencies are 82eda14cbcSMatt Macy * automatically enabled as well. Any future work to support disabling of 83eda14cbcSMatt Macy * features would need to ensure that features cannot be disabled if other 84eda14cbcSMatt Macy * enabled features depend on them. 85eda14cbcSMatt Macy * 86eda14cbcSMatt Macy * On-disk Format 87eda14cbcSMatt Macy * -------------- 88eda14cbcSMatt Macy * 89eda14cbcSMatt Macy * When feature flags are enabled spa_version() is set to SPA_VERSION_FEATURES 90eda14cbcSMatt Macy * (5000). In order for this to work the pool is automatically upgraded to 91eda14cbcSMatt Macy * SPA_VERSION_BEFORE_FEATURES (28) first, so all pre-feature flags on disk 92eda14cbcSMatt Macy * format changes will be in use. 93eda14cbcSMatt Macy * 94eda14cbcSMatt Macy * Information about features is stored in 3 ZAP objects in the pool's MOS. 95eda14cbcSMatt Macy * These objects are linked to by the following names in the pool directory 96eda14cbcSMatt Macy * object: 97eda14cbcSMatt Macy * 98eda14cbcSMatt Macy * 1) features_for_read: feature GUID -> reference count 99eda14cbcSMatt Macy * Features needed to open the pool for reading. 100eda14cbcSMatt Macy * 2) features_for_write: feature GUID -> reference count 101eda14cbcSMatt Macy * Features needed to open the pool for writing. 102eda14cbcSMatt Macy * 3) feature_descriptions: feature GUID -> descriptive string 103eda14cbcSMatt Macy * A human readable string. 104eda14cbcSMatt Macy * 105eda14cbcSMatt Macy * All enabled features appear in either features_for_read or 106eda14cbcSMatt Macy * features_for_write, but not both. 107eda14cbcSMatt Macy * 108eda14cbcSMatt Macy * To open a pool in read-only mode only the features listed in 109eda14cbcSMatt Macy * features_for_read need to be supported. 110eda14cbcSMatt Macy * 111eda14cbcSMatt Macy * To open the pool in read-write mode features in both features_for_read and 112eda14cbcSMatt Macy * features_for_write need to be supported. 113eda14cbcSMatt Macy * 114eda14cbcSMatt Macy * Some features may be required to read the ZAP objects containing feature 115eda14cbcSMatt Macy * information. To allow software to check for compatibility with these features 116eda14cbcSMatt Macy * before the pool is opened their names must be stored in the label in a 117eda14cbcSMatt Macy * new "features_for_read" entry (note that features that are only required 118eda14cbcSMatt Macy * to write to a pool never need to be stored in the label since the 119eda14cbcSMatt Macy * features_for_write ZAP object can be read before the pool is written to). 120eda14cbcSMatt Macy * To save space in the label features must be explicitly marked as needing to 121eda14cbcSMatt Macy * be written to the label. Also, reference counts are not stored in the label, 122eda14cbcSMatt Macy * instead any feature whose reference count drops to 0 is removed from the 123eda14cbcSMatt Macy * label. 124eda14cbcSMatt Macy * 125eda14cbcSMatt Macy * Adding New Features 126eda14cbcSMatt Macy * ------------------- 127eda14cbcSMatt Macy * 128eda14cbcSMatt Macy * Features must be registered in zpool_feature_init() function in 129eda14cbcSMatt Macy * zfeature_common.c using the zfeature_register() function. This function 130eda14cbcSMatt Macy * has arguments to specify if the feature should be stored in the 131eda14cbcSMatt Macy * features_for_read or features_for_write ZAP object and if it needs to be 132eda14cbcSMatt Macy * written to the label when active. 133eda14cbcSMatt Macy * 134eda14cbcSMatt Macy * Once a feature is registered it will appear as a "feature@<feature name>" 135eda14cbcSMatt Macy * property which can be set by an administrator. Feature implementors should 136eda14cbcSMatt Macy * use the spa_feature_is_enabled() and spa_feature_is_active() functions to 137eda14cbcSMatt Macy * query the state of a feature and the spa_feature_incr() and 138eda14cbcSMatt Macy * spa_feature_decr() functions to change an enabled feature's reference count. 139eda14cbcSMatt Macy * Reference counts may only be updated in the syncing context. 140eda14cbcSMatt Macy * 141eda14cbcSMatt Macy * Features may not perform enable-time initialization. Instead, any such 142eda14cbcSMatt Macy * initialization should occur when the feature is first used. This design 143eda14cbcSMatt Macy * enforces that on-disk changes be made only when features are used. Code 144eda14cbcSMatt Macy * should only check if a feature is enabled using spa_feature_is_enabled(), 145eda14cbcSMatt Macy * not by relying on any feature specific metadata existing. If a feature is 146eda14cbcSMatt Macy * enabled, but the feature's metadata is not on disk yet then it should be 147eda14cbcSMatt Macy * created as needed. 148eda14cbcSMatt Macy * 149eda14cbcSMatt Macy * As an example, consider the com.delphix:async_destroy feature. This feature 150eda14cbcSMatt Macy * relies on the existence of a bptree in the MOS that store blocks for 151eda14cbcSMatt Macy * asynchronous freeing. This bptree is not created when async_destroy is 152eda14cbcSMatt Macy * enabled. Instead, when a dataset is destroyed spa_feature_is_enabled() is 153eda14cbcSMatt Macy * called to check if async_destroy is enabled. If it is and the bptree object 154eda14cbcSMatt Macy * does not exist yet, the bptree object is created as part of the dataset 155eda14cbcSMatt Macy * destroy and async_destroy's reference count is incremented to indicate it 156eda14cbcSMatt Macy * has made an on-disk format change. Later, after the destroyed dataset's 157eda14cbcSMatt Macy * blocks have all been asynchronously freed there is no longer any use for the 158eda14cbcSMatt Macy * bptree object, so it is destroyed and async_destroy's reference count is 159eda14cbcSMatt Macy * decremented back to 0 to indicate that it has undone its on-disk format 160eda14cbcSMatt Macy * changes. 161eda14cbcSMatt Macy */ 162eda14cbcSMatt Macy 163eda14cbcSMatt Macy typedef enum { 164eda14cbcSMatt Macy FEATURE_ACTION_INCR, 165eda14cbcSMatt Macy FEATURE_ACTION_DECR, 166eda14cbcSMatt Macy } feature_action_t; 167eda14cbcSMatt Macy 168eda14cbcSMatt Macy /* 169eda14cbcSMatt Macy * Checks that the active features in the pool are supported by 170eda14cbcSMatt Macy * this software. Adds each unsupported feature (name -> description) to 171eda14cbcSMatt Macy * the supplied nvlist. 172eda14cbcSMatt Macy */ 173eda14cbcSMatt Macy boolean_t 174eda14cbcSMatt Macy spa_features_check(spa_t *spa, boolean_t for_write, 175eda14cbcSMatt Macy nvlist_t *unsup_feat, nvlist_t *enabled_feat) 176eda14cbcSMatt Macy { 177eda14cbcSMatt Macy objset_t *os = spa->spa_meta_objset; 178eda14cbcSMatt Macy boolean_t supported; 179eda14cbcSMatt Macy zap_cursor_t *zc; 180eda14cbcSMatt Macy zap_attribute_t *za; 181eda14cbcSMatt Macy uint64_t obj = for_write ? 182eda14cbcSMatt Macy spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj; 183eda14cbcSMatt Macy char *buf; 184eda14cbcSMatt Macy 185eda14cbcSMatt Macy zc = kmem_alloc(sizeof (zap_cursor_t), KM_SLEEP); 186eda14cbcSMatt Macy za = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP); 187eda14cbcSMatt Macy buf = kmem_alloc(MAXPATHLEN, KM_SLEEP); 188eda14cbcSMatt Macy 189eda14cbcSMatt Macy supported = B_TRUE; 190eda14cbcSMatt Macy for (zap_cursor_init(zc, os, obj); 191eda14cbcSMatt Macy zap_cursor_retrieve(zc, za) == 0; 192eda14cbcSMatt Macy zap_cursor_advance(zc)) { 193eda14cbcSMatt Macy ASSERT(za->za_integer_length == sizeof (uint64_t) && 194eda14cbcSMatt Macy za->za_num_integers == 1); 195eda14cbcSMatt Macy 196eda14cbcSMatt Macy if (NULL != enabled_feat) { 197eda14cbcSMatt Macy fnvlist_add_uint64(enabled_feat, za->za_name, 198eda14cbcSMatt Macy za->za_first_integer); 199eda14cbcSMatt Macy } 200eda14cbcSMatt Macy 201eda14cbcSMatt Macy if (za->za_first_integer != 0 && 202eda14cbcSMatt Macy !zfeature_is_supported(za->za_name)) { 203eda14cbcSMatt Macy supported = B_FALSE; 204eda14cbcSMatt Macy 205eda14cbcSMatt Macy if (NULL != unsup_feat) { 206*180f8225SMatt Macy const char *desc = ""; 207eda14cbcSMatt Macy 208eda14cbcSMatt Macy if (zap_lookup(os, spa->spa_feat_desc_obj, 209eda14cbcSMatt Macy za->za_name, 1, MAXPATHLEN, buf) == 0) 210eda14cbcSMatt Macy desc = buf; 211eda14cbcSMatt Macy 212eda14cbcSMatt Macy VERIFY(nvlist_add_string(unsup_feat, 213eda14cbcSMatt Macy za->za_name, desc) == 0); 214eda14cbcSMatt Macy } 215eda14cbcSMatt Macy } 216eda14cbcSMatt Macy } 217eda14cbcSMatt Macy zap_cursor_fini(zc); 218eda14cbcSMatt Macy 219eda14cbcSMatt Macy kmem_free(buf, MAXPATHLEN); 220eda14cbcSMatt Macy kmem_free(za, sizeof (zap_attribute_t)); 221eda14cbcSMatt Macy kmem_free(zc, sizeof (zap_cursor_t)); 222eda14cbcSMatt Macy 223eda14cbcSMatt Macy return (supported); 224eda14cbcSMatt Macy } 225eda14cbcSMatt Macy 226eda14cbcSMatt Macy /* 227eda14cbcSMatt Macy * Use an in-memory cache of feature refcounts for quick retrieval. 228eda14cbcSMatt Macy * 229eda14cbcSMatt Macy * Note: well-designed features will not need to use this; they should 230eda14cbcSMatt Macy * use spa_feature_is_enabled() and spa_feature_is_active() instead. 231eda14cbcSMatt Macy * However, this is non-static for zdb, zhack, and spa_add_feature_stats(). 232eda14cbcSMatt Macy */ 233eda14cbcSMatt Macy int 234eda14cbcSMatt Macy feature_get_refcount(spa_t *spa, zfeature_info_t *feature, uint64_t *res) 235eda14cbcSMatt Macy { 236eda14cbcSMatt Macy ASSERT(VALID_FEATURE_FID(feature->fi_feature)); 237eda14cbcSMatt Macy if (spa->spa_feat_refcount_cache[feature->fi_feature] == 238eda14cbcSMatt Macy SPA_FEATURE_DISABLED) { 239eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 240eda14cbcSMatt Macy } 241eda14cbcSMatt Macy *res = spa->spa_feat_refcount_cache[feature->fi_feature]; 242eda14cbcSMatt Macy return (0); 243eda14cbcSMatt Macy } 244eda14cbcSMatt Macy 245eda14cbcSMatt Macy /* 246eda14cbcSMatt Macy * Note: well-designed features will not need to use this; they should 247eda14cbcSMatt Macy * use spa_feature_is_enabled() and spa_feature_is_active() instead. 248eda14cbcSMatt Macy * However, this is non-static for zdb and zhack. 249eda14cbcSMatt Macy */ 250eda14cbcSMatt Macy int 251eda14cbcSMatt Macy feature_get_refcount_from_disk(spa_t *spa, zfeature_info_t *feature, 252eda14cbcSMatt Macy uint64_t *res) 253eda14cbcSMatt Macy { 254eda14cbcSMatt Macy int err; 255eda14cbcSMatt Macy uint64_t refcount; 256eda14cbcSMatt Macy uint64_t zapobj = (feature->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 257eda14cbcSMatt Macy spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj; 258eda14cbcSMatt Macy 259eda14cbcSMatt Macy /* 260eda14cbcSMatt Macy * If the pool is currently being created, the feature objects may not 261eda14cbcSMatt Macy * have been allocated yet. Act as though all features are disabled. 262eda14cbcSMatt Macy */ 263eda14cbcSMatt Macy if (zapobj == 0) 264eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 265eda14cbcSMatt Macy 266eda14cbcSMatt Macy err = zap_lookup(spa->spa_meta_objset, zapobj, 267eda14cbcSMatt Macy feature->fi_guid, sizeof (uint64_t), 1, &refcount); 268eda14cbcSMatt Macy if (err != 0) { 269eda14cbcSMatt Macy if (err == ENOENT) 270eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 271eda14cbcSMatt Macy else 272eda14cbcSMatt Macy return (err); 273eda14cbcSMatt Macy } 274eda14cbcSMatt Macy *res = refcount; 275eda14cbcSMatt Macy return (0); 276eda14cbcSMatt Macy } 277eda14cbcSMatt Macy 278eda14cbcSMatt Macy 279eda14cbcSMatt Macy static int 280eda14cbcSMatt Macy feature_get_enabled_txg(spa_t *spa, zfeature_info_t *feature, uint64_t *res) 281eda14cbcSMatt Macy { 282eda14cbcSMatt Macy uint64_t enabled_txg_obj __maybe_unused = spa->spa_feat_enabled_txg_obj; 283eda14cbcSMatt Macy 284eda14cbcSMatt Macy ASSERT(zfeature_depends_on(feature->fi_feature, 285eda14cbcSMatt Macy SPA_FEATURE_ENABLED_TXG)); 286eda14cbcSMatt Macy 287eda14cbcSMatt Macy if (!spa_feature_is_enabled(spa, feature->fi_feature)) { 288eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 289eda14cbcSMatt Macy } 290eda14cbcSMatt Macy 291eda14cbcSMatt Macy ASSERT(enabled_txg_obj != 0); 292eda14cbcSMatt Macy 293eda14cbcSMatt Macy VERIFY0(zap_lookup(spa->spa_meta_objset, spa->spa_feat_enabled_txg_obj, 294eda14cbcSMatt Macy feature->fi_guid, sizeof (uint64_t), 1, res)); 295eda14cbcSMatt Macy 296eda14cbcSMatt Macy return (0); 297eda14cbcSMatt Macy } 298eda14cbcSMatt Macy 299eda14cbcSMatt Macy /* 300eda14cbcSMatt Macy * This function is non-static for zhack; it should otherwise not be used 301eda14cbcSMatt Macy * outside this file. 302eda14cbcSMatt Macy */ 303eda14cbcSMatt Macy void 304eda14cbcSMatt Macy feature_sync(spa_t *spa, zfeature_info_t *feature, uint64_t refcount, 305eda14cbcSMatt Macy dmu_tx_t *tx) 306eda14cbcSMatt Macy { 307eda14cbcSMatt Macy ASSERT(VALID_FEATURE_OR_NONE(feature->fi_feature)); 308eda14cbcSMatt Macy uint64_t zapobj = (feature->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 309eda14cbcSMatt Macy spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj; 310eda14cbcSMatt Macy VERIFY0(zap_update(spa->spa_meta_objset, zapobj, feature->fi_guid, 311eda14cbcSMatt Macy sizeof (uint64_t), 1, &refcount, tx)); 312eda14cbcSMatt Macy 313eda14cbcSMatt Macy /* 314eda14cbcSMatt Macy * feature_sync is called directly from zhack, allowing the 315eda14cbcSMatt Macy * creation of arbitrary features whose fi_feature field may 316eda14cbcSMatt Macy * be greater than SPA_FEATURES. When called from zhack, the 317eda14cbcSMatt Macy * zfeature_info_t object's fi_feature field will be set to 318eda14cbcSMatt Macy * SPA_FEATURE_NONE. 319eda14cbcSMatt Macy */ 320eda14cbcSMatt Macy if (feature->fi_feature != SPA_FEATURE_NONE) { 321eda14cbcSMatt Macy uint64_t *refcount_cache = 322eda14cbcSMatt Macy &spa->spa_feat_refcount_cache[feature->fi_feature]; 323eda14cbcSMatt Macy VERIFY3U(*refcount_cache, ==, 324eda14cbcSMatt Macy atomic_swap_64(refcount_cache, refcount)); 325eda14cbcSMatt Macy } 326eda14cbcSMatt Macy 327eda14cbcSMatt Macy if (refcount == 0) 328eda14cbcSMatt Macy spa_deactivate_mos_feature(spa, feature->fi_guid); 329eda14cbcSMatt Macy else if (feature->fi_flags & ZFEATURE_FLAG_MOS) 330eda14cbcSMatt Macy spa_activate_mos_feature(spa, feature->fi_guid, tx); 331eda14cbcSMatt Macy } 332eda14cbcSMatt Macy 333eda14cbcSMatt Macy /* 334eda14cbcSMatt Macy * This function is non-static for zhack; it should otherwise not be used 335eda14cbcSMatt Macy * outside this file. 336eda14cbcSMatt Macy */ 337eda14cbcSMatt Macy void 338eda14cbcSMatt Macy feature_enable_sync(spa_t *spa, zfeature_info_t *feature, dmu_tx_t *tx) 339eda14cbcSMatt Macy { 340eda14cbcSMatt Macy uint64_t initial_refcount = 341eda14cbcSMatt Macy (feature->fi_flags & ZFEATURE_FLAG_ACTIVATE_ON_ENABLE) ? 1 : 0; 342eda14cbcSMatt Macy uint64_t zapobj = (feature->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 343eda14cbcSMatt Macy spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj; 344eda14cbcSMatt Macy 345eda14cbcSMatt Macy ASSERT(0 != zapobj); 346eda14cbcSMatt Macy ASSERT(zfeature_is_valid_guid(feature->fi_guid)); 347eda14cbcSMatt Macy ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES); 348eda14cbcSMatt Macy 349eda14cbcSMatt Macy /* 350eda14cbcSMatt Macy * If the feature is already enabled, ignore the request. 351eda14cbcSMatt Macy */ 352eda14cbcSMatt Macy if (zap_contains(spa->spa_meta_objset, zapobj, feature->fi_guid) == 0) 353eda14cbcSMatt Macy return; 354eda14cbcSMatt Macy 355eda14cbcSMatt Macy for (int i = 0; feature->fi_depends[i] != SPA_FEATURE_NONE; i++) 356eda14cbcSMatt Macy spa_feature_enable(spa, feature->fi_depends[i], tx); 357eda14cbcSMatt Macy 358eda14cbcSMatt Macy VERIFY0(zap_update(spa->spa_meta_objset, spa->spa_feat_desc_obj, 359eda14cbcSMatt Macy feature->fi_guid, 1, strlen(feature->fi_desc) + 1, 360eda14cbcSMatt Macy feature->fi_desc, tx)); 361eda14cbcSMatt Macy 362eda14cbcSMatt Macy feature_sync(spa, feature, initial_refcount, tx); 363eda14cbcSMatt Macy 364eda14cbcSMatt Macy if (spa_feature_is_enabled(spa, SPA_FEATURE_ENABLED_TXG)) { 365eda14cbcSMatt Macy uint64_t enabling_txg = dmu_tx_get_txg(tx); 366eda14cbcSMatt Macy 367eda14cbcSMatt Macy if (spa->spa_feat_enabled_txg_obj == 0ULL) { 368eda14cbcSMatt Macy spa->spa_feat_enabled_txg_obj = 369eda14cbcSMatt Macy zap_create_link(spa->spa_meta_objset, 370eda14cbcSMatt Macy DMU_OTN_ZAP_METADATA, DMU_POOL_DIRECTORY_OBJECT, 371eda14cbcSMatt Macy DMU_POOL_FEATURE_ENABLED_TXG, tx); 372eda14cbcSMatt Macy } 373eda14cbcSMatt Macy spa_feature_incr(spa, SPA_FEATURE_ENABLED_TXG, tx); 374eda14cbcSMatt Macy 375eda14cbcSMatt Macy VERIFY0(zap_add(spa->spa_meta_objset, 376eda14cbcSMatt Macy spa->spa_feat_enabled_txg_obj, feature->fi_guid, 377eda14cbcSMatt Macy sizeof (uint64_t), 1, &enabling_txg, tx)); 378eda14cbcSMatt Macy } 379eda14cbcSMatt Macy 380eda14cbcSMatt Macy /* 381eda14cbcSMatt Macy * Errata #4 is mostly a problem with encrypted datasets, but it 382eda14cbcSMatt Macy * is also a problem where the old encryption feature did not 383eda14cbcSMatt Macy * depend on the bookmark_v2 feature. If the pool does not have 384eda14cbcSMatt Macy * any encrypted datasets we can resolve this issue simply by 385eda14cbcSMatt Macy * enabling this dependency. 386eda14cbcSMatt Macy */ 387eda14cbcSMatt Macy if (spa->spa_errata == ZPOOL_ERRATA_ZOL_8308_ENCRYPTION && 388eda14cbcSMatt Macy spa_feature_is_enabled(spa, SPA_FEATURE_ENCRYPTION) && 389eda14cbcSMatt Macy !spa_feature_is_active(spa, SPA_FEATURE_ENCRYPTION) && 390eda14cbcSMatt Macy feature->fi_feature == SPA_FEATURE_BOOKMARK_V2) 391eda14cbcSMatt Macy spa->spa_errata = 0; 392eda14cbcSMatt Macy } 393eda14cbcSMatt Macy 394eda14cbcSMatt Macy static void 395eda14cbcSMatt Macy feature_do_action(spa_t *spa, spa_feature_t fid, feature_action_t action, 396eda14cbcSMatt Macy dmu_tx_t *tx) 397eda14cbcSMatt Macy { 398eda14cbcSMatt Macy uint64_t refcount = 0; 399eda14cbcSMatt Macy zfeature_info_t *feature = &spa_feature_table[fid]; 400eda14cbcSMatt Macy uint64_t zapobj __maybe_unused = 401eda14cbcSMatt Macy (feature->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 402eda14cbcSMatt Macy spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj; 403eda14cbcSMatt Macy 404eda14cbcSMatt Macy ASSERT(VALID_FEATURE_FID(fid)); 405eda14cbcSMatt Macy ASSERT(0 != zapobj); 406eda14cbcSMatt Macy ASSERT(zfeature_is_valid_guid(feature->fi_guid)); 407eda14cbcSMatt Macy 408eda14cbcSMatt Macy ASSERT(dmu_tx_is_syncing(tx)); 409eda14cbcSMatt Macy ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES); 410eda14cbcSMatt Macy 411eda14cbcSMatt Macy VERIFY3U(feature_get_refcount(spa, feature, &refcount), !=, ENOTSUP); 412eda14cbcSMatt Macy 413eda14cbcSMatt Macy switch (action) { 414eda14cbcSMatt Macy case FEATURE_ACTION_INCR: 415eda14cbcSMatt Macy VERIFY3U(refcount, !=, UINT64_MAX); 416eda14cbcSMatt Macy refcount++; 417eda14cbcSMatt Macy break; 418eda14cbcSMatt Macy case FEATURE_ACTION_DECR: 419eda14cbcSMatt Macy VERIFY3U(refcount, !=, 0); 420eda14cbcSMatt Macy refcount--; 421eda14cbcSMatt Macy break; 422eda14cbcSMatt Macy default: 423eda14cbcSMatt Macy ASSERT(0); 424eda14cbcSMatt Macy break; 425eda14cbcSMatt Macy } 426eda14cbcSMatt Macy 427eda14cbcSMatt Macy feature_sync(spa, feature, refcount, tx); 428eda14cbcSMatt Macy } 429eda14cbcSMatt Macy 430eda14cbcSMatt Macy void 431eda14cbcSMatt Macy spa_feature_create_zap_objects(spa_t *spa, dmu_tx_t *tx) 432eda14cbcSMatt Macy { 433eda14cbcSMatt Macy /* 434eda14cbcSMatt Macy * We create feature flags ZAP objects in two instances: during pool 435eda14cbcSMatt Macy * creation and during pool upgrade. 436eda14cbcSMatt Macy */ 437eda14cbcSMatt Macy ASSERT((!spa->spa_sync_on && tx->tx_txg == TXG_INITIAL) || 438eda14cbcSMatt Macy dsl_pool_sync_context(spa_get_dsl(spa))); 439eda14cbcSMatt Macy 440eda14cbcSMatt Macy spa->spa_feat_for_read_obj = zap_create_link(spa->spa_meta_objset, 441eda14cbcSMatt Macy DMU_OTN_ZAP_METADATA, DMU_POOL_DIRECTORY_OBJECT, 442eda14cbcSMatt Macy DMU_POOL_FEATURES_FOR_READ, tx); 443eda14cbcSMatt Macy spa->spa_feat_for_write_obj = zap_create_link(spa->spa_meta_objset, 444eda14cbcSMatt Macy DMU_OTN_ZAP_METADATA, DMU_POOL_DIRECTORY_OBJECT, 445eda14cbcSMatt Macy DMU_POOL_FEATURES_FOR_WRITE, tx); 446eda14cbcSMatt Macy spa->spa_feat_desc_obj = zap_create_link(spa->spa_meta_objset, 447eda14cbcSMatt Macy DMU_OTN_ZAP_METADATA, DMU_POOL_DIRECTORY_OBJECT, 448eda14cbcSMatt Macy DMU_POOL_FEATURE_DESCRIPTIONS, tx); 449eda14cbcSMatt Macy } 450eda14cbcSMatt Macy 451eda14cbcSMatt Macy /* 452eda14cbcSMatt Macy * Enable any required dependencies, then enable the requested feature. 453eda14cbcSMatt Macy */ 454eda14cbcSMatt Macy void 455eda14cbcSMatt Macy spa_feature_enable(spa_t *spa, spa_feature_t fid, dmu_tx_t *tx) 456eda14cbcSMatt Macy { 457eda14cbcSMatt Macy ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES); 458eda14cbcSMatt Macy ASSERT(VALID_FEATURE_FID(fid)); 459eda14cbcSMatt Macy feature_enable_sync(spa, &spa_feature_table[fid], tx); 460eda14cbcSMatt Macy } 461eda14cbcSMatt Macy 462eda14cbcSMatt Macy void 463eda14cbcSMatt Macy spa_feature_incr(spa_t *spa, spa_feature_t fid, dmu_tx_t *tx) 464eda14cbcSMatt Macy { 465eda14cbcSMatt Macy feature_do_action(spa, fid, FEATURE_ACTION_INCR, tx); 466eda14cbcSMatt Macy } 467eda14cbcSMatt Macy 468eda14cbcSMatt Macy void 469eda14cbcSMatt Macy spa_feature_decr(spa_t *spa, spa_feature_t fid, dmu_tx_t *tx) 470eda14cbcSMatt Macy { 471eda14cbcSMatt Macy feature_do_action(spa, fid, FEATURE_ACTION_DECR, tx); 472eda14cbcSMatt Macy } 473eda14cbcSMatt Macy 474eda14cbcSMatt Macy boolean_t 475eda14cbcSMatt Macy spa_feature_is_enabled(spa_t *spa, spa_feature_t fid) 476eda14cbcSMatt Macy { 477eda14cbcSMatt Macy int err; 478eda14cbcSMatt Macy uint64_t refcount = 0; 479eda14cbcSMatt Macy 480eda14cbcSMatt Macy ASSERT(VALID_FEATURE_FID(fid)); 481eda14cbcSMatt Macy if (spa_version(spa) < SPA_VERSION_FEATURES) 482eda14cbcSMatt Macy return (B_FALSE); 483eda14cbcSMatt Macy 484eda14cbcSMatt Macy err = feature_get_refcount(spa, &spa_feature_table[fid], &refcount); 485eda14cbcSMatt Macy ASSERT(err == 0 || err == ENOTSUP); 486eda14cbcSMatt Macy return (err == 0); 487eda14cbcSMatt Macy } 488eda14cbcSMatt Macy 489eda14cbcSMatt Macy boolean_t 490eda14cbcSMatt Macy spa_feature_is_active(spa_t *spa, spa_feature_t fid) 491eda14cbcSMatt Macy { 492eda14cbcSMatt Macy int err; 493eda14cbcSMatt Macy uint64_t refcount = 0; 494eda14cbcSMatt Macy 495eda14cbcSMatt Macy ASSERT(VALID_FEATURE_FID(fid)); 496eda14cbcSMatt Macy if (spa_version(spa) < SPA_VERSION_FEATURES) 497eda14cbcSMatt Macy return (B_FALSE); 498eda14cbcSMatt Macy 499eda14cbcSMatt Macy err = feature_get_refcount(spa, &spa_feature_table[fid], &refcount); 500eda14cbcSMatt Macy ASSERT(err == 0 || err == ENOTSUP); 501eda14cbcSMatt Macy return (err == 0 && refcount > 0); 502eda14cbcSMatt Macy } 503eda14cbcSMatt Macy 504eda14cbcSMatt Macy /* 505eda14cbcSMatt Macy * For the feature specified by fid (which must depend on 506eda14cbcSMatt Macy * SPA_FEATURE_ENABLED_TXG), return the TXG at which it was enabled in the 507eda14cbcSMatt Macy * OUT txg argument. 508eda14cbcSMatt Macy * 509eda14cbcSMatt Macy * Returns B_TRUE if the feature is enabled, in which case txg will be filled 510eda14cbcSMatt Macy * with the transaction group in which the specified feature was enabled. 511eda14cbcSMatt Macy * Returns B_FALSE otherwise (i.e. if the feature is not enabled). 512eda14cbcSMatt Macy */ 513eda14cbcSMatt Macy boolean_t 514eda14cbcSMatt Macy spa_feature_enabled_txg(spa_t *spa, spa_feature_t fid, uint64_t *txg) 515eda14cbcSMatt Macy { 516eda14cbcSMatt Macy int err; 517eda14cbcSMatt Macy 518eda14cbcSMatt Macy ASSERT(VALID_FEATURE_FID(fid)); 519eda14cbcSMatt Macy if (spa_version(spa) < SPA_VERSION_FEATURES) 520eda14cbcSMatt Macy return (B_FALSE); 521eda14cbcSMatt Macy 522eda14cbcSMatt Macy err = feature_get_enabled_txg(spa, &spa_feature_table[fid], txg); 523eda14cbcSMatt Macy ASSERT(err == 0 || err == ENOTSUP); 524eda14cbcSMatt Macy 525eda14cbcSMatt Macy return (err == 0); 526eda14cbcSMatt Macy } 527