spa.c revision 80eb36f241abf8c076119fb4c49a55fd61ebc710
1fa9e406ahrens/*
2fa9e406ahrens * CDDL HEADER START
3fa9e406ahrens *
4fa9e406ahrens * The contents of this file are subject to the terms of the
5ea8dc4beschrock * Common Development and Distribution License (the "License").
6ea8dc4beschrock * You may not use this file except in compliance with the License.
7fa9e406ahrens *
8fa9e406ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e406ahrens * or http://www.opensolaris.org/os/licensing.
10fa9e406ahrens * See the License for the specific language governing permissions
11fa9e406ahrens * and limitations under the License.
12fa9e406ahrens *
13fa9e406ahrens * When distributing Covered Code, include this CDDL HEADER in each
14fa9e406ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e406ahrens * If applicable, add the following below this CDDL HEADER, with the
16fa9e406ahrens * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e406ahrens * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e406ahrens *
19fa9e406ahrens * CDDL HEADER END
20fa9e406ahrens */
2199653d4eschrock
22fa9e406ahrens/*
23379c004Eric Schrock * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24fa9e406ahrens * Use is subject to license terms.
25fa9e406ahrens */
26fa9e406ahrens
27fa9e406ahrens/*
28fa9e406ahrens * This file contains all the routines used when modifying on-disk SPA state.
29fa9e406ahrens * This includes opening, importing, destroying, exporting a pool, and syncing a
30fa9e406ahrens * pool.
31fa9e406ahrens */
32fa9e406ahrens
33fa9e406ahrens#include <sys/zfs_context.h>
34ea8dc4beschrock#include <sys/fm/fs/zfs.h>
35fa9e406ahrens#include <sys/spa_impl.h>
36fa9e406ahrens#include <sys/zio.h>
37fa9e406ahrens#include <sys/zio_checksum.h>
38fa9e406ahrens#include <sys/dmu.h>
39fa9e406ahrens#include <sys/dmu_tx.h>
40fa9e406ahrens#include <sys/zap.h>
41fa9e406ahrens#include <sys/zil.h>
42b24ab67Jeff Bonwick#include <sys/ddt.h>
43fa9e406ahrens#include <sys/vdev_impl.h>
44fa9e406ahrens#include <sys/metaslab.h>
4588ecc94George Wilson#include <sys/metaslab_impl.h>
46fa9e406ahrens#include <sys/uberblock_impl.h>
47fa9e406ahrens#include <sys/txg.h>
48fa9e406ahrens#include <sys/avl.h>
49fa9e406ahrens#include <sys/dmu_traverse.h>
50b1b8ab3lling#include <sys/dmu_objset.h>
51fa9e406ahrens#include <sys/unique.h>
52fa9e406ahrens#include <sys/dsl_pool.h>
53b1b8ab3lling#include <sys/dsl_dataset.h>
54fa9e406ahrens#include <sys/dsl_dir.h>
55fa9e406ahrens#include <sys/dsl_prop.h>
56b1b8ab3lling#include <sys/dsl_synctask.h>
57fa9e406ahrens#include <sys/fs/zfs.h>
58fa94a07brendan#include <sys/arc.h>
59fa9e406ahrens#include <sys/callb.h>
609517395ek#include <sys/systeminfo.h>
61e7cbe64gw#include <sys/spa_boot.h>
62573ca77George Wilson#include <sys/zfs_ioctl.h>
63fa9e406ahrens
645679c89jv#ifdef	_KERNEL
655679c89jv#include <sys/zone.h>
66dedec47Jack Meng#include <sys/bootprops.h>
675679c89jv#endif	/* _KERNEL */
685679c89jv
69990b485lling#include "zfs_prop.h"
70b7b9745perrin#include "zfs_comutil.h"
71990b485lling
722e0c549Jonathan Adamsenum zti_modes {
732e0c549Jonathan Adams	zti_mode_fixed,			/* value is # of threads (min 1) */
742e0c549Jonathan Adams	zti_mode_online_percent,	/* value is % of online CPUs */
752e0c549Jonathan Adams	zti_mode_tune,			/* fill from zio_taskq_tune_* */
7680eb36fGeorge Wilson	zti_mode_null,			/* don't create a taskq */
772e0c549Jonathan Adams	zti_nmodes
78e14bb32Jeff Bonwick};
79416e0cdek
8080eb36fGeorge Wilson#define	ZTI_FIX(n)	{ zti_mode_fixed, (n) }
8180eb36fGeorge Wilson#define	ZTI_PCT(n)	{ zti_mode_online_percent, (n) }
8280eb36fGeorge Wilson#define	ZTI_TUNE	{ zti_mode_tune, 0 }
8380eb36fGeorge Wilson#define	ZTI_NULL	{ zti_mode_null, 0 }
842e0c549Jonathan Adams
8580eb36fGeorge Wilson#define	ZTI_ONE		ZTI_FIX(1)
862e0c549Jonathan Adams
872e0c549Jonathan Adamstypedef struct zio_taskq_info {
8880eb36fGeorge Wilson	enum zti_modes zti_mode;
8980eb36fGeorge Wilson	uint_t zti_value;
902e0c549Jonathan Adams} zio_taskq_info_t;
912e0c549Jonathan Adams
922e0c549Jonathan Adamsstatic const char *const zio_taskq_types[ZIO_TASKQ_TYPES] = {
9380eb36fGeorge Wilson		"issue", "issue_high", "intr", "intr_high"
942e0c549Jonathan Adams};
952e0c549Jonathan Adams
9680eb36fGeorge Wilson/*
9780eb36fGeorge Wilson * Define the taskq threads for the following I/O types:
9880eb36fGeorge Wilson * 	NULL, READ, WRITE, FREE, CLAIM, and IOCTL
9980eb36fGeorge Wilson */
10080eb36fGeorge Wilsonconst zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = {
10180eb36fGeorge Wilson	/* ISSUE	ISSUE_HIGH	INTR		INTR_HIGH */
10280eb36fGeorge Wilson	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
10380eb36fGeorge Wilson	{ ZTI_FIX(8),	ZTI_NULL,	ZTI_TUNE,	ZTI_NULL },
10480eb36fGeorge Wilson	{ ZTI_TUNE,	ZTI_FIX(5),	ZTI_FIX(8),	ZTI_FIX(5) },
10580eb36fGeorge Wilson	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
10680eb36fGeorge Wilson	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
10780eb36fGeorge Wilson	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
1082e0c549Jonathan Adams};
1092e0c549Jonathan Adams
1102e0c549Jonathan Adamsenum zti_modes zio_taskq_tune_mode = zti_mode_online_percent;
1112e0c549Jonathan Adamsuint_t zio_taskq_tune_value = 80;	/* #threads = 80% of # online CPUs */
1122e0c549Jonathan Adams
113990b485llingstatic void spa_sync_props(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx);
11489a89ebllingstatic boolean_t spa_has_active_shared_spare(spa_t *spa);
115990b485lling
116990b485lling/*
117990b485lling * ==========================================================================
118990b485lling * SPA properties routines
119990b485lling * ==========================================================================
120990b485lling */
121990b485lling
122990b485lling/*
123990b485lling * Add a (source=src, propname=propval) list to an nvlist.
124990b485lling */
1259d82f4fllingstatic void
126990b485llingspa_prop_add_list(nvlist_t *nvl, zpool_prop_t prop, char *strval,
127990b485lling    uint64_t intval, zprop_source_t src)
128990b485lling{
129990b485lling	const char *propname = zpool_prop_to_name(prop);
130990b485lling	nvlist_t *propval;
131990b485lling
1329d82f4flling	VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1339d82f4flling	VERIFY(nvlist_add_uint64(propval, ZPROP_SOURCE, src) == 0);
134990b485lling
1359d82f4flling	if (strval != NULL)
1369d82f4flling		VERIFY(nvlist_add_string(propval, ZPROP_VALUE, strval) == 0);
1379d82f4flling	else
1389d82f4flling		VERIFY(nvlist_add_uint64(propval, ZPROP_VALUE, intval) == 0);
139990b485lling
1409d82f4flling	VERIFY(nvlist_add_nvlist(nvl, propname, propval) == 0);
141990b485lling	nvlist_free(propval);
142990b485lling}
143990b485lling
144990b485lling/*
145990b485lling * Get property values from the spa configuration.
146990b485lling */
1479d82f4fllingstatic void
148990b485llingspa_prop_get_config(spa_t *spa, nvlist_t **nvp)
149990b485lling{
150379c004Eric Schrock	uint64_t size;
151485bbbfGeorge Wilson	uint64_t alloc;
152990b485lling	uint64_t cap, version;
153990b485lling	zprop_source_t src = ZPROP_SRC_NONE;
154c5904d1eschrock	spa_config_dirent_t *dp;
155990b485lling
156e14bb32Jeff Bonwick	ASSERT(MUTEX_HELD(&spa->spa_props_lock));
157e14bb32Jeff Bonwick
158379c004Eric Schrock	if (spa->spa_root_vdev != NULL) {
159485bbbfGeorge Wilson		alloc = metaslab_class_get_alloc(spa_normal_class(spa));
160b24ab67Jeff Bonwick		size = metaslab_class_get_space(spa_normal_class(spa));
161379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_NAME, spa_name(spa), 0, src);
162379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_SIZE, NULL, size, src);
163485bbbfGeorge Wilson		spa_prop_add_list(*nvp, ZPOOL_PROP_ALLOCATED, NULL, alloc, src);
164485bbbfGeorge Wilson		spa_prop_add_list(*nvp, ZPOOL_PROP_FREE, NULL,
165485bbbfGeorge Wilson		    size - alloc, src);
166379c004Eric Schrock
167485bbbfGeorge Wilson		cap = (size == 0) ? 0 : (alloc * 100 / size);
168379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_CAPACITY, NULL, cap, src);
169379c004Eric Schrock
170b24ab67Jeff Bonwick		spa_prop_add_list(*nvp, ZPOOL_PROP_DEDUPRATIO, NULL,
171b24ab67Jeff Bonwick		    ddt_get_pool_dedup_ratio(spa), src);
172b24ab67Jeff Bonwick
173379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_HEALTH, NULL,
174379c004Eric Schrock		    spa->spa_root_vdev->vdev_state, src);
175379c004Eric Schrock
176379c004Eric Schrock		version = spa_version(spa);
177379c004Eric Schrock		if (version == zpool_prop_default_numeric(ZPOOL_PROP_VERSION))
178379c004Eric Schrock			src = ZPROP_SRC_DEFAULT;
179379c004Eric Schrock		else
180379c004Eric Schrock			src = ZPROP_SRC_LOCAL;
181379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_VERSION, NULL, version, src);
182379c004Eric Schrock	}
183990b485lling
1849d82f4flling	spa_prop_add_list(*nvp, ZPOOL_PROP_GUID, NULL, spa_guid(spa), src);
185990b485lling
1869d82f4flling	if (spa->spa_root != NULL)
1879d82f4flling		spa_prop_add_list(*nvp, ZPOOL_PROP_ALTROOT, spa->spa_root,
1889d82f4flling		    0, ZPROP_SRC_LOCAL);
189990b485lling
190c5904d1eschrock	if ((dp = list_head(&spa->spa_config_list)) != NULL) {
191c5904d1eschrock		if (dp->scd_path == NULL) {
1929d82f4flling			spa_prop_add_list(*nvp, ZPOOL_PROP_CACHEFILE,
193c5904d1eschrock			    "none", 0, ZPROP_SRC_LOCAL);
194c5904d1eschrock		} else if (strcmp(dp->scd_path, spa_config_path) != 0) {
1959d82f4flling			spa_prop_add_list(*nvp, ZPOOL_PROP_CACHEFILE,
196c5904d1eschrock			    dp->scd_path, 0, ZPROP_SRC_LOCAL);
1972f8aaabeschrock		}
1982f8aaabeschrock	}
199990b485lling}
200990b485lling
201990b485lling/*
202990b485lling * Get zpool property values.
203990b485lling */
204990b485llingint
205990b485llingspa_prop_get(spa_t *spa, nvlist_t **nvp)
206990b485lling{
207b24ab67Jeff Bonwick	objset_t *mos = spa->spa_meta_objset;
208990b485lling	zap_cursor_t zc;
209990b485lling	zap_attribute_t za;
210990b485lling	int err;
211990b485lling
2129d82f4flling	VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
213990b485lling
214e14bb32Jeff Bonwick	mutex_enter(&spa->spa_props_lock);
215e14bb32Jeff Bonwick
216990b485lling	/*
217990b485lling	 * Get properties from the spa config.
218990b485lling	 */
2199d82f4flling	spa_prop_get_config(spa, nvp);
220990b485lling
221990b485lling	/* If no pool property object, no more prop to get. */
222990b485lling	if (spa->spa_pool_props_object == 0) {
223990b485lling		mutex_exit(&spa->spa_props_lock);
224990b485lling		return (0);
225990b485lling	}
226990b485lling
227990b485lling	/*
228990b485lling	 * Get properties from the MOS pool property object.
229990b485lling	 */
230990b485lling	for (zap_cursor_init(&zc, mos, spa->spa_pool_props_object);
231990b485lling	    (err = zap_cursor_retrieve(&zc, &za)) == 0;
232990b485lling	    zap_cursor_advance(&zc)) {
233990b485lling		uint64_t intval = 0;
234990b485lling		char *strval = NULL;
235990b485lling		zprop_source_t src = ZPROP_SRC_DEFAULT;
236990b485lling		zpool_prop_t prop;
237990b485lling
238990b485lling		if ((prop = zpool_name_to_prop(za.za_name)) == ZPROP_INVAL)
239990b485lling			continue;
240990b485lling
241990b485lling		switch (za.za_integer_length) {
242990b485lling		case 8:
243990b485lling			/* integer property */
244990b485lling			if (za.za_first_integer !=
245990b485lling			    zpool_prop_default_numeric(prop))
246990b485lling				src = ZPROP_SRC_LOCAL;
247990b485lling
248990b485lling			if (prop == ZPOOL_PROP_BOOTFS) {
249990b485lling				dsl_pool_t *dp;
250990b485lling				dsl_dataset_t *ds = NULL;
251990b485lling
252990b485lling				dp = spa_get_dsl(spa);
253990b485lling				rw_enter(&dp->dp_config_rwlock, RW_READER);
254745cd3cmaybee				if (err = dsl_dataset_hold_obj(dp,
255745cd3cmaybee				    za.za_first_integer, FTAG, &ds)) {
256990b485lling					rw_exit(&dp->dp_config_rwlock);
257990b485lling					break;
258990b485lling				}
259990b485lling
260990b485lling				strval = kmem_alloc(
261990b485lling				    MAXNAMELEN + strlen(MOS_DIR_NAME) + 1,
262990b485lling				    KM_SLEEP);
263990b485lling				dsl_dataset_name(ds, strval);
264745cd3cmaybee				dsl_dataset_rele(ds, FTAG);
265990b485lling				rw_exit(&dp->dp_config_rwlock);
266990b485lling			} else {
267990b485lling				strval = NULL;
268990b485lling				intval = za.za_first_integer;
269990b485lling			}
270990b485lling
2719d82f4flling			spa_prop_add_list(*nvp, prop, strval, intval, src);
272990b485lling
273990b485lling			if (strval != NULL)
274990b485lling				kmem_free(strval,
275990b485lling				    MAXNAMELEN + strlen(MOS_DIR_NAME) + 1);
276990b485lling
277990b485lling			break;
278990b485lling
279990b485lling		case 1:
280990b485lling			/* string property */
281990b485lling			strval = kmem_alloc(za.za_num_integers, KM_SLEEP);
282990b485lling			err = zap_lookup(mos, spa->spa_pool_props_object,
283990b485lling			    za.za_name, 1, za.za_num_integers, strval);
284990b485lling			if (err) {
285990b485lling				kmem_free(strval, za.za_num_integers);
286990b485lling				break;
287990b485lling			}
2889d82f4flling			spa_prop_add_list(*nvp, prop, strval, 0, src);
289990b485lling			kmem_free(strval, za.za_num_integers);
290990b485lling			break;
291990b485lling
292990b485lling		default:
293990b485lling			break;
294990b485lling		}
295990b485lling	}
296990b485lling	zap_cursor_fini(&zc);
297990b485lling	mutex_exit(&spa->spa_props_lock);
298990b485llingout:
299990b485lling	if (err && err != ENOENT) {
300990b485lling		nvlist_free(*nvp);
3019d82f4flling		*nvp = NULL;
302990b485lling		return (err);
303990b485lling	}
304990b485lling
305990b485lling	return (0);
306990b485lling}
307990b485lling
308990b485lling/*
309990b485lling * Validate the given pool properties nvlist and modify the list
310990b485lling * for the property values to be set.
311990b485lling */
312990b485llingstatic int
313990b485llingspa_prop_validate(spa_t *spa, nvlist_t *props)
314990b485lling{
315990b485lling	nvpair_t *elem;
316990b485lling	int error = 0, reset_bootfs = 0;
317990b485lling	uint64_t objnum;
318990b485lling
319990b485lling	elem = NULL;
320990b485lling	while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
321990b485lling		zpool_prop_t prop;
322990b485lling		char *propname, *strval;
323990b485lling		uint64_t intval;
324990b485lling		objset_t *os;
3252f8aaabeschrock		char *slash;
326990b485lling
327990b485lling		propname = nvpair_name(elem);
328990b485lling
329990b485lling		if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL)
330990b485lling			return (EINVAL);
331990b485lling
332990b485lling		switch (prop) {
333990b485lling		case ZPOOL_PROP_VERSION:
334990b485lling			error = nvpair_value_uint64(elem, &intval);
335990b485lling			if (!error &&
336990b485lling			    (intval < spa_version(spa) || intval > SPA_VERSION))
337990b485lling				error = EINVAL;
338990b485lling			break;
339990b485lling
340990b485lling		case ZPOOL_PROP_DELEGATION:
341990b485lling		case ZPOOL_PROP_AUTOREPLACE:
342d5b5bb2Rich Morris		case ZPOOL_PROP_LISTSNAPS:
343573ca77George Wilson		case ZPOOL_PROP_AUTOEXPAND:
344990b485lling			error = nvpair_value_uint64(elem, &intval);
345990b485lling			if (!error && intval > 1)
346990b485lling				error = EINVAL;
347990b485lling			break;
348990b485lling
349990b485lling		case ZPOOL_PROP_BOOTFS:
35025f89eeJeff Bonwick			/*
35125f89eeJeff Bonwick			 * If the pool version is less than SPA_VERSION_BOOTFS,
35225f89eeJeff Bonwick			 * or the pool is still being created (version == 0),
35325f89eeJeff Bonwick			 * the bootfs property cannot be set.
35425f89eeJeff Bonwick			 */
355990b485lling			if (spa_version(spa) < SPA_VERSION_BOOTFS) {
356990b485lling				error = ENOTSUP;
357990b485lling				break;
358990b485lling			}
359990b485lling
360990b485lling			/*
36115e6edfgw			 * Make sure the vdev config is bootable
362990b485lling			 */
36315e6edfgw			if (!vdev_is_bootable(spa->spa_root_vdev)) {
364990b485lling				error = ENOTSUP;
365990b485lling				break;
366990b485lling			}
367990b485lling
368990b485lling			reset_bootfs = 1;
369990b485lling
370990b485lling			error = nvpair_value_string(elem, &strval);
371990b485lling
372990b485lling			if (!error) {
37315e6edfgw				uint64_t compress;
37415e6edfgw
375990b485lling				if (strval == NULL || strval[0] == '\0') {
376990b485lling					objnum = zpool_prop_default_numeric(
377990b485lling					    ZPOOL_PROP_BOOTFS);
378990b485lling					break;
379990b485lling				}
380990b485lling
381503ad85Matthew Ahrens				if (error = dmu_objset_hold(strval, FTAG, &os))
382990b485lling					break;
38315e6edfgw
384503ad85Matthew Ahrens				/* Must be ZPL and not gzip compressed. */
385503ad85Matthew Ahrens
386503ad85Matthew Ahrens				if (dmu_objset_type(os) != DMU_OST_ZFS) {
387503ad85Matthew Ahrens					error = ENOTSUP;
388503ad85Matthew Ahrens				} else if ((error = dsl_prop_get_integer(strval,
38915e6edfgw				    zfs_prop_to_name(ZFS_PROP_COMPRESSION),
39015e6edfgw				    &compress, NULL)) == 0 &&
39115e6edfgw				    !BOOTFS_COMPRESS_VALID(compress)) {
39215e6edfgw					error = ENOTSUP;
39315e6edfgw				} else {
39415e6edfgw					objnum = dmu_objset_id(os);
39515e6edfgw				}
396503ad85Matthew Ahrens				dmu_objset_rele(os, FTAG);
397990b485lling			}
398990b485lling			break;
399e14bb32Jeff Bonwick
4000a4e951gw		case ZPOOL_PROP_FAILUREMODE:
4010a4e951gw			error = nvpair_value_uint64(elem, &intval);
4020a4e951gw			if (!error && (intval < ZIO_FAILURE_MODE_WAIT ||
4030a4e951gw			    intval > ZIO_FAILURE_MODE_PANIC))
4040a4e951gw				error = EINVAL;
4050a4e951gw
4060a4e951gw			/*
4070a4e951gw			 * This is a special case which only occurs when
4080a4e951gw			 * the pool has completely failed. This allows
4090a4e951gw			 * the user to change the in-core failmode property
4100a4e951gw			 * without syncing it out to disk (I/Os might
4110a4e951gw			 * currently be blocked). We do this by returning
4120a4e951gw			 * EIO to the caller (spa_prop_set) to trick it
4130a4e951gw			 * into thinking we encountered a property validation
4140a4e951gw			 * error.
4150a4e951gw			 */
416e14bb32Jeff Bonwick			if (!error && spa_suspended(spa)) {
4170a4e951gw				spa->spa_failmode = intval;
4180a4e951gw				error = EIO;
4190a4e951gw			}
4200a4e951gw			break;
4212f8aaabeschrock
4222f8aaabeschrock		case ZPOOL_PROP_CACHEFILE:
4232f8aaabeschrock			if ((error = nvpair_value_string(elem, &strval)) != 0)
4242f8aaabeschrock				break;
4252f8aaabeschrock
4262f8aaabeschrock			if (strval[0] == '\0')
4272f8aaabeschrock				break;
4282f8aaabeschrock
4292f8aaabeschrock			if (strcmp(strval, "none") == 0)
4302f8aaabeschrock				break;
4312f8aaabeschrock
4322f8aaabeschrock			if (strval[0] != '/') {
4332f8aaabeschrock				error = EINVAL;
4342f8aaabeschrock				break;
4352f8aaabeschrock			}
4362f8aaabeschrock
4372f8aaabeschrock			slash = strrchr(strval, '/');
4382f8aaabeschrock			ASSERT(slash != NULL);
4392f8aaabeschrock
4402f8aaabeschrock			if (slash[1] == '\0' || strcmp(slash, "/.") == 0 ||
4412f8aaabeschrock			    strcmp(slash, "/..") == 0)
4422f8aaabeschrock				error = EINVAL;
4432f8aaabeschrock			break;
444b24ab67Jeff Bonwick
445b24ab67Jeff Bonwick		case ZPOOL_PROP_DEDUPDITTO:
446b24ab67Jeff Bonwick			if (spa_version(spa) < SPA_VERSION_DEDUP)
447b24ab67Jeff Bonwick				error = ENOTSUP;
448b24ab67Jeff Bonwick			else
449b24ab67Jeff Bonwick				error = nvpair_value_uint64(elem, &intval);
450b24ab67Jeff Bonwick			if (error == 0 &&
451b24ab67Jeff Bonwick			    intval != 0 && intval < ZIO_DEDUPDITTO_MIN)
452b24ab67Jeff Bonwick				error = EINVAL;
453b24ab67Jeff Bonwick			break;
454990b485lling		}
455990b485lling
456990b485lling		if (error)
457990b485lling			break;
458990b485lling	}
459990b485lling
460990b485lling	if (!error && reset_bootfs) {
461990b485lling		error = nvlist_remove(props,
462990b485lling		    zpool_prop_to_name(ZPOOL_PROP_BOOTFS), DATA_TYPE_STRING);
463990b485lling
464990b485lling		if (!error) {
465990b485lling			error = nvlist_add_uint64(props,
466990b485lling			    zpool_prop_to_name(ZPOOL_PROP_BOOTFS), objnum);
467990b485lling		}
468990b485lling	}
469990b485lling
470990b485lling	return (error);
471990b485lling}
472990b485lling
473379c004Eric Schrockvoid
474379c004Eric Schrockspa_configfile_set(spa_t *spa, nvlist_t *nvp, boolean_t need_sync)
475379c004Eric Schrock{
476379c004Eric Schrock	char *cachefile;
477379c004Eric Schrock	spa_config_dirent_t *dp;
478379c004Eric Schrock
479379c004Eric Schrock	if (nvlist_lookup_string(nvp, zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
480379c004Eric Schrock	    &cachefile) != 0)
481379c004Eric Schrock		return;
482379c004Eric Schrock
483379c004Eric Schrock	dp = kmem_alloc(sizeof (spa_config_dirent_t),
484379c004Eric Schrock	    KM_SLEEP);
485379c004Eric Schrock
486379c004Eric Schrock	if (cachefile[0] == '\0')
487379c004Eric Schrock		dp->scd_path = spa_strdup(spa_config_path);
488379c004Eric Schrock	else if (strcmp(cachefile, "none") == 0)
489379c004Eric Schrock		dp->scd_path = NULL;
490379c004Eric Schrock	else
491379c004Eric Schrock		dp->scd_path = spa_strdup(cachefile);
492379c004Eric Schrock
493379c004Eric Schrock	list_insert_head(&spa->spa_config_list, dp);
494379c004Eric Schrock	if (need_sync)
495379c004Eric Schrock		spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE);
496379c004Eric Schrock}
497379c004Eric Schrock
498990b485llingint
499990b485llingspa_prop_set(spa_t *spa, nvlist_t *nvp)
500990b485lling{
501990b485lling	int error;
502379c004Eric Schrock	nvpair_t *elem;
503379c004Eric Schrock	boolean_t need_sync = B_FALSE;
504379c004Eric Schrock	zpool_prop_t prop;
505990b485lling
506990b485lling	if ((error = spa_prop_validate(spa, nvp)) != 0)
507990b485lling		return (error);
508990b485lling
509379c004Eric Schrock	elem = NULL;
510379c004Eric Schrock	while ((elem = nvlist_next_nvpair(nvp, elem)) != NULL) {
511379c004Eric Schrock		if ((prop = zpool_name_to_prop(
512379c004Eric Schrock		    nvpair_name(elem))) == ZPROP_INVAL)
513379c004Eric Schrock			return (EINVAL);
514379c004Eric Schrock
515379c004Eric Schrock		if (prop == ZPOOL_PROP_CACHEFILE || prop == ZPOOL_PROP_ALTROOT)
516379c004Eric Schrock			continue;
517379c004Eric Schrock
518379c004Eric Schrock		need_sync = B_TRUE;
519379c004Eric Schrock		break;
520379c004Eric Schrock	}
521379c004Eric Schrock
522379c004Eric Schrock	if (need_sync)
523379c004Eric Schrock		return (dsl_sync_task_do(spa_get_dsl(spa), NULL, spa_sync_props,
524379c004Eric Schrock		    spa, nvp, 3));
525379c004Eric Schrock	else
526379c004Eric Schrock		return (0);
527990b485lling}
528990b485lling
529990b485lling/*
530990b485lling * If the bootfs property value is dsobj, clear it.
531990b485lling */
532990b485llingvoid
533990b485llingspa_prop_clear_bootfs(spa_t *spa, uint64_t dsobj, dmu_tx_t *tx)
534990b485lling{
535990b485lling	if (spa->spa_bootfs == dsobj && spa->spa_pool_props_object != 0) {
536990b485lling		VERIFY(zap_remove(spa->spa_meta_objset,
537990b485lling		    spa->spa_pool_props_object,
538990b485lling		    zpool_prop_to_name(ZPOOL_PROP_BOOTFS), tx) == 0);
539990b485lling		spa->spa_bootfs = 0;
540990b485lling	}
541990b485lling}
542990b485lling
543fa9e406ahrens/*
544fa9e406ahrens * ==========================================================================
545fa9e406ahrens * SPA state manipulation (open/create/destroy/import/export)
546fa9e406ahrens * ==========================================================================
547fa9e406ahrens */
548fa9e406ahrens
549ea8dc4beschrockstatic int
550ea8dc4beschrockspa_error_entry_compare(const void *a, const void *b)
551ea8dc4beschrock{
552ea8dc4beschrock	spa_error_entry_t *sa = (spa_error_entry_t *)a;
553ea8dc4beschrock	spa_error_entry_t *sb = (spa_error_entry_t *)b;
554ea8dc4beschrock	int ret;
555ea8dc4beschrock
556ea8dc4beschrock	ret = bcmp(&sa->se_bookmark, &sb->se_bookmark,
557ea8dc4beschrock	    sizeof (zbookmark_t));
558ea8dc4beschrock
559ea8dc4beschrock	if (ret < 0)
560ea8dc4beschrock		return (-1);
561ea8dc4beschrock	else if (ret > 0)
562ea8dc4beschrock		return (1);
563ea8dc4beschrock	else
564ea8dc4beschrock		return (0);
565ea8dc4beschrock}
566ea8dc4beschrock
567ea8dc4beschrock/*
568ea8dc4beschrock * Utility function which retrieves copies of the current logs and
569ea8dc4beschrock * re-initializes them in the process.
570ea8dc4beschrock */
571ea8dc4beschrockvoid
572ea8dc4beschrockspa_get_errlists(spa_t *spa, avl_tree_t *last, avl_tree_t *scrub)
573ea8dc4beschrock{
574ea8dc4beschrock	ASSERT(MUTEX_HELD(&spa->spa_errlist_lock));
575ea8dc4beschrock
576ea8dc4beschrock	bcopy(&spa->spa_errlist_last, last, sizeof (avl_tree_t));
577ea8dc4beschrock	bcopy(&spa->spa_errlist_scrub, scrub, sizeof (avl_tree_t));
578ea8dc4beschrock
579ea8dc4beschrock	avl_create(&spa->spa_errlist_scrub,
580ea8dc4beschrock	    spa_error_entry_compare, sizeof (spa_error_entry_t),
581ea8dc4beschrock	    offsetof(spa_error_entry_t, se_avl));
582ea8dc4beschrock	avl_create(&spa->spa_errlist_last,
583ea8dc4beschrock	    spa_error_entry_compare, sizeof (spa_error_entry_t),
584ea8dc4beschrock	    offsetof(spa_error_entry_t, se_avl));
585ea8dc4beschrock}
586ea8dc4beschrock
587fa9e406ahrens/*
588fa9e406ahrens * Activate an uninitialized pool.
589fa9e406ahrens */
590fa9e406ahrensstatic void
5918ad4d6dJeff Bonwickspa_activate(spa_t *spa, int mode)
592fa9e406ahrens{
593fa9e406ahrens	ASSERT(spa->spa_state == POOL_STATE_UNINITIALIZED);
594fa9e406ahrens
595fa9e406ahrens	spa->spa_state = POOL_STATE_ACTIVE;
5968ad4d6dJeff Bonwick	spa->spa_mode = mode;
597fa9e406ahrens
59888ecc94George Wilson	spa->spa_normal_class = metaslab_class_create(spa, zfs_metaslab_ops);
59988ecc94George Wilson	spa->spa_log_class = metaslab_class_create(spa, zfs_metaslab_ops);
600fa9e406ahrens
601e14bb32Jeff Bonwick	for (int t = 0; t < ZIO_TYPES; t++) {
602e14bb32Jeff Bonwick		for (int q = 0; q < ZIO_TASKQ_TYPES; q++) {
60380eb36fGeorge Wilson			const zio_taskq_info_t *ztip = &zio_taskqs[t][q];
60480eb36fGeorge Wilson			enum zti_modes mode = ztip->zti_mode;
60580eb36fGeorge Wilson			uint_t value = ztip->zti_value;
6062e0c549Jonathan Adams			char name[32];
6072e0c549Jonathan Adams
6082e0c549Jonathan Adams			(void) snprintf(name, sizeof (name),
60980eb36fGeorge Wilson			    "%s_%s", zio_type_name[t], zio_taskq_types[q]);
6102e0c549Jonathan Adams
6112e0c549Jonathan Adams			if (mode == zti_mode_tune) {
6122e0c549Jonathan Adams				mode = zio_taskq_tune_mode;
6132e0c549Jonathan Adams				value = zio_taskq_tune_value;
6142e0c549Jonathan Adams				if (mode == zti_mode_tune)
6152e0c549Jonathan Adams					mode = zti_mode_online_percent;
6162e0c549Jonathan Adams			}
6172e0c549Jonathan Adams
6182e0c549Jonathan Adams			switch (mode) {
6192e0c549Jonathan Adams			case zti_mode_fixed:
6202e0c549Jonathan Adams				ASSERT3U(value, >=, 1);
6212e0c549Jonathan Adams				value = MAX(value, 1);
6222e0c549Jonathan Adams
6232e0c549Jonathan Adams				spa->spa_zio_taskq[t][q] = taskq_create(name,
6242e0c549Jonathan Adams				    value, maxclsyspri, 50, INT_MAX,
6252e0c549Jonathan Adams				    TASKQ_PREPOPULATE);
6262e0c549Jonathan Adams				break;
6272e0c549Jonathan Adams
6282e0c549Jonathan Adams			case zti_mode_online_percent:
6292e0c549Jonathan Adams				spa->spa_zio_taskq[t][q] = taskq_create(name,
6302e0c549Jonathan Adams				    value, maxclsyspri, 50, INT_MAX,
6312e0c549Jonathan Adams				    TASKQ_PREPOPULATE | TASKQ_THREADS_CPU_PCT);
6322e0c549Jonathan Adams				break;
6332e0c549Jonathan Adams
63480eb36fGeorge Wilson			case zti_mode_null:
63580eb36fGeorge Wilson				spa->spa_zio_taskq[t][q] = NULL;
63680eb36fGeorge Wilson				break;
63780eb36fGeorge Wilson
6382e0c549Jonathan Adams			case zti_mode_tune:
6392e0c549Jonathan Adams			default:
6402e0c549Jonathan Adams				panic("unrecognized mode for "
6412e0c549Jonathan Adams				    "zio_taskqs[%u]->zti_nthreads[%u] (%u:%u) "
6422e0c549Jonathan Adams				    "in spa_activate()",
6432e0c549Jonathan Adams				    t, q, mode, value);
6442e0c549Jonathan Adams				break;
6452e0c549Jonathan Adams			}
646e14bb32Jeff Bonwick		}
647fa9e406ahrens	}
648fa9e406ahrens
649e14bb32Jeff Bonwick	list_create(&spa->spa_config_dirty_list, sizeof (vdev_t),
650e14bb32Jeff Bonwick	    offsetof(vdev_t, vdev_config_dirty_node));
651e14bb32Jeff Bonwick	list_create(&spa->spa_state_dirty_list, sizeof (vdev_t),
652e14bb32Jeff Bonwick	    offsetof(vdev_t, vdev_state_dirty_node));
653fa9e406ahrens
654fa9e406ahrens	txg_list_create(&spa->spa_vdev_txg_list,
655fa9e406ahrens	    offsetof(struct vdev, vdev_txg_node));
656ea8dc4beschrock
657ea8dc4beschrock	avl_create(&spa->spa_errlist_scrub,
658ea8dc4beschrock	    spa_error_entry_compare, sizeof (spa_error_entry_t),
659ea8dc4beschrock	    offsetof(spa_error_entry_t, se_avl));
660ea8dc4beschrock	avl_create(&spa->spa_errlist_last,
661ea8dc4beschrock	    spa_error_entry_compare, sizeof (spa_error_entry_t),
662ea8dc4beschrock	    offsetof(spa_error_entry_t, se_avl));
663fa9e406ahrens}
664fa9e406ahrens
665fa9e406ahrens/*
666fa9e406ahrens * Opposite of spa_activate().
667fa9e406ahrens */
668fa9e406ahrensstatic void
669fa9e406ahrensspa_deactivate(spa_t *spa)
670fa9e406ahrens{
671fa9e406ahrens	ASSERT(spa->spa_sync_on == B_FALSE);
672fa9e406ahrens	ASSERT(spa->spa_dsl_pool == NULL);
673fa9e406ahrens	ASSERT(spa->spa_root_vdev == NULL);
67425f89eeJeff Bonwick	ASSERT(spa->spa_async_zio_root == NULL);
675fa9e406ahrens	ASSERT(spa->spa_state != POOL_STATE_UNINITIALIZED);
676fa9e406ahrens
677fa9e406ahrens	txg_list_destroy(&spa->spa_vdev_txg_list);
678fa9e406ahrens
679e14bb32Jeff Bonwick	list_destroy(&spa->spa_config_dirty_list);
680e14bb32Jeff Bonwick	list_destroy(&spa->spa_state_dirty_list);
681fa9e406ahrens
682e14bb32Jeff Bonwick	for (int t = 0; t < ZIO_TYPES; t++) {
683e14bb32Jeff Bonwick		for (int q = 0; q < ZIO_TASKQ_TYPES; q++) {
68480eb36fGeorge Wilson			if (spa->spa_zio_taskq[t][q] != NULL)
68580eb36fGeorge Wilson				taskq_destroy(spa->spa_zio_taskq[t][q]);
686e14bb32Jeff Bonwick			spa->spa_zio_taskq[t][q] = NULL;
687e14bb32Jeff Bonwick		}
688fa9e406ahrens	}
689fa9e406ahrens
690fa9e406ahrens	metaslab_class_destroy(spa->spa_normal_class);
691