/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
*/
/*
{ ZTI_ONE, ZTI_NULL, ZTI_ONE, ZTI_NULL },
{ ZTI_FIX(8), ZTI_NULL, ZTI_BATCH, ZTI_NULL },
{ ZTI_BATCH, ZTI_FIX(5), ZTI_FIX(16), ZTI_FIX(5) },
- { ZTI_FIX(100), ZTI_NULL, ZTI_ONE, ZTI_NULL },
+ { ZTI_PCT(100), ZTI_NULL, ZTI_ONE, ZTI_NULL },
{ ZTI_ONE, ZTI_NULL, ZTI_ONE, ZTI_NULL },
{ ZTI_ONE, ZTI_NULL, ZTI_ONE, ZTI_NULL },
};
spa_prop_add_list(*nvp, ZPOOL_PROP_GUID, NULL, spa_guid(spa), src);
+ if (spa->spa_comment != NULL) {
+ spa_prop_add_list(*nvp, ZPOOL_PROP_COMMENT, spa->spa_comment,
+ 0, ZPROP_SRC_LOCAL);
+ }
+
if (spa->spa_root != NULL)
spa_prop_add_list(*nvp, ZPOOL_PROP_ALTROOT, spa->spa_root,
0, ZPROP_SRC_LOCAL);
char *propname, *strval;
uint64_t intval;
objset_t *os;
- char *slash;
+ char *slash, *check;
propname = nvpair_name(elem);
error = EINVAL;
break;
+ case ZPOOL_PROP_COMMENT:
+ if ((error = nvpair_value_string(elem, &strval)) != 0)
+ break;
+ for (check = strval; *check != '\0'; check++) {
+ if (!isprint(*check)) {
+ error = EINVAL;
+ break;
+ }
+ check++;
+ }
+ if (strlen(strval) > ZPROP_MAX_COMMENT)
+ error = E2BIG;
+ break;
+
case ZPOOL_PROP_DEDUPDITTO:
if (spa_version(spa) < SPA_VERSION_DEDUP)
error = ENOTSUP;
}
/*
+ * Change the GUID for the pool. This is done so that we can later
+ * re-import a pool built from a clone of our own vdevs. We will modify
+ * the root vdev's guid, our own pool guid, and then mark all of our
+ * vdevs dirty. Note that we must make sure that all our vdevs are
+ * online when we do this, or else any vdevs that weren't present
+ * would be orphaned from our pool. We are also going to issue a
+ * sysevent to update any watchers.
+ */
+int
+spa_change_guid(spa_t *spa)
+{
+ uint64_t oldguid, newguid;
+ uint64_t txg;
+
+ if (!(spa_mode_global & FWRITE))
+ return (EROFS);
+
+ txg = spa_vdev_enter(spa);
+
+ if (spa->spa_root_vdev->vdev_state != VDEV_STATE_HEALTHY)
+ return (spa_vdev_exit(spa, NULL, txg, ENXIO));
+
+ oldguid = spa_guid(spa);
+ newguid = spa_generate_guid(NULL);
+ ASSERT3U(oldguid, !=, newguid);
+
+ spa->spa_root_vdev->vdev_guid = newguid;
+ spa->spa_root_vdev->vdev_guid_sum += (newguid - oldguid);
+
+ vdev_config_dirty(spa->spa_root_vdev);
+
+ spa_event_notify(spa, NULL, FM_EREPORT_ZFS_POOL_REGUID);
+
+ return (spa_vdev_exit(spa, NULL, txg, 0));
+}
+
+/*
* ==========================================================================
* SPA state manipulation (open/create/destroy/import/export)
* ==========================================================================
static taskq_t *
spa_taskq_create(spa_t *spa, const char *name, enum zti_modes mode,
- uint_t value)
+ uint_t value, uint_t flags)
{
- uint_t flags = TASKQ_PREPOPULATE;
boolean_t batch = B_FALSE;
switch (mode) {
const zio_taskq_info_t *ztip = &zio_taskqs[t][q];
enum zti_modes mode = ztip->zti_mode;
uint_t value = ztip->zti_value;
+ uint_t flags = 0;
char name[32];
+ if (t == ZIO_TYPE_WRITE)
+ flags |= TASKQ_NORECLAIM;
+
(void) snprintf(name, sizeof (name),
"%s_%s", zio_type_name[t], zio_taskq_types[q]);
spa->spa_zio_taskq[t][q] =
- spa_taskq_create(spa, name, mode, value);
+ spa_taskq_create(spa, name, mode, value, flags);
}
}
}
}
spa->spa_spares.sav_count = 0;
- for (i = 0; i < spa->spa_l2cache.sav_count; i++)
+ for (i = 0; i < spa->spa_l2cache.sav_count; i++) {
+ vdev_clear_stats(spa->spa_l2cache.sav_vdevs[i]);
vdev_free(spa->spa_l2cache.sav_vdevs[i]);
+ }
if (spa->spa_l2cache.sav_vdevs) {
kmem_free(spa->spa_l2cache.sav_vdevs,
spa->spa_l2cache.sav_count * sizeof (void *));
spa->spa_async_suspended = 0;
+ if (spa->spa_comment != NULL) {
+ spa_strfree(spa->spa_comment);
+ spa->spa_comment = NULL;
+ }
+
spa_config_exit(spa, SCL_ALL, FTAG);
}
vd = oldvdevs[i];
if (vd != NULL) {
+ ASSERT(vd->vdev_isl2cache);
+
if (spa_l2cache_exists(vd->vdev_guid, &pool) &&
pool != 0ULL && l2arc_vdev_present(vd))
l2arc_remove_vdev(vd);
- (void) vdev_close(vd);
- spa_l2cache_remove(vd);
+ vdev_clear_stats(vd);
+ vdev_free(vd);
}
}
{
nvlist_t *config = spa->spa_config;
char *ereport = FM_EREPORT_ZFS_POOL;
+ char *comment;
int error;
uint64_t pool_guid;
nvlist_t *nvl;
if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &pool_guid))
return (EINVAL);
+ ASSERT(spa->spa_comment == NULL);
+ if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
+ spa->spa_comment = spa_strdup(comment);
+
/*
* Versioning wasn't explicitly added to the label until later, so if
* it's not present treat it as the initial version.
spa_guid_exists(pool_guid, 0)) {
error = EEXIST;
} else {
- spa->spa_load_guid = pool_guid;
+ spa->spa_config_guid = pool_guid;
if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_SPLIT,
&nvl) == 0) {
*/
if (type != SPA_IMPORT_ASSEMBLE) {
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
- error = vdev_validate(rvd);
+ error = vdev_validate(rvd, mosconfig);
spa_config_exit(spa, SCL_ALL, FTAG);
if (error != 0)
cmn_err(CE_WARN, "pool '%s' could not be "
"loaded as it was last accessed by "
"another system (host: %s hostid: 0x%lx). "
- "See: http://www.sun.com/msg/ZFS-8000-EY",
+ "See: http://zfsonlinux.org/msg/ZFS-8000-EY",
spa_name(spa), hostname,
(unsigned long)hostid);
return (EBADF);
if ((strcmp(config, ZPOOL_CONFIG_L2CACHE) == 0) &&
strcmp(vd->vdev_ops->vdev_op_type, VDEV_TYPE_DISK) != 0) {
error = ENOTBLK;
+ vdev_free(vd);
goto out;
}
#endif
if (spa_l2cache_exists(vd->vdev_guid, &pool) &&
pool != 0ULL && l2arc_vdev_present(vd))
l2arc_remove_vdev(vd);
- if (vd->vdev_isl2cache)
- spa_l2cache_remove(vd);
- vdev_clear_stats(vd);
- (void) vdev_close(vd);
}
}
pvd = oldvd->vdev_parent;
if ((error = spa_config_parse(spa, &newrootvd, nvroot, NULL, 0,
- VDEV_ALLOC_ADD)) != 0)
+ VDEV_ALLOC_ATTACH)) != 0)
return (spa_vdev_exit(spa, NULL, txg, EINVAL));
if (newrootvd->vdev_children != 1)
* properties.
*/
break;
+ case ZPOOL_PROP_COMMENT:
+ VERIFY(nvpair_value_string(elem, &strval) == 0);
+ if (spa->spa_comment != NULL)
+ spa_strfree(spa->spa_comment);
+ spa->spa_comment = spa_strdup(strval);
+ /*
+ * We need to dirty the configuration on all the vdevs
+ * so that their labels get updated. It's unnecessary
+ * to do this for pool creation since the vdev's
+ * configuratoin has already been dirtied.
+ */
+ if (tx->tx_txg != TXG_INITIAL)
+ vdev_config_dirty(spa->spa_root_vdev);
+ break;
default:
/*
* Set pool property values in the poolprops mos object.