spa.c revision 1195e687f1c03c8d57417b5999578922e20a3554
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/*
231195e68Mark J Musante * Copyright 2010 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
65dedec47Jack Meng#include <sys/bootprops.h>
6635a5a35Jonathan Adams#include <sys/callb.h>
6735a5a35Jonathan Adams#include <sys/cpupart.h>
6835a5a35Jonathan Adams#include <sys/pool.h>
6935a5a35Jonathan Adams#include <sys/sysdc.h>
7035a5a35Jonathan Adams#include <sys/zone.h>
715679c89jv#endif	/* _KERNEL */
725679c89jv
73990b485lling#include "zfs_prop.h"
74b7b9745perrin#include "zfs_comutil.h"
75990b485lling
7635a5a35Jonathan Adamstypedef enum zti_modes {
772e0c549Jonathan Adams	zti_mode_fixed,			/* value is # of threads (min 1) */
782e0c549Jonathan Adams	zti_mode_online_percent,	/* value is % of online CPUs */
7935a5a35Jonathan Adams	zti_mode_batch,			/* cpu-intensive; value is ignored */
8080eb36fGeorge Wilson	zti_mode_null,			/* don't create a taskq */
812e0c549Jonathan Adams	zti_nmodes
8235a5a35Jonathan Adams} zti_modes_t;
83416e0cdek
8480eb36fGeorge Wilson#define	ZTI_FIX(n)	{ zti_mode_fixed, (n) }
8580eb36fGeorge Wilson#define	ZTI_PCT(n)	{ zti_mode_online_percent, (n) }
8635a5a35Jonathan Adams#define	ZTI_BATCH	{ zti_mode_batch, 0 }
8780eb36fGeorge Wilson#define	ZTI_NULL	{ zti_mode_null, 0 }
882e0c549Jonathan Adams
8980eb36fGeorge Wilson#define	ZTI_ONE		ZTI_FIX(1)
902e0c549Jonathan Adams
912e0c549Jonathan Adamstypedef struct zio_taskq_info {
9280eb36fGeorge Wilson	enum zti_modes zti_mode;
9380eb36fGeorge Wilson	uint_t zti_value;
942e0c549Jonathan Adams} zio_taskq_info_t;
952e0c549Jonathan Adams
962e0c549Jonathan Adamsstatic const char *const zio_taskq_types[ZIO_TASKQ_TYPES] = {
9735a5a35Jonathan Adams	"issue", "issue_high", "intr", "intr_high"
982e0c549Jonathan Adams};
992e0c549Jonathan Adams
10080eb36fGeorge Wilson/*
10180eb36fGeorge Wilson * Define the taskq threads for the following I/O types:
10280eb36fGeorge Wilson * 	NULL, READ, WRITE, FREE, CLAIM, and IOCTL
10380eb36fGeorge Wilson */
10480eb36fGeorge Wilsonconst zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = {
10580eb36fGeorge Wilson	/* ISSUE	ISSUE_HIGH	INTR		INTR_HIGH */
10680eb36fGeorge Wilson	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
10735a5a35Jonathan Adams	{ ZTI_FIX(8),	ZTI_NULL,	ZTI_BATCH,	ZTI_NULL },
10835a5a35Jonathan Adams	{ ZTI_BATCH,	ZTI_FIX(5),	ZTI_FIX(8),	ZTI_FIX(5) },
10980eb36fGeorge Wilson	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
11080eb36fGeorge Wilson	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
11180eb36fGeorge Wilson	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
1122e0c549Jonathan Adams};
1132e0c549Jonathan Adams
114990b485llingstatic void spa_sync_props(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx);
11589a89ebllingstatic boolean_t spa_has_active_shared_spare(spa_t *spa);
1161195e68Mark J Musantestatic int spa_load_impl(spa_t *spa, uint64_t, nvlist_t *config,
1171195e68Mark J Musante    spa_load_state_t state, spa_import_type_t type, boolean_t mosconfig,
1181195e68Mark J Musante    char **ereport);
119990b485lling
12035a5a35Jonathan Adamsuint_t		zio_taskq_batch_pct = 100;	/* 1 thread per cpu in pset */
12135a5a35Jonathan Adamsid_t		zio_taskq_psrset_bind = PS_NONE;
12235a5a35Jonathan Adamsboolean_t	zio_taskq_sysdc = B_TRUE;	/* use SDC scheduling class */
12335a5a35Jonathan Adamsuint_t		zio_taskq_basedc = 80;		/* base duty cycle */
12435a5a35Jonathan Adams
12535a5a35Jonathan Adamsboolean_t	spa_create_process = B_TRUE;	/* no process ==> no sysdc */
12635a5a35Jonathan Adams
12735a5a35Jonathan Adams/*
12835a5a35Jonathan Adams * This (illegal) pool name is used when temporarily importing a spa_t in order
12935a5a35Jonathan Adams * to get the vdev stats associated with the imported devices.
13035a5a35Jonathan Adams */
13135a5a35Jonathan Adams#define	TRYIMPORT_NAME	"$import"
13235a5a35Jonathan Adams
133990b485lling/*
134990b485lling * ==========================================================================
135990b485lling * SPA properties routines
136990b485lling * ==========================================================================
137990b485lling */
138990b485lling
139990b485lling/*
140990b485lling * Add a (source=src, propname=propval) list to an nvlist.
141990b485lling */
1429d82f4fllingstatic void
143990b485llingspa_prop_add_list(nvlist_t *nvl, zpool_prop_t prop, char *strval,
144990b485lling    uint64_t intval, zprop_source_t src)
145990b485lling{
146990b485lling	const char *propname = zpool_prop_to_name(prop);
147990b485lling	nvlist_t *propval;
148990b485lling
1499d82f4flling	VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1509d82f4flling	VERIFY(nvlist_add_uint64(propval, ZPROP_SOURCE, src) == 0);
151990b485lling
1529d82f4flling	if (strval != NULL)
1539d82f4flling		VERIFY(nvlist_add_string(propval, ZPROP_VALUE, strval) == 0);
1549d82f4flling	else
1559d82f4flling		VERIFY(nvlist_add_uint64(propval, ZPROP_VALUE, intval) == 0);
156990b485lling
1579d82f4flling	VERIFY(nvlist_add_nvlist(nvl, propname, propval) == 0);
158990b485lling	nvlist_free(propval);
159990b485lling}
160990b485lling
161990b485lling/*
162990b485lling * Get property values from the spa configuration.
163990b485lling */
1649d82f4fllingstatic void
165990b485llingspa_prop_get_config(spa_t *spa, nvlist_t **nvp)
166990b485lling{
167379c004Eric Schrock	uint64_t size;
168485bbbfGeorge Wilson	uint64_t alloc;
169990b485lling	uint64_t cap, version;
170990b485lling	zprop_source_t src = ZPROP_SRC_NONE;
171c5904d1eschrock	spa_config_dirent_t *dp;
172990b485lling
173e14bb32Jeff Bonwick	ASSERT(MUTEX_HELD(&spa->spa_props_lock));
174e14bb32Jeff Bonwick
175379c004Eric Schrock	if (spa->spa_root_vdev != NULL) {
176485bbbfGeorge Wilson		alloc = metaslab_class_get_alloc(spa_normal_class(spa));
177b24ab67Jeff Bonwick		size = metaslab_class_get_space(spa_normal_class(spa));
178379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_NAME, spa_name(spa), 0, src);
179379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_SIZE, NULL, size, src);
180485bbbfGeorge Wilson		spa_prop_add_list(*nvp, ZPOOL_PROP_ALLOCATED, NULL, alloc, src);
181485bbbfGeorge Wilson		spa_prop_add_list(*nvp, ZPOOL_PROP_FREE, NULL,
182485bbbfGeorge Wilson		    size - alloc, src);
183379c004Eric Schrock
184485bbbfGeorge Wilson		cap = (size == 0) ? 0 : (alloc * 100 / size);
185379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_CAPACITY, NULL, cap, src);
186379c004Eric Schrock
187b24ab67Jeff Bonwick		spa_prop_add_list(*nvp, ZPOOL_PROP_DEDUPRATIO, NULL,
188b24ab67Jeff Bonwick		    ddt_get_pool_dedup_ratio(spa), src);
189b24ab67Jeff Bonwick
190379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_HEALTH, NULL,
191379c004Eric Schrock		    spa->spa_root_vdev->vdev_state, src);
192379c004Eric Schrock
193379c004Eric Schrock		version = spa_version(spa);
194379c004Eric Schrock		if (version == zpool_prop_default_numeric(ZPOOL_PROP_VERSION))
195379c004Eric Schrock			src = ZPROP_SRC_DEFAULT;
196379c004Eric Schrock		else
197379c004Eric Schrock			src = ZPROP_SRC_LOCAL;
198379c004Eric Schrock		spa_prop_add_list(*nvp, ZPOOL_PROP_VERSION, NULL, version, src);
199379c004Eric Schrock	}
200990b485lling
2019d82f4flling	spa_prop_add_list(*nvp, ZPOOL_PROP_GUID, NULL, spa_guid(spa), src);
202990b485lling
2039d82f4flling	if (spa->spa_root != NULL)
2049d82f4flling		spa_prop_add_list(*nvp, ZPOOL_PROP_ALTROOT, spa->spa_root,
2059d82f4flling		    0, ZPROP_SRC_LOCAL);
206990b485lling
207c5904d1eschrock	if ((dp = list_head(&spa->spa_config_list)) != NULL) {
208c5904d1eschrock		if (dp->scd_path == NULL) {
2099d82f4flling			spa_prop_add_list(*nvp, ZPOOL_PROP_CACHEFILE,
210c5904d1eschrock			    "none", 0, ZPROP_SRC_LOCAL);
211c5904d1eschrock		} else if (strcmp(dp->scd_path, spa_config_path) != 0) {
2129d82f4flling			spa_prop_add_list(*nvp, ZPOOL_PROP_CACHEFILE,
213c5904d1eschrock			    dp->scd_path, 0, ZPROP_SRC_LOCAL);
2142f8aaabeschrock		}
2152f8aaabeschrock	}
216990b485lling}
217990b485lling
218990b485lling/*
219990b485lling * Get zpool property values.
220990b485lling */
221990b485llingint
222990b485llingspa_prop_get(spa_t *spa, nvlist_t **nvp)
223990b485lling{
224b24ab67Jeff Bonwick	objset_t *mos = spa->spa_meta_objset;
225990b485lling	zap_cursor_t zc;
226990b485lling	zap_attribute_t za;
227990b485lling	int err;
228990b485lling
2299d82f4flling	VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
230990b485lling
231e14bb32Jeff Bonwick	mutex_enter(&spa->spa_props_lock);
232e14bb32Jeff Bonwick
233990b485lling	/*
234990b485lling	 * Get properties from the spa config.
235990b485lling	 */
2369d82f4flling	spa_prop_get_config(spa, nvp);
237990b485lling
238990b485lling	/* If no pool property object, no more prop to get. */
239990b485lling	if (spa->spa_pool_props_object == 0) {
240990b485lling		mutex_exit(&spa->spa_props_lock);
241990b485lling		return (0);
242990b485lling	}
243990b485lling
244990b485lling	/*
245990b485lling	 * Get properties from the MOS pool property object.
246990b485lling	 */
247990b485lling	for (zap_cursor_init(&zc, mos, spa->spa_pool_props_object);
248990b485lling	    (err = zap_cursor_retrieve(&zc, &za)) == 0;
249990b485lling	    zap_cursor_advance(&zc)) {
250990b485lling		uint64_t intval = 0;
251990b485lling		char *strval = NULL;
252990b485lling		zprop_source_t src = ZPROP_SRC_DEFAULT;
253990b485lling		zpool_prop_t prop;
254990b485lling
255990b485lling		if ((prop = zpool_name_to_prop(za.za_name)) == ZPROP_INVAL)
256990b485lling			continue;
257990b485lling
258990b485lling		switch (za.za_integer_length) {
259990b485lling		case 8:
260990b485lling			/* integer property */
261990b485lling			if (za.za_first_integer !=
262990b485lling			    zpool_prop_default_numeric(prop))
263990b485lling				src = ZPROP_SRC_LOCAL;
264990b485lling
265990b485lling			if (prop == ZPOOL_PROP_BOOTFS) {
266990b485lling				dsl_pool_t *dp;
267990b485lling				dsl_dataset_t *ds = NULL;
268990b485lling
269990b485lling				dp = spa_get_dsl(spa);
270990b485lling				rw_enter(&dp->dp_config_rwlock, RW_READER);
271745cd3cmaybee				if (err = dsl_dataset_hold_obj(dp,
272745cd3cmaybee				    za.za_first_integer, FTAG, &ds)) {
273990b485lling					rw_exit(&dp->dp_config_rwlock);
274990b485lling					break;
275990b485lling				}
276990b485lling
277990b485lling				strval = kmem_alloc(
278990b485lling				    MAXNAMELEN + strlen(MOS_DIR_NAME) + 1,
279990b485lling				    KM_SLEEP);
280990b485lling				dsl_dataset_name(ds, strval);
281745cd3cmaybee				dsl_dataset_rele(ds, FTAG);
282990b485lling				rw_exit(&dp->dp_config_rwlock);
283990b485lling			} else {
284990b485lling				strval = NULL;
285990b485lling				intval = za.za_first_integer;
286990b485lling			}
287990b485lling
2889d82f4flling			spa_prop_add_list(*nvp, prop, strval, intval, src);
289990b485lling
290990b485lling			if (strval != NULL)
291990b485lling				kmem_free(strval,
292990b485lling				    MAXNAMELEN + strlen(MOS_DIR_NAME) + 1);
293990b485lling
294990b485lling			break;
295990b485lling
296990b485lling		case 1:
297990b485lling			/* string property */
298990b485lling			strval = kmem_alloc(za.za_num_integers, KM_SLEEP);
299990b485lling			err = zap_lookup(mos, spa->spa_pool_props_object,
300990b485lling			    za.za_name, 1, za.za_num_integers, strval);
301990b485lling			if (err) {
302990b485lling				kmem_free(strval, za.za_num_integers);
303990b485lling				break;
304990b485lling			}
3059d82f4flling			spa_prop_add_list(*nvp, prop, strval, 0, src);
306990b485lling			kmem_free(strval, za.za_num_integers);
307990b485lling			break;
308990b485lling
309990b485lling		default:
310990b485lling			break;
311990b485lling		}
312990b485lling	}
313990b485lling	zap_cursor_fini(&zc);
314990b485lling	mutex_exit(&spa->spa_props_lock);
315990b485llingout:
316990b485lling	if (err && err != ENOENT) {
317990b485lling		nvlist_free(*nvp);
3189d82f4flling		*nvp = NULL;
319990b485lling		return (err);
320990b485lling	}
321990b485lling
322990b485lling	return (0);
323990b485lling}
324990b485lling
325990b485lling/*
326990b485lling * Validate the given pool properties nvlist and modify the list
327990b485lling * for the property values to be set.
328990b485lling */
329990b485llingstatic int
330990b485llingspa_prop_validate(spa_t *spa, nvlist_t *props)
331990b485lling{
332990b485lling	nvpair_t *elem;
333990b485lling	int error = 0, reset_bootfs = 0;
334990b485lling	uint64_t objnum;
335990b485lling
336990b485lling	elem = NULL;
337990b485lling	while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
338990b485lling		zpool_prop_t prop;
339990b485lling		char *propname, *strval;
340990b485lling		uint64_t intval;
341990b485lling		objset_t *os;
3422f8aaabeschrock		char *slash;
343990b485lling
344990b485lling		propname = nvpair_name(elem);
345990b485lling
346990b485lling		if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL)
347990b485lling			return (EINVAL);
348990b485lling
349990b485lling		switch (prop) {
350990b485lling		case ZPOOL_PROP_VERSION:
351990b485lling			error = nvpair_value_uint64(elem, &intval);
352990b485lling			if (!error &&
353990b485lling			    (intval < spa_version(spa) || intval > SPA_VERSION))
354990b485lling				error = EINVAL;
355990b485lling			break;
356990b485lling
357990b485lling		case ZPOOL_PROP_DELEGATION:
358990b485lling		case ZPOOL_PROP_AUTOREPLACE:
359d5b5bb2Rich Morris		case ZPOOL_PROP_LISTSNAPS:
360573ca77George Wilson		case ZPOOL_PROP_AUTOEXPAND:
361990b485lling			error = nvpair_value_uint64(elem, &intval);
362990b485lling			if (!error && intval > 1)
363990b485lling				error = EINVAL;
364990b485lling			break;
365990b485lling
366990b485lling		case ZPOOL_PROP_BOOTFS:
36725f89eeJeff Bonwick			/*
36825f89eeJeff Bonwick			 * If the pool version is less than SPA_VERSION_BOOTFS,
36925f89eeJeff Bonwick			 * or the pool is still being created (version == 0),
37025f89eeJeff Bonwick			 * the bootfs property cannot be set.
37125f89eeJeff Bonwick			 */
372990b485lling			if (spa_version(spa) < SPA_VERSION_BOOTFS) {
373990b485lling				error = ENOTSUP;
374990b485lling				break;
375990b485lling			}
376990b485lling
377990b485lling			/*
37815e6edfgw			 * Make sure the vdev config is bootable
379990b485lling			 */
38015e6edfgw			if (!vdev_is_bootable(spa->spa_root_vdev)) {
381990b485lling				error = ENOTSUP;
382990b485lling				break;
383990b485lling			}
384990b485lling
385990b485lling			reset_bootfs = 1;
386990b485lling
387990b485lling			error = nvpair_value_string(elem, &strval);
388990b485lling
389990b485lling			if (!error) {
39015e6edfgw				uint64_t compress;
39115e6edfgw
392990b485lling				if (strval == NULL || strval[0] == '\0') {
393990b485lling					objnum = zpool_prop_default_numeric(
394990b485lling					    ZPOOL_PROP_BOOTFS);
395990b485lling					break;
396990b485lling				}
397990b485lling
398503ad85Matthew Ahrens				if (error = dmu_objset_hold(strval, FTAG, &os))
399990b485lling					break;
40015e6edfgw
401503ad85Matthew Ahrens				/* Must be ZPL and not gzip compressed. */
402503ad85Matthew Ahrens
403503ad85Matthew Ahrens				if (dmu_objset_type(os) != DMU_OST_ZFS) {
404503ad85Matthew Ahrens					error = ENOTSUP;
405503ad85Matthew Ahrens				} else if ((error = dsl_prop_get_integer(strval,
40615e6edfgw				    zfs_prop_to_name(ZFS_PROP_COMPRESSION),
40715e6edfgw				    &compress, NULL)) == 0 &&
40815e6edfgw				    !BOOTFS_COMPRESS_VALID(compress)) {
40915e6edfgw					error = ENOTSUP;
41015e6edfgw				} else {
41115e6edfgw					objnum = dmu_objset_id(os);
41215e6edfgw				}
413503ad85Matthew Ahrens				dmu_objset_rele(os, FTAG);
414990b485lling			}
415990b485lling			break;
416e14bb32Jeff Bonwick
4170a4e951gw		case ZPOOL_PROP_FAILUREMODE:
4180a4e951gw			error = nvpair_value_uint64(elem, &intval);
4190a4e951gw			if (!error && (intval < ZIO_FAILURE_MODE_WAIT ||
4200a4e951gw			    intval > ZIO_FAILURE_MODE_PANIC))
4210a4e951gw				error = EINVAL;
4220a4e951gw
4230a4e951gw			/*
4240a4e951gw			 * This is a special case which only occurs when
4250a4e951gw			 * the pool has completely failed. This allows
4260a4e951gw			 * the user to change the in-core failmode property
4270a4e951gw			 * without syncing it out to disk (I/Os might
4280a4e951gw			 * currently be blocked). We do this by returning
4290a4e951gw			 * EIO to the caller (spa_prop_set) to trick it
4300a4e951gw			 * into thinking we encountered a property validation
4310a4e951gw			 * error.
4320a4e951gw			 */
433e14bb32Jeff Bonwick			if (!error && spa_suspended(spa)) {
4340a4e951gw				spa->spa_failmode = intval;
4350a4e951gw				error = EIO;
4360a4e951gw			}
4370a4e951gw			break;
4382f8aaabeschrock
4392f8aaabeschrock		case ZPOOL_PROP_CACHEFILE:
4402f8aaabeschrock			if ((error = nvpair_value_string(elem, &strval)) != 0)
4412f8aaabeschrock				break;
4422f8aaabeschrock
4432f8aaabeschrock			if (strval[0] == '\0')
4442f8aaabeschrock				break;
4452f8aaabeschrock
4462f8aaabeschrock			if (strcmp(strval, "none") == 0)
4472f8aaabeschrock				break;
4482f8aaabeschrock
4492f8aaabeschrock			if (strval[0] != '/') {
4502f8aaabeschrock				error = EINVAL;
4512f8aaabeschrock				break;
4522f8aaabeschrock			}
4532f8aaabeschrock
4542f8aaabeschrock			slash = strrchr(strval, '/');
4552f8aaabeschrock			ASSERT(slash != NULL);
4562f8aaabeschrock
4572f8aaabeschrock			if (slash[1] == '\0' || strcmp(slash, "/.") == 0 ||
4582f8aaabeschrock			    strcmp(slash, "/..") == 0)
4592f8aaabeschrock				error = EINVAL;
4602f8aaabeschrock			break;
461b24ab67Jeff Bonwick
462b24ab67Jeff Bonwick		case ZPOOL_PROP_DEDUPDITTO:
463b24ab67Jeff Bonwick			if (spa_version(spa) < SPA_VERSION_DEDUP)
464b24ab67Jeff Bonwick				error = ENOTSUP;
465b24ab67Jeff Bonwick			else
466b24ab67Jeff Bonwick				error = nvpair_value_uint64(elem, &intval);
467b24ab67Jeff Bonwick			if (error == 0 &&
468b24ab67Jeff Bonwick			    intval != 0 && intval < ZIO_DEDUPDITTO_MIN)
469b24ab67Jeff Bonwick				error = EINVAL;
470b24ab67Jeff Bonwick			break;
471990b485lling		}
472990b485lling
473990b485lling		if (error)
474990b485lling			break;
475990b485lling	}
476990b485lling
477990b485lling	if (!error && reset_bootfs) {
478990b485lling		error = nvlist_remove(props,
479990b485lling		    zpool_prop_to_name(ZPOOL_PROP_BOOTFS), DATA_TYPE_STRING);
480990b485lling
481990b485lling		if (!error) {
482990b485lling			error = nvlist_add_uint64(props,
483990b485lling			    zpool_prop_to_name(ZPOOL_PROP_BOOTFS), objnum);
484990b485lling		}
485990b485lling	}
486990b485lling
487990b485lling	return (error);
488990b485lling}
489990b485lling
490379c004Eric Schrockvoid
491379c004Eric Schrockspa_configfile_set(spa_t *spa, nvlist_t *nvp, boolean_t need_sync)
492379c004Eric Schrock{
493379c004Eric Schrock	char *cachefile;
494379c004Eric Schrock	spa_config_dirent_t *dp;
495379c004Eric Schrock
496379c004Eric Schrock	if (nvlist_lookup_string(nvp, zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
497379c004Eric Schrock	    &cachefile) != 0)
498379c004Eric Schrock		return;
499379c004Eric Schrock
500379c004Eric Schrock	dp = kmem_alloc(sizeof (spa_config_dirent_t),
501379c004Eric Schrock	    KM_SLEEP);
502379c004Eric Schrock
503379c004Eric Schrock	if (cachefile[0] == '\0')
504379c004Eric Schrock		dp->scd_path = spa_strdup(spa_config_path);
505379c004Eric Schrock	else if (strcmp(cachefile, "none") == 0)
506379c004Eric Schrock		dp->scd_path = NULL;
507379c004Eric Schrock	else
508379c004Eric Schrock		dp->scd_path = spa_strdup(cachefile);
509379c004Eric Schrock
510379c004Eric Schrock	list_insert_head(&spa->spa_config_list, dp);
511379c004Eric Schrock	if (need_sync)
512379c004Eric Schrock		spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE);
513379c004Eric Schrock}
514379c004Eric Schrock
515990b485llingint
516990b485llingspa_prop_set(spa_t *spa, nvlist_t *nvp)
517990b485lling{
518990b485lling	int error;
519379c004Eric Schrock	nvpair_t *elem;
520379c004Eric Schrock	boolean_t need_sync = B_FALSE;
521379c004Eric Schrock	zpool_prop_t prop;
522990b485lling
523990b485lling	if ((error = spa_prop_validate(spa, nvp)) != 0)
524990b485lling		return (error);
525990b485lling
526379c004Eric Schrock	elem = NULL;
527379c004Eric Schrock	while ((elem = nvlist_next_nvpair(nvp, elem)) != NULL) {
528379c004Eric Schrock		if ((prop = zpool_name_to_prop(
529379c004Eric Schrock		    nvpair_name(elem))) == ZPROP_INVAL)
530379c004Eric Schrock			return (EINVAL);
531379c004Eric Schrock
532379c004Eric Schrock		if (prop == ZPOOL_PROP_CACHEFILE || prop == ZPOOL_PROP_ALTROOT)
533379c004Eric Schrock			continue;
534379c004Eric Schrock
535379c004Eric Schrock		need_sync = B_TRUE;
536379c004Eric Schrock		break;
537379c004Eric Schrock	}
538379c004Eric Schrock
539379c004Eric Schrock	if (need_sync)
540379c004Eric Schrock		return (dsl_sync_task_do(spa_get_dsl(spa), NULL, spa_sync_props,
541379c004Eric Schrock		    spa, nvp, 3));
542379c004Eric Schrock	else
543379c004Eric Schrock		return (0);
544990b485lling}
545990b485lling
546990b485lling/*
547990b485lling * If the bootfs property value is dsobj, clear it.
548990b485lling */
549990b485llingvoid
550990b485llingspa_prop_clear_bootfs(spa_t *spa, uint64_t dsobj, dmu_tx_t *tx)
551990b485lling{
552990b485lling	if (spa->spa_bootfs == dsobj && spa->spa_pool_props_object != 0) {
553990b485lling		VERIFY(zap_remove(spa->spa_meta_objset,
554990b485lling		    spa->spa_pool_props_object,
555990b485lling		    zpool_prop_to_name(ZPOOL_PROP_BOOTFS), tx) == 0);
556990b485lling		spa->spa_bootfs = 0;
557990b485lling	}
558990b485lling}
559990b485lling
560fa9e406ahrens/*
561fa9e406ahrens * ==========================================================================
562fa9e406ahrens * SPA state manipulation (open/create/destroy/import/export)
563fa9e406ahrens * ==========================================================================
564fa9e406ahrens */
565fa9e406ahrens
566ea8dc4beschrockstatic int
567ea8dc4beschrockspa_error_entry_compare(const void *a, const void *b)
568ea8dc4beschrock{
569ea8dc4beschrock	spa_error_entry_t *sa = (spa_error_entry_t *)a;
570ea8dc4beschrock	spa_error_entry_t *sb = (spa_error_entry_t *)b;
571ea8dc4beschrock	int ret;
572ea8dc4beschrock
573ea8dc4beschrock	ret = bcmp(&sa->se_bookmark, &sb->se_bookmark,
574ea8dc4beschrock	    sizeof (zbookmark_t));
575ea8dc4beschrock
576ea8dc4beschrock	if (ret < 0)
577ea8dc4beschrock		return (-1);
578ea8dc4beschrock	else if (ret > 0)
579ea8dc4beschrock		return (1);
580ea8dc4beschrock	else
581ea8dc4beschrock		return (0);
582ea8dc4beschrock}
583ea8dc4beschrock
584ea8dc4beschrock/*
585ea8dc4beschrock * Utility function which retrieves copies of the current logs and
586ea8dc4beschrock * re-initializes them in the process.
587ea8dc4beschrock */
588ea8dc4beschrockvoid
589ea8dc4beschrockspa_get_errlists(spa_t *spa, avl_tree_t *last, avl_tree_t *scrub)
590ea8dc4beschrock{
591ea8dc4beschrock	ASSERT(MUTEX_HELD(&spa->spa_errlist_lock));
592ea8dc4beschrock
593ea8dc4beschrock	bcopy(&spa->spa_errlist_last, last, sizeof (avl_tree_t));
594ea8dc4beschrock	bcopy(&spa->spa_errlist_scrub, scrub, sizeof (avl_tree_t));
595ea8dc4beschrock
596ea8dc4beschrock	avl_create(&spa->spa_errlist_scrub,
597ea8dc4beschrock	    spa_error_entry_compare, sizeof (spa_error_entry_t),
598ea8dc4beschrock	    offsetof(spa_error_entry_t, se_avl));
599ea8dc4beschrock	avl_create(&spa->spa_errlist_last,
600ea8dc4beschrock	    spa_error_entry_compare, sizeof (spa_error_entry_t),
601ea8dc4beschrock	    offsetof(spa_error_entry_t, se_avl));
602ea8dc4beschrock}
603ea8dc4beschrock
60435a5a35Jonathan Adamsstatic taskq_t *
60535a5a35Jonathan Adamsspa_taskq_create(spa_t *spa, const char *name, enum zti_modes mode,
60635a5a35Jonathan Adams    uint_t value)
607fa9e406ahrens{
60835a5a35Jonathan Adams	uint_t flags = TASKQ_PREPOPULATE;
60935a5a35Jonathan Adams	boolean_t batch = B_FALSE;
610fa9e406ahrens
61135a5a35Jonathan Adams	switch (mode) {
61235a5a35Jonathan Adams	case zti_mode_null:
61335a5a35Jonathan Adams		return (NULL);		/* no taskq needed */
614fa9e406ahrens
61535a5a35Jonathan Adams	case zti_mode_fixed:
61635a5a35Jonathan Adams		ASSERT3U(value, >=, 1);
61735a5a35Jonathan Adams		value = MAX(value, 1);
61835a5a35Jonathan Adams		break;
619fa9e406ahrens
62035a5a35Jonathan Adams	case zti_mode_batch:
62135a5a35Jonathan Adams		batch = B_TRUE;
62235a5a35Jonathan Adams		flags |= TASKQ_THREADS_CPU_PCT;
62335a5a35Jonathan Adams		value = zio_taskq_batch_pct;
62435a5a35Jonathan Adams		break;
62535a5a35Jonathan Adams
62635a5a35Jonathan Adams	case zti_mode_online_percent:
62735a5a35Jonathan Adams		flags |= TASKQ_THREADS_CPU_PCT;
62835a5a35Jonathan Adams		break;
62935a5a35Jonathan Adams
63035a5a35Jonathan Adams	default:
63135a5a35Jonathan Adams		panic("unrecognized mode for %s taskq (%u:%u) in "
63235a5a35Jonathan Adams		    "spa_activate()",
63335a5a35Jonathan Adams		    name, mode, value);
63435a5a35Jonathan Adams		break;
63535a5a35Jonathan Adams	}
63635a5a35Jonathan Adams
63735a5a35Jonathan Adams	if (zio_taskq_sysdc && spa->spa_proc != &p0) {
63835a5a35Jonathan Adams		if (batch)
63935a5a35Jonathan Adams			flags |= TASKQ_DC_BATCH;
64035a5a35Jonathan Adams
64135a5a35Jonathan Adams		return (taskq_create_sysdc(name, value, 50, INT_MAX,
64235a5a35Jonathan Adams		    spa->spa_proc, zio_taskq_basedc, flags));
64335a5a35Jonathan Adams	}
64435a5a35Jonathan Adams	return (taskq_create_proc(name, value, maxclsyspri, 50, INT_MAX,
64535a5a35Jonathan Adams	    spa->spa_proc, flags));
64635a5a35Jonathan Adams}
64735a5a35Jonathan Adams
64835a5a35Jonathan Adamsstatic void
64935a5a35Jonathan Adamsspa_create_zio_taskqs(spa_t *spa)
65035a5a35Jonathan Adams{
651e14bb32Jeff Bonwick	for (int t = 0; t < ZIO_TYPES; t++) {
652e14bb32Jeff Bonwick		for (int q = 0; q < ZIO_TASKQ_TYPES; q++) {
65380eb36fGeorge Wilson			const zio_taskq_info_t *ztip = &zio_taskqs[t][q];
65480eb36fGeorge Wilson			enum zti_modes mode = ztip->zti_mode;
65580eb36fGeorge Wilson			uint_t value = ztip->zti_value;
6562e0c549Jonathan Adams			char name[32];
6572e0c549Jonathan Adams
6582e0c549Jonathan Adams			(void) snprintf(name, sizeof (name),
65980eb36fGeorge Wilson			    "%s_%s", zio_type_name[t], zio_taskq_types[q]);
6602e0c549Jonathan Adams
66135a5a35Jonathan Adams			spa->spa_zio_taskq[t][q] =
66235a5a35Jonathan Adams			    spa_taskq_create(spa, name, mode, value);
66335a5a35Jonathan Adams		}
66435a5a35Jonathan Adams	}
66535a5a35Jonathan Adams}
66635a5a35Jonathan Adams
66735a5a35Jonathan Adams#ifdef _KERNEL
66835a5a35Jonathan Adamsstatic void
66935a5a35Jonathan Adamsspa_thread(void *arg)
67035a5a35Jonathan Adams{
67135a5a35Jonathan Adams	callb_cpr_t cprinfo;
6722e0c549Jonathan Adams
67335a5a35Jonathan Adams	spa_t *spa = arg;
67435a5a35Jonathan Adams	user_t *pu = PTOU(curproc);
6752e0c549Jonathan Adams
67635a5a35Jonathan Adams	CALLB_CPR_INIT(&cprinfo, &spa->spa_proc_lock, callb_generic_cpr,
67735a5a35Jonathan Adams	    spa->spa_name);
6782e0c549Jonathan Adams
67935a5a35Jonathan Adams	ASSERT(curproc != &p0);
68035a5a35Jonathan Adams	(void) snprintf(pu->u_psargs, sizeof (pu->u_psargs),
68135a5a35Jonathan Adams	    "zpool-%s", spa->spa_name);
68235a5a35Jonathan Adams	(void) strlcpy(pu->u_comm, pu->u_psargs, sizeof (pu->u_comm));
6832e0c549Jonathan Adams
68435a5a35Jonathan Adams	/* bind this thread to the requested psrset */
68535a5a35Jonathan Adams	if (zio_taskq_psrset_bind != PS_NONE) {
68635a5a35Jonathan Adams		pool_lock();
68735a5a35Jonathan Adams		mutex_enter(&cpu_lock);
68835a5a35Jonathan Adams		mutex_enter(&pidlock);
68935a5a35Jonathan Adams		mutex_enter(&curproc->p_lock);
69080eb36fGeorge Wilson
69135a5a35Jonathan Adams		if (cpupart_bind_thread(curthread, zio_taskq_psrset_bind,
69235a5a35Jonathan Adams		    0, NULL, NULL) == 0)  {
69335a5a35Jonathan Adams			curthread->t_bind_pset = zio_taskq_psrset_bind;
69435a5a35Jonathan Adams		} else {
69535a5a35Jonathan Adams			cmn_err(CE_WARN,
69635a5a35Jonathan Adams			    "Couldn't bind process for zfs pool \"%s\" to "
69735a5a35Jonathan Adams			    "pset %d\n", spa->spa_name, zio_taskq_psrset_bind);
69835a5a35Jonathan Adams		}
69935a5a35Jonathan Adams
70035a5a35Jonathan Adams		mutex_exit(&curproc->p_lock);
70135a5a35Jonathan Adams		mutex_exit(&pidlock);
70235a5a35Jonathan Adams		mutex_exit(&cpu_lock);
70335a5a35Jonathan Adams		pool_unlock();
70435a5a35Jonathan Adams	}
70535a5a35