libzfs_pool.c revision 069f55e237020c4a4907b235fc38fafc6442ce94
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER START
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file are subject to the terms of the
441d80aa4f613b6298fc8bd3151f4be02dbf84fclling * Common Development and Distribution License (the "License").
441d80aa4f613b6298fc8bd3151f4be02dbf84fclling * You may not use this file except in compliance with the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens * or http://www.opensolaris.org/os/licensing.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * See the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * When distributing Covered Code, include this CDDL HEADER in each
fa9e4066f08beec538e775443c5be79dd423fcabahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If applicable, add the following below this CDDL HEADER, with the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * fields enclosed by brackets "[]" replaced with your own identifying
fa9e4066f08beec538e775443c5be79dd423fcabahrens * information: Portions Copyright [yyyy] [name of copyright owner]
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER END
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
99653d4ee642c6528e88224f12409a5f23060994eschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Use is subject to license terms.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <ctype.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <errno.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <devid.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <fcntl.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <libintl.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <stdio.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <stdlib.h>
f3861e1a2ceec23a5b699c24d814b7775a9e0b52ahl#include <strings.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <unistd.h>
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor#include <sys/efi_partition.h>
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor#include <sys/vtoc.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/zfs_ioctl.h>
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson#include <dlfcn.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "zfs_namecheck.h"
b1b8ab34de515a5e83206da22c3d7e563241b021lling#include "zfs_prop.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "libzfs_impl.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilsonconst char *hist_event_table[LOG_END] = {
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "invalid event",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "pool create",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "vdev add",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "pool remove",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "pool destroy",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "pool export",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "pool import",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "vdev attach",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "vdev replace",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "vdev detach",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "vdev online",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "vdev offline",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "vdev upgrade",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "pool clear",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "pool scrub",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "pool property set",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "create",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "clone",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "destroy",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "destroy_begin_sync",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "inherit",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "property set",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "quota set",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "permission update",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "permission remove",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "permission who remove",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "promote",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "receive",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "rename",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "reservation set",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "replay_inc_sync",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "replay_full_sync",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "rollback",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "snapshot",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "filesystem version upgrade",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "refquota set",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "refreservation set",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "pool scrub done",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "user hold",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson "user release",
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson};
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson
15e6edf145a9c2bb0e0272cf8debe823bb97529bgwstatic int read_efi_label(nvlist_t *config, diskaddr_t *sb);
990b4856d0eaada6f8140335733a1b1771ed2746lling
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson#if defined(__i386) || defined(__amd64)
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson#define BOOTCMD "installgrub(1M)"
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson#else
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson#define BOOTCMD "installboot(1M)"
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson#endif
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson#define DISK_ROOT "/dev/dsk"
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson#define RDISK_ROOT "/dev/rdsk"
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson#define BACKUP_SLICE "s2"
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
990b4856d0eaada6f8140335733a1b1771ed2746lling/*
990b4856d0eaada6f8140335733a1b1771ed2746lling * ====================================================================
990b4856d0eaada6f8140335733a1b1771ed2746lling * zpool property functions
990b4856d0eaada6f8140335733a1b1771ed2746lling * ====================================================================
990b4856d0eaada6f8140335733a1b1771ed2746lling */
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746llingstatic int
990b4856d0eaada6f8140335733a1b1771ed2746llingzpool_get_all_props(zpool_handle_t *zhp)
990b4856d0eaada6f8140335733a1b1771ed2746lling{
990b4856d0eaada6f8140335733a1b1771ed2746lling zfs_cmd_t zc = { 0 };
990b4856d0eaada6f8140335733a1b1771ed2746lling libzfs_handle_t *hdl = zhp->zpool_hdl;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0)
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling while (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) {
990b4856d0eaada6f8140335733a1b1771ed2746lling if (errno == ENOMEM) {
990b4856d0eaada6f8140335733a1b1771ed2746lling if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
990b4856d0eaada6f8140335733a1b1771ed2746lling zcmd_free_nvlists(&zc);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling } else {
990b4856d0eaada6f8140335733a1b1771ed2746lling zcmd_free_nvlists(&zc);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) {
990b4856d0eaada6f8140335733a1b1771ed2746lling zcmd_free_nvlists(&zc);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling zcmd_free_nvlists(&zc);
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling return (0);
990b4856d0eaada6f8140335733a1b1771ed2746lling}
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746llingstatic int
990b4856d0eaada6f8140335733a1b1771ed2746llingzpool_props_refresh(zpool_handle_t *zhp)
990b4856d0eaada6f8140335733a1b1771ed2746lling{
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_t *old_props;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling old_props = zhp->zpool_props;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (zpool_get_all_props(zhp) != 0)
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_free(old_props);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (0);
990b4856d0eaada6f8140335733a1b1771ed2746lling}
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746llingstatic char *
990b4856d0eaada6f8140335733a1b1771ed2746llingzpool_get_prop_string(zpool_handle_t *zhp, zpool_prop_t prop,
990b4856d0eaada6f8140335733a1b1771ed2746lling zprop_source_t *src)
990b4856d0eaada6f8140335733a1b1771ed2746lling{
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_t *nv, *nvl;
990b4856d0eaada6f8140335733a1b1771ed2746lling uint64_t ival;
990b4856d0eaada6f8140335733a1b1771ed2746lling char *value;
990b4856d0eaada6f8140335733a1b1771ed2746lling zprop_source_t source;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling nvl = zhp->zpool_props;
990b4856d0eaada6f8140335733a1b1771ed2746lling if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) {
990b4856d0eaada6f8140335733a1b1771ed2746lling verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &ival) == 0);
990b4856d0eaada6f8140335733a1b1771ed2746lling source = ival;
990b4856d0eaada6f8140335733a1b1771ed2746lling verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
990b4856d0eaada6f8140335733a1b1771ed2746lling } else {
990b4856d0eaada6f8140335733a1b1771ed2746lling source = ZPROP_SRC_DEFAULT;
990b4856d0eaada6f8140335733a1b1771ed2746lling if ((value = (char *)zpool_prop_default_string(prop)) == NULL)
990b4856d0eaada6f8140335733a1b1771ed2746lling value = "-";
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (src)
990b4856d0eaada6f8140335733a1b1771ed2746lling *src = source;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling return (value);
990b4856d0eaada6f8140335733a1b1771ed2746lling}
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746llinguint64_t
990b4856d0eaada6f8140335733a1b1771ed2746llingzpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop, zprop_source_t *src)
990b4856d0eaada6f8140335733a1b1771ed2746lling{
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_t *nv, *nvl;
990b4856d0eaada6f8140335733a1b1771ed2746lling uint64_t value;
990b4856d0eaada6f8140335733a1b1771ed2746lling zprop_source_t source;
990b4856d0eaada6f8140335733a1b1771ed2746lling
b87f3af36bb994656da117319f5129ddfd05ed21perrin if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) {
b87f3af36bb994656da117319f5129ddfd05ed21perrin /*
b87f3af36bb994656da117319f5129ddfd05ed21perrin * zpool_get_all_props() has most likely failed because
b87f3af36bb994656da117319f5129ddfd05ed21perrin * the pool is faulted, but if all we need is the top level
b87f3af36bb994656da117319f5129ddfd05ed21perrin * vdev's guid then get it from the zhp config nvlist.
b87f3af36bb994656da117319f5129ddfd05ed21perrin */
b87f3af36bb994656da117319f5129ddfd05ed21perrin if ((prop == ZPOOL_PROP_GUID) &&
b87f3af36bb994656da117319f5129ddfd05ed21perrin (nvlist_lookup_nvlist(zhp->zpool_config,
b87f3af36bb994656da117319f5129ddfd05ed21perrin ZPOOL_CONFIG_VDEV_TREE, &nv) == 0) &&
b87f3af36bb994656da117319f5129ddfd05ed21perrin (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &value)
b87f3af36bb994656da117319f5129ddfd05ed21perrin == 0)) {
b87f3af36bb994656da117319f5129ddfd05ed21perrin return (value);
b87f3af36bb994656da117319f5129ddfd05ed21perrin }
990b4856d0eaada6f8140335733a1b1771ed2746lling return (zpool_prop_default_numeric(prop));
b87f3af36bb994656da117319f5129ddfd05ed21perrin }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling nvl = zhp->zpool_props;
990b4856d0eaada6f8140335733a1b1771ed2746lling if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) {
990b4856d0eaada6f8140335733a1b1771ed2746lling verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &value) == 0);
990b4856d0eaada6f8140335733a1b1771ed2746lling source = value;
990b4856d0eaada6f8140335733a1b1771ed2746lling verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0);
990b4856d0eaada6f8140335733a1b1771ed2746lling } else {
990b4856d0eaada6f8140335733a1b1771ed2746lling source = ZPROP_SRC_DEFAULT;
990b4856d0eaada6f8140335733a1b1771ed2746lling value = zpool_prop_default_numeric(prop);
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (src)
990b4856d0eaada6f8140335733a1b1771ed2746lling *src = source;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling return (value);
990b4856d0eaada6f8140335733a1b1771ed2746lling}
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling/*
990b4856d0eaada6f8140335733a1b1771ed2746lling * Map VDEV STATE to printed strings.
990b4856d0eaada6f8140335733a1b1771ed2746lling */
990b4856d0eaada6f8140335733a1b1771ed2746llingchar *
990b4856d0eaada6f8140335733a1b1771ed2746llingzpool_state_to_name(vdev_state_t state, vdev_aux_t aux)
990b4856d0eaada6f8140335733a1b1771ed2746lling{
990b4856d0eaada6f8140335733a1b1771ed2746lling switch (state) {
990b4856d0eaada6f8140335733a1b1771ed2746lling case VDEV_STATE_CLOSED:
990b4856d0eaada6f8140335733a1b1771ed2746lling case VDEV_STATE_OFFLINE:
990b4856d0eaada6f8140335733a1b1771ed2746lling return (gettext("OFFLINE"));
990b4856d0eaada6f8140335733a1b1771ed2746lling case VDEV_STATE_REMOVED:
990b4856d0eaada6f8140335733a1b1771ed2746lling return (gettext("REMOVED"));
990b4856d0eaada6f8140335733a1b1771ed2746lling case VDEV_STATE_CANT_OPEN:
b87f3af36bb994656da117319f5129ddfd05ed21perrin if (aux == VDEV_AUX_CORRUPT_DATA || aux == VDEV_AUX_BAD_LOG)
990b4856d0eaada6f8140335733a1b1771ed2746lling return (gettext("FAULTED"));
990b4856d0eaada6f8140335733a1b1771ed2746lling else
990b4856d0eaada6f8140335733a1b1771ed2746lling return (gettext("UNAVAIL"));
990b4856d0eaada6f8140335733a1b1771ed2746lling case VDEV_STATE_FAULTED:
990b4856d0eaada6f8140335733a1b1771ed2746lling return (gettext("FAULTED"));
990b4856d0eaada6f8140335733a1b1771ed2746lling case VDEV_STATE_DEGRADED:
990b4856d0eaada6f8140335733a1b1771ed2746lling return (gettext("DEGRADED"));
990b4856d0eaada6f8140335733a1b1771ed2746lling case VDEV_STATE_HEALTHY:
990b4856d0eaada6f8140335733a1b1771ed2746lling return (gettext("ONLINE"));
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling return (gettext("UNKNOWN"));
990b4856d0eaada6f8140335733a1b1771ed2746lling}
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling/*
990b4856d0eaada6f8140335733a1b1771ed2746lling * Get a zpool property value for 'prop' and return the value in
990b4856d0eaada6f8140335733a1b1771ed2746lling * a pre-allocated buffer.
990b4856d0eaada6f8140335733a1b1771ed2746lling */
990b4856d0eaada6f8140335733a1b1771ed2746llingint
990b4856d0eaada6f8140335733a1b1771ed2746llingzpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
990b4856d0eaada6f8140335733a1b1771ed2746lling zprop_source_t *srctype)
990b4856d0eaada6f8140335733a1b1771ed2746lling{
990b4856d0eaada6f8140335733a1b1771ed2746lling uint64_t intval;
990b4856d0eaada6f8140335733a1b1771ed2746lling const char *strval;
990b4856d0eaada6f8140335733a1b1771ed2746lling zprop_source_t src = ZPROP_SRC_NONE;
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_t *nvroot;
990b4856d0eaada6f8140335733a1b1771ed2746lling vdev_stat_t *vs;
990b4856d0eaada6f8140335733a1b1771ed2746lling uint_t vsc;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock switch (prop) {
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock case ZPOOL_PROP_NAME:
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) strlcpy(buf, zpool_get_name(zhp), len);
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock break;
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock case ZPOOL_PROP_HEALTH:
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) strlcpy(buf, "FAULTED", len);
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock break;
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock case ZPOOL_PROP_GUID:
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock intval = zpool_get_prop_int(zhp, prop, &src);
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock (void) snprintf(buf, len, "%llu", intval);
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock break;
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock case ZPOOL_PROP_ALTROOT:
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock case ZPOOL_PROP_CACHEFILE:
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock if (zhp->zpool_props != NULL ||
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock zpool_get_all_props(zhp) == 0) {
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock (void) strlcpy(buf,
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock zpool_get_prop_string(zhp, prop, &src),
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock len);
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock if (srctype != NULL)
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock *srctype = src;
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock return (0);
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock }
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock /* FALLTHROUGH */
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock default:
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) strlcpy(buf, "-", len);
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock break;
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock }
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock if (srctype != NULL)
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock *srctype = src;
990b4856d0eaada6f8140335733a1b1771ed2746lling return (0);
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) &&
990b4856d0eaada6f8140335733a1b1771ed2746lling prop != ZPOOL_PROP_NAME)
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling switch (zpool_prop_get_type(prop)) {
990b4856d0eaada6f8140335733a1b1771ed2746lling case PROP_TYPE_STRING:
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) strlcpy(buf, zpool_get_prop_string(zhp, prop, &src),
990b4856d0eaada6f8140335733a1b1771ed2746lling len);
990b4856d0eaada6f8140335733a1b1771ed2746lling break;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling case PROP_TYPE_NUMBER:
990b4856d0eaada6f8140335733a1b1771ed2746lling intval = zpool_get_prop_int(zhp, prop, &src);
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling switch (prop) {
990b4856d0eaada6f8140335733a1b1771ed2746lling case ZPOOL_PROP_SIZE:
990b4856d0eaada6f8140335733a1b1771ed2746lling case ZPOOL_PROP_USED:
990b4856d0eaada6f8140335733a1b1771ed2746lling case ZPOOL_PROP_AVAILABLE:
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) zfs_nicenum(intval, buf, len);
990b4856d0eaada6f8140335733a1b1771ed2746lling break;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling case ZPOOL_PROP_CAPACITY:
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) snprintf(buf, len, "%llu%%",
990b4856d0eaada6f8140335733a1b1771ed2746lling (u_longlong_t)intval);
990b4856d0eaada6f8140335733a1b1771ed2746lling break;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling case ZPOOL_PROP_HEALTH:
990b4856d0eaada6f8140335733a1b1771ed2746lling verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
990b4856d0eaada6f8140335733a1b1771ed2746lling ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
990b4856d0eaada6f8140335733a1b1771ed2746lling verify(nvlist_lookup_uint64_array(nvroot,
990b4856d0eaada6f8140335733a1b1771ed2746lling ZPOOL_CONFIG_STATS, (uint64_t **)&vs, &vsc) == 0);
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) strlcpy(buf, zpool_state_to_name(intval,
990b4856d0eaada6f8140335733a1b1771ed2746lling vs->vs_aux), len);
990b4856d0eaada6f8140335733a1b1771ed2746lling break;
990b4856d0eaada6f8140335733a1b1771ed2746lling default:
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) snprintf(buf, len, "%llu", intval);
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling break;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling case PROP_TYPE_INDEX:
990b4856d0eaada6f8140335733a1b1771ed2746lling intval = zpool_get_prop_int(zhp, prop, &src);
990b4856d0eaada6f8140335733a1b1771ed2746lling if (zpool_prop_index_to_string(prop, intval, &strval)
990b4856d0eaada6f8140335733a1b1771ed2746lling != 0)
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) strlcpy(buf, strval, len);
990b4856d0eaada6f8140335733a1b1771ed2746lling break;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling default:
990b4856d0eaada6f8140335733a1b1771ed2746lling abort();
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (srctype)
990b4856d0eaada6f8140335733a1b1771ed2746lling *srctype = src;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling return (0);
990b4856d0eaada6f8140335733a1b1771ed2746lling}
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling/*
990b4856d0eaada6f8140335733a1b1771ed2746lling * Check if the bootfs name has the same pool name as it is set to.
990b4856d0eaada6f8140335733a1b1771ed2746lling * Assuming bootfs is a valid dataset name.
990b4856d0eaada6f8140335733a1b1771ed2746lling */
990b4856d0eaada6f8140335733a1b1771ed2746llingstatic boolean_t
990b4856d0eaada6f8140335733a1b1771ed2746llingbootfs_name_valid(const char *pool, char *bootfs)
990b4856d0eaada6f8140335733a1b1771ed2746lling{
990b4856d0eaada6f8140335733a1b1771ed2746lling int len = strlen(pool);
990b4856d0eaada6f8140335733a1b1771ed2746lling
fe3e2633be44d2f5361a7bba26abeb80fcc04fbcEric Taylor if (!zfs_name_valid(bootfs, ZFS_TYPE_FILESYSTEM|ZFS_TYPE_SNAPSHOT))
990b4856d0eaada6f8140335733a1b1771ed2746lling return (B_FALSE);
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (strncmp(pool, bootfs, len) == 0 &&
990b4856d0eaada6f8140335733a1b1771ed2746lling (bootfs[len] == '/' || bootfs[len] == '\0'))
990b4856d0eaada6f8140335733a1b1771ed2746lling return (B_TRUE);
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling return (B_FALSE);
990b4856d0eaada6f8140335733a1b1771ed2746lling}
990b4856d0eaada6f8140335733a1b1771ed2746lling
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw/*
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw * Inspect the configuration to determine if any of the devices contain
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw * an EFI label.
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw */
15e6edf145a9c2bb0e0272cf8debe823bb97529bgwstatic boolean_t
15e6edf145a9c2bb0e0272cf8debe823bb97529bgwpool_uses_efi(nvlist_t *config)
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw{
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw nvlist_t **child;
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw uint_t c, children;
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN,
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw &child, &children) != 0)
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw return (read_efi_label(config, NULL) >= 0);
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw for (c = 0; c < children; c++) {
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw if (pool_uses_efi(child[c]))
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw return (B_TRUE);
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw }
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw return (B_FALSE);
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw}
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw
b5b76fec872120fb1395471edcf51f378acd7e83George Wilsonstatic boolean_t
b5b76fec872120fb1395471edcf51f378acd7e83George Wilsonpool_is_bootable(zpool_handle_t *zhp)
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson{
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson char bootfs[ZPOOL_MAXNAMELEN];
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson return (zpool_get_prop(zhp, ZPOOL_PROP_BOOTFS, bootfs,
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson sizeof (bootfs), NULL) == 0 && strncmp(bootfs, "-",
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson sizeof (bootfs)) != 0);
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson}
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson
990b4856d0eaada6f8140335733a1b1771ed2746lling/*
990b4856d0eaada6f8140335733a1b1771ed2746lling * Given an nvlist of zpool properties to be set, validate that they are
990b4856d0eaada6f8140335733a1b1771ed2746lling * correct, and parse any numeric properties (index, boolean, etc) if they are
990b4856d0eaada6f8140335733a1b1771ed2746lling * specified as strings.
990b4856d0eaada6f8140335733a1b1771ed2746lling */
990b4856d0eaada6f8140335733a1b1771ed2746llingstatic nvlist_t *
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimhzpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_t *props, uint64_t version, boolean_t create_or_import, char *errbuf)
990b4856d0eaada6f8140335733a1b1771ed2746lling{
990b4856d0eaada6f8140335733a1b1771ed2746lling nvpair_t *elem;
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_t *retprops;
990b4856d0eaada6f8140335733a1b1771ed2746lling zpool_prop_t prop;
990b4856d0eaada6f8140335733a1b1771ed2746lling char *strval;
990b4856d0eaada6f8140335733a1b1771ed2746lling uint64_t intval;
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock char *slash;
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock struct stat64 statbuf;
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw zpool_handle_t *zhp;
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw nvlist_t *nvroot;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) {
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) no_memory(hdl);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (NULL);
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling elem = NULL;
990b4856d0eaada6f8140335733a1b1771ed2746lling while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
990b4856d0eaada6f8140335733a1b1771ed2746lling const char *propname = nvpair_name(elem);
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling /*
990b4856d0eaada6f8140335733a1b1771ed2746lling * Make sure this property is valid and applies to this type.
990b4856d0eaada6f8140335733a1b1771ed2746lling */
990b4856d0eaada6f8140335733a1b1771ed2746lling if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
990b4856d0eaada6f8140335733a1b1771ed2746lling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
990b4856d0eaada6f8140335733a1b1771ed2746lling "invalid property '%s'"), propname);
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
990b4856d0eaada6f8140335733a1b1771ed2746lling goto error;
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (zpool_prop_readonly(prop)) {
990b4856d0eaada6f8140335733a1b1771ed2746lling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
990b4856d0eaada6f8140335733a1b1771ed2746lling "is readonly"), propname);
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
990b4856d0eaada6f8140335733a1b1771ed2746lling goto error;
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (zprop_parse_value(hdl, elem, prop, ZFS_TYPE_POOL, retprops,
990b4856d0eaada6f8140335733a1b1771ed2746lling &strval, &intval, errbuf) != 0)
990b4856d0eaada6f8140335733a1b1771ed2746lling goto error;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling /*
990b4856d0eaada6f8140335733a1b1771ed2746lling * Perform additional checking for specific properties.
990b4856d0eaada6f8140335733a1b1771ed2746lling */
990b4856d0eaada6f8140335733a1b1771ed2746lling switch (prop) {
990b4856d0eaada6f8140335733a1b1771ed2746lling case ZPOOL_PROP_VERSION:
990b4856d0eaada6f8140335733a1b1771ed2746lling if (intval < version || intval > SPA_VERSION) {
990b4856d0eaada6f8140335733a1b1771ed2746lling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
990b4856d0eaada6f8140335733a1b1771ed2746lling "property '%s' number %d is invalid."),
990b4856d0eaada6f8140335733a1b1771ed2746lling propname, intval);
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
990b4856d0eaada6f8140335733a1b1771ed2746lling goto error;
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling break;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling case ZPOOL_PROP_BOOTFS:
990b4856d0eaada6f8140335733a1b1771ed2746lling if (create_or_import) {
990b4856d0eaada6f8140335733a1b1771ed2746lling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
990b4856d0eaada6f8140335733a1b1771ed2746lling "property '%s' cannot be set at creation "
990b4856d0eaada6f8140335733a1b1771ed2746lling "or import time"), propname);
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
990b4856d0eaada6f8140335733a1b1771ed2746lling goto error;
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (version < SPA_VERSION_BOOTFS) {
990b4856d0eaada6f8140335733a1b1771ed2746lling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
990b4856d0eaada6f8140335733a1b1771ed2746lling "pool must be upgraded to support "
990b4856d0eaada6f8140335733a1b1771ed2746lling "'%s' property"), propname);
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
990b4856d0eaada6f8140335733a1b1771ed2746lling goto error;
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling /*
990b4856d0eaada6f8140335733a1b1771ed2746lling * bootfs property value has to be a dataset name and
990b4856d0eaada6f8140335733a1b1771ed2746lling * the dataset has to be in the same pool as it sets to.
990b4856d0eaada6f8140335733a1b1771ed2746lling */
990b4856d0eaada6f8140335733a1b1771ed2746lling if (strval[0] != '\0' && !bootfs_name_valid(poolname,
990b4856d0eaada6f8140335733a1b1771ed2746lling strval)) {
990b4856d0eaada6f8140335733a1b1771ed2746lling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
990b4856d0eaada6f8140335733a1b1771ed2746lling "is an invalid name"), strval);
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
990b4856d0eaada6f8140335733a1b1771ed2746lling goto error;
990b4856d0eaada6f8140335733a1b1771ed2746lling }
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw if ((zhp = zpool_open_canfail(hdl, poolname)) == NULL) {
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw "could not open pool '%s'"), poolname);
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf);
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw goto error;
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw }
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw /*
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw * bootfs property cannot be set on a disk which has
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw * been EFI labeled.
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw */
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw if (pool_uses_efi(nvroot)) {
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw "property '%s' not supported on "
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw "EFI labeled devices"), propname);
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw (void) zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf);
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw zpool_close(zhp);
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw goto error;
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw }
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw zpool_close(zhp);
990b4856d0eaada6f8140335733a1b1771ed2746lling break;
990b4856d0eaada6f8140335733a1b1771ed2746lling
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock case ZPOOL_PROP_ALTROOT:
990b4856d0eaada6f8140335733a1b1771ed2746lling if (!create_or_import) {
990b4856d0eaada6f8140335733a1b1771ed2746lling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
990b4856d0eaada6f8140335733a1b1771ed2746lling "property '%s' can only be set during pool "
990b4856d0eaada6f8140335733a1b1771ed2746lling "creation or import"), propname);
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
990b4856d0eaada6f8140335733a1b1771ed2746lling goto error;
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock if (strval[0] != '/') {
990b4856d0eaada6f8140335733a1b1771ed2746lling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock "bad alternate root '%s'"), strval);
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
990b4856d0eaada6f8140335733a1b1771ed2746lling goto error;
990b4856d0eaada6f8140335733a1b1771ed2746lling }
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock break;
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock case ZPOOL_PROP_CACHEFILE:
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock if (strval[0] == '\0')
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock break;
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock if (strcmp(strval, "none") == 0)
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock break;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (strval[0] != '/') {
990b4856d0eaada6f8140335733a1b1771ed2746lling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock "property '%s' must be empty, an "
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock "absolute path, or 'none'"), propname);
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
990b4856d0eaada6f8140335733a1b1771ed2746lling goto error;
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock slash = strrchr(strval, '/');
990b4856d0eaada6f8140335733a1b1771ed2746lling
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock if (slash[1] == '\0' || strcmp(slash, "/.") == 0 ||
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock strcmp(slash, "/..") == 0) {
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock "'%s' is not a valid file"), strval);
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock goto error;
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock }
990b4856d0eaada6f8140335733a1b1771ed2746lling
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock *slash = '\0';
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock
2c32020f848d8e5619a1f441a92f0ee4aca1b297eschrock if (strval[0] != '\0' &&
2c32020f848d8e5619a1f441a92f0ee4aca1b297eschrock (stat64(strval, &statbuf) != 0 ||
2c32020f848d8e5619a1f441a92f0ee4aca1b297eschrock !S_ISDIR(statbuf.st_mode))) {
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock "'%s' is not a valid directory"),
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock strval);
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock goto error;
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock }
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock *slash = '/';
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock break;
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling return (retprops);
990b4856d0eaada6f8140335733a1b1771ed2746llingerror:
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_free(retprops);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (NULL);
990b4856d0eaada6f8140335733a1b1771ed2746lling}
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling/*
990b4856d0eaada6f8140335733a1b1771ed2746lling * Set zpool property : propname=propval.
990b4856d0eaada6f8140335733a1b1771ed2746lling */
990b4856d0eaada6f8140335733a1b1771ed2746llingint
990b4856d0eaada6f8140335733a1b1771ed2746llingzpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval)
990b4856d0eaada6f8140335733a1b1771ed2746lling{
990b4856d0eaada6f8140335733a1b1771ed2746lling zfs_cmd_t zc = { 0 };
990b4856d0eaada6f8140335733a1b1771ed2746lling int ret = -1;
990b4856d0eaada6f8140335733a1b1771ed2746lling char errbuf[1024];
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_t *nvl = NULL;
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_t *realprops;
990b4856d0eaada6f8140335733a1b1771ed2746lling uint64_t version;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) snprintf(errbuf, sizeof (errbuf),
990b4856d0eaada6f8140335733a1b1771ed2746lling dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
990b4856d0eaada6f8140335733a1b1771ed2746lling zhp->zpool_name);
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
990b4856d0eaada6f8140335733a1b1771ed2746lling return (no_memory(zhp->zpool_hdl));
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (nvlist_add_string(nvl, propname, propval) != 0) {
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_free(nvl);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (no_memory(zhp->zpool_hdl));
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh if ((realprops = zpool_valid_proplist(zhp->zpool_hdl,
990b4856d0eaada6f8140335733a1b1771ed2746lling zhp->zpool_name, nvl, version, B_FALSE, errbuf)) == NULL) {
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_free(nvl);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_free(nvl);
990b4856d0eaada6f8140335733a1b1771ed2746lling nvl = realprops;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling /*
990b4856d0eaada6f8140335733a1b1771ed2746lling * Execute the corresponding ioctl() to set this property.
990b4856d0eaada6f8140335733a1b1771ed2746lling */
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl) != 0) {
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_free(nvl);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SET_PROPS, &zc);
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling zcmd_free_nvlists(&zc);
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_free(nvl);
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (ret)
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf);
990b4856d0eaada6f8140335733a1b1771ed2746lling else
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) zpool_props_refresh(zhp);
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling return (ret);
990b4856d0eaada6f8140335733a1b1771ed2746lling}
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746llingint
990b4856d0eaada6f8140335733a1b1771ed2746llingzpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
990b4856d0eaada6f8140335733a1b1771ed2746lling{
990b4856d0eaada6f8140335733a1b1771ed2746lling libzfs_handle_t *hdl = zhp->zpool_hdl;
990b4856d0eaada6f8140335733a1b1771ed2746lling zprop_list_t *entry;
990b4856d0eaada6f8140335733a1b1771ed2746lling char buf[ZFS_MAXPROPLEN];
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0)
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling for (entry = *plp; entry != NULL; entry = entry->pl_next) {
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (entry->pl_fixed)
990b4856d0eaada6f8140335733a1b1771ed2746lling continue;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (entry->pl_prop != ZPROP_INVAL &&
990b4856d0eaada6f8140335733a1b1771ed2746lling zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf),
990b4856d0eaada6f8140335733a1b1771ed2746lling NULL) == 0) {
990b4856d0eaada6f8140335733a1b1771ed2746lling if (strlen(buf) > entry->pl_width)
990b4856d0eaada6f8140335733a1b1771ed2746lling entry->pl_width = strlen(buf);
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling return (0);
990b4856d0eaada6f8140335733a1b1771ed2746lling}
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson/*
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * Don't start the slice at the default block of 34; many storage
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * devices will use a stripe width of 128k, so start there instead.
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson#define NEW_START_BLOCK 256
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Validate the given pool name, optionally putting an extended error message in
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 'buf'.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gwboolean_t
99653d4ee642c6528e88224f12409a5f23060994eschrockzpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens namecheck_err_t why;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char what;
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock int ret;
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock ret = pool_namecheck(pool, &why, &what);
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock /*
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock * The rules for reserved pool names were extended at a later point.
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock * But we need to support users with existing pools that may now be
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock * invalid. So we only check for this expanded set of names during a
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock * create (or import), and only in userland.
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock */
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock if (ret == 0 && !isopen &&
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock (strncmp(pool, "mirror", 6) == 0 ||
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock strncmp(pool, "raidz", 5) == 0 ||
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin strncmp(pool, "spare", 5) == 0 ||
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin strcmp(pool, "log") == 0)) {
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if (hdl != NULL)
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw zfs_error_aux(hdl,
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw dgettext(TEXT_DOMAIN, "name is reserved"));
99653d4ee642c6528e88224f12409a5f23060994eschrock return (B_FALSE);
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock }
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b468a217b67dc26ce21da5d5a2ca09bb6249e4faeschrock if (ret != 0) {
99653d4ee642c6528e88224f12409a5f23060994eschrock if (hdl != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (why) {
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling case NAME_ERR_TOOLONG:
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl,
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling dgettext(TEXT_DOMAIN, "name is too long"));
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling break;
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling
fa9e4066f08beec538e775443c5be79dd423fcabahrens case NAME_ERR_INVALCHAR:
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl,
fa9e4066f08beec538e775443c5be79dd423fcabahrens dgettext(TEXT_DOMAIN, "invalid character "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "'%c' in pool name"), what);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens case NAME_ERR_NOLETTER:
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "name must begin with a letter"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens case NAME_ERR_RESERVED:
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "name is reserved"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens case NAME_ERR_DISKLIKE:
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "pool name is reserved"));
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
5ad820458efd0fdb914baff9c1447c22b819fa23nd
5ad820458efd0fdb914baff9c1447c22b819fa23nd case NAME_ERR_LEADING_SLASH:
5ad820458efd0fdb914baff9c1447c22b819fa23nd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5ad820458efd0fdb914baff9c1447c22b819fa23nd "leading slash in name"));
5ad820458efd0fdb914baff9c1447c22b819fa23nd break;
5ad820458efd0fdb914baff9c1447c22b819fa23nd
5ad820458efd0fdb914baff9c1447c22b819fa23nd case NAME_ERR_EMPTY_COMPONENT:
5ad820458efd0fdb914baff9c1447c22b819fa23nd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5ad820458efd0fdb914baff9c1447c22b819fa23nd "empty component in name"));
5ad820458efd0fdb914baff9c1447c22b819fa23nd break;
5ad820458efd0fdb914baff9c1447c22b819fa23nd
5ad820458efd0fdb914baff9c1447c22b819fa23nd case NAME_ERR_TRAILING_SLASH:
5ad820458efd0fdb914baff9c1447c22b819fa23nd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5ad820458efd0fdb914baff9c1447c22b819fa23nd "trailing slash in name"));
5ad820458efd0fdb914baff9c1447c22b819fa23nd break;
5ad820458efd0fdb914baff9c1447c22b819fa23nd
5ad820458efd0fdb914baff9c1447c22b819fa23nd case NAME_ERR_MULTIPLE_AT:
5ad820458efd0fdb914baff9c1447c22b819fa23nd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5ad820458efd0fdb914baff9c1447c22b819fa23nd "multiple '@' delimiters in name"));
5ad820458efd0fdb914baff9c1447c22b819fa23nd break;
5ad820458efd0fdb914baff9c1447c22b819fa23nd
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
99653d4ee642c6528e88224f12409a5f23060994eschrock return (B_FALSE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock return (B_TRUE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Open a handle to the given pool, even if the pool is currently in the FAULTED
fa9e4066f08beec538e775443c5be79dd423fcabahrens * state.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrenszpool_handle_t *
99653d4ee642c6528e88224f12409a5f23060994eschrockzpool_open_canfail(libzfs_handle_t *hdl, const char *pool)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zpool_handle_t *zhp;
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock boolean_t missing;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Make sure the pool name is valid.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
99653d4ee642c6528e88224f12409a5f23060994eschrock if (!zpool_name_valid(hdl, B_TRUE, pool)) {
ece3d9b3bacef51a5f34d993935eedbb7bb87059lling (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME,
99653d4ee642c6528e88224f12409a5f23060994eschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"),
99653d4ee642c6528e88224f12409a5f23060994eschrock pool);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock zhp->zpool_hdl = hdl;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock if (zpool_refresh_stats(zhp, &missing) != 0) {
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock zpool_close(zhp);
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock return (NULL);
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock }
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock if (missing) {
990b4856d0eaada6f8140335733a1b1771ed2746lling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "no such pool"));
ece3d9b3bacef51a5f34d993935eedbb7bb87059lling (void) zfs_error_fmt(hdl, EZFS_NOENT,
990b4856d0eaada6f8140335733a1b1771ed2746lling dgettext(TEXT_DOMAIN, "cannot open '%s'"), pool);
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock zpool_close(zhp);
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock return (NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (zhp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Like the above, but silent on error. Used when iterating over pools (because
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the configuration cache may be out of date).
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrockint
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrockzpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zpool_handle_t *zhp;
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock boolean_t missing;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock zhp->zpool_hdl = hdl;
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock if (zpool_refresh_stats(zhp, &missing) != 0) {
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock zpool_close(zhp);
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock if (missing) {
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock zpool_close(zhp);
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock *ret = NULL;
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock return (0);
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock }
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock *ret = zhp;
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Similar to zpool_open_canfail(), but refuses to open pools in the faulted
fa9e4066f08beec538e775443c5be79dd423fcabahrens * state.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrenszpool_handle_t *
99653d4ee642c6528e88224f12409a5f23060994eschrockzpool_open(libzfs_handle_t *hdl, const char *pool)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zpool_handle_t *zhp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock if ((zhp = zpool_open_canfail(hdl, pool)) == NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (zhp->zpool_state == POOL_STATE_UNAVAIL) {
ece3d9b3bacef51a5f34d993935eedbb7bb87059lling (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL,
99653d4ee642c6528e88224f12409a5f23060994eschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens zpool_close(zhp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (zhp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Close the handle. Simply frees the memory associated with the handle.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrenszpool_close(zpool_handle_t *zhp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (zhp->zpool_config)
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvlist_free(zhp->zpool_config);
088e9d477eee66081e407fbc5a33c4da25f66f6aeschrock if (zhp->zpool_old_config)
088e9d477eee66081e407fbc5a33c4da25f66f6aeschrock nvlist_free(zhp->zpool_old_config);
b1b8ab34de515a5e83206da22c3d7e563241b021lling if (zhp->zpool_props)
b1b8ab34de515a5e83206da22c3d7e563241b021lling nvlist_free(zhp->zpool_props);
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(zhp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Return the name of the pool.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensconst char *
fa9e4066f08beec538e775443c5be79dd423fcabahrenszpool_get_name(zpool_handle_t *zhp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (zhp->zpool_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Return the state of the pool (ACTIVE or UNAVAILABLE)
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
fa9e4066f08beec538e775443c5be79dd423fcabahrenszpool_get_state(zpool_handle_t *zhp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (zhp->zpool_state);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Create the named pool, using the provided vdev list. It is assumed
fa9e4066f08beec538e775443c5be79dd423fcabahrens * that the consumer has already validated the contents of the nvlist, so we
fa9e4066f08beec538e775443c5be79dd423fcabahrens * don't have to worry about error semantics.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
99653d4ee642c6528e88224f12409a5f23060994eschrockzpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh nvlist_t *props, nvlist_t *fsprops)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_cmd_t zc = { 0 };
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh nvlist_t *zc_fsprops = NULL;
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh nvlist_t *zc_props = NULL;
99653d4ee642c6528e88224f12409a5f23060994eschrock char msg[1024];
990b4856d0eaada6f8140335733a1b1771ed2746lling char *altroot;
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh int ret = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "cannot create '%s'"), pool);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock if (!zpool_name_valid(hdl, B_FALSE, pool))
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_INVALIDNAME, msg));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
351420b34707afeafa8d5c3e0c77b7bcffb1edc0lling if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh if (props) {
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh if ((zc_props = zpool_valid_proplist(hdl, pool, props,
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh SPA_VERSION_1, B_TRUE, msg)) == NULL) {
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh goto create_failed;
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh }
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh }
99653d4ee642c6528e88224f12409a5f23060994eschrock
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh if (fsprops) {
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh uint64_t zoned;
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh char *zonestr;
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh zoned = ((nvlist_lookup_string(fsprops,
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh zfs_prop_to_name(ZFS_PROP_ZONED), &zonestr) == 0) &&
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh strcmp(zonestr, "on") == 0);
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh if ((zc_fsprops = zfs_valid_proplist(hdl,
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh ZFS_TYPE_FILESYSTEM, fsprops, zoned, NULL, msg)) == NULL) {
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh goto create_failed;
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh }
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh if (!zc_props &&
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh (nvlist_alloc(&zc_props, NV_UNIQUE_NAME, 0) != 0)) {
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh goto create_failed;
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh }
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh if (nvlist_add_nvlist(zc_props,
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh ZPOOL_ROOTFS_PROPS, zc_fsprops) != 0) {
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh goto create_failed;
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh }
351420b34707afeafa8d5c3e0c77b7bcffb1edc0lling }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh if (zc_props && zcmd_write_src_nvlist(hdl, &zc, zc_props) != 0)
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh goto create_failed;
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh if ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_CREATE, &zc)) != 0) {
351420b34707afeafa8d5c3e0c77b7bcffb1edc0lling
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock zcmd_free_nvlists(&zc);
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh nvlist_free(zc_props);
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh nvlist_free(zc_fsprops);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock switch (errno) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens case EBUSY:
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This can happen if the user has specified the same
fa9e4066f08beec538e775443c5be79dd423fcabahrens * device multiple times. We can't reliably detect this
fa9e4066f08beec538e775443c5be79dd423fcabahrens * until we try to add it and see we already have a
fa9e4066f08beec538e775443c5be79dd423fcabahrens * label.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "one or more vdevs refer to the same device"));
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_BADDEV, msg));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens case EOVERFLOW:
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
99653d4ee642c6528e88224f12409a5f23060994eschrock * This occurs when one of the devices is below
fa9e4066f08beec538e775443c5be79dd423fcabahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which
fa9e4066f08beec538e775443c5be79dd423fcabahrens * device was the problem device since there's no
fa9e4066f08beec538e775443c5be79dd423fcabahrens * reliable way to determine device size from userland.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens char buf[64];
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "one or more devices is less than the "
99653d4ee642c6528e88224f12409a5f23060994eschrock "minimum size (%s)"), buf);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_BADDEV, msg));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens case ENOSPC:
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "one or more devices is out of space"));
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_BADDEV, msg));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan case ENOTBLK:
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan "cache device must be a disk or disk slice"));
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan return (zfs_error(hdl, EZFS_BADDEV, msg));
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan
fa9e4066f08beec538e775443c5be79dd423fcabahrens default:
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zpool_standard_error(hdl, errno, msg));
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If this is an alternate root pool, then we automatically set the
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * mountpoint of the root dataset to be '/'.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
990b4856d0eaada6f8140335733a1b1771ed2746lling if (nvlist_lookup_string(props, zpool_prop_to_name(ZPOOL_PROP_ALTROOT),
990b4856d0eaada6f8140335733a1b1771ed2746lling &altroot) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_handle_t *zhp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
990b4856d0eaada6f8140335733a1b1771ed2746lling verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_DATASET)) != NULL);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock "/") == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_close(zhp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimhcreate_failed:
351420b34707afeafa8d5c3e0c77b7bcffb1edc0lling zcmd_free_nvlists(&zc);
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh nvlist_free(zc_props);
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh nvlist_free(zc_fsprops);
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh return (ret);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Destroy the given pool. It is up to the caller to ensure that there are no
fa9e4066f08beec538e775443c5be79dd423fcabahrens * datasets left in the pool.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
fa9e4066f08beec538e775443c5be79dd423fcabahrenszpool_destroy(zpool_handle_t *zhp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_cmd_t zc = { 0 };
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_handle_t *zfp = NULL;
99653d4ee642c6528e88224f12409a5f23060994eschrock libzfs_handle_t *hdl = zhp->zpool_hdl;
99653d4ee642c6528e88224f12409a5f23060994eschrock char msg[1024];
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (zhp->zpool_state == POOL_STATE_ACTIVE &&
99653d4ee642c6528e88224f12409a5f23060994eschrock (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name,
99653d4ee642c6528e88224f12409a5f23060994eschrock ZFS_TYPE_FILESYSTEM)) == NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "cannot destroy '%s'"), zhp->zpool_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock if (errno == EROFS) {
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "one or more devices is read only"));
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zfs_error(hdl, EZFS_BADDEV, msg);
99653d4ee642c6528e88224f12409a5f23060994eschrock } else {
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zpool_standard_error(hdl, errno, msg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (zfp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_close(zfp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (zfp) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens remove_mountpoint(zfp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_close(zfp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Add the given vdevs to the pool. The caller must have already performed the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * necessary verification to ensure that the vdev specification is well-formed.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
fa9e4066f08beec538e775443c5be79dd423fcabahrenszpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock zfs_cmd_t zc = { 0 };
99653d4ee642c6528e88224f12409a5f23060994eschrock int ret;
99653d4ee642c6528e88224f12409a5f23060994eschrock libzfs_handle_t *hdl = zhp->zpool_hdl;
99653d4ee642c6528e88224f12409a5f23060994eschrock char msg[1024];
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan nvlist_t **spares, **l2cache;
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan uint_t nspares, nl2cache;
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "cannot add to '%s'"), zhp->zpool_name);
99653d4ee642c6528e88224f12409a5f23060994eschrock
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan SPA_VERSION_SPARES &&
99653d4ee642c6528e88224f12409a5f23060994eschrock nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
99653d4ee642c6528e88224f12409a5f23060994eschrock &spares, &nspares) == 0) {
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
99653d4ee642c6528e88224f12409a5f23060994eschrock "upgraded to add hot spares"));
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_BADVERSION, msg));
99653d4ee642c6528e88224f12409a5f23060994eschrock }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson if (pool_is_bootable(zhp) && nvlist_lookup_nvlist_array(nvroot,
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0) {
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson uint64_t s;
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson for (s = 0; s < nspares; s++) {
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson char *path;
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson if (nvlist_lookup_string(spares[s], ZPOOL_CONFIG_PATH,
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson &path) == 0 && pool_uses_efi(spares[s])) {
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson "device '%s' contains an EFI label and "
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson "cannot be used on root pools."),
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson zpool_vdev_name(hdl, NULL, spares[s],
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson B_FALSE));
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg));
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson }
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson }
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson }
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan SPA_VERSION_L2CACHE &&
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan &l2cache, &nl2cache) == 0) {
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan "upgraded to add cache devices"));
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan return (zfs_error(hdl, EZFS_BADVERSION, msg));
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan }
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan
990b4856d0eaada6f8140335733a1b1771ed2746lling if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_ADD, &zc) != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (errno) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens case EBUSY:
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This can happen if the user has specified the same
fa9e4066f08beec538e775443c5be79dd423fcabahrens * device multiple times. We can't reliably detect this
fa9e4066f08beec538e775443c5be79dd423fcabahrens * until we try to add it and see we already have a
fa9e4066f08beec538e775443c5be79dd423fcabahrens * label.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "one or more vdevs refer to the same device"));
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zfs_error(hdl, EZFS_BADDEV, msg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens case EOVERFLOW:
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This occurrs when one of the devices is below
fa9e4066f08beec538e775443c5be79dd423fcabahrens * SPA_MINDEVSIZE. Unfortunately, we can't detect which
fa9e4066f08beec538e775443c5be79dd423fcabahrens * device was the problem device since there's no
fa9e4066f08beec538e775443c5be79dd423fcabahrens * reliable way to determine device size from userland.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens char buf[64];
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "device is less than the minimum "
99653d4ee642c6528e88224f12409a5f23060994eschrock "size (%s)"), buf);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zfs_error(hdl, EZFS_BADDEV, msg);
99653d4ee642c6528e88224f12409a5f23060994eschrock break;
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock case ENOTSUP:
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin "pool must be upgraded to add these vdevs"));
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zfs_error(hdl, EZFS_BADVERSION, msg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b1b8ab34de515a5e83206da22c3d7e563241b021lling case EDOM:
b1b8ab34de515a5e83206da22c3d7e563241b021lling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin "root pool can not have multiple vdevs"
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin " or separate logs"));
b1b8ab34de515a5e83206da22c3d7e563241b021lling (void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg);
b1b8ab34de515a5e83206da22c3d7e563241b021lling break;
b1b8ab34de515a5e83206da22c3d7e563241b021lling
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan case ENOTBLK:
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan "cache device must be a disk or disk slice"));
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan (void) zfs_error(hdl, EZFS_BADDEV, msg);
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan break;
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan
fa9e4066f08beec538e775443c5be79dd423fcabahrens default:
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zpool_standard_error(hdl, errno, msg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock ret = -1;
99653d4ee642c6528e88224f12409a5f23060994eschrock } else {
99653d4ee642c6528e88224f12409a5f23060994eschrock ret = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock zcmd_free_nvlists(&zc);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock return (ret);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Exports the pool from the system. The caller must ensure that there are no
fa9e4066f08beec538e775443c5be79dd423fcabahrens * mounted datasets in the pool.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilsonzpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_cmd_t zc = { 0 };
89a89ebfd7c3b4056afe2c03e959e22824df777dlling char msg[1024];
fa9e4066f08beec538e775443c5be79dd423fcabahrens
89a89ebfd7c3b4056afe2c03e959e22824df777dlling (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
89a89ebfd7c3b4056afe2c03e959e22824df777dlling "cannot export '%s'"), zhp->zpool_name);
89a89ebfd7c3b4056afe2c03e959e22824df777dlling
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
89a89ebfd7c3b4056afe2c03e959e22824df777dlling zc.zc_cookie = force;
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilson zc.zc_guid = hardforce;
89a89ebfd7c3b4056afe2c03e959e22824df777dlling
89a89ebfd7c3b4056afe2c03e959e22824df777dlling if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) {
89a89ebfd7c3b4056afe2c03e959e22824df777dlling switch (errno) {
89a89ebfd7c3b4056afe2c03e959e22824df777dlling case EXDEV:
89a89ebfd7c3b4056afe2c03e959e22824df777dlling zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
89a89ebfd7c3b4056afe2c03e959e22824df777dlling "use '-f' to override the following errors:\n"
89a89ebfd7c3b4056afe2c03e959e22824df777dlling "'%s' has an active shared spare which could be"
89a89ebfd7c3b4056afe2c03e959e22824df777dlling " used by other pools once '%s' is exported."),
89a89ebfd7c3b4056afe2c03e959e22824df777dlling zhp->zpool_name, zhp->zpool_name);
89a89ebfd7c3b4056afe2c03e959e22824df777dlling return (zfs_error(zhp->zpool_hdl, EZFS_ACTIVE_SPARE,
89a89ebfd7c3b4056afe2c03e959e22824df777dlling msg));
89a89ebfd7c3b4056afe2c03e959e22824df777dlling default:
89a89ebfd7c3b4056afe2c03e959e22824df777dlling return (zpool_standard_error_fmt(zhp->zpool_hdl, errno,
89a89ebfd7c3b4056afe2c03e959e22824df777dlling msg));
89a89ebfd7c3b4056afe2c03e959e22824df777dlling }
89a89ebfd7c3b4056afe2c03e959e22824df777dlling }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilsonint
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilsonzpool_export(zpool_handle_t *zhp, boolean_t force)
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilson{
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilson return (zpool_export_common(zhp, force, B_FALSE));
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilson}
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilson
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilsonint
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilsonzpool_export_force(zpool_handle_t *zhp)
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilson{
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilson return (zpool_export_common(zhp, B_TRUE, B_TRUE));
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilson}
394ab0cbe9de0b3be5bf232d9224a9d050999ae5George Wilson
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
990b4856d0eaada6f8140335733a1b1771ed2746lling * zpool_import() is a contracted interface. Should be kept the same
990b4856d0eaada6f8140335733a1b1771ed2746lling * if possible.
990b4856d0eaada6f8140335733a1b1771ed2746lling *
990b4856d0eaada6f8140335733a1b1771ed2746lling * Applications should use zpool_import_props() to import a pool with
990b4856d0eaada6f8140335733a1b1771ed2746lling * new properties value to be set.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
99653d4ee642c6528e88224f12409a5f23060994eschrockzpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
990b4856d0eaada6f8140335733a1b1771ed2746lling char *altroot)
990b4856d0eaada6f8140335733a1b1771ed2746lling{
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_t *props = NULL;
990b4856d0eaada6f8140335733a1b1771ed2746lling int ret;
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (altroot != NULL) {
990b4856d0eaada6f8140335733a1b1771ed2746lling if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
990b4856d0eaada6f8140335733a1b1771ed2746lling return (zfs_error_fmt(hdl, EZFS_NOMEM,
990b4856d0eaada6f8140335733a1b1771ed2746lling dgettext(TEXT_DOMAIN, "cannot import '%s'"),
990b4856d0eaada6f8140335733a1b1771ed2746lling newname));
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling if (nvlist_add_string(props,
352d8027a91dfc2f3c5bdda788b82548169bf512George Wilson zpool_prop_to_name(ZPOOL_PROP_ALTROOT), altroot) != 0 ||
352d8027a91dfc2f3c5bdda788b82548169bf512George Wilson nvlist_add_string(props,
352d8027a91dfc2f3c5bdda788b82548169bf512George Wilson zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), "none") != 0) {
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_free(props);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (zfs_error_fmt(hdl, EZFS_NOMEM,
990b4856d0eaada6f8140335733a1b1771ed2746lling dgettext(TEXT_DOMAIN, "cannot import '%s'"),
990b4856d0eaada6f8140335733a1b1771ed2746lling newname));
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
c5904d138f3bdf0762dbf452a43d5a5c387ea6a8eschrock ret = zpool_import_props(hdl, config, newname, props, B_FALSE);
990b4856d0eaada6f8140335733a1b1771ed2746lling if (props)
990b4856d0eaada6f8140335733a1b1771ed2746lling nvlist_free(props);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (ret);
990b4856d0eaada6f8140335733a1b1771ed2746lling}
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling/*
990b4856d0eaada6f8140335733a1b1771ed2746lling * Import the given pool using the known configuration and a list of
990b4856d0eaada6f8140335733a1b1771ed2746lling * properties to be set. The configuration should have come from
990b4856d0eaada6f8140335733a1b1771ed2746lling * zpool_find_import(). The 'newname' parameters control whether the pool
990b4856d0eaada6f8140335733a1b1771ed2746lling * is imported with a different name.
990b4856d0eaada6f8140335733a1b1771ed2746lling */
990b4856d0eaada6f8140335733a1b1771ed2746llingint
990b4856d0eaada6f8140335733a1b1771ed2746llingzpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
c5904d138f3bdf0762dbf452a43d5a5c387ea6a8eschrock nvlist_t *props, boolean_t importfaulted)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock zfs_cmd_t zc = { 0 };
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *thename;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *origname;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int ret;
990b4856d0eaada6f8140335733a1b1771ed2746lling char errbuf[1024];
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
fa9e4066f08beec538e775443c5be79dd423fcabahrens &origname) == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
990b4856d0eaada6f8140335733a1b1771ed2746lling "cannot import pool '%s'"), origname);
990b4856d0eaada6f8140335733a1b1771ed2746lling
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (newname != NULL) {
99653d4ee642c6528e88224f12409a5f23060994eschrock if (!zpool_name_valid(hdl, B_FALSE, newname))
ece3d9b3bacef51a5f34d993935eedbb7bb87059lling return (zfs_error_fmt(hdl, EZFS_INVALIDNAME,
99653d4ee642c6528e88224f12409a5f23060994eschrock dgettext(TEXT_DOMAIN, "cannot import '%s'"),
99653d4ee642c6528e88224f12409a5f23060994eschrock newname));
fa9e4066f08beec538e775443c5be79dd423fcabahrens thename = (char *)newname;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens thename = origname;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
990b4856d0eaada6f8140335733a1b1771ed2746lling if (props) {
990b4856d0eaada6f8140335733a1b1771ed2746lling uint64_t version;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
990b4856d0eaada6f8140335733a1b1771ed2746lling verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
990b4856d0eaada6f8140335733a1b1771ed2746lling &version) == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh if ((props = zpool_valid_proplist(hdl, origname,
351420b34707afeafa8d5c3e0c77b7bcffb1edc0lling props, version, B_TRUE, errbuf)) == NULL) {
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
351420b34707afeafa8d5c3e0c77b7bcffb1edc0lling } else if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
351420b34707afeafa8d5c3e0c77b7bcffb1edc0lling nvlist_free(props);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
351420b34707afeafa8d5c3e0c77b7bcffb1edc0lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling }
990b4856d0eaada6f8140335733a1b1771ed2746lling
990b4856d0eaada6f8140335733a1b1771ed2746lling (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock &zc.zc_guid) == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
351420b34707afeafa8d5c3e0c77b7bcffb1edc0lling if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0) {
351420b34707afeafa8d5c3e0c77b7bcffb1edc0lling nvlist_free(props);
99653d4ee642c6528e88224f12409a5f23060994eschrock return (-1);
351420b34707afeafa8d5c3e0c77b7bcffb1edc0lling }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
c5904d138f3bdf0762dbf452a43d5a5c387ea6a8eschrock zc.zc_cookie = (uint64_t)importfaulted;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = 0;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zfs_ioctl(hdl, ZFS_IOC_POOL_IMPORT, &zc) != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens char desc[1024];
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (newname == NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) snprintf(desc, sizeof (desc),
fa9e4066f08beec538e775443c5be79dd423fcabahrens dgettext(TEXT_DOMAIN, "cannot import '%s'"),
fa9e4066f08beec538e775443c5be79dd423fcabahrens thename);
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) snprintf(desc, sizeof (desc),
fa9e4066f08beec538e775443c5be79dd423fcabahrens dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"),
fa9e4066f08beec538e775443c5be79dd423fcabahrens origname, thename);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (errno) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock case ENOTSUP:
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Unsupported version.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zfs_error(hdl, EZFS_BADVERSION, desc);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock break;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
b5989ec7cd031c9bb066c68877fb5017e45f205beschrock case EINVAL:
b5989ec7cd031c9bb066c68877fb5017e45f205beschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, desc);
b5989ec7cd031c9bb066c68877fb5017e45f205beschrock break;
b5989ec7cd031c9bb066c68877fb5017e45f205beschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens default:
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zpool_standard_error(hdl, errno, desc);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens zpool_handle_t *zhp;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This should never fail, but play it safe anyway.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (zpool_open_silent(hdl, thename, &zhp) != 0)
94de1d4cf6ec0a3bf040dcc4b8df107c4ed36b51eschrock ret = -1;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor else if (zhp != NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens zpool_close(zhp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock zcmd_free_nvlists(&zc);
351420b34707afeafa8d5c3e0c77b7bcffb1edc0lling nvlist_free(props);
351420b34707afeafa8d5c3e0c77b7bcffb1edc0lling
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (ret);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Scrub the pool.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
fa9e4066f08beec538e775443c5be79dd423fcabahrenszpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_cmd_t zc = { 0 };
fa9e4066f08beec538e775443c5be79dd423fcabahrens char msg[1024];
99653d4ee642c6528e88224f12409a5f23060994eschrock libzfs_handle_t *hdl = zhp->zpool_hdl;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens zc.zc_cookie = type;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SCRUB, &zc) == 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) snprintf(msg, sizeof (msg),
fa9e4066f08beec538e775443c5be79dd423fcabahrens dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock if (errno == EBUSY)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_RESILVERING, msg));
99653d4ee642c6528e88224f12409a5f23060994eschrock else
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zpool_standard_error(hdl, errno, msg));
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
a43d325b828008a3ab54eed57fd7c00b6470172bek/*
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * Find a vdev that matches the search criteria specified. We use the
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * the nvpair name to determine how we should look for the device.
a43d325b828008a3ab54eed57fd7c00b6470172bek * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL
a43d325b828008a3ab54eed57fd7c00b6470172bek * spare; but FALSE if its an INUSE spare.
a43d325b828008a3ab54eed57fd7c00b6470172bek */
99653d4ee642c6528e88224f12409a5f23060994eschrockstatic nvlist_t *
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonvdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson boolean_t *l2cache, boolean_t *log)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock uint_t c, children;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock nvlist_t **child;
99653d4ee642c6528e88224f12409a5f23060994eschrock nvlist_t *ret;
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock uint64_t is_log;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson char *srchkey;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson nvpair_t *pair = nvlist_next_nvpair(search, NULL);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /* Nothing to look for */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (search == NULL || pair == NULL)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (NULL);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /* Obtain the key we will use to search */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson srchkey = nvpair_name(pair);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson switch (nvpair_type(pair)) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson case DATA_TYPE_UINT64: {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson uint64_t srchval, theguid, present;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson verify(nvpair_value_uint64(pair, &srchval) == 0);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (strcmp(srchkey, ZPOOL_CONFIG_GUID) == 0) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson &present) == 0) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /*
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * If the device has never been present since
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * import, the only reliable way to match the
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * vdev is by GUID.
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson verify(nvlist_lookup_uint64(nv,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ZPOOL_CONFIG_GUID, &theguid) == 0);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (theguid == srchval)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (nv);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson break;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson case DATA_TYPE_STRING: {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson char *srchval, *val;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson verify(nvpair_value_string(pair, &srchval) == 0);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (nvlist_lookup_string(nv, srchkey, &val) != 0)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson break;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * Search for the requested value. We special case the search
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * for ZPOOL_CONFIG_PATH when it's a wholedisk and when
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * Looking for a top-level vdev name (i.e. ZPOOL_CONFIG_TYPE).
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * Otherwise, all other searches are simple string compares.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (strcmp(srchkey, ZPOOL_CONFIG_PATH) == 0 && val) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson uint64_t wholedisk = 0;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson &wholedisk);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (wholedisk) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /*
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * For whole disks, the internal path has 's0',
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * but the path passed in by the user doesn't.
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (strlen(srchval) == strlen(val) - 2 &&
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson strncmp(srchval, val, strlen(srchval)) == 0)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (nv);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson break;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson } else if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0 && val) {
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson char *type, *idx, *end, *p;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson uint64_t id, vdev_id;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson /*
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * Determine our vdev type, keeping in mind
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * that the srchval is composed of a type and
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * vdev id pair (i.e. mirror-4).
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson */
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson if ((type = strdup(srchval)) == NULL)
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson return (NULL);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson if ((p = strrchr(type, '-')) == NULL) {
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson free(type);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson break;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson }
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson idx = p + 1;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson *p = '\0';
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson /*
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * If the types don't match then keep looking.
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson */
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson if (strncmp(val, type, strlen(val)) != 0) {
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson free(type);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson break;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson }
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson verify(strncmp(type, VDEV_TYPE_RAIDZ,
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson strlen(VDEV_TYPE_RAIDZ)) == 0 ||
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson strncmp(type, VDEV_TYPE_MIRROR,
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson strlen(VDEV_TYPE_MIRROR)) == 0);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID,
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson &id) == 0);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson errno = 0;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson vdev_id = strtoull(idx, &end, 10);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson free(type);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson if (errno != 0)
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson return (NULL);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson /*
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * Now verify that we have the correct vdev id.
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson */
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson if (vdev_id == id)
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson return (nv);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /*
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * Common case
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (strcmp(srchval, val) == 0)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (nv);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson break;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson default:
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson break;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock &child, &children) != 0)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (NULL);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock for (c = 0; c < children; c++) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if ((ret = vdev_to_nvlist_iter(child[c], search,
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock avail_spare, l2cache, NULL)) != NULL) {
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock /*
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock * The 'is_log' value is only set for the toplevel
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock * vdev, not the leaf vdevs. So we always lookup the
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock * log device from the root of the vdev tree (where
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock * 'log' is non-NULL).
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock */
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock if (log != NULL &&
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock nvlist_lookup_uint64(child[c],
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock ZPOOL_CONFIG_IS_LOG, &is_log) == 0 &&
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock is_log) {
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock *log = B_TRUE;
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (ret);
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock }
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
99653d4ee642c6528e88224f12409a5f23060994eschrock &child, &children) == 0) {
99653d4ee642c6528e88224f12409a5f23060994eschrock for (c = 0; c < children; c++) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if ((ret = vdev_to_nvlist_iter(child[c], search,
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock avail_spare, l2cache, NULL)) != NULL) {
a43d325b828008a3ab54eed57fd7c00b6470172bek *avail_spare = B_TRUE;
99653d4ee642c6528e88224f12409a5f23060994eschrock return (ret);
99653d4ee642c6528e88224f12409a5f23060994eschrock }
99653d4ee642c6528e88224f12409a5f23060994eschrock }
99653d4ee642c6528e88224f12409a5f23060994eschrock }
99653d4ee642c6528e88224f12409a5f23060994eschrock
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan &child, &children) == 0) {
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan for (c = 0; c < children; c++) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if ((ret = vdev_to_nvlist_iter(child[c], search,
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock avail_spare, l2cache, NULL)) != NULL) {
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan *l2cache = B_TRUE;
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan return (ret);
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan }
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan }
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan }
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan
99653d4ee642c6528e88224f12409a5f23060994eschrock return (NULL);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock}
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson/*
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * Given a physical path (minus the "/devices" prefix), find the
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * associated vdev.
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonnvlist_t *
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonzpool_find_vdev_by_physpath(zpool_handle_t *zhp, const char *ppath,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson{
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson nvlist_t *search, *nvroot, *ret;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson verify(nvlist_alloc(&search, NV_UNIQUE_NAME, KM_SLEEP) == 0);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson verify(nvlist_add_string(search, ZPOOL_CONFIG_PHYS_PATH, ppath) == 0);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson &nvroot) == 0);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson *avail_spare = B_FALSE;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson nvlist_free(search);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (ret);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson}
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson/*
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * Determine if we have an "interior" top-level vdev (i.e mirror/raidz).
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson */
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilsonboolean_t
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilsonzpool_vdev_is_interior(const char *name)
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson{
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson if (strncmp(name, VDEV_TYPE_RAIDZ, strlen(VDEV_TYPE_RAIDZ)) == 0 ||
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson strncmp(name, VDEV_TYPE_MIRROR, strlen(VDEV_TYPE_MIRROR)) == 0)
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson return (B_TRUE);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson return (B_FALSE);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson}
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
99653d4ee642c6528e88224f12409a5f23060994eschrocknvlist_t *
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendanzpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock boolean_t *l2cache, boolean_t *log)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock char buf[MAXPATHLEN];
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock char *end;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson nvlist_t *nvroot, *search, *ret;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock uint64_t guid;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson verify(nvlist_alloc(&search, NV_UNIQUE_NAME, KM_SLEEP) == 0);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
0917b783fd655a0c943e0b8fb848db2301774947eschrock guid = strtoull(path, &end, 10);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (guid != 0 && *end == '\0') {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson verify(nvlist_add_uint64(search, ZPOOL_CONFIG_GUID, guid) == 0);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson } else if (zpool_vdev_is_interior(path)) {
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson verify(nvlist_add_string(search, ZPOOL_CONFIG_TYPE, path) == 0);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } else if (path[0] != '/') {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, buf) == 0);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } else {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, path) == 0);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock &nvroot) == 0);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
a43d325b828008a3ab54eed57fd7c00b6470172bek *avail_spare = B_FALSE;
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan *l2cache = B_FALSE;
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock if (log != NULL)
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock *log = B_FALSE;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson nvlist_free(search);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (ret);
a43d325b828008a3ab54eed57fd7c00b6470172bek}
a43d325b828008a3ab54eed57fd7c00b6470172bek
193974072f41a843678abf5f61979c748687e66bSherry Moorestatic int
193974072f41a843678abf5f61979c748687e66bSherry Moorevdev_online(nvlist_t *nv)
193974072f41a843678abf5f61979c748687e66bSherry Moore{
193974072f41a843678abf5f61979c748687e66bSherry Moore uint64_t ival;
193974072f41a843678abf5f61979c748687e66bSherry Moore
193974072f41a843678abf5f61979c748687e66bSherry Moore if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_OFFLINE, &ival) == 0 ||
193974072f41a843678abf5f61979c748687e66bSherry Moore nvlist_lookup_uint64(nv, ZPOOL_CONFIG_FAULTED, &ival) == 0 ||
193974072f41a843678abf5f61979c748687e66bSherry Moore nvlist_lookup_uint64(nv, ZPOOL_CONFIG_REMOVED, &ival) == 0)
193974072f41a843678abf5f61979c748687e66bSherry Moore return (0);
193974072f41a843678abf5f61979c748687e66bSherry Moore
193974072f41a843678abf5f61979c748687e66bSherry Moore return (1);
193974072f41a843678abf5f61979c748687e66bSherry Moore}
193974072f41a843678abf5f61979c748687e66bSherry Moore
193974072f41a843678abf5f61979c748687e66bSherry Moore/*
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling * Helper function for zpool_get_physpaths().
193974072f41a843678abf5f61979c748687e66bSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic int
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Lingvdev_get_one_physpath(nvlist_t *config, char *physpath, size_t physpath_size,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore size_t *bytes_written)
193974072f41a843678abf5f61979c748687e66bSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore size_t bytes_left, pos, rsz;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char *tmppath;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore const char *format;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (nvlist_lookup_string(config, ZPOOL_CONFIG_PHYS_PATH,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore &tmppath) != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EZFS_NODEVICE);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore pos = *bytes_written;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore bytes_left = physpath_size - pos;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore format = (pos == 0) ? "%s" : " %s";
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore rsz = snprintf(physpath + pos, bytes_left, format, tmppath);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore *bytes_written += rsz;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (rsz >= bytes_left) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /* if physpath was not copied properly, clear it */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (bytes_left != 0) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore physpath[pos] = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EZFS_NOSPC);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (0);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Lingstatic int
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Lingvdev_get_physpaths(nvlist_t *nv, char *physpath, size_t phypath_size,
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling size_t *rsz, boolean_t is_spare)
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling{
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling char *type;
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling int ret;
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling return (EZFS_INVALCONFIG);
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling if (strcmp(type, VDEV_TYPE_DISK) == 0) {
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling /*
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling * An active spare device has ZPOOL_CONFIG_IS_SPARE set.
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling * For a spare vdev, we only want to boot from the active
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling * spare device.
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling */
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling if (is_spare) {
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling uint64_t spare = 0;
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_SPARE,
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling &spare);
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling if (!spare)
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling return (EZFS_INVALCONFIG);
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling }
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling if (vdev_online(nv)) {
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling if ((ret = vdev_get_one_physpath(nv, physpath,
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling phypath_size, rsz)) != 0)
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling return (ret);
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling }
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0 ||
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling strcmp(type, VDEV_TYPE_REPLACING) == 0 ||
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling (is_spare = (strcmp(type, VDEV_TYPE_SPARE) == 0))) {
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling nvlist_t **child;
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling uint_t count;
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling int i, ret;
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling if (nvlist_lookup_nvlist_array(nv,
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling ZPOOL_CONFIG_CHILDREN, &child, &count) != 0)
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling return (EZFS_INVALCONFIG);
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling for (i = 0; i < count; i++) {
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling ret = vdev_get_physpaths(child[i], physpath,
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling phypath_size, rsz, is_spare);
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling if (ret == EZFS_NOSPC)
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling return (ret);
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling }
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling }
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling return (EZFS_POOL_INVALARG);
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling}
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Get phys_path for a root pool config.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Return 0 on success; non-zero on failure.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic int
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorezpool_get_config_physpath(nvlist_t *config, char *physpath, size_t phypath_size)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore size_t rsz;
193974072f41a843678abf5f61979c748687e66bSherry Moore nvlist_t *vdev_root;
193974072f41a843678abf5f61979c748687e66bSherry Moore nvlist_t **child;
193974072f41a843678abf5f61979c748687e66bSherry Moore uint_t count;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char *type;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore rsz = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore &vdev_root) != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EZFS_INVALCONFIG);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (nvlist_lookup_string(vdev_root, ZPOOL_CONFIG_TYPE, &type) != 0 ||
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore nvlist_lookup_nvlist_array(vdev_root, ZPOOL_CONFIG_CHILDREN,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore &child, &count) != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EZFS_INVALCONFIG);
193974072f41a843678abf5f61979c748687e66bSherry Moore
193974072f41a843678abf5f61979c748687e66bSherry Moore /*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * root pool can not have EFI labeled disks and can only have
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * a single top-level vdev.
193974072f41a843678abf5f61979c748687e66bSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (strcmp(type, VDEV_TYPE_ROOT) != 0 || count != 1 ||
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore pool_uses_efi(vdev_root))
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EZFS_POOL_INVALARG);
193974072f41a843678abf5f61979c748687e66bSherry Moore
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling (void) vdev_get_physpaths(child[0], physpath, phypath_size, &rsz,
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling B_FALSE);
193974072f41a843678abf5f61979c748687e66bSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /* No online devices */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (rsz == 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EZFS_NODEVICE);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
193974072f41a843678abf5f61979c748687e66bSherry Moore return (0);
193974072f41a843678abf5f61979c748687e66bSherry Moore}
193974072f41a843678abf5f61979c748687e66bSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Get phys_path for a root pool
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Return 0 on success; non-zero on failure.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreint
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorezpool_get_physpath(zpool_handle_t *zhp, char *physpath, size_t phypath_size)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (zpool_get_config_physpath(zhp->zpool_config, physpath,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore phypath_size));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson/*
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * If the device has being dynamically expanded then we need to relabel
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * the disk to use the new unallocated space.
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonstatic int
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilsonzpool_relabel_disk(libzfs_handle_t *hdl, const char *name)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson{
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson char path[MAXPATHLEN];
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson char errbuf[1024];
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson int fd, error;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson int (*_efi_use_whole_disk)(int);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if ((_efi_use_whole_disk = (int (*)(int))dlsym(RTLD_DEFAULT,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson "efi_use_whole_disk")) == NULL)
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (-1);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) snprintf(path, sizeof (path), "%s/%s", RDISK_ROOT, name);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson "relabel '%s': unable to open device"), name);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (zfs_error(hdl, EZFS_OPENFAILED, errbuf));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /*
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * It's possible that we might encounter an error if the device
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * does not have any unallocated space left. If so, we simply
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * ignore that error and continue on.
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson error = _efi_use_whole_disk(fd);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) close(fd);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (error && error != VT_ENOSPC) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson "relabel '%s': unable to read disk capacity"), name);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (zfs_error(hdl, EZFS_NOCAP, errbuf));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (0);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson}
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * Bring the specified vdev online. The 'flags' parameter is a set of the
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * ZFS_ONLINE_* flags.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrockzpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock vdev_state_t *newstate)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_cmd_t zc = { 0 };
fa9e4066f08beec538e775443c5be79dd423fcabahrens char msg[1024];
99653d4ee642c6528e88224f12409a5f23060994eschrock nvlist_t *tgt;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson boolean_t avail_spare, l2cache, islog;
99653d4ee642c6528e88224f12409a5f23060994eschrock libzfs_handle_t *hdl = zhp->zpool_hdl;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (flags & ZFS_ONLINE_EXPAND) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) snprintf(msg, sizeof (msg),
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson dgettext(TEXT_DOMAIN, "cannot expand %s"), path);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson } else {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) snprintf(msg, sizeof (msg),
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson dgettext(TEXT_DOMAIN, "cannot online %s"), path);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson &islog)) == NULL)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_NODEVICE, msg));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock if (avail_spare)
a43d325b828008a3ab54eed57fd7c00b6470172bek return (zfs_error(hdl, EZFS_ISSPARE, msg));
a43d325b828008a3ab54eed57fd7c00b6470172bek
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (flags & ZFS_ONLINE_EXPAND ||
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson char *pathname = NULL;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson uint64_t wholedisk = 0;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson &wholedisk);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson verify(nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson &pathname) == 0);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson /*
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson * XXX - L2ARC 1.0 devices can't support expansion.
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson */
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (l2cache) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson "cannot expand cache devices"));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson return (zfs_error(hdl, EZFS_VDEVNOTSUP, msg));
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson if (wholedisk) {
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson pathname += strlen(DISK_ROOT) + 1;
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson (void) zpool_relabel_disk(zhp->zpool_hdl, pathname);
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson }
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock zc.zc_cookie = VDEV_STATE_ONLINE;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock zc.zc_obj = flags;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_SET_STATE, &zc) != 0)
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock return (zpool_standard_error(hdl, errno, msg));
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock *newstate = zc.zc_cookie;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Take the specified vdev offline
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrockzpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_cmd_t zc = { 0 };
fa9e4066f08beec538e775443c5be79dd423fcabahrens char msg[1024];
99653d4ee642c6528e88224f12409a5f23060994eschrock nvlist_t *tgt;
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan boolean_t avail_spare, l2cache;
99653d4ee642c6528e88224f12409a5f23060994eschrock libzfs_handle_t *hdl = zhp->zpool_hdl;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) snprintf(msg, sizeof (msg),
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dgettext(TEXT_DOMAIN, "cannot offline %s"), path);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock NULL)) == NULL)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_NODEVICE, msg));
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock if (avail_spare)
a43d325b828008a3ab54eed57fd7c00b6470172bek return (zfs_error(hdl, EZFS_ISSPARE, msg));
a43d325b828008a3ab54eed57fd7c00b6470172bek
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock zc.zc_cookie = VDEV_STATE_OFFLINE;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock return (0);
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock switch (errno) {
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock case EBUSY:
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock /*
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * There are no other replicas of this device.
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock */
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
e6ca193ded880d478cc39e34ef82d4be36e4445dGeorge Wilson case EEXIST:
e6ca193ded880d478cc39e34ef82d4be36e4445dGeorge Wilson /*
e6ca193ded880d478cc39e34ef82d4be36e4445dGeorge Wilson * The log device has unplayed logs
e6ca193ded880d478cc39e34ef82d4be36e4445dGeorge Wilson */
e6ca193ded880d478cc39e34ef82d4be36e4445dGeorge Wilson return (zfs_error(hdl, EZFS_UNPLAYED_LOGS, msg));
e6ca193ded880d478cc39e34ef82d4be36e4445dGeorge Wilson
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock default:
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock return (zpool_standard_error(hdl, errno, msg));
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock }
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock}
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock/*
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * Mark the given vdev faulted.
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock */
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrockint
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrockzpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock{
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock zfs_cmd_t zc = { 0 };
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock char msg[1024];
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock libzfs_handle_t *hdl = zhp->zpool_hdl;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock (void) snprintf(msg, sizeof (msg),
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock dgettext(TEXT_DOMAIN, "cannot fault %llu"), guid);
441d80aa4f613b6298fc8bd3151f4be02dbf84fclling
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock zc.zc_guid = guid;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock zc.zc_cookie = VDEV_STATE_FAULTED;
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock zc.zc_obj = aux;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (errno) {
99653d4ee642c6528e88224f12409a5f23060994eschrock case EBUSY:
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * There are no other replicas of this device.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock default:
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zpool_standard_error(hdl, errno, msg));
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock}
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock/*
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * Mark the given vdev degraded.
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock */
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrockint
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrockzpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock{
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock zfs_cmd_t zc = { 0 };
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock char msg[1024];
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock libzfs_handle_t *hdl = zhp->zpool_hdl;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock (void) snprintf(msg, sizeof (msg),
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock dgettext(TEXT_DOMAIN, "cannot degrade %llu"), guid);
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock zc.zc_guid = guid;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock zc.zc_cookie = VDEV_STATE_DEGRADED;
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock zc.zc_obj = aux;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock return (0);
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock return (zpool_standard_error(hdl, errno, msg));
99653d4ee642c6528e88224f12409a5f23060994eschrock}
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock/*
99653d4ee642c6528e88224f12409a5f23060994eschrock * Returns TRUE if the given nvlist is a vdev that was originally swapped in as
99653d4ee642c6528e88224f12409a5f23060994eschrock * a hot spare.
99653d4ee642c6528e88224f12409a5f23060994eschrock */
99653d4ee642c6528e88224f12409a5f23060994eschrockstatic boolean_t
99653d4ee642c6528e88224f12409a5f23060994eschrockis_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which)
99653d4ee642c6528e88224f12409a5f23060994eschrock{
99653d4ee642c6528e88224f12409a5f23060994eschrock nvlist_t **child;
99653d4ee642c6528e88224f12409a5f23060994eschrock uint_t c, children;
99653d4ee642c6528e88224f12409a5f23060994eschrock char *type;
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child,
99653d4ee642c6528e88224f12409a5f23060994eschrock &children) == 0) {
99653d4ee642c6528e88224f12409a5f23060994eschrock verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE,
99653d4ee642c6528e88224f12409a5f23060994eschrock &type) == 0);
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock if (strcmp(type, VDEV_TYPE_SPARE) == 0 &&
99653d4ee642c6528e88224f12409a5f23060994eschrock children == 2 && child[which] == tgt)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (B_TRUE);
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock for (c = 0; c < children; c++)
99653d4ee642c6528e88224f12409a5f23060994eschrock if (is_replacing_spare(child[c], tgt, which))
99653d4ee642c6528e88224f12409a5f23060994eschrock return (B_TRUE);
99653d4ee642c6528e88224f12409a5f23060994eschrock }
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock return (B_FALSE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Attach new_disk (fully described by nvroot) to old_disk.
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin * If 'replacing' is specified, the new disk will replace the old one.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
fa9e4066f08beec538e775443c5be79dd423fcabahrenszpool_vdev_attach(zpool_handle_t *zhp,
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_cmd_t zc = { 0 };
fa9e4066f08beec538e775443c5be79dd423fcabahrens char msg[1024];
fa9e4066f08beec538e775443c5be79dd423fcabahrens int ret;
99653d4ee642c6528e88224f12409a5f23060994eschrock nvlist_t *tgt;
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock boolean_t avail_spare, l2cache, islog;
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock uint64_t val;
0430f8daa551890e0788d3fd28aef3be44cf8730eschrock char *path, *newname;
99653d4ee642c6528e88224f12409a5f23060994eschrock nvlist_t **child;
99653d4ee642c6528e88224f12409a5f23060994eschrock uint_t children;
99653d4ee642c6528e88224f12409a5f23060994eschrock nvlist_t *config_root;
99653d4ee642c6528e88224f12409a5f23060994eschrock libzfs_handle_t *hdl = zhp->zpool_hdl;
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson boolean_t rootpool = pool_is_bootable(zhp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (replacing)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock "cannot replace %s with %s"), old_disk, new_disk);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock else
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock "cannot attach %s to %s"), new_disk, old_disk);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson /*
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson * If this is a root pool, make sure that we're not attaching an
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson * EFI labeled device.
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson */
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson if (rootpool && pool_uses_efi(nvroot)) {
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson "EFI labeled devices are not supported on root pools."));
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg));
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson }
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare, &l2cache,
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock &islog)) == 0)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_NODEVICE, msg));
99653d4ee642c6528e88224f12409a5f23060994eschrock
a43d325b828008a3ab54eed57fd7c00b6470172bek if (avail_spare)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_ISSPARE, msg));
99653d4ee642c6528e88224f12409a5f23060994eschrock
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan if (l2cache)
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan return (zfs_error(hdl, EZFS_ISL2CACHE, msg));
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan
99653d4ee642c6528e88224f12409a5f23060994eschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens zc.zc_cookie = replacing;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
99653d4ee642c6528e88224f12409a5f23060994eschrock &child, &children) != 0 || children != 1) {
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "new device must be a single disk"));
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_INVALCONFIG, msg));
99653d4ee642c6528e88224f12409a5f23060994eschrock }
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
99653d4ee642c6528e88224f12409a5f23060994eschrock ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0);
99653d4ee642c6528e88224f12409a5f23060994eschrock
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson if ((newname = zpool_vdev_name(NULL, NULL, child[0], B_FALSE)) == NULL)
0430f8daa551890e0788d3fd28aef3be44cf8730eschrock return (-1);
0430f8daa551890e0788d3fd28aef3be44cf8730eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock /*
99653d4ee642c6528e88224f12409a5f23060994eschrock * If the target is a hot spare that has been swapped in, we can only
99653d4ee642c6528e88224f12409a5f23060994eschrock * replace it with another hot spare.
99653d4ee642c6528e88224f12409a5f23060994eschrock */
99653d4ee642c6528e88224f12409a5f23060994eschrock if (replacing &&
99653d4ee642c6528e88224f12409a5f23060994eschrock nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 &&
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock (zpool_find_vdev(zhp, newname, &avail_spare, &l2cache,
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock NULL) == NULL || !avail_spare) &&
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock is_replacing_spare(config_root, tgt, 1)) {
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "can only be replaced by another hot spare"));
0430f8daa551890e0788d3fd28aef3be44cf8730eschrock free(newname);
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_BADTARGET, msg));
99653d4ee642c6528e88224f12409a5f23060994eschrock }
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock /*
99653d4ee642c6528e88224f12409a5f23060994eschrock * If we are attempting to replace a spare, it canot be applied to an
99653d4ee642c6528e88224f12409a5f23060994eschrock * already spared device.
99653d4ee642c6528e88224f12409a5f23060994eschrock */
99653d4ee642c6528e88224f12409a5f23060994eschrock if (replacing &&
99653d4ee642c6528e88224f12409a5f23060994eschrock nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 &&
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock zpool_find_vdev(zhp, newname, &avail_spare,
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock &l2cache, NULL) != NULL && avail_spare &&
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock is_replacing_spare(config_root, tgt, 0)) {
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "device has already been replaced with a spare"));
0430f8daa551890e0788d3fd28aef3be44cf8730eschrock free(newname);
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_BADTARGET, msg));
99653d4ee642c6528e88224f12409a5f23060994eschrock }
99653d4ee642c6528e88224f12409a5f23060994eschrock
0430f8daa551890e0788d3fd28aef3be44cf8730eschrock free(newname);
0430f8daa551890e0788d3fd28aef3be44cf8730eschrock
990b4856d0eaada6f8140335733a1b1771ed2746lling if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_ATTACH, &zc);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock zcmd_free_nvlists(&zc);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson if (ret == 0) {
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson if (rootpool) {
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson /*
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson * XXX - This should be removed once we can
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson * automatically install the bootblocks on the
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson * newly attached disk.
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson */
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Please "
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson "be sure to invoke %s to make '%s' bootable.\n"),
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson BOOTCMD, new_disk);
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling /*
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling * XXX need a better way to prevent user from
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling * booting up a half-baked vdev.
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling */
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Make "
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling "sure to wait until resilver is done "
21ecdf64e1e200cd74cadf771fc7ddc3d0062080Lin Ling "before rebooting.\n"));
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (errno) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock case ENOTSUP:
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Can't attach to or replace this type of vdev.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin if (replacing) {
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock if (islog)
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin "cannot replace a log with a spare"));
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin else
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin "cannot replace a replacing device"));
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin } else {
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "can only attach to mirrors and top-level "
99653d4ee642c6528e88224f12409a5f23060994eschrock "disks"));
8654d0253136055bd4cc2423d87378e8a37f2eb5perrin }
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zfs_error(hdl, EZFS_BADTARGET, msg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock case EINVAL:
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The new device must be a single disk.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "new device must be a single disk"));
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zfs_error(hdl, EZFS_INVALCONFIG, msg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock case EBUSY:
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"),
99653d4ee642c6528e88224f12409a5f23060994eschrock new_disk);
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zfs_error(hdl, EZFS_BADDEV, msg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock case EOVERFLOW:
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The new device is too small.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "device is too small"));
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zfs_error(hdl, EZFS_BADDEV, msg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock case EDOM:
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The new device has a different alignment requirement.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
99653d4ee642c6528e88224f12409a5f23060994eschrock "devices have different sector alignment"));
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zfs_error(hdl, EZFS_BADDEV, msg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock case ENAMETOOLONG:
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The resulting top-level vdev spec won't fit in the label.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock default:
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zpool_standard_error(hdl, errno, msg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrock return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Detach the specified device.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
fa9e4066f08beec538e775443c5be79dd423fcabahrenszpool_vdev_detach(zpool_handle_t *zhp, const char *path)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_cmd_t zc = { 0 };
fa9e4066f08beec538e775443c5be79dd423fcabahrens char msg[1024];
99653d4ee642c6528e88224f12409a5f23060994eschrock nvlist_t *tgt;
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan boolean_t avail_spare, l2cache;
99653d4ee642c6528e88224f12409a5f23060994eschrock libzfs_handle_t *hdl = zhp->zpool_hdl;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) snprintf(msg, sizeof (msg),
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dgettext(TEXT_DOMAIN, "cannot detach %s"), path);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock NULL)) == 0)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_NODEVICE, msg));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
a43d325b828008a3ab54eed57fd7c00b6470172bek if (avail_spare)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_ISSPARE, msg));
99653d4ee642c6528e88224f12409a5f23060994eschrock
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan if (l2cache)
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan return (zfs_error(hdl, EZFS_ISL2CACHE, msg));
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan
99653d4ee642c6528e88224f12409a5f23060994eschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
99653d4ee642c6528e88224f12409a5f23060994eschrock
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zfs_ioctl(hdl, ZFS_IOC_VDEV_DETACH, &zc) == 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (errno) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock case ENOTSUP:
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Can't detach from this type of vdev.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only "
99653d4ee642c6528e88224f12409a5f23060994eschrock "applicable to mirror and replacing vdevs"));
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock case EBUSY:
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * There are no other replicas of this device.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zfs_error(hdl, EZFS_NOREPLICAS, msg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock default:
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zpool_standard_error(hdl, errno, msg);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock return (-1);
99653d4ee642c6528e88224f12409a5f23060994eschrock}
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock/*
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan * Remove the given device. Currently, this is supported only for hot spares
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan * and level 2 cache devices.
99653d4ee642c6528e88224f12409a5f23060994eschrock */
99653d4ee642c6528e88224f12409a5f23060994eschrockint
99653d4ee642c6528e88224f12409a5f23060994eschrockzpool_vdev_remove(zpool_handle_t *zhp, const char *path)
99653d4ee642c6528e88224f12409a5f23060994eschrock{
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_cmd_t zc = { 0 };
99653d4ee642c6528e88224f12409a5f23060994eschrock char msg[1024];
99653d4ee642c6528e88224f12409a5f23060994eschrock nvlist_t *tgt;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson boolean_t avail_spare, l2cache, islog;
99653d4ee642c6528e88224f12409a5f23060994eschrock libzfs_handle_t *hdl = zhp->zpool_hdl;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson uint64_t version;
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) snprintf(msg, sizeof (msg),
99653d4ee642c6528e88224f12409a5f23060994eschrock dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson &islog)) == 0)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_NODEVICE, msg));
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson /*
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * XXX - this should just go away.
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson */
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson if (!avail_spare && !l2cache && !islog) {
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson "only inactive hot spares, cache, top-level, "
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson "or log devices can be removed"));
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_NODEVICE, msg));
99653d4ee642c6528e88224f12409a5f23060994eschrock }
99653d4ee642c6528e88224f12409a5f23060994eschrock
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson if (islog && version < SPA_VERSION_HOLES) {
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson "pool must be upgrade to support log removal"));
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson return (zfs_error(hdl, EZFS_BADVERSION, msg));
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson }
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
99653d4ee642c6528e88224f12409a5f23060994eschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
99653d4ee642c6528e88224f12409a5f23060994eschrock
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (0);
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zpool_standard_error(hdl, errno, msg));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock}
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock/*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Clear the errors for the pool, or the particular device if specified.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockint
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockzpool_clear(zpool_handle_t *zhp, const char *path)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zfs_cmd_t zc = { 0 };
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock char msg[1024];
99653d4ee642c6528e88224f12409a5f23060994eschrock nvlist_t *tgt;
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan boolean_t avail_spare, l2cache;
99653d4ee642c6528e88224f12409a5f23060994eschrock libzfs_handle_t *hdl = zhp->zpool_hdl;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (path)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) snprintf(msg, sizeof (msg),
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock path);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock else
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) snprintf(msg, sizeof (msg),
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zhp->zpool_name);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
99653d4ee642c6528e88224f12409a5f23060994eschrock if (path) {
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan if ((tgt = zpool_find_vdev(zhp, path, &avail_spare,
ee0eb9f2d12b8a03b5a193cd667735c1962e0c7bEric Schrock &l2cache, NULL)) == 0)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_NODEVICE, msg));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan /*
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan * Don't allow error clearing for hot spares. Do allow
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan * error clearing for l2cache devices.
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan */
a43d325b828008a3ab54eed57fd7c00b6470172bek if (avail_spare)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_error(hdl, EZFS_ISSPARE, msg));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID,
99653d4ee642c6528e88224f12409a5f23060994eschrock &zc.zc_guid) == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc) == 0)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (0);
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zpool_standard_error(hdl, errno, msg));
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock/*
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * Similar to zpool_clear(), but takes a GUID (used by fmd).
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock */
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrockint
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrockzpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid)
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock{
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock zfs_cmd_t zc = { 0 };
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock char msg[1024];
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock libzfs_handle_t *hdl = zhp->zpool_hdl;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock (void) snprintf(msg, sizeof (msg),
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"),
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock guid);
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock zc.zc_guid = guid;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0)
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock return (0);
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock return (zpool_standard_error(hdl, errno, msg));
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock}
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock/*
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * Convert from a devid string to a path.
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock */
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrockstatic char *
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrockdevid_to_path(char *devid_str)
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock{
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock ddi_devid_t devid;
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock char *minor;
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock char *path;
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock devid_nmlist_t *list = NULL;
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock int ret;
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock if (devid_str_decode(devid_str, &devid, &minor) != 0)
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock return (NULL);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock devid_str_free(minor);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock devid_free(devid);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock if (ret != 0)
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock return (NULL);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock if ((path = strdup(list[0].devname)) == NULL)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (NULL);
99653d4ee642c6528e88224f12409a5f23060994eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock devid_free_nmlist(list);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock return (path);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock}
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock/*
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * Convert from a path to a devid string.
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock */
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrockstatic char *
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrockpath_to_devid(const char *path)
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock{
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock int fd;
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock ddi_devid_t devid;
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock char *minor, *ret;
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock if ((fd = open(path, O_RDONLY)) < 0)
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock return (NULL);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock minor = NULL;
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock ret = NULL;
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock if (devid_get(fd, &devid) == 0) {
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock if (devid_get_minor_name(fd, &minor) == 0)
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock ret = devid_str_encode(devid, minor);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock if (minor != NULL)
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock devid_str_free(minor);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock devid_free(devid);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock }
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock (void) close(fd);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock return (ret);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock}
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock/*
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * Issue the necessary ioctl() to update the stored path value for the vdev. We
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * ignore any failure here, since a common case is for an unprivileged user to
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * type 'zpool status', and we'll display the correct information anyway.
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock */
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrockstatic void
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrockset_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path)
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock{
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock zfs_cmd_t zc = { 0 };
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value));
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock &zc.zc_guid) == 0);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock}
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock/*
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * Given a vdev, return the name to display in iostat. If the vdev has a path,
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type.
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * We also check if this is a whole disk, in which case we strip off the
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * trailing 's0' slice name.
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock *
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * This routine is also responsible for identifying when disks have been
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * reconfigured in a new location. The kernel will have opened the device by
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * devid, but the path will still refer to the old location. To catch this, we
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * first do a path -> devid translation (which is fast for the common case). If
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * the devid matches, we're done. If not, we do a reverse devid -> path
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * translation and issue the appropriate ioctl() to update the path of the vdev.
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * of these checks.
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock */
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrockchar *
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilsonzpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson boolean_t verbose)
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock{
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock char *path, *devid;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock uint64_t value;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock char buf[64];
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock vdev_stat_t *vs;
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock uint_t vsc;
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock &value) == 0) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock &value) == 0);
5ad820458efd0fdb914baff9c1447c22b819fa23nd (void) snprintf(buf, sizeof (buf), "%llu",
5ad820458efd0fdb914baff9c1447c22b819fa23nd (u_longlong_t)value);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock path = buf;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock /*
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * If the device is dead (faulted, offline, etc) then don't
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * bother opening it. Otherwise we may be forcing the user to
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * open a misbehaving device, which can have undesirable
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * effects.
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock */
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock if ((nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock (uint64_t **)&vs, &vsc) != 0 ||
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock vs->vs_state >= VDEV_STATE_DEGRADED) &&
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock zhp != NULL &&
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) {
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock /*
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * Determine if the current path is correct.
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock */
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock char *newdevid = path_to_devid(path);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock if (newdevid == NULL ||
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock strcmp(devid, newdevid) != 0) {
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock char *newpath;
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock if ((newpath = devid_to_path(devid)) != NULL) {
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock /*
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock * Update the path appropriately.
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock */
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock set_path(zhp, nv, newpath);
99653d4ee642c6528e88224f12409a5f23060994eschrock if (nvlist_add_string(nv,
99653d4ee642c6528e88224f12409a5f23060994eschrock ZPOOL_CONFIG_PATH, newpath) == 0)
99653d4ee642c6528e88224f12409a5f23060994eschrock verify(nvlist_lookup_string(nv,
99653d4ee642c6528e88224f12409a5f23060994eschrock ZPOOL_CONFIG_PATH,
99653d4ee642c6528e88224f12409a5f23060994eschrock &path) == 0);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock free(newpath);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock }
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock }
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock if (newdevid)
99653d4ee642c6528e88224f12409a5f23060994eschrock devid_str_free(newdevid);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock }
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock if (strncmp(path, "/dev/dsk/", 9) == 0)
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock path += 9;
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock &value) == 0 && value) {
99653d4ee642c6528e88224f12409a5f23060994eschrock char *tmp = zfs_strdup(hdl, path);
99653d4ee642c6528e88224f12409a5f23060994eschrock if (tmp == NULL)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (NULL);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock tmp[strlen(path) - 2] = '\0';
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock return (tmp);
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock }
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock } else {
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0);
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock /*
99653d4ee642c6528e88224f12409a5f23060994eschrock * If it's a raidz device, we need to stick in the parity level.
99653d4ee642c6528e88224f12409a5f23060994eschrock */
99653d4ee642c6528e88224f12409a5f23060994eschrock if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) {
99653d4ee642c6528e88224f12409a5f23060994eschrock verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY,
99653d4ee642c6528e88224f12409a5f23060994eschrock &value) == 0);
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) snprintf(buf, sizeof (buf), "%s%llu", path,
5ad820458efd0fdb914baff9c1447c22b819fa23nd (u_longlong_t)value);
99653d4ee642c6528e88224f12409a5f23060994eschrock path = buf;
99653d4ee642c6528e88224f12409a5f23060994eschrock }
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson /*
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * We identify each top-level vdev by using a <type-id>
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson * naming convention.
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson */
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson if (verbose) {
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson uint64_t id;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID,
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson &id) == 0);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson (void) snprintf(buf, sizeof (buf), "%s-%llu", path,
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson (u_longlong_t)id);
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson path = buf;
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson }
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock }
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrock return (zfs_strdup(hdl, path));
c67d9675bbc8392fe45f3a7dfbda1ad4daa1eb07eschrock}
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockstatic int
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockzbookmark_compare(const void *a, const void *b)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (memcmp(a, b, sizeof (zbookmark_t)));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock}
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock/*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Retrieve the persistent error log, uniquify the members, and return to the
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * caller.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockint
55434c770c89aa1b84474f2559a106803511aba0ekzpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zfs_cmd_t zc = { 0 };
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock uint64_t count;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock zbookmark_t *zb = NULL;
55434c770c89aa1b84474f2559a106803511aba0ek int i;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Retrieve the raw error list from the kernel. If the number of errors
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * has increased, allocate more space and continue until we get the
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * entire list.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock &count) == 0);
75519f380eac71fe6d10b26e736f01567d6c13c9ek if (count == 0)
75519f380eac71fe6d10b26e736f01567d6c13c9ek return (0);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl,
5ad820458efd0fdb914baff9c1447c22b819fa23nd count * sizeof (zbookmark_t))) == (uintptr_t)NULL)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (-1);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock zc.zc_nvlist_dst_size = count;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock (void) strcpy(zc.zc_name, zhp->zpool_name);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock for (;;) {
99653d4ee642c6528e88224f12409a5f23060994eschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG,
99653d4ee642c6528e88224f12409a5f23060994eschrock &zc) != 0) {
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock free((void *)(uintptr_t)zc.zc_nvlist_dst);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (errno == ENOMEM) {
bf561db0030e7d3435bcc1e1f5889fac05a18814vb count = zc.zc_nvlist_dst_size;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if ((zc.zc_nvlist_dst = (uintptr_t)
bf561db0030e7d3435bcc1e1f5889fac05a18814vb zfs_alloc(zhp->zpool_hdl, count *
bf561db0030e7d3435bcc1e1f5889fac05a18814vb sizeof (zbookmark_t))) == (uintptr_t)NULL)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (-1);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } else {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (-1);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock } else {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock break;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Sort the resulting bookmarks. This is a little confusing due to the
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * _not_ copied as part of the process. So we point the start of our
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * array appropriate and decrement the total number of elements.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) +
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock zc.zc_nvlist_dst_size;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock count -= zc.zc_nvlist_dst_size;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
55434c770c89aa1b84474f2559a106803511aba0ek verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
55434c770c89aa1b84474f2559a106803511aba0ek * Fill in the nverrlistp with nvlist's of dataset and object numbers.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock for (i = 0; i < count; i++) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock nvlist_t *nv;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
c0a81264b59ba24de8701436570c3aae5689dc89ek /* ignoring zb_blkid and zb_level for now */
c0a81264b59ba24de8701436570c3aae5689dc89ek if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset &&
c0a81264b59ba24de8701436570c3aae5689dc89ek zb[i-1].zb_object == zb[i].zb_object)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock continue;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
55434c770c89aa1b84474f2559a106803511aba0ek if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0)
55434c770c89aa1b84474f2559a106803511aba0ek goto nomem;
55434c770c89aa1b84474f2559a106803511aba0ek if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET,
55434c770c89aa1b84474f2559a106803511aba0ek zb[i].zb_objset) != 0) {
55434c770c89aa1b84474f2559a106803511aba0ek nvlist_free(nv);
99653d4ee642c6528e88224f12409a5f23060994eschrock goto nomem;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
55434c770c89aa1b84474f2559a106803511aba0ek if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT,
55434c770c89aa1b84474f2559a106803511aba0ek zb[i].zb_object) != 0) {
55434c770c89aa1b84474f2559a106803511aba0ek nvlist_free(nv);
55434c770c89aa1b84474f2559a106803511aba0ek goto nomem;
55434c770c89aa1b84474f2559a106803511aba0ek }
55434c770c89aa1b84474f2559a106803511aba0ek if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) {
55434c770c89aa1b84474f2559a106803511aba0ek nvlist_free(nv);
55434c770c89aa1b84474f2559a106803511aba0ek goto nomem;
55434c770c89aa1b84474f2559a106803511aba0ek }
55434c770c89aa1b84474f2559a106803511aba0ek nvlist_free(nv);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
3ccfa83cd9cddd1e34808ba18082c156758c5ec8ahrens free((void *)(uintptr_t)zc.zc_nvlist_dst);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (0);
99653d4ee642c6528e88224f12409a5f23060994eschrock
99653d4ee642c6528e88224f12409a5f23060994eschrocknomem:
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock free((void *)(uintptr_t)zc.zc_nvlist_dst);
99653d4ee642c6528e88224f12409a5f23060994eschrock return (no_memory(zhp->zpool_hdl));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock}
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock/*
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock * Upgrade a ZFS pool to the latest on-disk version.
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock */
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrockint
990b4856d0eaada6f8140335733a1b1771ed2746llingzpool_upgrade(zpool_handle_t *zhp, uint64_t new_version)
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock{
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock zfs_cmd_t zc = { 0 };
99653d4ee642c6528e88224f12409a5f23060994eschrock libzfs_handle_t *hdl = zhp->zpool_hdl;
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock (void) strcpy(zc.zc_name, zhp->zpool_name);
990b4856d0eaada6f8140335733a1b1771ed2746lling zc.zc_cookie = new_version;
990b4856d0eaada6f8140335733a1b1771ed2746lling
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zfs_ioctl(hdl, ZFS_IOC_POOL_UPGRADE, &zc) != 0)
ece3d9b3bacef51a5f34d993935eedbb7bb87059lling return (zpool_standard_error_fmt(hdl, errno,
99653d4ee642c6528e88224f12409a5f23060994eschrock dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"),
99653d4ee642c6528e88224f12409a5f23060994eschrock zhp->zpool_name));
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock return (0);
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock}
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ekvoid
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ekzpool_set_history_str(const char *subcommand, int argc, char **argv,
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek char *history_str)
06eeb2ad640ce72d394ac521094bed7681044408ek{
06eeb2ad640ce72d394ac521094bed7681044408ek int i;
06eeb2ad640ce72d394ac521094bed7681044408ek
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek (void) strlcpy(history_str, subcommand, HIS_MAX_RECORD_LEN);
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek for (i = 1; i < argc; i++) {
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek if (strlen(history_str) + 1 + strlen(argv[i]) >
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek HIS_MAX_RECORD_LEN)
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek break;
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek (void) strlcat(history_str, " ", HIS_MAX_RECORD_LEN);
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek (void) strlcat(history_str, argv[i], HIS_MAX_RECORD_LEN);
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek }
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek}
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek/*
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek * Stage command history for logging.
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek */
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ekint
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ekzpool_stage_history(libzfs_handle_t *hdl, const char *history_str)
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek{
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek if (history_str == NULL)
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek return (EINVAL);
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek if (strlen(history_str) > HIS_MAX_RECORD_LEN)
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek return (EINVAL);
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek
228975cc44c2290cc190960e5894ac6ce0863855ek if (hdl->libzfs_log_str != NULL)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks free(hdl->libzfs_log_str);
06eeb2ad640ce72d394ac521094bed7681044408ek
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek if ((hdl->libzfs_log_str = strdup(history_str)) == NULL)
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek return (no_memory(hdl));
06eeb2ad640ce72d394ac521094bed7681044408ek
2a6b87f07ac0c0b819179c84afe5a60afa04cfa5ek return (0);
06eeb2ad640ce72d394ac521094bed7681044408ek}
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek/*
06eeb2ad640ce72d394ac521094bed7681044408ek * Perform ioctl to get some command history of a pool.
06eeb2ad640ce72d394ac521094bed7681044408ek *
06eeb2ad640ce72d394ac521094bed7681044408ek * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the
06eeb2ad640ce72d394ac521094bed7681044408ek * logical offset of the history buffer to start reading from.
06eeb2ad640ce72d394ac521094bed7681044408ek *
06eeb2ad640ce72d394ac521094bed7681044408ek * Upon return, 'off' is the next logical offset to read from and
06eeb2ad640ce72d394ac521094bed7681044408ek * 'len' is the actual amount of bytes read into 'buf'.
06eeb2ad640ce72d394ac521094bed7681044408ek */
06eeb2ad640ce72d394ac521094bed7681044408ekstatic int
06eeb2ad640ce72d394ac521094bed7681044408ekget_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len)
06eeb2ad640ce72d394ac521094bed7681044408ek{
06eeb2ad640ce72d394ac521094bed7681044408ek zfs_cmd_t zc = { 0 };
06eeb2ad640ce72d394ac521094bed7681044408ek libzfs_handle_t *hdl = zhp->zpool_hdl;
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek zc.zc_history = (uint64_t)(uintptr_t)buf;
06eeb2ad640ce72d394ac521094bed7681044408ek zc.zc_history_len = *len;
06eeb2ad640ce72d394ac521094bed7681044408ek zc.zc_history_offset = *off;
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) {
06eeb2ad640ce72d394ac521094bed7681044408ek switch (errno) {
06eeb2ad640ce72d394ac521094bed7681044408ek case EPERM:
ece3d9b3bacef51a5f34d993935eedbb7bb87059lling return (zfs_error_fmt(hdl, EZFS_PERM,
ece3d9b3bacef51a5f34d993935eedbb7bb87059lling dgettext(TEXT_DOMAIN,
06eeb2ad640ce72d394ac521094bed7681044408ek "cannot show history for pool '%s'"),
06eeb2ad640ce72d394ac521094bed7681044408ek zhp->zpool_name));
06eeb2ad640ce72d394ac521094bed7681044408ek case ENOENT:
ece3d9b3bacef51a5f34d993935eedbb7bb87059lling return (zfs_error_fmt(hdl, EZFS_NOHISTORY,
06eeb2ad640ce72d394ac521094bed7681044408ek dgettext(TEXT_DOMAIN, "cannot get history for pool "
06eeb2ad640ce72d394ac521094bed7681044408ek "'%s'"), zhp->zpool_name));
d7306b64c847d897abb9ece8624fca9cf28d358fek case ENOTSUP:
d7306b64c847d897abb9ece8624fca9cf28d358fek return (zfs_error_fmt(hdl, EZFS_BADVERSION,
d7306b64c847d897abb9ece8624fca9cf28d358fek dgettext(TEXT_DOMAIN, "cannot get history for pool "
d7306b64c847d897abb9ece8624fca9cf28d358fek "'%s', pool must be upgraded"), zhp->zpool_name));
06eeb2ad640ce72d394ac521094bed7681044408ek default:
ece3d9b3bacef51a5f34d993935eedbb7bb87059lling return (zpool_standard_error_fmt(hdl, errno,
06eeb2ad640ce72d394ac521094bed7681044408ek dgettext(TEXT_DOMAIN,
06eeb2ad640ce72d394ac521094bed7681044408ek "cannot get history for '%s'"), zhp->zpool_name));
06eeb2ad640ce72d394ac521094bed7681044408ek }
06eeb2ad640ce72d394ac521094bed7681044408ek }
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek *len = zc.zc_history_len;
06eeb2ad640ce72d394ac521094bed7681044408ek *off = zc.zc_history_offset;
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek return (0);
06eeb2ad640ce72d394ac521094bed7681044408ek}
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek/*
06eeb2ad640ce72d394ac521094bed7681044408ek * Process the buffer of nvlists, unpacking and storing each nvlist record
06eeb2ad640ce72d394ac521094bed7681044408ek * into 'records'. 'leftover' is set to the number of bytes that weren't
06eeb2ad640ce72d394ac521094bed7681044408ek * processed as there wasn't a complete record.
06eeb2ad640ce72d394ac521094bed7681044408ek */
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilsonint
06eeb2ad640ce72d394ac521094bed7681044408ekzpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover,
06eeb2ad640ce72d394ac521094bed7681044408ek nvlist_t ***records, uint_t *numrecords)
06eeb2ad640ce72d394ac521094bed7681044408ek{
06eeb2ad640ce72d394ac521094bed7681044408ek uint64_t reclen;
06eeb2ad640ce72d394ac521094bed7681044408ek nvlist_t *nv;
06eeb2ad640ce72d394ac521094bed7681044408ek int i;
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek while (bytes_read > sizeof (reclen)) {
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek /* get length of packed record (stored as little endian) */
06eeb2ad640ce72d394ac521094bed7681044408ek for (i = 0, reclen = 0; i < sizeof (reclen); i++)
06eeb2ad640ce72d394ac521094bed7681044408ek reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i);
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek if (bytes_read < sizeof (reclen) + reclen)
06eeb2ad640ce72d394ac521094bed7681044408ek break;
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek /* unpack record */
06eeb2ad640ce72d394ac521094bed7681044408ek if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0)
06eeb2ad640ce72d394ac521094bed7681044408ek return (ENOMEM);
06eeb2ad640ce72d394ac521094bed7681044408ek bytes_read -= sizeof (reclen) + reclen;
06eeb2ad640ce72d394ac521094bed7681044408ek buf += sizeof (reclen) + reclen;
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek /* add record to nvlist array */
06eeb2ad640ce72d394ac521094bed7681044408ek (*numrecords)++;
06eeb2ad640ce72d394ac521094bed7681044408ek if (ISP2(*numrecords + 1)) {
06eeb2ad640ce72d394ac521094bed7681044408ek *records = realloc(*records,
06eeb2ad640ce72d394ac521094bed7681044408ek *numrecords * 2 * sizeof (nvlist_t *));
06eeb2ad640ce72d394ac521094bed7681044408ek }
06eeb2ad640ce72d394ac521094bed7681044408ek (*records)[*numrecords - 1] = nv;
06eeb2ad640ce72d394ac521094bed7681044408ek }
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek *leftover = bytes_read;
06eeb2ad640ce72d394ac521094bed7681044408ek return (0);
06eeb2ad640ce72d394ac521094bed7681044408ek}
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek#define HIS_BUF_LEN (128*1024)
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek/*
06eeb2ad640ce72d394ac521094bed7681044408ek * Retrieve the command history of a pool.
06eeb2ad640ce72d394ac521094bed7681044408ek */
06eeb2ad640ce72d394ac521094bed7681044408ekint
06eeb2ad640ce72d394ac521094bed7681044408ekzpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
06eeb2ad640ce72d394ac521094bed7681044408ek{
06eeb2ad640ce72d394ac521094bed7681044408ek char buf[HIS_BUF_LEN];
06eeb2ad640ce72d394ac521094bed7681044408ek uint64_t off = 0;
06eeb2ad640ce72d394ac521094bed7681044408ek nvlist_t **records = NULL;
06eeb2ad640ce72d394ac521094bed7681044408ek uint_t numrecords = 0;
06eeb2ad640ce72d394ac521094bed7681044408ek int err, i;
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek do {
06eeb2ad640ce72d394ac521094bed7681044408ek uint64_t bytes_read = sizeof (buf);
06eeb2ad640ce72d394ac521094bed7681044408ek uint64_t leftover;
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0)
06eeb2ad640ce72d394ac521094bed7681044408ek break;
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek /* if nothing else was read in, we're at EOF, just return */
06eeb2ad640ce72d394ac521094bed7681044408ek if (!bytes_read)
06eeb2ad640ce72d394ac521094bed7681044408ek break;
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek if ((err = zpool_history_unpack(buf, bytes_read,
06eeb2ad640ce72d394ac521094bed7681044408ek &leftover, &records, &numrecords)) != 0)
06eeb2ad640ce72d394ac521094bed7681044408ek break;
06eeb2ad640ce72d394ac521094bed7681044408ek off -= leftover;
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek /* CONSTCOND */
06eeb2ad640ce72d394ac521094bed7681044408ek } while (1);
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek if (!err) {
06eeb2ad640ce72d394ac521094bed7681044408ek verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0);
06eeb2ad640ce72d394ac521094bed7681044408ek verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD,
06eeb2ad640ce72d394ac521094bed7681044408ek records, numrecords) == 0);
06eeb2ad640ce72d394ac521094bed7681044408ek }
06eeb2ad640ce72d394ac521094bed7681044408ek for (i = 0; i < numrecords; i++)
06eeb2ad640ce72d394ac521094bed7681044408ek nvlist_free(records[i]);
06eeb2ad640ce72d394ac521094bed7681044408ek free(records);
06eeb2ad640ce72d394ac521094bed7681044408ek
06eeb2ad640ce72d394ac521094bed7681044408ek return (err);
06eeb2ad640ce72d394ac521094bed7681044408ek}
55434c770c89aa1b84474f2559a106803511aba0ek
55434c770c89aa1b84474f2559a106803511aba0ekvoid
55434c770c89aa1b84474f2559a106803511aba0ekzpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
55434c770c89aa1b84474f2559a106803511aba0ek char *pathname, size_t len)
55434c770c89aa1b84474f2559a106803511aba0ek{
55434c770c89aa1b84474f2559a106803511aba0ek zfs_cmd_t zc = { 0 };
55434c770c89aa1b84474f2559a106803511aba0ek boolean_t mounted = B_FALSE;
55434c770c89aa1b84474f2559a106803511aba0ek char *mntpnt = NULL;
55434c770c89aa1b84474f2559a106803511aba0ek char dsname[MAXNAMELEN];
55434c770c89aa1b84474f2559a106803511aba0ek
55434c770c89aa1b84474f2559a106803511aba0ek if (dsobj == 0) {
55434c770c89aa1b84474f2559a106803511aba0ek /* special case for the MOS */
55434c770c89aa1b84474f2559a106803511aba0ek (void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj);
55434c770c89aa1b84474f2559a106803511aba0ek return;
55434c770c89aa1b84474f2559a106803511aba0ek }
55434c770c89aa1b84474f2559a106803511aba0ek
55434c770c89aa1b84474f2559a106803511aba0ek /* get the dataset's name */
55434c770c89aa1b84474f2559a106803511aba0ek (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
55434c770c89aa1b84474f2559a106803511aba0ek zc.zc_obj = dsobj;
55434c770c89aa1b84474f2559a106803511aba0ek if (ioctl(zhp->zpool_hdl->libzfs_fd,
55434c770c89aa1b84474f2559a106803511aba0ek ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) {
55434c770c89aa1b84474f2559a106803511aba0ek /* just write out a path of two object numbers */
55434c770c89aa1b84474f2559a106803511aba0ek (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>",
55434c770c89aa1b84474f2559a106803511aba0ek dsobj, obj);
55434c770c89aa1b84474f2559a106803511aba0ek return;
55434c770c89aa1b84474f2559a106803511aba0ek }
55434c770c89aa1b84474f2559a106803511aba0ek (void) strlcpy(dsname, zc.zc_value, sizeof (dsname));
55434c770c89aa1b84474f2559a106803511aba0ek
55434c770c89aa1b84474f2559a106803511aba0ek /* find out if the dataset is mounted */
55434c770c89aa1b84474f2559a106803511aba0ek mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt);
55434c770c89aa1b84474f2559a106803511aba0ek
55434c770c89aa1b84474f2559a106803511aba0ek /* get the corrupted object's path */
55434c770c89aa1b84474f2559a106803511aba0ek (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name));
55434c770c89aa1b84474f2559a106803511aba0ek zc.zc_obj = obj;
55434c770c89aa1b84474f2559a106803511aba0ek if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH,
55434c770c89aa1b84474f2559a106803511aba0ek &zc) == 0) {
55434c770c89aa1b84474f2559a106803511aba0ek if (mounted) {
55434c770c89aa1b84474f2559a106803511aba0ek (void) snprintf(pathname, len, "%s%s", mntpnt,
55434c770c89aa1b84474f2559a106803511aba0ek zc.zc_value);
55434c770c89aa1b84474f2559a106803511aba0ek } else {
55434c770c89aa1b84474f2559a106803511aba0ek (void) snprintf(pathname, len, "%s:%s",
55434c770c89aa1b84474f2559a106803511aba0ek dsname, zc.zc_value);
55434c770c89aa1b84474f2559a106803511aba0ek }
55434c770c89aa1b84474f2559a106803511aba0ek } else {
55434c770c89aa1b84474f2559a106803511aba0ek (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj);
55434c770c89aa1b84474f2559a106803511aba0ek }
55434c770c89aa1b84474f2559a106803511aba0ek free(mntpnt);
55434c770c89aa1b84474f2559a106803511aba0ek}
b1b8ab34de515a5e83206da22c3d7e563241b021lling
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw/*
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw * Read the EFI label from the config, if a label does not exist then
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw * pass back the error to the caller. If the caller has passed a non-NULL
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw * diskaddr argument then we set it to the starting address of the EFI
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw * partition.
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw */
15e6edf145a9c2bb0e0272cf8debe823bb97529bgwstatic int
15e6edf145a9c2bb0e0272cf8debe823bb97529bgwread_efi_label(nvlist_t *config, diskaddr_t *sb)
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw{
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw char *path;
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw int fd;
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw char diskname[MAXPATHLEN];
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw int err = -1;
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw if (nvlist_lookup_string(config, ZPOOL_CONFIG_PATH, &path) != 0)
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw return (err);
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw (void) snprintf(diskname, sizeof (diskname), "%s%s", RDISK_ROOT,
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw strrchr(path, '/'));
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) {
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw struct dk_gpt *vtoc;
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw if ((err = efi_alloc_and_read(fd, &vtoc)) >= 0) {
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw if (sb != NULL)
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw *sb = vtoc->efi_parts[0].p_start;
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw efi_free(vtoc);
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw }
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw (void) close(fd);
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw }
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw return (err);
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw}
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor/*
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * determine where a partition starts on a disk in the current
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * configuration
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor */
8488aeb5df27784d479c16cde06a9e25cd9a1152taylorstatic diskaddr_t
8488aeb5df27784d479c16cde06a9e25cd9a1152taylorfind_start_block(nvlist_t *config)
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor{
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor nvlist_t **child;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor uint_t c, children;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor diskaddr_t sb = MAXOFFSET_T;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor uint64_t wholedisk;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor if (nvlist_lookup_nvlist_array(config,
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) {
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor if (nvlist_lookup_uint64(config,
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor ZPOOL_CONFIG_WHOLE_DISK,
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor &wholedisk) != 0 || !wholedisk) {
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor return (MAXOFFSET_T);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor }
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw if (read_efi_label(config, &sb) < 0)
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw sb = MAXOFFSET_T;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor return (sb);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor }
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor for (c = 0; c < children; c++) {
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor sb = find_start_block(child[c]);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor if (sb != MAXOFFSET_T) {
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor return (sb);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor }
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor }
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor return (MAXOFFSET_T);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor}
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor/*
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * Label an individual disk. The name provided is the short name,
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * stripped of any leading /dev path.
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor */
8488aeb5df27784d479c16cde06a9e25cd9a1152taylorint
8488aeb5df27784d479c16cde06a9e25cd9a1152taylorzpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor{
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor char path[MAXPATHLEN];
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor struct dk_gpt *vtoc;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor int fd;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor size_t resv = EFI_MIN_RESV_SIZE;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor uint64_t slice_size;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor diskaddr_t start_block;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor char errbuf[1024];
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
c6ef114f2f708797a9cba68e8c08f42a03f094bbmmusante /* prepare an error message just in case */
c6ef114f2f708797a9cba68e8c08f42a03f094bbmmusante (void) snprintf(errbuf, sizeof (errbuf),
c6ef114f2f708797a9cba68e8c08f42a03f094bbmmusante dgettext(TEXT_DOMAIN, "cannot label '%s'"), name);
c6ef114f2f708797a9cba68e8c08f42a03f094bbmmusante
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor if (zhp) {
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor nvlist_t *nvroot;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson if (pool_is_bootable(zhp)) {
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson "EFI labeled devices are not supported on root "
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson "pools."));
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf));
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson }
b5b76fec872120fb1395471edcf51f378acd7e83George Wilson
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor verify(nvlist_lookup_nvlist(zhp->zpool_config,
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor if (zhp->zpool_start_block == 0)
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor start_block = find_start_block(nvroot);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor else
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor start_block = zhp->zpool_start_block;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor zhp->zpool_start_block = start_block;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor } else {
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor /* new pool */
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor start_block = NEW_START_BLOCK;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor }
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor (void) snprintf(path, sizeof (path), "%s/%s%s", RDISK_ROOT, name,
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor BACKUP_SLICE);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) {
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor /*
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * This shouldn't happen. We've long since verified that this
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * is a valid device.
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor */
c6ef114f2f708797a9cba68e8c08f42a03f094bbmmusante zfs_error_aux(hdl,
c6ef114f2f708797a9cba68e8c08f42a03f094bbmmusante dgettext(TEXT_DOMAIN, "unable to open device"));
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor return (zfs_error(hdl, EZFS_OPENFAILED, errbuf));
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor }
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) {
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor /*
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * The only way this can fail is if we run out of memory, or we
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * were unable to read the disk's capacity
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor */
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor if (errno == ENOMEM)
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor (void) no_memory(hdl);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor (void) close(fd);
c6ef114f2f708797a9cba68e8c08f42a03f094bbmmusante zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
c6ef114f2f708797a9cba68e8c08f42a03f094bbmmusante "unable to read disk capacity"), name);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor return (zfs_error(hdl, EZFS_NOCAP, errbuf));
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor }
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor slice_size = vtoc->efi_last_u_lba + 1;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor slice_size -= EFI_MIN_RESV_SIZE;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor if (start_block == MAXOFFSET_T)
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor start_block = NEW_START_BLOCK;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor slice_size -= start_block;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor vtoc->efi_parts[0].p_start = start_block;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor vtoc->efi_parts[0].p_size = slice_size;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor /*
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * Why we use V_USR: V_BACKUP confuses users, and is considered
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * disposable by some EFI utilities (since EFI doesn't have a backup
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * slice). V_UNASSIGNED is supposed to be used only for zero size
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * partitions, and efi_write() will fail if we use it. V_ROOT, V_BOOT,
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * etc. were all pretty specific. V_USR is as close to reality as we
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * can get, in the absence of V_OTHER.
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor */
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor vtoc->efi_parts[0].p_tag = V_USR;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor (void) strcpy(vtoc->efi_parts[0].p_name, "zfs");
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor vtoc->efi_parts[8].p_start = slice_size + start_block;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor vtoc->efi_parts[8].p_size = resv;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor vtoc->efi_parts[8].p_tag = V_RESERVED;
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor if (efi_write(fd, vtoc) != 0) {
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor /*
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * Some block drivers (like pcata) may not support EFI
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * GPT labels. Print out a helpful error message dir-
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * ecting the user to manually label the disk and give
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * a specific slice.
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor */
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor (void) close(fd);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor efi_free(vtoc);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
c6ef114f2f708797a9cba68e8c08f42a03f094bbmmusante "try using fdisk(1M) and then provide a specific slice"));
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor return (zfs_error(hdl, EZFS_LABELFAILED, errbuf));
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor }
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor (void) close(fd);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor efi_free(vtoc);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor return (0);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor}
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gwstatic boolean_t
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gwsupported_dump_vdev_type(libzfs_handle_t *hdl, nvlist_t *config, char *errbuf)
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw{
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw char *type;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw nvlist_t **child;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw uint_t children, c;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw verify(nvlist_lookup_string(config, ZPOOL_CONFIG_TYPE, &type) == 0);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if (strcmp(type, VDEV_TYPE_RAIDZ) == 0 ||
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw strcmp(type, VDEV_TYPE_FILE) == 0 ||
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw strcmp(type, VDEV_TYPE_LOG) == 0 ||
88ecc943b4eb72f7c4fbbd8435997b85ef171fc3George Wilson strcmp(type, VDEV_TYPE_HOLE) == 0 ||
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw strcmp(type, VDEV_TYPE_MISSING) == 0) {
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw "vdev type '%s' is not supported"), type);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw (void) zfs_error(hdl, EZFS_VDEVNOTSUP, errbuf);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw return (B_FALSE);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw }
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN,
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw &child, &children) == 0) {
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw for (c = 0; c < children; c++) {
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if (!supported_dump_vdev_type(hdl, child[c], errbuf))
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw return (B_FALSE);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw }
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw }
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw return (B_TRUE);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw}
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw/*
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw * check if this zvol is allowable for use as a dump device; zero if
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw * it is, > 0 if it isn't, < 0 if it isn't a zvol
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw */
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gwint
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gwzvol_check_dump_config(char *arg)
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw{
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw zpool_handle_t *zhp = NULL;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw nvlist_t *config, *nvroot;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw char *p, *volname;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw nvlist_t **top;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw uint_t toplevels;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw libzfs_handle_t *hdl;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw char errbuf[1024];
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw char poolname[ZPOOL_MAXNAMELEN];
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw int pathlen = strlen(ZVOL_FULL_DEV_DIR);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw int ret = 1;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if (strncmp(arg, ZVOL_FULL_DEV_DIR, pathlen)) {
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw return (-1);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw }
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw "dump is not supported on device '%s'"), arg);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if ((hdl = libzfs_init()) == NULL)
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw return (1);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw libzfs_print_on_error(hdl, B_TRUE);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw volname = arg + pathlen;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw /* check the configuration of the pool */
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if ((p = strchr(volname, '/')) == NULL) {
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw "malformed dataset name"));
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw return (1);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw } else if (p - volname >= ZFS_MAXNAMELEN) {
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw "dataset name is too long"));
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw (void) zfs_error(hdl, EZFS_NAMETOOLONG, errbuf);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw return (1);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw } else {
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw (void) strncpy(poolname, volname, p - volname);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw poolname[p - volname] = '\0';
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw }
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if ((zhp = zpool_open(hdl, poolname)) == NULL) {
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw "could not open pool '%s'"), poolname);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw goto out;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw }
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw config = zpool_get_config(zhp, NULL);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw &nvroot) != 0) {
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw "could not obtain vdev configuration for '%s'"), poolname);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw (void) zfs_error(hdl, EZFS_INVALCONFIG, errbuf);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw goto out;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw }
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw &top, &toplevels) == 0);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if (toplevels != 1) {
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw "'%s' has multiple top level vdevs"), poolname);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw (void) zfs_error(hdl, EZFS_DEVOVERFLOW, errbuf);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw goto out;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw }
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if (!supported_dump_vdev_type(hdl, top[0], errbuf)) {
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw goto out;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw }
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw ret = 0;
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gwout:
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if (zhp)
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw zpool_close(zhp);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw libzfs_fini(hdl);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw return (ret);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw}