spa.c revision 4263d13f00c9691fa14620eff82abef795be0693
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/*
2398d1cbfGeorge Wilson * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
245aeb947Garrett D'Amore * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
254263d13George Wilson * Copyright (c) 2012 by Delphix. All rights reserved.
265aeb947Garrett D'Amore */
27fa9e406ahrens
28fa9e406ahrens/*
29fa9e406ahrens * This file contains all the routines used when modifying on-disk SPA state.
30fa9e406ahrens * This includes opening, importing, destroying, exporting a pool, and syncing a
31fa9e406ahrens * pool.
32fa9e406ahrens */
33fa9e406ahrens
34fa9e406ahrens#include <sys/zfs_context.h>
35ea8dc4beschrock#include <sys/fm/fs/zfs.h>
36fa9e406ahrens#include <sys/spa_impl.h>
37fa9e406ahrens#include <sys/zio.h>
38fa9e406ahrens#include <sys/zio_checksum.h>
39fa9e406ahrens#include <sys/dmu.h>
40fa9e406ahrens#include <sys/dmu_tx.h>
41fa9e406ahrens#include <sys/zap.h>
42fa9e406ahrens#include <sys/zil.h>
43b24ab67Jeff Bonwick#include <sys/ddt.h>
44fa9e406ahrens#include <sys/vdev_impl.h>
45fa9e406ahrens#include <sys/metaslab.h>
4688ecc94George Wilson#include <sys/metaslab_impl.h>
47fa9e406ahrens#include <sys/uberblock_impl.h>
48fa9e406ahrens#include <sys/txg.h>
49fa9e406ahrens#include <sys/avl.h>
50fa9e406ahrens#include <sys/dmu_traverse.h>
51b1b8ab3lling#include <sys/dmu_objset.h>
52fa9e406ahrens#include <sys/unique.h>
53fa9e406ahrens#include <sys/dsl_pool.h>
54b1b8ab3lling#include <sys/dsl_dataset.h>
55fa9e406ahrens#include <sys/dsl_dir.h>
56fa9e406ahrens#include <sys/dsl_prop.h>
57b1b8ab3lling#include <sys/dsl_synctask.h>
58fa9e406ahrens#include <sys/fs/zfs.h>
59fa94a07brendan#include <sys/arc.h>
60fa9e406ahrens#include <sys/callb.h>
619517395ek#include <sys/systeminfo.h>
62e7cbe64gw#include <sys/spa_boot.h>
63573ca77George Wilson#include <sys/zfs_ioctl.h>
643f9d6adLin Ling#include <sys/dsl_scan.h>
65fa9e406ahrens
665679c89jv#ifdef	_KERNEL
67dedec47Jack Meng#include <sys/bootprops.h>
6835a5a35Jonathan Adams#include <sys/callb.h>
6935a5a35Jonathan Adams#include <sys/cpupart.h>
7035a5a35Jonathan Adams#include <sys/pool.h>
7135a5a35Jonathan Adams#include <sys/sysdc.h>
7235a5a35Jonathan Adams#include <sys/zone.h>
735679c89jv#endif	/* _KERNEL */
745679c89jv
75990b485lling#include "zfs_prop.h"
76b7b9745perrin#include "zfs_comutil.h"
77990b485lling
7835a5a35Jonathan Adamstypedef enum zti_modes {
792e0c549Jonathan Adams	zti_mode_fixed,			/* value is # of threads (min 1) */
802e0c549Jonathan Adams	zti_mode_online_percent,	/* value is % of online CPUs */
8135a5a35Jonathan Adams	zti_mode_batch,			/* cpu-intensive; value is ignored */
8280eb36fGeorge Wilson	zti_mode_null,			/* don't create a taskq */
832e0c549Jonathan Adams	zti_nmodes
8435a5a35Jonathan Adams} zti_modes_t;
85416e0cdek
8680eb36fGeorge Wilson#define	ZTI_FIX(n)	{ zti_mode_fixed, (n) }
8780eb36fGeorge Wilson#define	ZTI_PCT(n)	{ zti_mode_online_percent, (n) }
8835a5a35Jonathan Adams#define	ZTI_BATCH	{ zti_mode_batch, 0 }
8980eb36fGeorge Wilson#define	ZTI_NULL	{ zti_mode_null, 0 }
902e0c549Jonathan Adams
9180eb36fGeorge Wilson#define	ZTI_ONE		ZTI_FIX(1)
922e0c549Jonathan Adams
932e0c549Jonathan Adamstypedef struct zio_taskq_info {
9480eb36fGeorge Wilson	enum zti_modes zti_mode;
9580eb36fGeorge Wilson	uint_t zti_value;
962e0c549Jonathan Adams} zio_taskq_info_t;
972e0c549Jonathan Adams
982e0c549Jonathan Adamsstatic const char *const zio_taskq_types[ZIO_TASKQ_TYPES] = {
9935a5a35Jonathan Adams	"issue", "issue_high", "intr", "intr_high"
1002e0c549Jonathan Adams};
1012e0c549Jonathan Adams
10280eb36fGeorge Wilson/*
10380eb36fGeorge Wilson * Define the taskq threads for the following I/O types:
10480eb36fGeorge Wilson * 	NULL, READ, WRITE, FREE, CLAIM, and IOCTL
10580eb36fGeorge Wilson */
10680eb36fGeorge Wilsonconst zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = {
10780eb36fGeorge Wilson	/* ISSUE	ISSUE_HIGH	INTR		INTR_HIGH */
10880eb36fGeorge Wilson	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
10935a5a35Jonathan Adams	{ ZTI_FIX(8),	ZTI_NULL,	ZTI_BATCH,	ZTI_NULL },
11035a5a35Jonathan Adams	{ ZTI_BATCH,	ZTI_FIX(5),	ZTI_FIX(8),	ZTI_FIX(5) },
111c7cd242George Wilson	{ ZTI_FIX(100),	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
11280eb36fGeorge Wilson	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
11380eb36fGeorge Wilson	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
1142e0c549Jonathan Adams};
1152e0c549Jonathan Adams
1163f9d6adLin Lingstatic dsl_syncfunc_t spa_sync_props;
11789a89ebllingstatic boolean_t spa_has_active_shared_spare(spa_t *spa);
1181195e68Mark J Musantestatic int spa_load_impl(spa_t *spa, uint64_t, nvlist_t *config,
1191195e68Mark J Musante    spa_load_state_t state, spa_import_type_t type, boolean_t mosconfig,
1201195e68Mark J Musante    char **ereport);
121cb04b87Mark J Musantestatic void spa_vdev_resilver_done(spa_t *spa);
122990b485lling
12335a5a35Jonathan Adamsuint_t		zio_taskq_batch_pct = 100;	/* 1 thread per cpu in pset */
12435a5a35Jonathan Adamsid_t		zio_taskq_psrset_bind = PS_NONE;
12535a5a35Jonathan Adamsboolean_t	zio_taskq_sysdc = B_TRUE;	/* use SDC scheduling class */
12635a5a35Jonathan Adamsuint_t		zio_taskq_basedc = 80;		/* base duty cycle */
12735a5a35Jonathan Adams
12835a5a35Jonathan Adamsboolean_t	spa_create_process = B_TRUE;	/* no process ==> no sysdc */
12935a5a35Jonathan Adams
13035a5a35Jonathan Adams/*
13135a5a35Jonathan Adams * This (illegal) pool name is used when temporarily importing a spa_t in order
13235a5a35Jonathan Adams * to get the vdev stats associated with the imported devices.
13335a5a35Jonathan Adams */
13435a5a35Jonathan Adams#define	TRYIMPORT_NAME	"$import"
13535a5a35Jonathan Adams
136990b485lling/*
137990b485lling * ==========================================================================
138990b485lling * SPA properties routines
139990b485lling * ==========================================================================
140990b485lling */
141990b485lling
142990b485lling/*
143990b485lling * Add a (source=src, propname=propval) list to an nvlist.
144990b485lling */
1459d82f4fllingstatic void
146990b485llingspa_prop_add_list(nvlist_t *nvl, zpool_prop_t prop, char *strval,
147990b485lling    uint64_t intval, zprop_source_t src)
148990b485lling{
149990b485lling	const char *propname = zpool_prop_to_name(prop);
150990b485lling	nvlist_t *propval;
151990b485lling
1529d82f4flling	VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1539d82f4flling	VERIFY(nvlist_add_uint64(propval, ZPROP_SOURCE, src) == 0);
154990b485lling
1559d82f4flling	if (strval != NULL)
1569d82f4flling		VERIFY(nvlist_add_string(propval, ZPROP_VALUE, strval) == 0);
1579d82f4flling	else
1589d82f4flling		VERIFY(nvlist_add_uint64(propval, ZPROP_VALUE, intval) == 0);
159990b485lling
1609d82f4flling	VERIFY(nvlist_add_nvlist(nvl, propname, propval) == 0);
161990b485lling	nvlist_free(propval);
162990b485lling}
163990b485lling
164990b485lling/*
165990b485lling * Get property values from the spa configuration.
166990b485lling */
1679d82f4fllingstatic void
168990b485llingspa_prop_get_config(spa_t *spa, nvlist_t **nvp)
169990b485lling{
1704263d13George Wilson	vdev_t *rvd = spa->spa_root_vdev;
171379c004Eric Schrock	uint64_t size;
172485bbbfGeorge Wilson	uint64_t alloc;
1734263d13George Wilson	uint64_t space;
174990b485lling	uint64_t cap, version;
175990b485lling	zprop_source_t src = ZPROP_SRC_NONE;
176c5904d1eschrock	spa_config_dirent_t *dp;
177990b485lling
178e14bb32Jeff Bonwick	ASSERT(MUTEX_HELD(&spa->spa_props_lock));
179e14bb32Jeff Bonwick
1804263d13George Wilson	if (rvd != NULL) {
181485bbbfGeorge Wilson		alloc = metaslab_class_get_alloc(spa_normal_class(spa));
182b24ab67Jeff Bonwick		size = metaslab_class_get_space(spa_normal_class(spa));
183379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_NAME, spa_name(spa), 0, src);
184379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_SIZE, NULL, size, src);
185485bbbfGeorge Wilson		spa_prop_add_list(*nvp, ZPOOL_PROP_ALLOCATED, NULL, alloc, src);
186485bbbfGeorge Wilson		spa_prop_add_list(*nvp, ZPOOL_PROP_FREE, NULL,
187485bbbfGeorge Wilson		    size - alloc, src);
1884263d13George Wilson
1894263d13George Wilson		space = 0;
1904263d13George Wilson		for (int c = 0; c < rvd->vdev_children; c++) {
1914263d13George Wilson			vdev_t *tvd = rvd->vdev_child[c];
1924263d13George Wilson			space += tvd->vdev_max_asize - tvd->vdev_asize;
1934263d13George Wilson		}
1944263d13George Wilson		spa_prop_add_list(*nvp, ZPOOL_PROP_EXPANDSZ, NULL, space,
1954263d13George Wilson		    src);
1964263d13George Wilson
197f9af39bGeorge Wilson		spa_prop_add_list(*nvp, ZPOOL_PROP_READONLY, NULL,
198f9af39bGeorge Wilson		    (spa_mode(spa) == FREAD), src);
199379c004Eric Schrock
200485bbbfGeorge Wilson		cap = (size == 0) ? 0 : (alloc * 100 / size);
201379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_CAPACITY, NULL, cap, src);
202379c004Eric Schrock
203b24ab67Jeff Bonwick		spa_prop_add_list(*nvp, ZPOOL_PROP_DEDUPRATIO, NULL,
204b24ab67Jeff Bonwick		    ddt_get_pool_dedup_ratio(spa), src);
205b24ab67Jeff Bonwick
206379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_HEALTH, NULL,
2074263d13George Wilson		    rvd->vdev_state, src);
208379c004Eric Schrock
209379c004Eric Schrock		version = spa_version(spa);
210379c004Eric Schrock		if (version == zpool_prop_default_numeric(ZPOOL_PROP_VERSION))
211379c004Eric Schrock			src = ZPROP_SRC_DEFAULT;
212379c004Eric Schrock		else
213379c004Eric Schrock			src = ZPROP_SRC_LOCAL;
214379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_VERSION, NULL, version, src);
215379c004Eric Schrock	}
216990b485lling
2179d82f4flling	spa_prop_add_list(*nvp, ZPOOL_PROP_GUID, NULL, spa_guid(spa), src);
218990b485lling
2198704186Dan McDonald	if (spa->spa_comment != NULL) {
2208704186Dan McDonald		spa_prop_add_list(*nvp, ZPOOL_PROP_COMMENT, spa->spa_comment,
2218704186Dan McDonald		    0, ZPROP_SRC_LOCAL);
2228704186Dan McDonald	}
2238704186Dan McDonald
2249d82f4flling	if (spa->spa_root != NULL)
2259d82f4flling		spa_prop_add_list(*nvp, ZPOOL_PROP_ALTROOT, spa->spa_root,
2269d82f4flling		    0, ZPROP_SRC_LOCAL);
227990b485lling
228c5904d1eschrock	if ((dp = list_head(&spa->spa_config_list)) != NULL) {
229c5904d1eschrock		if (dp->scd_path == NULL) {
2309d82f4flling			spa_prop_add_list(*nvp, ZPOOL_PROP_CACHEFILE,
231c5904d1eschrock			    "none", 0, ZPROP_SRC_LOCAL);
232c5904d1eschrock		} else if (strcmp(dp->scd_path, spa_config_path) != 0) {
2339d82f4flling			spa_prop_add_list(*nvp, ZPOOL_PROP_CACHEFILE,
234c5904d1eschrock			    dp->scd_path, 0, ZPROP_SRC_LOCAL);
2352f8aaabeschrock		}
2362f8aaabeschrock	}
237990b485lling}
238990b485lling
239990b485lling/*
240990b485lling * Get zpool property values.
241990b485lling */
242990b485llingint
243990b485llingspa_prop_get(spa_t *spa, nvlist_t **nvp)
244990b485lling{
245b24ab67Jeff Bonwick	objset_t *mos = spa->spa_meta_objset;
246990b485lling	zap_cursor_t zc;
247990b485lling	zap_attribute_t za;
248990b485lling	int err;
249990b485lling
2509d82f4flling	VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
251990b485lling
252e14bb32Jeff Bonwick	mutex_enter(&spa->spa_props_lock);
253e14bb32Jeff Bonwick
254990b485lling	/*
255990b485lling	 * Get properties from the spa config.
256990b485lling	 */
2579d82f4flling	spa_prop_get_config(spa, nvp);
258990b485lling
259990b485lling	/* If no pool property object, no more prop to get. */
260afee20eGeorge Wilson	if (mos == NULL || spa->spa_pool_props_object == 0) {
261990b485lling		mutex_exit(&spa->spa_props_lock);
262990b485lling		return (0);
263990b485lling	}
264990b485lling
265990b485lling	/*
266990b485lling	 * Get properties from the MOS pool property object.
267990b485lling	 */
268990b485lling	for (zap_cursor_init(&zc, mos, spa->spa_pool_props_object);
269990b485lling	    (err = zap_cursor_retrieve(&zc, &za)) == 0;
270990b485lling	    zap_cursor_advance(&zc)) {
271990b485lling		uint64_t intval = 0;
272990b485lling		char *strval = NULL;
273990b485lling		zprop_source_t src = ZPROP_SRC_DEFAULT;
274990b485lling		zpool_prop_t prop;
275990b485lling
276990b485lling		if ((prop = zpool_name_to_prop(za.za_name)) == ZPROP_INVAL)
277990b485lling			continue;
278990b485lling
279990b485lling		switch (za.za_integer_length) {
280990b485lling		case 8:
281990b485lling			/* integer property */
282990b485lling			if (za.za_first_integer !=
283990b485lling			    zpool_prop_default_numeric(prop))
284990b485lling				src = ZPROP_SRC_LOCAL;
285990b485lling
286990b485lling			if (prop == ZPOOL_PROP_BOOTFS) {
287990b485lling				dsl_pool_t *dp;
288990b485lling				dsl_dataset_t *ds = NULL;
289990b485lling
290990b485lling				dp = spa_get_dsl(spa);
291990b485lling				rw_enter(&dp->dp_config_rwlock, RW_READER);
292745cd3cmaybee				if (err = dsl_dataset_hold_obj(dp,
293745cd3cmaybee				    za.za_first_integer, FTAG, &ds)) {
294990b485lling					rw_exit(&dp->dp_config_rwlock);
295990b485lling					break;
296990b485lling				}
297990b485lling
298990b485lling				strval = kmem_alloc(
299990b485lling				    MAXNAMELEN + strlen(MOS_DIR_NAME) + 1,
300990b485lling				    KM_SLEEP);
301990b485lling				dsl_dataset_name(ds, strval);
302745cd3cmaybee				dsl_dataset_rele(ds, FTAG);
303990b485lling				rw_exit(&dp->dp_config_rwlock);
304990b485lling			} else {
305990b485lling				strval = NULL;
306990b485lling				intval = za.za_first_integer;
307990b485lling			}
308990b485lling
3099d82f4flling			spa_prop_add_list(*nvp, prop, strval, intval, src);
310990b485lling
311990b485lling			if (strval != NULL)
312990b485lling				kmem_free(strval,
313990b485lling				    MAXNAMELEN + strlen(MOS_DIR_NAME) + 1);
314990b485lling
315990b485lling			break;
316990b485lling
317990b485lling		case 1:
318990b485lling			/* string property */
319990b485lling			strval = kmem_alloc(za.za_num_integers, KM_SLEEP);
320990b485lling			err = zap_lookup(mos, spa->spa_pool_props_object,
321990b485lling			    za.za_name, 1, za.za_num_integers, strval);
322990b485lling			if (err) {
323990b485lling				kmem_free(strval, za.za_num_integers);
324990b485lling				break;
325990b485lling			}
3269d82f4flling			spa_prop_add_list(*nvp, prop, strval, 0, src);
327990b485lling			kmem_free(strval, za.za_num_integers);
328990b485lling			break;
329990b485lling
330990b485lling		default:
331990b485lling			break;
332990b485lling		}
333990b485lling	}
334990b485lling	zap_cursor_fini(&zc);
335990b485lling	mutex_exit(&spa->spa_props_lock);
336990b485llingout:
337990b485lling	if (err && err != ENOENT) {
338990b485lling		nvlist_free(*nvp);
3399d82f4flling		*nvp = NULL;
340990b485lling		return (err);
341990b485lling	}
342990b485lling
343990b485lling	return (0);
344990b485lling}
345990b485lling
346990b485lling/*
347990b485lling * Validate the given pool properties nvlist and modify the list
348990b485lling * for the property values to be set.
349990b485lling */
350990b485llingstatic int
351990b485llingspa_prop_validate(spa_t *spa, nvlist_t *props)
352990b485lling{
353990b485lling	nvpair_t *elem;
354990b485lling	int error = 0, reset_bootfs = 0;
355990b485lling	uint64_t objnum;
356990b485lling
357990b485lling	elem = NULL;
358990b485lling	while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
359990b485lling		zpool_prop_t prop;
360990b485lling		char *propname, *strval;
361990b485lling		uint64_t intval;
362990b485lling		objset_t *os;
3638704186Dan McDonald		char *slash, *check;
364990b485lling
365990b485lling		propname = nvpair_name(elem);
366990b485lling
367990b485lling		if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL)
368990b485lling			return (EINVAL);
369990b485lling
370990b485lling		switch (prop) {
371990b485lling		case ZPOOL_PROP_VERSION:
372990b485lling			error = nvpair_value_uint64(elem, &intval);
373990b485lling			if (!error &&
374990b485lling			    (intval < spa_version(spa) || intval > SPA_VERSION))
375990b485lling				error = EINVAL;
376990b485lling			break;
377990b485lling
378990b485lling		case ZPOOL_PROP_DELEGATION:
379990b485lling		case ZPOOL_PROP_AUTOREPLACE:
380d5b5bb2Rich Morris		case ZPOOL_PROP_LISTSNAPS:
381573ca77George Wilson		case ZPOOL_PROP_AUTOEXPAND:
382990b485lling			error = nvpair_value_uint64(elem, &intval);
383990b485lling			if (!error && intval > 1)
384990b485lling				error = EINVAL;
385990b485lling			break;
386990b485lling
387990b485lling		case ZPOOL_PROP_BOOTFS:
38825f89eeJeff Bonwick			/*
38925f89eeJeff Bonwick			 * If the pool version is less than SPA_VERSION_BOOTFS,
39025f89eeJeff Bonwick			 * or the pool is still being created (version == 0),
39125f89eeJeff Bonwick			 * the bootfs property cannot be set.
39225f89eeJeff Bonwick			 */
393990b485lling			if (spa_version(spa) < SPA_VERSION_BOOTFS) {
394990b485lling				error = ENOTSUP;
395990b485lling				break;
396990b485lling			}
397990b485lling
398990b485lling			/*
39915e6edfgw			 * Make sure the vdev config is bootable
400990b485lling			 */
40115e6edfgw			if (!vdev_is_bootable(spa->spa_root_vdev)) {
402990b485lling				error = ENOTSUP;
403990b485lling				break;
404990b485lling			}
405990b485lling
406990b485lling			reset_bootfs = 1;
407990b485lling
408990b485lling			error = nvpair_value_string(elem, &strval);
409990b485lling
410990b485lling			if (!error) {
41115e6edfgw				uint64_t compress;
41215e6edfgw
413990b485lling				if (strval == NULL || strval[0] == '\0') {
414990b485lling					objnum = zpool_prop_default_numeric(
415990b485lling					    ZPOOL_PROP_BOOTFS);
416990b485lling					break;
417990b485lling				}
418990b485lling
419503ad85Matthew Ahrens				if (error = dmu_objset_hold(strval, FTAG, &os))
420990b485lling					break;
42115e6edfgw
422503ad85Matthew Ahrens				/* Must be ZPL and not gzip compressed. */
423503ad85Matthew Ahrens
424503ad85Matthew Ahrens				if (dmu_objset_type(os) != DMU_OST_ZFS) {
425503ad85Matthew Ahrens					error = ENOTSUP;
426503ad85Matthew Ahrens				} else if ((error = dsl_prop_get_integer(strval,
42715e6edfgw				    zfs_prop_to_name(ZFS_PROP_COMPRESSION),
42815e6edfgw				    &compress, NULL)) == 0 &&
42915e6edfgw				    !BOOTFS_COMPRESS_VALID(compress)) {
43015e6edfgw					error = ENOTSUP;
43115e6edfgw				} else {
43215e6edfgw					objnum = dmu_objset_id(os);
43315e6edfgw				}
434503ad85Matthew Ahrens				dmu_objset_rele(os, FTAG);
435990b485lling			}
436990b485lling			break;
437e14bb32Jeff Bonwick
4380a4e951gw		case ZPOOL_PROP_FAILUREMODE:
4390a4e951gw			error = nvpair_value_uint64(elem, &intval);
4400a4e951gw			if (!error && (intval < ZIO_FAILURE_MODE_WAIT ||
4410a4e951gw			    intval > ZIO_FAILURE_MODE_PANIC))
4420a4e951gw				error = EINVAL;
4430a4e951gw
4440a4e951gw			/*
4450a4e951gw			 * This is a special case which only occurs when
4460a4e951gw			 * the pool has completely failed. This allows
4470a4e951gw			 * the user to change the in-core failmode property
4480a4e951gw			 * without syncing it out to disk (I/Os might
4490a4e951gw			 * currently be blocked). We do this by returning
4500a4e951gw			 * EIO to the caller (spa_prop_set) to trick it
4510a4e951gw			 * into thinking we encountered a property validation
4520a4e951gw			 * error.
4530a4e951gw			 */
454e14bb32Jeff Bonwick			if (!error && spa_suspended(spa)) {
4550a4e951gw				spa->spa_failmode = intval;
4560a4e951gw				error = EIO;
4570a4e951gw			}
4580a4e951gw			break;
4592f8aaabeschrock
4602f8aaabeschrock		case ZPOOL_PROP_CACHEFILE:
4612f8aaabeschrock			if ((error = nvpair_value_string(elem, &strval)) != 0)
4622f8aaabeschrock				break;
4632f8aaabeschrock
4642f8aaabeschrock			if (strval[0] == '\0')
4652f8aaabeschrock				break;
4662f8aaabeschrock
4672f8aaabeschrock			if (strcmp(strval, "none") == 0)
4682f8aaabeschrock				break;
4692f8aaabeschrock
4702f8aaabeschrock			if (strval[0] != '/') {
4712f8aaabeschrock				error = EINVAL;
4722f8aaabeschrock				break;
4732f8aaabeschrock			}
4742f8aaabeschrock
4752f8aaabeschrock			slash = strrchr(strval, '/');
4762f8aaabeschrock			ASSERT(slash != NULL);
4772f8aaabeschrock
4782f8aaabeschrock			if (slash[1] == '\0' || strcmp(slash, "/.") == 0 ||
4792f8aaabeschrock			    strcmp(slash, "/..") == 0)
4802f8aaabeschrock				error = EINVAL;
4812f8aaabeschrock			break;
482b24ab67Jeff Bonwick
4838704186Dan McDonald		case ZPOOL_PROP_COMMENT:
4848704186Dan McDonald			if ((error = nvpair_value_string(elem, &strval)) != 0)
4858704186Dan McDonald				break;
4868704186Dan McDonald			for (check = strval; *check != '\0'; check++) {
4878704186Dan McDonald				/*
4888704186Dan McDonald				 * The kernel doesn't have an easy isprint()
4898704186Dan McDonald				 * check.  For this kernel check, we merely
4908704186Dan McDonald				 * check ASCII apart from DEL.  Fix this if
4918704186Dan McDonald				 * there is an easy-to-use kernel isprint().
4928704186Dan McDonald				 */
4938704186Dan McDonald				if (*check >= 0x7f) {
4948704186Dan McDonald					error = EINVAL;
4958704186Dan McDonald					break;
4968704186Dan McDonald				}
4978704186Dan McDonald				check++;
4988704186Dan McDonald			}
4998704186Dan McDonald			if (strlen(strval) > ZPROP_MAX_COMMENT)
5008704186Dan McDonald				error = E2BIG;
5018704186Dan McDonald			break;
5028704186Dan McDonald
503b24ab67Jeff Bonwick		case ZPOOL_PROP_DEDUPDITTO:
504b24ab67Jeff Bonwick			if (spa_version(spa) < SPA_VERSION_DEDUP)
505b24ab67Jeff Bonwick				error = ENOTSUP;
506b24ab67Jeff Bonwick			else
507b24ab67Jeff Bonwick				error = nvpair_value_uint64(elem, &intval);
508b24ab67Jeff Bonwick			if (error == 0 &&
509b24ab67Jeff Bonwick			    intval != 0 && intval < ZIO_DEDUPDITTO_MIN)
510b24ab67Jeff Bonwick				error = EINVAL;
511b24ab67Jeff Bonwick			break;
512990b485lling		}
513990b485lling
514990b485lling		if (error)
515990b485lling			break;
516990b485lling	}
517990b485lling
518990b485lling	if (!error && reset_bootfs) {
519990b485lling		error = nvlist_remove(props,
520990b485lling		    zpool_prop_to_name(ZPOOL_PROP_BOOTFS), DATA_TYPE_STRING);
521990b485lling
522990b485lling		if (!error) {
523990b485lling			error = nvlist_add_uint64(props,
524990b485lling			    zpool_prop_to_name(ZPOOL_PROP_BOOTFS), objnum);
525990b485lling		}
526990b485lling	}
527990b485lling
528990b485lling	return (error);
529990b485lling}
530990b485lling
531379c004Eric Schrockvoid
532379c004Eric Schrockspa_configfile_set(spa_t *spa, nvlist_t *nvp, boolean_t need_sync)
533379c004Eric Schrock{
534379c004Eric Schrock	char *cachefile;
535379c004Eric Schrock	spa_config_dirent_t *dp;
536379c004Eric Schrock
537379c004Eric Schrock	if (nvlist_lookup_string(nvp, zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
538379c004Eric Schrock	    &cachefile) != 0)
539379c004Eric Schrock		return;
540379c004Eric Schrock
541379c004Eric Schrock	dp = kmem_alloc(sizeof (spa_config_dirent_t),
542379c004Eric Schrock	    KM_SLEEP);
543379c004Eric Schrock
544379c004Eric Schrock	if (cachefile[0] == '\0')
545379c004Eric Schrock		dp->scd_path = spa_strdup(spa_config_path);
546379c004Eric Schrock	else if (strcmp(cachefile, "none") == 0)
547379c004Eric Schrock		dp->scd_path = NULL;
548379c004Eric Schrock	else
549379c004Eric Schrock		dp->scd_path = spa_strdup(cachefile);
550379c004Eric Schrock
551379c004Eric Schrock	list_insert_head(&spa->spa_config_list, dp);
552379c004Eric Schrock	if (need_sync)
553379c004Eric Schrock		spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE);
554379c004Eric Schrock}
555379c004Eric Schrock
556990b485llingint
557990b485llingspa_prop_set(spa_t *spa, nvlist_t *nvp)
558990b485lling{
559990b485lling	int error;
560379c004Eric Schrock	nvpair_t *elem;
561379c004Eric Schrock	boolean_t need_sync = B_FALSE;
562379c004Eric Schrock	zpool_prop_t prop;
563990b485lling
564990b485lling	if ((error = spa_prop_validate(spa, nvp)) != 0)
565990b485lling		return (error);
566990b485lling
567379c004Eric Schrock	elem = NULL;
568379c004Eric Schrock	while ((elem = nvlist_next_nvpair(nvp, elem)) != NULL) {
569379c004Eric Schrock		if ((prop = zpool_name_to_prop(
570379c004Eric Schrock		    nvpair_name(elem))) == ZPROP_INVAL)
571379c004Eric Schrock			return (EINVAL);
572379c004Eric Schrock
573f9af39bGeorge Wilson		if (prop == ZPOOL_PROP_CACHEFILE ||
574f9af39bGeorge Wilson		    prop == ZPOOL_PROP_ALTROOT ||
575f9af39bGeorge Wilson		    prop == ZPOOL_PROP_READONLY)
576379c004Eric Schrock			continue;
577379c004Eric Schrock
578379c004Eric Schrock		need_sync = B_TRUE;
579379c004Eric Schrock		break;
580379c004Eric Schrock	}
581379c004Eric Schrock
582379c004Eric Schrock	if (need_sync)
583379c004Eric Schrock		return (dsl_sync_task_do(spa_get_dsl(spa), NULL, spa_sync_props,
584379c004Eric Schrock		    spa, nvp, 3));
585379c004Eric Schrock	else
586379c004Eric Schrock		return (0);
587990b485lling}
588990b485lling
589990b485lling/*
590990b485lling * If the bootfs property value is dsobj, clear it.
591990b485lling */
592990b485llingvoid
593990b485llingspa_prop_clear_bootfs(spa_t *spa, uint64_t dsobj, dmu_tx_t *tx)
594990b485lling{
595990b485lling	if (spa->spa_bootfs == dsobj && spa->spa_pool_props_object != 0) {
596990b485lling		VERIFY(zap_remove(spa->spa_meta_objset,
597990b485lling		    spa->spa_pool_props_object,
598990b485lling		    zpool_prop_to_name(ZPOOL_PROP_BOOTFS), tx) == 0);
599990b485lling		spa->spa_bootfs = 0;
600990b485lling	}
601990b485lling}
602990b485lling
603fa9e406ahrens/*
604e9103aaGarrett D'Amore * Change the GUID for the pool.  This is done so that we can later
605e9103aaGarrett D'Amore * re-import a pool built from a clone of our own vdevs.  We will modify
606e9103aaGarrett D'Amore * the root vdev's guid, our own pool guid, and then mark all of our
607e9103aaGarrett D'Amore * vdevs dirty.  Note that we must make sure that all our vdevs are
608e9103aaGarrett D'Amore * online when we do this, or else any vdevs that weren't present
609e9103aaGarrett D'Amore * would be orphaned from our pool.  We are also going to issue a
610e9103aaGarrett D'Amore * sysevent to update any watchers.
611e9103aaGarrett D'Amore */
612e9103aaGarrett D'Amoreint
613e9103aaGarrett D'Amorespa_change_guid(spa_t *spa)
614e9103aaGarrett D'Amore{
615e9103aaGarrett D'Amore	uint64_t	oldguid, newguid;
616e9103aaGarrett D'Amore	uint64_t	txg;
617e9103aaGarrett D'Amore
618e9103aaGarrett D'Amore	if (!(spa_mode_global & FWRITE))
619e9103aaGarrett D'Amore		return (EROFS);
620e9103aaGarrett D'Amore
621e9103aaGarrett D'Amore	txg = spa_vdev_enter(spa);
622e9103aaGarrett D'Amore
623e9103aaGarrett D'Amore	if (spa->spa_root_vdev->vdev_state != VDEV_STATE_HEALTHY)
624e9103aaGarrett D'Amore		return (spa_vdev_exit(spa, NULL, txg, ENXIO));
625e9103aaGarrett D'Amore
626e9103aaGarrett D'Amore	oldguid = spa_guid(spa);
627e9103aaGarrett D'Amore	newguid = spa_generate_guid(NULL);
628e9103aaGarrett D'Amore	ASSERT3U(oldguid, !=, newguid);
629e9103aaGarrett D'Amore
630e9103aaGarrett D'Amore	spa->spa_root_vdev->vdev_guid = newguid;
631e9103aaGarrett D'Amore	spa->spa_root_vdev->vdev_guid_sum += (newguid - oldguid);
632e9103aaGarrett D'Amore
633e9103aaGarrett D'Amore	vdev_config_dirty(spa->spa_root_vdev);
634e9103aaGarrett D'Amore
635e9103aaGarrett D'Amore	spa_event_notify(spa, NULL, ESC_ZFS_POOL_REGUID);
636e9103aaGarrett D'Amore
637e9103aaGarrett D'Amore	return (spa_vdev_exit(spa, NULL, txg, 0));
638e9103aaGarrett D'Amore}
639e9103aaGarrett D'Amore
640e9103aaGarrett D'Amore/*
641fa9e406ahrens * ==========================================================================
642fa9e406ahrens * SPA state manipulation (open/create/destroy/import/export)
643fa9e406ahrens * ==========================================================================
644fa9e406ahrens */
645fa9e406ahrens
646ea8dc4beschrockstatic int
647ea8dc4beschrockspa_error_entry_compare(const void *a, const void *b)
648ea8dc4beschrock{
649ea8dc4beschrock	spa_error_entry_t *sa = (spa_error_entry_t *)a;
650ea8dc4beschrock	spa_error_entry_t *sb = (spa_error_entry_t *)b;
651ea8dc4beschrock	int ret;
652ea8dc4beschrock
653ea8dc4beschrock	ret = bcmp(&sa->se_bookmark, &sb->se_bookmark,
654ea8dc4beschrock	    sizeof (zbookmark_t));
655ea8dc4beschrock
656ea8dc4beschrock	if (ret < 0)
657ea8dc4beschrock		return (-1);
658ea8dc4beschrock	else if (ret > 0)
659ea8dc4beschrock		return (1);
660ea8dc4beschrock	else
661ea8dc4beschrock		return (0);
662ea8dc4beschrock}
663ea8dc4beschrock
664ea8dc4beschrock/*
665ea8dc4beschrock * Utility function which retrieves copies of the current logs and
666ea8dc4beschrock * re-initializes them in the process.
667ea8dc4beschrock */
668ea8dc4beschrockvoid
669ea8dc4beschrockspa_get_errlists(spa_t *spa, avl_tree_t *last, avl_tree_t *scrub)
670ea8dc4beschrock{
671ea8dc4beschrock	ASSERT(MUTEX_HELD(&spa->spa_errlist_lock));
672ea8dc4beschrock
673ea8dc4beschrock	bcopy(&spa->spa_errlist_last, last, sizeof (avl_tree_t));
674ea8dc4beschrock	bcopy(&spa->spa_errlist_scrub, scrub, sizeof (avl_tree_t));
675ea8dc4beschrock
676ea8dc4beschrock	avl_create(&spa->spa_errlist_scrub,
677ea8dc4beschrock	    spa_error_entry_compare, sizeof (spa_error_entry_t),
678ea8dc4beschrock	    offsetof(spa_error_entry_t, se_avl));
679ea8dc4beschrock	avl_create(&spa->spa_errlist_last,
680ea8dc4beschrock	    spa_error_entry_compare, sizeof (spa_error_entry_t),
681ea8dc4beschrock	    offsetof(spa_error_entry_t, se_avl));
682ea8dc4beschrock}
683ea8dc4beschrock
68435a5a35Jonathan Adamsstatic taskq_t *
68535a5a35Jonathan Adamsspa_taskq_create(spa_t *spa, const char *name, enum zti_modes mode,
68635a5a35Jonathan Adams    uint_t value)
687fa9e406ahrens{
688