spa.c revision 20128a0826f9c53167caa9215c12f08beee48e30
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
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 */
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 */
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 */
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>
65ad135b5Christopher Siden#include <sys/zfeature.h>
675679c89jv#ifdef	_KERNEL
68dedec47Jack Meng#include <sys/bootprops.h>
6935a5a35Jonathan Adams#include <sys/callb.h>
7035a5a35Jonathan Adams#include <sys/cpupart.h>
7135a5a35Jonathan Adams#include <sys/pool.h>
7235a5a35Jonathan Adams#include <sys/sysdc.h>
7335a5a35Jonathan Adams#include <sys/zone.h>
745679c89jv#endif	/* _KERNEL */
76990b485lling#include "zfs_prop.h"
77b7b9745perrin#include "zfs_comutil.h"
7935a5a35Jonathan Adamstypedef enum zti_modes {
802e0c549Jonathan Adams	zti_mode_fixed,			/* value is # of threads (min 1) */
812e0c549Jonathan Adams	zti_mode_online_percent,	/* value is % of online CPUs */
8235a5a35Jonathan Adams	zti_mode_batch,			/* cpu-intensive; value is ignored */
8380eb36fGeorge Wilson	zti_mode_null,			/* don't create a taskq */
842e0c549Jonathan Adams	zti_nmodes
8535a5a35Jonathan Adams} zti_modes_t;
8780eb36fGeorge Wilson#define	ZTI_FIX(n)	{ zti_mode_fixed, (n) }
8880eb36fGeorge Wilson#define	ZTI_PCT(n)	{ zti_mode_online_percent, (n) }
8935a5a35Jonathan Adams#define	ZTI_BATCH	{ zti_mode_batch, 0 }
9080eb36fGeorge Wilson#define	ZTI_NULL	{ zti_mode_null, 0 }
912e0c549Jonathan Adams
9280eb36fGeorge Wilson#define	ZTI_ONE		ZTI_FIX(1)
932e0c549Jonathan Adams
942e0c549Jonathan Adamstypedef struct zio_taskq_info {
9580eb36fGeorge Wilson	enum zti_modes zti_mode;
9680eb36fGeorge Wilson	uint_t zti_value;
972e0c549Jonathan Adams} zio_taskq_info_t;
982e0c549Jonathan Adams
992e0c549Jonathan Adamsstatic const char *const zio_taskq_types[ZIO_TASKQ_TYPES] = {
10035a5a35Jonathan Adams	"issue", "issue_high", "intr", "intr_high"
1012e0c549Jonathan Adams};
1022e0c549Jonathan Adams
10380eb36fGeorge Wilson/*
10480eb36fGeorge Wilson * Define the taskq threads for the following I/O types:
10580eb36fGeorge Wilson * 	NULL, READ, WRITE, FREE, CLAIM, and IOCTL
10680eb36fGeorge Wilson */
10780eb36fGeorge Wilsonconst zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = {
10880eb36fGeorge Wilson	/* ISSUE	ISSUE_HIGH	INTR		INTR_HIGH */
10980eb36fGeorge Wilson	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
11035a5a35Jonathan Adams	{ ZTI_FIX(8),	ZTI_NULL,	ZTI_BATCH,	ZTI_NULL },
11135a5a35Jonathan Adams	{ ZTI_BATCH,	ZTI_FIX(5),	ZTI_FIX(8),	ZTI_FIX(5) },
112c7cd242George Wilson	{ ZTI_FIX(100),	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
11380eb36fGeorge Wilson	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
11480eb36fGeorge Wilson	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
1152e0c549Jonathan Adams};
1162e0c549Jonathan Adams
117ad135b5Christopher Sidenstatic dsl_syncfunc_t spa_sync_version;
1183f9d6adLin Lingstatic dsl_syncfunc_t spa_sync_props;
119dfbb943George Wilsonstatic dsl_checkfunc_t spa_change_guid_check;
120dfbb943George Wilsonstatic dsl_syncfunc_t spa_change_guid_sync;
12189a89ebllingstatic boolean_t spa_has_active_shared_spare(spa_t *spa);
1221195e68Mark J Musantestatic int spa_load_impl(spa_t *spa, uint64_t, nvlist_t *config,
1231195e68Mark J Musante    spa_load_state_t state, spa_import_type_t type, boolean_t mosconfig,
1241195e68Mark J Musante    char **ereport);
125cb04b87Mark J Musantestatic void spa_vdev_resilver_done(spa_t *spa);
12735a5a35Jonathan Adamsuint_t		zio_taskq_batch_pct = 100;	/* 1 thread per cpu in pset */
12835a5a35Jonathan Adamsid_t		zio_taskq_psrset_bind = PS_NONE;
12935a5a35Jonathan Adamsboolean_t	zio_taskq_sysdc = B_TRUE;	/* use SDC scheduling class */
13035a5a35Jonathan Adamsuint_t		zio_taskq_basedc = 80;		/* base duty cycle */
13135a5a35Jonathan Adams
13235a5a35Jonathan Adamsboolean_t	spa_create_process = B_TRUE;	/* no process ==> no sysdc */
13301f55e4George Wilsonextern int	zfs_sync_pass_deferred_free;
13435a5a35Jonathan Adams
13535a5a35Jonathan Adams/*
13635a5a35Jonathan Adams * This (illegal) pool name is used when temporarily importing a spa_t in order
13735a5a35Jonathan Adams * to get the vdev stats associated with the imported devices.
13835a5a35Jonathan Adams */
13935a5a35Jonathan Adams#define	TRYIMPORT_NAME	"$import"
14035a5a35Jonathan Adams
142990b485lling * ==========================================================================
143990b485lling * SPA properties routines
144990b485lling * ==========================================================================
145990b485lling */
148990b485lling * Add a (source=src, propname=propval) list to an nvlist.
149990b485lling */
1509d82f4fllingstatic void
151990b485llingspa_prop_add_list(nvlist_t *nvl, zpool_prop_t prop, char *strval,
152990b485lling    uint64_t intval, zprop_source_t src)
154990b485lling	const char *propname = zpool_prop_to_name(prop);
155990b485lling	nvlist_t *propval;
1579d82f4flling	VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1589d82f4flling	VERIFY(nvlist_add_uint64(propval, ZPROP_SOURCE, src) == 0);
1609d82f4flling	if (strval != NULL)
1619d82f4flling		VERIFY(nvlist_add_string(propval, ZPROP_VALUE, strval) == 0);
1629d82f4flling	else
1639d82f4flling		VERIFY(nvlist_add_uint64(propval, ZPROP_VALUE, intval) == 0);
1659d82f4flling	VERIFY(nvlist_add_nvlist(nvl, propname, propval) == 0);
166990b485lling	nvlist_free(propval);
170990b485lling * Get property values from the spa configuration.
171990b485lling */
1729d82f4fllingstatic void
173990b485llingspa_prop_get_config(spa_t *spa, nvlist_t **nvp)
1754263d13George Wilson	vdev_t *rvd = spa->spa_root_vdev;
176ad135b5Christopher Siden	dsl_pool_t *pool = spa->spa_dsl_pool;
177379c004Eric Schrock	uint64_t size;
178485bbbfGeorge Wilson	uint64_t alloc;
1794263d13George Wilson	uint64_t space;
180990b485lling	uint64_t cap, version;
181990b485lling	zprop_source_t src = ZPROP_SRC_NONE;
182c5904d1eschrock	spa_config_dirent_t *dp;
184e14bb32Jeff Bonwick	ASSERT(MUTEX_HELD(&spa->spa_props_lock));
185e14bb32Jeff Bonwick
1864263d13George Wilson	if (rvd != NULL) {
187485bbbfGeorge Wilson		alloc = metaslab_class_get_alloc(spa_normal_class(spa));
188b24ab67Jeff Bonwick		size = metaslab_class_get_space(spa_normal_class(spa));
189379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_NAME, spa_name(spa), 0, src);
190379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_SIZE, NULL, size, src);
191485bbbfGeorge Wilson		spa_prop_add_list(*nvp, ZPOOL_PROP_ALLOCATED, NULL, alloc, src);
192485bbbfGeorge Wilson		spa_prop_add_list(*nvp, ZPOOL_PROP_FREE, NULL,
193485bbbfGeorge Wilson		    size - alloc, src);
1944263d13George Wilson
1954263d13George Wilson		space = 0;
1964263d13George Wilson		for (int c = 0; c < rvd->vdev_children; c++) {
1974263d13George Wilson			vdev_t *tvd = rvd->vdev_child[c];
1984263d13George Wilson			space += tvd->vdev_max_asize - tvd->vdev_asize;
1994263d13George Wilson		}
2004263d13George Wilson		spa_prop_add_list(*nvp, ZPOOL_PROP_EXPANDSZ, NULL, space,
2014263d13George Wilson		    src);
2024263d13George Wilson
203f9af39bGeorge Wilson		spa_prop_add_list(*nvp, ZPOOL_PROP_READONLY, NULL,
204f9af39bGeorge Wilson		    (spa_mode(spa) == FREAD), src);
205379c004Eric Schrock
206485bbbfGeorge Wilson		cap = (size == 0) ? 0 : (alloc * 100 / size);
207379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_CAPACITY, NULL, cap, src);
208379c004Eric Schrock
209b24ab67Jeff Bonwick		spa_prop_add_list(*nvp, ZPOOL_PROP_DEDUPRATIO, NULL,
210b24ab67Jeff Bonwick		    ddt_get_pool_dedup_ratio(spa), src);
211b24ab67Jeff Bonwick
212379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_HEALTH, NULL,
2134263d13George Wilson		    rvd->vdev_state, src);
214379c004Eric Schrock
215379c004Eric Schrock		version = spa_version(spa);
216379c004Eric Schrock		if (version == zpool_prop_default_numeric(ZPOOL_PROP_VERSION))
217379c004Eric Schrock			src = ZPROP_SRC_DEFAULT;
218379c004Eric Schrock		else
219379c004Eric Schrock			src = ZPROP_SRC_LOCAL;
220379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_VERSION, NULL, version, src);
221379c004Eric Schrock	}
223ad135b5Christopher Siden	if (pool != NULL) {
224ad135b5Christopher Siden		dsl_dir_t *freedir = pool->dp_free_dir;
225ad135b5Christopher Siden
226ad135b5Christopher Siden		/*
227ad135b5Christopher Siden		 * The $FREE directory was introduced in SPA_VERSION_DEADLISTS,
228ad135b5Christopher Siden		 * when opening pools before this version freedir will be NULL.
229ad135b5Christopher Siden		 */
230ad135b5Christopher Siden		if (freedir != NULL) {
231ad135b5Christopher Siden			spa_prop_add_list(*nvp, ZPOOL_PROP_FREEING, NULL,
232ad135b5Christopher Siden			    freedir->dd_phys->dd_used_bytes, src);
233ad135b5Christopher Siden		} else {
234ad135b5Christopher Siden			spa_prop_add_list(*nvp, ZPOOL_PROP_FREEING,
235ad135b5Christopher Siden			    NULL, 0, src);
236ad135b5Christopher Siden		}
237ad135b5Christopher Siden	}
238ad135b5Christopher Siden
2399d82f4flling	spa_prop_add_list(*nvp, ZPOOL_PROP_GUID, NULL, spa_guid(spa), src);
2418704186Dan McDonald	if (spa->spa_comment != NULL) {
2428704186Dan McDonald		spa_prop_add_list(*nvp, ZPOOL_PROP_COMMENT, spa->spa_comment,
2438704186Dan McDonald		    0, ZPROP_SRC_LOCAL);
2448704186Dan McDonald	}
2458704186Dan McDonald
2469d82f4flling	if (spa->spa_root != NULL)
2479d82f4flling		spa_prop_add_list(*nvp, ZPOOL_PROP_ALTROOT, spa->spa_root,
2489d82f4flling		    0, ZPROP_SRC_LOCAL);
250c5904d1eschrock	if ((dp = list_head(&spa->spa_config_list)) != NULL) {
251c5904d1eschrock		if (dp->scd_path == NULL) {
2529d82f4flling			spa_prop_add_list(*nvp, ZPOOL_PROP_CACHEFILE,
253c5904d1eschrock			    "none", 0, ZPROP_SRC_LOCAL);
254c5904d1eschrock		} else if (strcmp(dp->scd_path, spa_config_path) != 0) {
2559d82f4flling			spa_prop_add_list(*nvp, ZPOOL_PROP_CACHEFILE,
256c5904d1eschrock			    dp->scd_path, 0, ZPROP_SRC_LOCAL);
2572f8aaabeschrock		}
2582f8aaabeschrock	}
262990b485lling * Get zpool property values.
263990b485lling */
265990b485llingspa_prop_get(spa_t *spa, nvlist_t **nvp)
267b24ab67Jeff Bonwick	objset_t *mos = spa->spa_meta_objset;
268990b485lling	zap_cursor_t zc;
269990b485lling	zap_attribute_t za;
270990b485lling	int err;
2729d82f4flling	VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
274e14bb32Jeff Bonwick	mutex_enter(&spa->spa_props_lock);
275e14bb32Jeff Bonwick
276990b485lling	/*
277990b485lling	 * Get properties from the spa config.
278990b485lling	 */
2799d82f4flling	spa_prop_get_config(spa, nvp);
281990b485lling	/* If no pool property object, no more prop to get. */
282afee20eGeorge Wilson	if (mos == NULL || spa->spa_pool_props_object == 0) {
283990b485lling		mutex_exit(&spa->spa_props_lock);
284990b485lling		return (0);
285990b485lling	}
287990b485lling	/*
288990b485lling	 * Get properties from the MOS pool property object.
289990b485lling	 */
290990b485lling	for (zap_cursor_init(&zc, mos, spa->spa_pool_props_object);
291990b485lling	    (err = zap_cursor_retrieve(&zc, &za)) == 0;
292990b485lling	    zap_cursor_advance(&zc)) {
293990b485lling		uint64_t intval = 0;
294990b485lling		char *strval = NULL;
295990b485lling		zprop_source_t src = ZPROP_SRC_DEFAULT;
296990b485lling		zpool_prop_t prop;
298990b485lling		if ((prop = zpool_name_to_prop(za.za_name)) == ZPROP_INVAL)
299990b485lling			continue;
301990b485lling		switch (za.za_integer_length) {
302990b485lling		case 8:
303990b485lling			/* integer property */
304990b485lling			if (za.za_first_integer !=
305990b485lling			    zpool_prop_default_numeric(prop))
306990b485lling				src = ZPROP_SRC_LOCAL;
308990b485lling			if (prop == ZPOOL_PROP_BOOTFS) {
309990b485lling				dsl_pool_t *dp;
310990b485lling				dsl_dataset_t *ds = NULL;
312990b485lling				dp = spa_get_dsl(spa);
313990b485lling				rw_enter(&dp->dp_config_rwlock, RW_READER);
314745cd3cmaybee				if (err = dsl_dataset_hold_obj(dp,
315745cd3cmaybee				    za.za_first_integer, FTAG, &ds)) {
316990b485lling					rw_exit(&dp->dp_config_rwlock);
317990b485lling					break;
318990b485lling				}
320990b485lling				strval = kmem_alloc(
321990b485lling				    MAXNAMELEN + strlen(MOS_DIR_NAME) + 1,
322990b485lling				    KM_SLEEP);
323990b485lling				dsl_dataset_name(ds, strval);
324745cd3cmaybee				dsl_dataset_rele(ds, FTAG);
325990b485lling				rw_exit(&dp->dp_config_rwlock);
326990b485lling			} else {
327990b485lling				strval = NULL;
328990b485lling				intval = za.za_first_integer;
329990b485lling			}
3319d82f4flling			spa_prop_add_list(*nvp, prop, strval, intval, src);
333990b485lling			if (strval != NULL)
334990b485lling				kmem_free(strval,
335990b485lling				    MAXNAMELEN + strlen(MOS_DIR_NAME) + 1);
337990b485lling			break;
339990b485lling		case 1:
340990b485lling			/* string property */
341990b485lling			strval = kmem_alloc(za.za_num_integers, KM_SLEEP);
342990b485lling			err = zap_lookup(mos, spa->spa_pool_props_object,
343990b485lling			    za.za_name, 1, za.za_num_integers, strval);
344990b485lling			if (err) {
345990b485lling				kmem_free(strval, za.za_num_integers);
346990b485lling				break;
347990b485lling			}
3489d82f4flling			spa_prop_add_list(*nvp, prop, strval, 0, src);
349990b485lling			kmem_free(strval, za.za_num_integers);
350990b485lling			break;
352990b485lling		default:
353990b485lling			break;
354990b485lling		}
355990b485lling	}
356990b485lling	zap_cursor_fini(&zc);
357990b485lling	mutex_exit(&spa->spa_props_lock);
359990b485lling	if (err && err != ENOENT) {
360990b485lling		nvlist_free(*nvp);
3619d82f4flling		*nvp = NULL;
362990b485lling		return (err);
363990b485lling	}
365990b485lling	return (0);
369990b485lling * Validate the given pool properties nvlist and modify the list
370990b485lling * for the property values to be set.
371990b485lling */
372990b485llingstatic int
373990b485llingspa_prop_validate(spa_t *spa, nvlist_t *props)
375990b485lling	nvpair_t *elem;
376990b485lling	int error = 0, reset_bootfs = 0;
377d5285caGeorge Wilson	uint64_t objnum = 0;
378ad135b5Christopher Siden	boolean_t has_feature = B_FALSE;
380990b485lling	elem = NULL;
381990b485lling	while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
382990b485lling		uint64_t intval;
383ad135b5Christopher Siden		char *strval, *slash, *check, *fname;
384ad135b5Christopher Siden		const char *propname = nvpair_name(elem);
385ad135b5Christopher Siden		zpool_prop_t prop = zpool_name_to_prop(propname);
386ad135b5Christopher Siden
387ad135b5Christopher Siden		switch (prop) {
388ad135b5Christopher Siden		case ZPROP_INVAL:
389ad135b5Christopher Siden			if (!zpool_prop_feature(propname)) {
390ad135b5Christopher Siden				error = EINVAL;
391ad135b5Christopher Siden				break;
392ad135b5Christopher Siden			}
394ad135b5Christopher Siden			/*
395ad135b5Christopher Siden			 * Sanitize the input.
396ad135b5Christopher Siden			 */
397ad135b5Christopher Siden			if (nvpair_type(elem) != DATA_TYPE_UINT64) {
398ad135b5Christopher Siden				error = EINVAL;
399ad135b5Christopher Siden				break;
400ad135b5Christopher Siden			}
402ad135b5Christopher Siden			if (nvpair_value_uint64(elem, &intval) != 0) {
403ad135b5Christopher Siden				error = EINVAL;
404ad135b5Christopher Siden				break;
405ad135b5Christopher Siden			}
406ad135b5Christopher Siden
407ad135b5Christopher Siden			if (intval != 0) {
408ad135b5Christopher Siden				error = EINVAL;
409ad135b5Christopher Siden				break;
410ad135b5Christopher Siden			}
411ad135b5Christopher Siden
412ad135b5Christopher Siden			fname = strchr(propname, '@') + 1;
413ad135b5Christopher Siden			if (zfeature_lookup_name(fname, NULL) != 0) {
414ad135b5Christopher Siden				error = EINVAL;
415ad135b5Christopher Siden				break;
416ad135b5Christopher Siden			}
417ad135b5Christopher Siden
418ad135b5Christopher Siden			has_feature = B_TRUE;
419ad135b5Christopher Siden			break;
421990b485lling		case ZPOOL_PROP_VERSION:
422990b485lling			error = nvpair_value_uint64(elem, &intval);
423990b485lling			if (!error &&
424ad135b5Christopher Siden			    (intval < spa_version(spa) ||
425ad135b5Christopher Siden			    intval > SPA_VERSION_BEFORE_FEATURES ||
426ad135b5Christopher Siden			    has_feature))
427990b485lling				error = EINVAL;
428990b485lling			break;
430990b485lling		case ZPOOL_PROP_DELEGATION:
431990b485lling		case ZPOOL_PROP_AUTOREPLACE:
432d5b5bb2Rich Morris		case ZPOOL_PROP_LISTSNAPS:
433573ca77George Wilson		case ZPOOL_PROP_AUTOEXPAND:
434990b485lling			error = nvpair_value_uint64(elem, &intval);
435990b485lling			if (!error && intval > 1)
436990b485lling				error = EINVAL;
437990b485lling			break;
439990b485lling		case ZPOOL_PROP_BOOTFS:
44025f89eeJeff Bonwick			/*
44125f89eeJeff Bonwick			 * If the pool version is less than SPA_VERSION_BOOTFS,
44225f89eeJeff Bonwick			 * or the pool is still being created (version == 0),
44325f89eeJeff Bonwick			 * the bootfs property cannot be set.
44425f89eeJeff Bonwick			 */
445990b485lling			if (spa_version(spa) < SPA_VERSION_BOOTFS) {
446990b485lling				error = ENOTSUP;
447990b485lling				break;
448990b485lling			}
450990b485lling			/*
45115e6edfgw			 * Make sure the vdev config is bootable
452990b485lling			 */
45315e6edfgw			if (!vdev_is_bootable(spa->spa_root_vdev)) {
454990b485lling				error = ENOTSUP;
455990b485lling				break;
456990b485lling			}
458990b485lling			reset_bootfs = 1;
460990b485lling			error = nvpair_value_string(elem, &strval);
462990b485lling			if (!error) {
463ad135b5Christopher Siden				objset_t *os;
46415e6edfgw				uint64_t compress;
466990b485lling				if (strval == NULL || strval[0] == '\0') {
467990b485lling					objnum = zpool_prop_default_numeric(
468990b485lling					    ZPOOL_PROP_BOOTFS);
469990b485lling					break;
470990b485lling				}
472503ad85Matthew Ahrens				if (error = dmu_objset_hold(strval, FTAG, &os))
473990b485lling					break;
475503ad85Matthew Ahrens				/* Must be ZPL and not gzip compressed. */
476503ad85Matthew Ahrens
477503ad85Matthew Ahrens				if (dmu_objset_type(os) != DMU_OST_ZFS) {
478503ad85Matthew Ahrens					error = ENOTSUP;
479503ad85Matthew Ahrens				} else if ((error = dsl_prop_get_integer(strval,
48015e6edfgw				    zfs_prop_to_name(ZFS_PROP_COMPRESSION),
48115e6edfgw				    &compress, NULL)) == 0 &&
48215e6edfgw				    !BOOTFS_COMPRESS_VALID(compress)) {
48315e6edfgw					error = ENOTSUP;
48415e6edfgw				} else {
48515e6edfgw					objnum = dmu_objset_id(os);
48615e6edfgw				}
487503ad85Matthew Ahrens				dmu_objset_rele(os, FTAG);
488990b485lling			}
489990b485lling			break;
490e14bb32Jeff Bonwick
4910a4e951gw		case ZPOOL_PROP_FAILUREMODE:
4920a4e951gw			error = nvpair_value_uint64(elem, &intval);
4930a4e951gw			if (!error && (intval < ZIO_FAILURE_MODE_WAIT ||
4940a4e951gw			    intval > ZIO_FAILURE_MODE_PANIC))
4950a4e951gw				error = EINVAL;
4970a4e951gw			/*
4980a4e951gw			 * This is a special case which only occurs when
4990a4e951gw			 * the pool has completely failed. This allows
5000a4e951gw			 * the user to change the in-core failmode property
5010a4e951gw			 * without syncing it out to disk (I/Os might
5020a4e951gw			 * currently be blocked). We do this by returning
5030a4e951gw			 * EIO to the caller (spa_prop_set) to trick it
5040a4e951gw			 * into thinking we encountered a property validation
5050a4e951gw			 * error.
5060a4e951gw			 */
507e14bb32Jeff Bonwick			if (!error && spa_suspended(spa)) {
5080a4e951gw				spa->spa_failmode = intval;
5090a4e951gw				error = EIO;
5100a4e951gw			}
5110a4e951gw			break;
5132f8aaabeschrock		case ZPOOL_PROP_CACHEFILE:
5142f8aaabeschrock			if ((error = nvpair_value_string(elem, &strval)) != 0)
5152f8aaabeschrock				break;
5172f8aaabeschrock			if (strval[0] == '\0')
5182f8aaabeschrock				break;
5202f8aaabeschrock			if (strcmp(strval, "none") == 0)
5212f8aaabeschrock				break;
5232f8aaabeschrock			if (strval[0] != '/') {
5242f8aaabeschrock				error = EINVAL;
5252f8aaabeschrock				break;
5262f8aaabeschrock			}
5282f8aaabeschrock			slash = strrchr(strval, '/');
5292f8aaabeschrock			ASSERT(slash != NULL);
5312f8aaabeschrock			if (slash[1] == '\0' || strcmp(slash, "/.") == 0 ||
5322f8aaabeschrock			    strcmp(slash, "/..") == 0)
5332f8aaabeschrock				error = EINVAL;
5342f8aaabeschrock			break;
535b24ab67Jeff Bonwick
5368704186Dan McDonald		case ZPOOL_PROP_COMMENT:
5378704186Dan McDonald			if ((error = nvpair_value_string(elem, &strval)) != 0)
5388704186Dan McDonald				break;
5398704186Dan McDonald			for (check = strval; *check != '\0'; check++) {
5408704186Dan McDonald				/*
5418704186Dan McDonald				 * The kernel doesn't have an easy isprint()
5428704186Dan McDonald				 * check.  For this kernel check, we merely
5438704186Dan McDonald				 * check ASCII apart from DEL.  Fix this if
5448704186Dan McDonald				 * there is an easy-to-use kernel isprint().
5458704186Dan McDonald				 */
5468704186Dan McDonald				if (*check >= 0x7f) {
5478704186Dan McDonald					error = EINVAL;
5488704186Dan McDonald					break;
5498704186Dan McDonald				}
5508704186Dan McDonald				check++;
5518704186Dan McDonald			}
5528704186Dan McDonald			if (strlen(strval) > ZPROP_MAX_COMMENT)
5538704186Dan McDonald				error = E2BIG;
5548704186Dan McDonald			break;
5558704186Dan McDonald
556b24ab67Jeff Bonwick		case ZPOOL_PROP_DEDUPDITTO:
557b24ab67Jeff Bonwick			if (spa_version(spa) < SPA_VERSION_DEDUP)
558b24ab67Jeff Bonwick				error = ENOTSUP;
559b24ab67Jeff Bonwick			else
560b24ab67Jeff Bonwick				error = nvpair_value_uint64(elem, &intval);
561b24ab67Jeff Bonwick			if (error == 0 &&
562b24ab67Jeff Bonwick			    intval != 0 && intval < ZIO_DEDUPDITTO_MIN)
563b24ab67Jeff Bonwick				error = EINVAL;
564b24ab67Jeff Bonwick			break;
565990b485lling		}
567990b485lling		if (error)
568990b485lling			break;
569990b485lling	}
571990b485lling	if (!error && reset_bootfs) {
572990b485lling		error = nvlist_remove(props,
573990b485lling		    zpool_prop_to_name(ZPOOL_PROP_BOOTFS), DATA_TYPE_STRING);
575990b485lling		if (!error) {
576990b485lling			error = nvlist_add_uint64(props,
577990b485lling			    zpool_prop_to_name(ZPOOL_PROP_BOOTFS), objnum);
578990b485lling		}
579990b485lling	}
581990b485lling	return (error);
584379c004Eric Schrockvoid
585379c004Eric Schrockspa_configfile_set(spa_t *spa, nvlist_t *nvp, boolean_t need_sync)
586379c004Eric Schrock{
587379c004Eric Schrock	char *cachefile;
588379c004Eric Schrock	spa_config_dirent_t *dp;
589379c004Eric Schrock
590379c004Eric Schrock	if (nvlist_lookup_string(nvp, zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
591379c004Eric Schrock	    &cachefile) != 0)
592379c004Eric Schrock		return;
593379c004Eric Schrock
594379c004Eric Schrock	dp = kmem_alloc(sizeof (spa_config_dirent_t),
595379c004Eric Schrock	    KM_SLEEP);
596379c004Eric Schrock
597379c004Eric Schrock	if (cachefile[0] == '\0')
598379c004Eric Schrock		dp->scd_path = spa_strdup(spa_config_path);
599379c004Eric Schrock	else if (strcmp(cachefile, "none") == 0)
600379c004Eric Schrock		dp->scd_path = NULL;
601379c004Eric Schrock	else
602379c004Eric Schrock		dp->scd_path = spa_strdup(cachefile);
603379c004Eric Schrock
604379c004Eric Schrock	list_insert_head(&spa->spa_config_list, dp);
605379c004Eric Schrock	if (need_sync)
606379c004Eric Schrock		spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE);
607379c004Eric Schrock}
608379c004Eric Schrock
610990b485llingspa_prop_set(spa_t *spa, nvlist_t *nvp)
612990b485lling	int error;
613ad135b5Christopher Siden	nvpair_t *elem = NULL;
614379c004Eric Schrock	boolean_t need_sync = B_FALSE;
616990b485lling	if ((error = spa_prop_validate(spa, nvp)) != 0)
617990b485lling		return (error);
619379c004Eric Schrock	while ((elem = nvlist_next_nvpair(nvp, elem)) != NULL) {
620ad135b5Christopher Siden		zpool_prop_t prop = zpool_name_to_prop(nvpair_name(elem));
621379c004Eric Schrock
622f9af39bGeorge Wilson		if (prop == ZPOOL_PROP_CACHEFILE ||
623f9af39bGeorge Wilson		    prop == ZPOOL_PROP_ALTROOT ||
624f9af39bGeorge Wilson		    prop == ZPOOL_PROP_READONLY)
625379c004Eric Schrock			continue;
626379c004Eric Schrock
627ad135b5Christopher Siden		if (prop == ZPOOL_PROP_VERSION || prop == ZPROP_INVAL) {
628ad135b5Christopher Siden			uint64_t ver;
629ad135b5Christopher Siden
630ad135b5Christopher Siden			if (prop == ZPOOL_PROP_VERSION) {
631ad135b5Christopher Siden				VERIFY(nvpair_value_uint64(elem, &ver) == 0);
632ad135b5Christopher Siden			} else {
633ad135b5Christopher Siden				ASSERT(zpool_prop_feature(nvpair_name(elem)));
634ad135b5Christopher Siden				ver = SPA_VERSION_FEATURES;
635ad135b5Christopher Siden				need_sync = B_TRUE;
636ad135b5Christopher Siden			}
637ad135b5Christopher Siden
638ad135b5Christopher Siden			/* Save time if the version is already set. */
639ad135b5Christopher Siden			if (ver == spa_version(spa))
640ad135b5Christopher Siden				continue;
641ad135b5Christopher Siden
642ad135b5Christopher Siden			/*
643ad135b5Christopher Siden			 * In addition to the pool directory object, we might
644ad135b5Christopher Siden			 * create the pool properties object, the features for
645ad135b5Christopher Siden			 * read object, the features for write object, or the
646ad135b5Christopher Siden			 * feature descriptions object.
647ad135b5Christopher Siden			 */
648ad135b5Christopher Siden			error = dsl_sync_task_do(spa_get_dsl(spa), NULL,
649ad135b5Christopher Siden			    spa_sync_version, spa, &ver, 6);
650ad135b5Christopher Siden			if (error)
651ad135b5Christopher Siden				return (error);
652ad135b5Christopher Siden			continue;
653ad135b5Christopher Siden		}
654ad135b5Christopher Siden
655379c004Eric Schrock		need_sync = B_TRUE;
656379c004Eric Schrock		break;
657379c004Eric Schrock	}
658379c004Eric Schrock
659ad135b5Christopher Siden	if (need_sync) {
660379c004Eric Schrock		return (dsl_sync_task_do(spa_get_dsl(spa), NULL, spa_sync_props,
661ad135b5Christopher Siden		    spa, nvp, 6));
662ad135b5Christopher Siden	}
663ad135b5Christopher Siden
664ad135b5Christopher Siden	return (0);
668990b485lling * If the bootfs property value is dsobj, clear it.
669990b485lling */
671990b485llingspa_prop_clear_bootfs(spa_t *spa, uint64_t dsobj, dmu_tx_t *tx)
673990b485lling	if (spa->spa_bootfs == dsobj && spa->spa_pool_props_object != 0) {
674990b485lling		VERIFY(zap_remove(spa->spa_meta_objset,
675990b485lling		    spa->spa_pool_props_object,
676990b485lling		    zpool_prop_to_name(ZPOOL_PROP_BOOTFS), tx) == 0);
677990b485lling		spa->spa_bootfs = 0;
678990b485lling	}
681dfbb943George Wilson/*ARGSUSED*/
682dfbb943George Wilsonstatic int
683dfbb943George Wilsonspa_change_guid_check(void *arg1, void *arg2, dmu_tx_t *tx)
684dfbb943George Wilson{
685dfbb943George Wilson	spa_t *spa = arg1;
686dfbb943George Wilson	uint64_t *newguid = arg2;
687dfbb943George Wilson	vdev_t *rvd = spa->spa_root_vdev;
688dfbb943George Wilson	uint64_t vdev_state;
689dfbb943George Wilson
690dfbb943George Wilson	spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
691dfbb943George Wilson	vdev_state = rvd->vdev_state;
692dfbb943George Wilson	spa_config_exit(spa, SCL_STATE, FTAG);
693dfbb943George Wilson
694dfbb943George Wilson	if (vdev_state != VDEV_STATE_HEALTHY)
695dfbb943George Wilson		return (ENXIO);
696dfbb943George Wilson
697dfbb943George Wilson	ASSERT3U(spa_guid(spa), !=, *newguid);
698dfbb943George Wilson
699dfbb943George Wilson	return (0);
700dfbb943George Wilson}
701dfbb943George Wilson
702dfbb943George Wilsonstatic void
703dfbb943George Wilsonspa_change_guid_sync(void *arg1, void *arg2, dmu_tx_t *tx)
704dfbb943George Wilson{
705dfbb943George Wilson	spa_t *spa = arg1;
706dfbb943George Wilson	uint64_t *newguid = arg2;
707dfbb943George Wilson	uint64_t oldguid;
708dfbb943George Wilson	vdev_t *rvd = spa->spa_root_vdev;
709dfbb943George Wilson
710dfbb943George Wilson	oldguid = spa_guid(spa);
711dfbb943George Wilson
712dfbb943George Wilson	spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
713dfbb943George Wilson	rvd->vdev_guid = *newguid;
714dfbb943George Wilson	rvd->vdev_guid_sum += (*newguid - oldguid);
715dfbb943George Wilson	vdev_config_dirty(rvd);
716dfbb943George Wilson	spa_config_exit(spa, SCL_STATE, FTAG);
717dfbb943George Wilson
71820128a0George Wilson	spa_history_log_internal(spa, "guid change", tx, "old=%llu new=%llu",
719dfbb943George Wilson	    oldguid, *newguid);
720dfbb943George Wilson}
721dfbb943George Wilson
723e9103aaGarrett D'Amore * Change the GUID for the pool.  This is done so that we can later
724e9103aaGarrett D'Amore * re-import a pool built from a clone of our own vdevs.  We will modify
725e9103aaGarrett D'Amore * the root vdev's guid, our own pool guid, and then mark all of our
726e9103aaGarrett D'Amore * vdevs dirty.  Note that we must make sure that all our vdevs are
727e9103aaGarrett D'Amore * online when we do this, or else any vdevs that weren't present
728e9103aaGarrett D'Amore * would be orphaned from our pool.  We are also going to issue a
729e9103aaGarrett D'Amore * sysevent to update any watchers.
730e9103aaGarrett D'Amore */
731e9103aaGarrett D'Amoreint
732e9103aaGarrett D'Amorespa_change_guid(spa_t *spa)
733e9103aaGarrett D'Amore{
734dfbb943George Wilson	int error;
735dfbb943George Wilson	uint64_t guid;
736e9103aaGarrett D'Amore
737dfbb943George Wilson	mutex_enter(&spa_namespace_lock);
738dfbb943George Wilson	guid = spa_generate_guid(NULL);
739e9103aaGarrett D'Amore
740dfbb943George Wilson	error = dsl_sync_task_do(spa_get_dsl(spa), spa_change_guid_check,
741dfbb943George Wilson	    spa_change_guid_sync, spa, &guid, 5);
742e9103aaGarrett D'Amore
743dfbb943George Wilson	if (error == 0) {
744dfbb943George Wilson		spa_config_sync(spa, B_FALSE, B_TRUE);
745dfbb943George Wilson		spa_event_notify(spa, NULL, ESC_ZFS_POOL_REGUID);
746dfbb943George Wilson	}
747e9103aaGarrett D'Amore
748dfbb943George Wilson	mutex_exit(&spa_namespace_lock);
749e9103aaGarrett D'Amore
750dfbb943George Wilson	return (error);
751e9103aaGarrett D'Amore}
752e9103aaGarrett D'Amore
753e9103aaGarrett D'Amore/*
754fa9e406ahrens * ==========================================================================
755fa9e406ahrens * SPA state manipulation (open/create/destroy/import/export)
756fa9e406ahrens * ==========================================================================
757fa9e406ahrens */
759ea8dc4beschrockstatic int
760ea8dc4beschrockspa_error_entry_compare(const void *a, const void *b)
762ea8dc4beschrock	spa_error_entry_t *sa = (spa_error_entry_t *)a;
763ea8dc4beschrock	spa_error_entry_t *sb = (spa_error_entry_t *)b;
764ea8dc4beschrock	int ret;
766ea8dc4beschrock	ret = bcmp(&sa->se_bookmark, &sb->se_bookmark,
767ea8dc4beschrock	    sizeof (zbookmark_t));
769ea8dc4beschrock	if (ret < 0)
770ea8dc4beschrock		return (-1);