spa.c revision 503ad85c168c7992ccc310af845a581cff3c72b5
1fa9e406ahrens/* 2fa9e406ahrens * CDDL HEADER START 3fa9e406ahrens * 4fa9e406ahrens * The contents of this file are subject to the terms of the 5ea8dc4beschrock * Common Development and Distribution License (the "License"). 6ea8dc4beschrock * You may not use this file except in compliance with the License. 7fa9e406ahrens * 8fa9e406ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e406ahrens * or http://www.opensolaris.org/os/licensing. 10fa9e406ahrens * See the License for the specific language governing permissions 11fa9e406ahrens * and limitations under the License. 12fa9e406ahrens * 13fa9e406ahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e406ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e406ahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e406ahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e406ahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e406ahrens * 19fa9e406ahrens * CDDL HEADER END 20fa9e406ahrens */ 2199653d4eschrock 22fa9e406ahrens/* 23379c004Eric Schrock * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24fa9e406ahrens * Use is subject to license terms. 25fa9e406ahrens */ 26fa9e406ahrens 27fa9e406ahrens/* 28fa9e406ahrens * This file contains all the routines used when modifying on-disk SPA state. 29fa9e406ahrens * This includes opening, importing, destroying, exporting a pool, and syncing a 30fa9e406ahrens * pool. 31fa9e406ahrens */ 32fa9e406ahrens 33fa9e406ahrens#include <sys/zfs_context.h> 34ea8dc4beschrock#include <sys/fm/fs/zfs.h> 35fa9e406ahrens#include <sys/spa_impl.h> 36fa9e406ahrens#include <sys/zio.h> 37fa9e406ahrens#include <sys/zio_checksum.h> 38fa9e406ahrens#include <sys/zio_compress.h> 39fa9e406ahrens#include <sys/dmu.h> 40fa9e406ahrens#include <sys/dmu_tx.h> 41fa9e406ahrens#include <sys/zap.h> 42fa9e406ahrens#include <sys/zil.h> 43fa9e406ahrens#include <sys/vdev_impl.h> 44fa9e406ahrens#include <sys/metaslab.h> 45fa9e406ahrens#include <sys/uberblock_impl.h> 46fa9e406ahrens#include <sys/txg.h> 47fa9e406ahrens#include <sys/avl.h> 48fa9e406ahrens#include <sys/dmu_traverse.h> 49b1b8ab3lling#include <sys/dmu_objset.h> 50fa9e406ahrens#include <sys/unique.h> 51fa9e406ahrens#include <sys/dsl_pool.h> 52b1b8ab3lling#include <sys/dsl_dataset.h> 53fa9e406ahrens#include <sys/dsl_dir.h> 54fa9e406ahrens#include <sys/dsl_prop.h> 55b1b8ab3lling#include <sys/dsl_synctask.h> 56fa9e406ahrens#include <sys/fs/zfs.h> 57fa94a07brendan#include <sys/arc.h> 58fa9e406ahrens#include <sys/callb.h> 599517395ek#include <sys/systeminfo.h> 609517395ek#include <sys/sunddi.h> 61e7cbe64gw#include <sys/spa_boot.h> 62573ca77George Wilson#include <sys/zfs_ioctl.h> 63fa9e406ahrens 645679c89jv#ifdef _KERNEL 655679c89jv#include <sys/zone.h> 665679c89jv#endif /* _KERNEL */ 675679c89jv 68990b485lling#include "zfs_prop.h" 69b7b9745perrin#include "zfs_comutil.h" 70990b485lling 712e0c549Jonathan Adamsenum zti_modes { 722e0c549Jonathan Adams zti_mode_fixed, /* value is # of threads (min 1) */ 732e0c549Jonathan Adams zti_mode_online_percent, /* value is % of online CPUs */ 742e0c549Jonathan Adams zti_mode_tune, /* fill from zio_taskq_tune_* */ 752e0c549Jonathan Adams zti_nmodes 76e14bb32Jeff Bonwick}; 77416e0cdek 782e0c549Jonathan Adams#define ZTI_THREAD_FIX(n) { zti_mode_fixed, (n) } 792e0c549Jonathan Adams#define ZTI_THREAD_PCT(n) { zti_mode_online_percent, (n) } 802e0c549Jonathan Adams#define ZTI_THREAD_TUNE { zti_mode_tune, 0 } 812e0c549Jonathan Adams 822e0c549Jonathan Adams#define ZTI_THREAD_ONE ZTI_THREAD_FIX(1) 832e0c549Jonathan Adams 842e0c549Jonathan Adamstypedef struct zio_taskq_info { 852e0c549Jonathan Adams const char *zti_name; 862e0c549Jonathan Adams struct { 872e0c549Jonathan Adams enum zti_modes zti_mode; 882e0c549Jonathan Adams uint_t zti_value; 892e0c549Jonathan Adams } zti_nthreads[ZIO_TASKQ_TYPES]; 902e0c549Jonathan Adams} zio_taskq_info_t; 912e0c549Jonathan Adams 922e0c549Jonathan Adamsstatic const char *const zio_taskq_types[ZIO_TASKQ_TYPES] = { 932e0c549Jonathan Adams "issue", "intr" 942e0c549Jonathan Adams}; 952e0c549Jonathan Adams 962e0c549Jonathan Adamsconst zio_taskq_info_t zio_taskqs[ZIO_TYPES] = { 972e0c549Jonathan Adams /* ISSUE INTR */ 982e0c549Jonathan Adams { "spa_zio_null", { ZTI_THREAD_ONE, ZTI_THREAD_ONE } }, 992e0c549Jonathan Adams { "spa_zio_read", { ZTI_THREAD_FIX(8), ZTI_THREAD_TUNE } }, 1002e0c549Jonathan Adams { "spa_zio_write", { ZTI_THREAD_TUNE, ZTI_THREAD_FIX(8) } }, 1012e0c549Jonathan Adams { "spa_zio_free", { ZTI_THREAD_ONE, ZTI_THREAD_ONE } }, 1022e0c549Jonathan Adams { "spa_zio_claim", { ZTI_THREAD_ONE, ZTI_THREAD_ONE } }, 1032e0c549Jonathan Adams { "spa_zio_ioctl", { ZTI_THREAD_ONE, ZTI_THREAD_ONE } }, 1042e0c549Jonathan Adams}; 1052e0c549Jonathan Adams 1062e0c549Jonathan Adamsenum zti_modes zio_taskq_tune_mode = zti_mode_online_percent; 1072e0c549Jonathan Adamsuint_t zio_taskq_tune_value = 80; /* #threads = 80% of # online CPUs */ 1082e0c549Jonathan Adams 109990b485llingstatic void spa_sync_props(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx); 11089a89ebllingstatic boolean_t spa_has_active_shared_spare(spa_t *spa); 111990b485lling 112990b485lling/* 113990b485lling * ========================================================================== 114990b485lling * SPA properties routines 115990b485lling * ========================================================================== 116990b485lling */ 117990b485lling 118990b485lling/* 119990b485lling * Add a (source=src, propname=propval) list to an nvlist. 120990b485lling */ 1219d82f4fllingstatic void 122990b485llingspa_prop_add_list(nvlist_t *nvl, zpool_prop_t prop, char *strval, 123990b485lling uint64_t intval, zprop_source_t src) 124990b485lling{ 125990b485lling const char *propname = zpool_prop_to_name(prop); 126990b485lling nvlist_t *propval; 127990b485lling 1289d82f4flling VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0); 1299d82f4flling VERIFY(nvlist_add_uint64(propval, ZPROP_SOURCE, src) == 0); 130990b485lling 1319d82f4flling if (strval != NULL) 1329d82f4flling VERIFY(nvlist_add_string(propval, ZPROP_VALUE, strval) == 0); 1339d82f4flling else 1349d82f4flling VERIFY(nvlist_add_uint64(propval, ZPROP_VALUE, intval) == 0); 135990b485lling 1369d82f4flling VERIFY(nvlist_add_nvlist(nvl, propname, propval) == 0); 137990b485lling nvlist_free(propval); 138990b485lling} 139990b485lling 140990b485lling/* 141990b485lling * Get property values from the spa configuration. 142990b485lling */ 1439d82f4fllingstatic void 144990b485llingspa_prop_get_config(spa_t *spa, nvlist_t **nvp) 145990b485lling{ 146379c004Eric Schrock uint64_t size; 147379c004Eric Schrock uint64_t used; 148990b485lling uint64_t cap, version; 149990b485lling zprop_source_t src = ZPROP_SRC_NONE; 150c5904d1eschrock spa_config_dirent_t *dp; 151990b485lling 152e14bb32Jeff Bonwick ASSERT(MUTEX_HELD(&spa->spa_props_lock)); 153e14bb32Jeff Bonwick 154379c004Eric Schrock if (spa->spa_root_vdev != NULL) { 155379c004Eric Schrock size = spa_get_space(spa); 156379c004Eric Schrock used = spa_get_alloc(spa); 157379c004Eric Schrock spa_prop_add_list(*nvp, ZPOOL_PROP_NAME, spa_name(spa), 0, src); 158379c004Eric Schrock spa_prop_add_list(*nvp, ZPOOL_PROP_SIZE, NULL, size, src); 159379c004Eric Schrock spa_prop_add_list(*nvp, ZPOOL_PROP_USED, NULL, used, src); 160379c004Eric Schrock spa_prop_add_list(*nvp, ZPOOL_PROP_AVAILABLE, NULL, 161379c004Eric Schrock size - used, src); 162379c004Eric Schrock 163379c004Eric Schrock cap = (size == 0) ? 0 : (used * 100 / size); 164379c004Eric Schrock spa_prop_add_list(*nvp, ZPOOL_PROP_CAPACITY, NULL, cap, src); 165379c004Eric Schrock 166379c004Eric Schrock spa_prop_add_list(*nvp, ZPOOL_PROP_HEALTH, NULL, 167379c004Eric Schrock spa->spa_root_vdev->vdev_state, src); 168379c004Eric Schrock 169379c004Eric Schrock version = spa_version(spa); 170379c004Eric Schrock if (version == zpool_prop_default_numeric(ZPOOL_PROP_VERSION)) 171379c004Eric Schrock src = ZPROP_SRC_DEFAULT; 172379c004Eric Schrock else 173379c004Eric Schrock src = ZPROP_SRC_LOCAL; 174379c004Eric Schrock spa_prop_add_list(*nvp, ZPOOL_PROP_VERSION, NULL, version, src); 175379c004Eric Schrock } 176990b485lling 1779d82f4flling spa_prop_add_list(*nvp, ZPOOL_PROP_GUID, NULL, spa_guid(spa), src); 178990b485lling 1799d82f4flling if (spa->spa_root != NULL) 1809d82f4flling spa_prop_add_list(*nvp, ZPOOL_PROP_ALTROOT, spa->spa_root, 1819d82f4flling 0, ZPROP_SRC_LOCAL); 182990b485lling 183c5904d1eschrock if ((dp = list_head(&spa->spa_config_list)) != NULL) { 184c5904d1eschrock if (dp->scd_path == NULL) { 1859d82f4flling spa_prop_add_list(*nvp, ZPOOL_PROP_CACHEFILE, 186c5904d1eschrock "none", 0, ZPROP_SRC_LOCAL); 187c5904d1eschrock } else if (strcmp(dp->scd_path, spa_config_path) != 0) { 1889d82f4flling spa_prop_add_list(*nvp, ZPOOL_PROP_CACHEFILE, 189c5904d1eschrock dp->scd_path, 0, ZPROP_SRC_LOCAL); 1902f8aaabeschrock } 1912f8aaabeschrock } 192990b485lling} 193990b485lling 194990b485lling/* 195990b485lling * Get zpool property values. 196990b485lling */ 197990b485llingint 198990b485llingspa_prop_get(spa_t *spa, nvlist_t **nvp) 199990b485lling{ 200990b485lling zap_cursor_t zc; 201990b485lling zap_attribute_t za; 202990b485lling objset_t *mos = spa->spa_meta_objset; 203990b485lling int err; 204990b485lling 2059d82f4flling VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0); 206990b485lling 207e14bb32Jeff Bonwick mutex_enter(&spa->spa_props_lock); 208e14bb32Jeff Bonwick 209990b485lling /* 210990b485lling * Get properties from the spa config. 211990b485lling */ 2129d82f4flling spa_prop_get_config(spa, nvp); 213990b485lling 214990b485lling /* If no pool property object, no more prop to get. */ 215990b485lling if (spa->spa_pool_props_object == 0) { 216990b485lling mutex_exit(&spa->spa_props_lock); 217990b485lling return (0); 218990b485lling } 219990b485lling 220990b485lling /* 221990b485lling * Get properties from the MOS pool property object. 222990b485lling */ 223990b485lling for (zap_cursor_init(&zc, mos, spa->spa_pool_props_object); 224990b485lling (err = zap_cursor_retrieve(&zc, &za)) == 0; 225990b485lling zap_cursor_advance(&zc)) { 226990b485lling uint64_t intval = 0; 227990b485lling char *strval = NULL; 228990b485lling zprop_source_t src = ZPROP_SRC_DEFAULT; 229990b485lling zpool_prop_t prop; 230990b485lling 231990b485lling if ((prop = zpool_name_to_prop(za.za_name)) == ZPROP_INVAL) 232990b485lling continue; 233990b485lling 234990b485lling switch (za.za_integer_length) { 235990b485lling case 8: 236990b485lling /* integer property */ 237990b485lling if (za.za_first_integer != 238990b485lling zpool_prop_default_numeric(prop)) 239990b485lling src = ZPROP_SRC_LOCAL; 240990b485lling 241990b485lling if (prop == ZPOOL_PROP_BOOTFS) { 242990b485lling dsl_pool_t *dp; 243990b485lling dsl_dataset_t *ds = NULL; 244990b485lling 245990b485lling dp = spa_get_dsl(spa); 246990b485lling rw_enter(&dp->dp_config_rwlock, RW_READER); 247745cd3cmaybee if (err = dsl_dataset_hold_obj(dp, 248745cd3cmaybee za.za_first_integer, FTAG, &ds)) { 249990b485lling rw_exit(&dp->dp_config_rwlock); 250990b485lling break; 251990b485lling } 252990b485lling 253990b485lling strval = kmem_alloc( 254990b485lling MAXNAMELEN + strlen(MOS_DIR_NAME) + 1, 255990b485lling KM_SLEEP); 256990b485lling dsl_dataset_name(ds, strval); 257745cd3cmaybee dsl_dataset_rele(ds, FTAG); 258990b485lling rw_exit(&dp->dp_config_rwlock); 259990b485lling } else { 260990b485lling strval = NULL; 261990b485lling intval = za.za_first_integer; 262990b485lling } 263990b485lling 2649d82f4flling spa_prop_add_list(*nvp, prop, strval, intval, src); 265990b485lling 266990b485lling if (strval != NULL) 267990b485lling kmem_free(strval, 268990b485lling MAXNAMELEN + strlen(MOS_DIR_NAME) + 1); 269990b485lling 270990b485lling break; 271990b485lling 272990b485lling case 1: 273990b485lling /* string property */ 274990b485lling strval = kmem_alloc(za.za_num_integers, KM_SLEEP); 275990b485lling err = zap_lookup(mos, spa->spa_pool_props_object, 276990b485lling za.za_name, 1, za.za_num_integers, strval); 277990b485lling if (err) { 278990b485lling kmem_free(strval, za.za_num_integers); 279990b485lling break; 280990b485lling } 2819d82f4flling spa_prop_add_list(*nvp, prop, strval, 0, src); 282990b485lling kmem_free(strval, za.za_num_integers); 283990b485lling break; 284990b485lling 285990b485lling default: 286990b485lling break; 287990b485lling } 288990b485lling } 289990b485lling zap_cursor_fini(&zc); 290990b485lling mutex_exit(&spa->spa_props_lock); 291990b485llingout: 292990b485lling if (err && err != ENOENT) { 293990b485lling nvlist_free(*nvp); 2949d82f4flling *nvp = NULL; 295990b485lling return (err); 296990b485lling } 297990b485lling 298990b485lling return (0); 299990b485lling} 300990b485lling 301990b485lling/* 302990b485lling * Validate the given pool properties nvlist and modify the list 303990b485lling * for the property values to be set. 304990b485lling */ 305990b485llingstatic int 306990b485llingspa_prop_validate(spa_t *spa, nvlist_t *props) 307990b485lling{ 308990b485lling nvpair_t *elem; 309990b485lling int error = 0, reset_bootfs = 0; 310990b485lling uint64_t objnum; 311990b485lling 312990b485lling elem = NULL; 313990b485lling while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { 314990b485lling zpool_prop_t prop; 315990b485lling char *propname, *strval; 316990b485lling uint64_t intval; 317990b485lling objset_t *os; 3182f8aaabeschrock char *slash; 319990b485lling 320990b485lling propname = nvpair_name(elem); 321990b485lling 322990b485lling if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) 323990b485lling return (EINVAL); 324990b485lling 325990b485lling switch (prop) { 326990b485lling case ZPOOL_PROP_VERSION: 327990b485lling error = nvpair_value_uint64(elem, &intval); 328990b485lling if (!error && 329990b485lling (intval < spa_version(spa) || intval > SPA_VERSION)) 330990b485lling error = EINVAL; 331990b485lling break; 332990b485lling 333990b485lling case ZPOOL_PROP_DELEGATION: 334990b485lling case ZPOOL_PROP_AUTOREPLACE: 335d5b5bb2Rich Morris case ZPOOL_PROP_LISTSNAPS: 336573ca77George Wilson case ZPOOL_PROP_AUTOEXPAND: 337990b485lling error = nvpair_value_uint64(elem, &intval); 338990b485lling if (!error && intval > 1) 339990b485lling error = EINVAL; 340990b485lling break; 341990b485lling 342990b485lling case ZPOOL_PROP_BOOTFS: 34325f89eeJeff Bonwick /* 34425f89eeJeff Bonwick * If the pool version is less than SPA_VERSION_BOOTFS, 34525f89eeJeff Bonwick * or the pool is still being created (version == 0), 34625f89eeJeff Bonwick * the bootfs property cannot be set. 34725f89eeJeff Bonwick */ 348990b485lling if (spa_version(spa) < SPA_VERSION_BOOTFS) { 349990b485lling error = ENOTSUP; 350990b485lling break; 351990b485lling } 352990b485lling 353990b485lling /* 35415e6edfgw * Make sure the vdev config is bootable 355990b485lling */ 35615e6edfgw if (!vdev_is_bootable(spa->spa_root_vdev)) { 357990b485lling error = ENOTSUP; 358990b485lling break; 359990b485lling } 360990b485lling 361990b485lling reset_bootfs = 1; 362990b485lling 363990b485lling error = nvpair_value_string(elem, &strval); 364990b485lling 365990b485lling if (!error) { 36615e6edfgw uint64_t compress; 36715e6edfgw 368990b485lling if (strval == NULL || strval[0] == '\0') { 369990b485lling objnum = zpool_prop_default_numeric( 370990b485lling ZPOOL_PROP_BOOTFS); 371990b485lling break; 372990b485lling } 373990b485lling 374503ad85Matthew Ahrens if (error = dmu_objset_hold(strval, FTAG, &os)) 375990b485lling break; 37615e6edfgw 377503ad85Matthew Ahrens /* Must be ZPL and not gzip compressed. */ 378503ad85Matthew Ahrens 379503ad85Matthew Ahrens if (dmu_objset_type(os) != DMU_OST_ZFS) { 380503ad85Matthew Ahrens error = ENOTSUP; 381503ad85Matthew Ahrens } else if ((error = dsl_prop_get_integer(strval, 38215e6edfgw zfs_prop_to_name(ZFS_PROP_COMPRESSION), 38315e6edfgw &compress, NULL)) == 0 && 38415e6edfgw !BOOTFS_COMPRESS_VALID(compress)) { 38515e6edfgw error = ENOTSUP; 38615e6edfgw } else { 38715e6edfgw objnum = dmu_objset_id(os); 38815e6edfgw } 389503ad85Matthew Ahrens dmu_objset_rele(os, FTAG); 390990b485lling } 391990b485lling break; 392e14bb32Jeff Bonwick 3930a4e951gw case ZPOOL_PROP_FAILUREMODE: 3940a4e951gw error = nvpair_value_uint64(elem, &intval); 3950a4e951gw if (!error && (intval < ZIO_FAILURE_MODE_WAIT || 3960a4e951gw intval > ZIO_FAILURE_MODE_PANIC)) 3970a4e951gw error = EINVAL; 3980a4e951gw 3990a4e951gw /* 4000a4e951gw * This is a special case which only occurs when 4010a4e951gw * the pool has completely failed. This allows 4020a4e951gw * the user to change the in-core failmode property 4030a4e951gw * without syncing it out to disk (I/Os might 4040a4e951gw * currently be blocked). We do this by returning 4050a4e951gw * EIO to the caller (spa_prop_set) to trick it 4060a4e951gw * into thinking we encountered a property validation 4070a4e951gw * error. 4080a4e951gw */ 409e14bb32Jeff Bonwick if (!error && spa_suspended(spa)) { 4100a4e951gw spa->spa_failmode = intval; 4110a4e951gw error = EIO; 4120a4e951gw } 4130a4e951gw break; 4142f8aaabeschrock 4152f8aaabeschrock case ZPOOL_PROP_CACHEFILE: 4162f8aaabeschrock if ((error = nvpair_value_string(elem, &strval)) != 0) 4172f8aaabeschrock break; 4182f8aaabeschrock 4192f8aaabeschrock if (strval[0] == '\0') 4202f8aaabeschrock break; 4212f8aaabeschrock 4222f8aaabeschrock if (strcmp(strval, "none") == 0) 4232f8aaabeschrock break; 4242f8aaabeschrock 4252f8aaabeschrock if (strval[0] != '/') { 4262f8aaabeschrock error = EINVAL; 4272f8aaabeschrock break; 4282f8aaabeschrock } 4292f8aaabeschrock 4302f8aaabeschrock slash = strrchr(strval, '/'); 4312f8aaabeschrock ASSERT(slash != NULL); 4322f8aaabeschrock 4332f8aaabeschrock if (slash[1] == '\0' || strcmp(slash, "/.") == 0 || 4342f8aaabeschrock strcmp(slash, "/..") == 0) 4352f8aaabeschrock error = EINVAL; 4362f8aaabeschrock break; 437990b485lling } 438990b485lling 439990b485lling if (error) 440990b485lling break; 441990b485lling } 442990b485lling 443990b485lling if (!error && reset_bootfs) { 444990b485lling error = nvlist_remove(props, 445990b485lling zpool_prop_to_name(ZPOOL_PROP_BOOTFS), DATA_TYPE_STRING); 446990b485lling 447990b485lling if (!error) { 448990b485lling error = nvlist_add_uint64(props, 449990b485lling zpool_prop_to_name(ZPOOL_PROP_BOOTFS), objnum); 450990b485lling } 451990b485lling } 452990b485lling 453990b485lling return (error); 454990b485lling} 455990b485lling 456379c004Eric Schrockvoid 457379c004Eric Schrockspa_configfile_set(spa_t *spa, nvlist_t *nvp, boolean_t need_sync) 458379c004Eric Schrock{ 459379c004Eric Schrock char *cachefile; 460379c004Eric Schrock spa_config_dirent_t *dp; 461379c004Eric Schrock 462379c004Eric Schrock if (nvlist_lookup_string(nvp, zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 463379c004Eric Schrock &cachefile) != 0) 464379c004Eric Schrock return; 465379c004Eric Schrock 466379c004Eric Schrock dp = kmem_alloc(sizeof (spa_config_dirent_t), 467379c004Eric Schrock KM_SLEEP); 468379c004Eric Schrock 469379c004Eric Schrock if (cachefile[0] == '\0') 470379c004Eric Schrock dp->scd_path = spa_strdup(spa_config_path); 471379c004Eric Schrock else if (strcmp(cachefile, "none") == 0) 472379c004Eric Schrock dp->scd_path = NULL; 473379c004Eric Schrock else 474379c004Eric Schrock dp->scd_path = spa_strdup(cachefile); 475379c004Eric Schrock 476379c004Eric Schrock list_insert_head(&spa->spa_config_list, dp); 477379c004Eric Schrock if (need_sync) 478379c004Eric Schrock spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE); 479379c004Eric Schrock} 480379c004Eric Schrock 481990b485llingint 482990b485llingspa_prop_set(spa_t *spa, nvlist_t *nvp) 483990b485lling{ 484990b485lling int error; 485379c004Eric Schrock nvpair_t *elem; 486379c004Eric Schrock boolean_t need_sync = B_FALSE; 487379c004Eric Schrock zpool_prop_t prop; 488990b485lling 489990b485lling if ((error = spa_prop_validate(spa, nvp)) != 0) 490990b485lling return (error); 491990b485lling 492379c004Eric Schrock elem = NULL; 493379c004Eric Schrock while ((elem = nvlist_next_nvpair(nvp, elem)) != NULL) { 494379c004Eric Schrock if ((prop = zpool_name_to_prop( 495379c004Eric Schrock nvpair_name(elem))) == ZPROP_INVAL) 496379c004Eric Schrock return (EINVAL); 497379c004Eric Schrock 498379c004Eric Schrock if (prop == ZPOOL_PROP_CACHEFILE || prop == ZPOOL_PROP_ALTROOT) 499379c004Eric Schrock continue; 500379c004Eric Schrock 501379c004Eric Schrock need_sync = B_TRUE; 502379c004Eric Schrock break; 503379c004Eric Schrock } 504379c004Eric Schrock 505379c004Eric Schrock if (need_sync) 506379c004Eric Schrock return (dsl_sync_task_do(spa_get_dsl(spa), NULL, spa_sync_props, 507379c004Eric Schrock spa, nvp, 3)); 508379c004Eric Schrock else 509379c004Eric Schrock return (0); 510990b485lling} 511990b485lling 512990b485lling/* 513990b485lling * If the bootfs property value is dsobj, clear it. 514990b485lling */ 515990b485llingvoid 516990b485llingspa_prop_clear_bootfs(spa_t *spa, uint64_t dsobj, dmu_tx_t *tx) 517990b485lling{ 518990b485lling if (spa->spa_bootfs == dsobj && spa->spa_pool_props_object != 0) { 519990b485lling VERIFY(zap_remove(spa->spa_meta_objset, 520990b485lling spa->spa_pool_props_object, 521990b485lling zpool_prop_to_name(ZPOOL_PROP_BOOTFS), tx) == 0); 522990b485lling spa->spa_bootfs = 0; 523990b485lling } 524990b485lling} 525990b485lling 526fa9e406ahrens/* 527fa9e406ahrens * ========================================================================== 528fa9e406ahrens * SPA state manipulation (open/create/destroy/import/export) 529fa9e406ahrens * ========================================================================== 530fa9e406ahrens */ 531fa9e406ahrens 532ea8dc4beschrockstatic int 533ea8dc4beschrockspa_error_entry_compare(const void *a, const void *b) 534ea8dc4beschrock{ 535ea8dc4beschrock spa_error_entry_t *sa = (spa_error_entry_t *)a; 536ea8dc4beschrock spa_error_entry_t *sb = (spa_error_entry_t *)b; 537ea8dc4beschrock int ret; 538ea8dc4beschrock 539ea8dc4beschrock ret = bcmp(&sa->se_bookmark, &sb->se_bookmark, 540ea8dc4beschrock sizeof (zbookmark_t)); 541ea8dc4beschrock 542ea8dc4beschrock if (ret < 0) 543ea8dc4beschrock return (-1); 544ea8dc4beschrock else if (ret > 0) 545ea8dc4beschrock return (1); 546ea8dc4beschrock else 547ea8dc4beschrock return (0); 548ea8dc4beschrock} 549ea8dc4beschrock 550ea8dc4beschrock/* 551ea8dc4beschrock * Utility function which retrieves copies of the current logs and 552ea8dc4beschrock * re-initializes them in the process. 553ea8dc4beschrock */ 554ea8dc4beschrockvoid 555ea8dc4beschrockspa_get_errlists(spa_t *spa, avl_tree_t *last, avl_tree_t *scrub) 556ea8dc4beschrock{ 557ea8dc4beschrock ASSERT(MUTEX_HELD(&spa->spa_errlist_lock)); 558ea8dc4beschrock 559ea8dc4beschrock bcopy(&spa->spa_errlist_last, last, sizeof (avl_tree_t)); 560ea8dc4beschrock bcopy(&spa->spa_errlist_scrub, scrub, sizeof (avl_tree_t)); 561ea8dc4beschrock 562ea8dc4beschrock avl_create(&spa->spa_errlist_scrub, 563ea8dc4beschrock spa_error_entry_compare, sizeof (spa_error_entry_t), 564ea8dc4beschrock offsetof(spa_error_entry_t, se_avl)); 565ea8dc4beschrock avl_create(&spa->spa_errlist_last, 566ea8dc4beschrock spa_error_entry_compare, sizeof (spa_error_entry_t), 567ea8dc4beschrock offsetof(spa_error_entry_t, se_avl)); 568ea8dc4beschrock} 569ea8dc4beschrock 570fa9e406ahrens/* 571fa9e406ahrens * Activate an uninitialized pool. 572fa9e406ahrens */ 573fa9e406ahrensstatic void 5748ad4d6dJeff Bonwickspa_activate(spa_t *spa, int mode) 575fa9e406ahrens{ 576fa9e406ahrens ASSERT(spa->spa_state == POOL_STATE_UNINITIALIZED); 577fa9e406ahrens 578fa9e406ahrens spa->spa_state = POOL_STATE_ACTIVE; 5798ad4d6dJeff Bonwick spa->spa_mode = mode; 580fa9e406ahrens 581d6e555bGeorge Wilson spa->spa_normal_class = metaslab_class_create(zfs_metaslab_ops); 582d6e555bGeorge Wilson spa->spa_log_class = metaslab_class_create(zfs_metaslab_ops); 583fa9e406ahrens 584e14bb32Jeff Bonwick for (int t = 0; t < ZIO_TYPES; t++) { 5852e0c549Jonathan Adams const zio_taskq_info_t *ztip = &zio_taskqs[t]; 586e14bb32Jeff Bonwick for (int q = 0; q < ZIO_TASKQ_TYPES; q++) { 5872e0c549Jonathan Adams enum zti_modes mode = ztip->zti_nthreads[q].zti_mode; 5882e0c549Jonathan Adams uint_t value = ztip->zti_nthreads[q].zti_value; 5892e0c549Jonathan Adams char name[32]; 5902e0c549Jonathan Adams 5912e0c549Jonathan Adams (void) snprintf(name, sizeof (name), 5922e0c549Jonathan Adams "%s_%s", ztip->zti_name, zio_taskq_types[q]); 5932e0c549Jonathan Adams 5942e0c549Jonathan Adams if (mode == zti_mode_tune) { 5952e0c549Jonathan Adams mode = zio_taskq_tune_mode; 5962e0c549Jonathan Adams value = zio_taskq_tune_value; 5972e0c549Jonathan Adams if (mode == zti_mode_tune) 5982e0c549Jonathan Adams mode = zti_mode_online_percent; 5992e0c549Jonathan Adams } 6002e0c549Jonathan Adams 6012e0c549Jonathan Adams switch (mode) { 6022e0c549Jonathan Adams case zti_mode_fixed: 6032e0c549Jonathan Adams ASSERT3U(value, >=, 1); 6042e0c549Jonathan Adams value = MAX(value, 1); 6052e0c549Jonathan Adams 6062e0c549Jonathan Adams spa->spa_zio_taskq[t][q] = taskq_create(name, 6072e0c549Jonathan Adams value, maxclsyspri, 50, INT_MAX, 6082e0c549Jonathan Adams TASKQ_PREPOPULATE); 6092e0c549Jonathan Adams break; 6102e0c549Jonathan Adams 6112e0c549Jonathan Adams case zti_mode_online_percent: 6122e0c549Jonathan Adams spa->spa_zio_taskq[t][q] = taskq_create(name, 6132e0c549Jonathan Adams value, maxclsyspri, 50, INT_MAX, 6142e0c549Jonathan Adams TASKQ_PREPOPULATE | TASKQ_THREADS_CPU_PCT); 6152e0c549Jonathan Adams break; 6162e0c549Jonathan Adams 6172e0c549Jonathan Adams case zti_mode_tune: 6182e0c549Jonathan Adams default: 6192e0c549Jonathan Adams panic("unrecognized mode for " 6202e0c549Jonathan Adams "zio_taskqs[%u]->zti_nthreads[%u] (%u:%u) " 6212e0c549Jonathan Adams "in spa_activate()", 6222e0c549Jonathan Adams t, q, mode, value); 6232e0c549Jonathan Adams break; 6242e0c549Jonathan Adams } 625e14bb32Jeff Bonwick } 626fa9e406ahrens } 627fa9e406ahrens 628e14bb32Jeff Bonwick list_create(&spa->spa_config_dirty_list, sizeof (vdev_t), 629e14bb32Jeff Bonwick offsetof(vdev_t, vdev_config_dirty_node)); 630e14bb32Jeff Bonwick list_create(&spa->spa_state_dirty_list, sizeof (vdev_t), 631e14bb32Jeff Bonwick offsetof(vdev_t, vdev_state_dirty_node)); 632fa9e406ahrens 633fa9e406ahrens txg_list_create(&spa->spa_vdev_txg_list, 634fa9e406ahrens offsetof(struct vdev, vdev_txg_node)); 635ea8dc4beschrock 636ea8dc4beschrock avl_create(&spa->spa_errlist_scrub, 637ea8dc4beschrock spa_error_entry_compare, sizeof (spa_error_entry_t), 638ea8dc4beschrock offsetof(spa_error_entry_t, se_avl)); 639ea8dc4beschrock avl_create(&spa->spa_errlist_last, 640ea8dc4beschrock spa_error_entry_compare, sizeof (spa_error_entry_t), 641ea8dc4beschrock offsetof(spa_error_entry_t, se_avl)); 642fa9e406ahrens} 643fa9e406ahrens 644fa9e406ahrens/* 645fa9e406ahrens * Opposite of spa_activate(). 646fa9e406ahrens */ 647fa9e406ahrensstatic void 648fa9e406ahrensspa_deactivate(spa_t *spa) 649fa9e406ahrens{ 650fa9e406ahrens ASSERT(spa->spa_sync_on == B_FALSE); 651fa9e406ahrens ASSERT(spa->spa_dsl_pool == NULL); 652fa9e406ahrens ASSERT(spa->spa_root_vdev == NULL); 65325f89eeJeff Bonwick ASSERT(spa->spa_async_zio_root == NULL); 654fa9e406ahrens ASSERT(spa->spa_state != POOL_STATE_UNINITIALIZED); 655fa9e406ahrens 656fa9e406ahrens txg_list_destroy(&spa->spa_vdev_txg_list); 657fa9e406ahrens 658e14bb32Jeff Bonwick list_destroy(&spa->spa_config_dirty_list); 659e14bb32Jeff Bonwick list_destroy(&spa->spa_state_dirty_list); 660fa9e406ahrens 661e14bb32Jeff Bonwick for (int t = 0; t < ZIO_TYPES; t++) { 662e14bb32Jeff Bonwick for (int q = 0; q < ZIO_TASKQ_TYPES; q++) { 663e14bb32Jeff Bonwick taskq_destroy(spa->spa_zio_taskq[t][q]); 664e14bb32Jeff Bonwick spa->spa_zio_taskq[t][q] = NULL; 665e14bb32Jeff Bonwick } 666fa9e406ahrens } 667fa9e406ahrens 668fa9e406ahrens metaslab_class_destroy(spa->spa_normal_class); 669fa9e406ahrens spa->spa_normal_class = NULL; 670fa9e406ahrens 6718654d02perrin metaslab_class_destroy(spa->spa_log_class); 6728654d02perrin spa->spa_log_class = NULL; 6738654d02perrin 674ea8dc4beschrock /* 675ea8dc4beschrock * If this was part of an import or the open otherwise failed, we may 676