xref: /freebsd/sys/contrib/openzfs/module/zfs/zfeature.c (revision 180f822596ecc49d3074dcc9dfea9628aae1d48d)
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