1789Sahrens /*
2789Sahrens  * CDDL HEADER START
3789Sahrens  *
4789Sahrens  * The contents of this file are subject to the terms of the
51485Slling  * Common Development and Distribution License (the "License").
61485Slling  * You may not use this file except in compliance with the License.
7789Sahrens  *
8789Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9789Sahrens  * or http://www.opensolaris.org/os/licensing.
10789Sahrens  * See the License for the specific language governing permissions
11789Sahrens  * and limitations under the License.
12789Sahrens  *
13789Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14789Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15789Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16789Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17789Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18789Sahrens  *
19789Sahrens  * CDDL HEADER END
20789Sahrens  */
212082Seschrock 
22789Sahrens /*
233377Seschrock  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24789Sahrens  * Use is subject to license terms.
25789Sahrens  */
26789Sahrens 
27789Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
28789Sahrens 
293126Sahl #include <alloca.h>
30789Sahrens #include <assert.h>
31789Sahrens #include <ctype.h>
32789Sahrens #include <errno.h>
33789Sahrens #include <devid.h>
343126Sahl #include <dirent.h>
35789Sahrens #include <fcntl.h>
36789Sahrens #include <libintl.h>
37789Sahrens #include <stdio.h>
38789Sahrens #include <stdlib.h>
393126Sahl #include <strings.h>
40789Sahrens #include <unistd.h>
414276Staylor #include <sys/efi_partition.h>
424276Staylor #include <sys/vtoc.h>
43789Sahrens #include <sys/zfs_ioctl.h>
441544Seschrock #include <sys/zio.h>
452926Sek110237 #include <strings.h>
46789Sahrens 
47789Sahrens #include "zfs_namecheck.h"
483912Slling #include "zfs_prop.h"
49789Sahrens #include "libzfs_impl.h"
50789Sahrens 
515094Slling 
525094Slling /*
535094Slling  * ====================================================================
545094Slling  *   zpool property functions
555094Slling  * ====================================================================
565094Slling  */
575094Slling 
585094Slling static int
595094Slling zpool_get_all_props(zpool_handle_t *zhp)
605094Slling {
615094Slling 	zfs_cmd_t zc = { 0 };
625094Slling 	libzfs_handle_t *hdl = zhp->zpool_hdl;
635094Slling 
645094Slling 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
655094Slling 
665094Slling 	if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0)
675094Slling 		return (-1);
685094Slling 
695094Slling 	while (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) {
705094Slling 		if (errno == ENOMEM) {
715094Slling 			if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
725094Slling 				zcmd_free_nvlists(&zc);
735094Slling 				return (-1);
745094Slling 			}
755094Slling 		} else {
765094Slling 			zcmd_free_nvlists(&zc);
775094Slling 			return (-1);
785094Slling 		}
795094Slling 	}
805094Slling 
815094Slling 	if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) {
825094Slling 		zcmd_free_nvlists(&zc);
835094Slling 		return (-1);
845094Slling 	}
855094Slling 
865094Slling 	zcmd_free_nvlists(&zc);
875094Slling 
885094Slling 	return (0);
895094Slling }
905094Slling 
915094Slling static int
925094Slling zpool_props_refresh(zpool_handle_t *zhp)
935094Slling {
945094Slling 	nvlist_t *old_props;
955094Slling 
965094Slling 	old_props = zhp->zpool_props;
975094Slling 
985094Slling 	if (zpool_get_all_props(zhp) != 0)
995094Slling 		return (-1);
1005094Slling 
1015094Slling 	nvlist_free(old_props);
1025094Slling 	return (0);
1035094Slling }
1045094Slling 
1055094Slling static char *
1065094Slling zpool_get_prop_string(zpool_handle_t *zhp, zpool_prop_t prop,
1075094Slling     zprop_source_t *src)
1085094Slling {
1095094Slling 	nvlist_t *nv, *nvl;
1105094Slling 	uint64_t ival;
1115094Slling 	char *value;
1125094Slling 	zprop_source_t source;
1135094Slling 
1145094Slling 	nvl = zhp->zpool_props;
1155094Slling 	if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) {
1165094Slling 		verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &ival) == 0);
1175094Slling 		source = ival;
1185094Slling 		verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
1195094Slling 	} else {
1205094Slling 		source = ZPROP_SRC_DEFAULT;
1215094Slling 		if ((value = (char *)zpool_prop_default_string(prop)) == NULL)
1225094Slling 			value = "-";
1235094Slling 	}
1245094Slling 
1255094Slling 	if (src)
1265094Slling 		*src = source;
1275094Slling 
1285094Slling 	return (value);
1295094Slling }
1305094Slling 
1315094Slling uint64_t
1325094Slling zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop, zprop_source_t *src)
1335094Slling {
1345094Slling 	nvlist_t *nv, *nvl;
1355094Slling 	uint64_t value;
1365094Slling 	zprop_source_t source;
1375094Slling 
1385094Slling 	if (zhp->zpool_props == NULL && zpool_get_all_props(zhp))
1395094Slling 		return (zpool_prop_default_numeric(prop));
1405094Slling 
1415094Slling 	nvl = zhp->zpool_props;
1425094Slling 	if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) {
1435094Slling 		verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &value) == 0);
1445094Slling 		source = value;
1455094Slling 		verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0);
1465094Slling 	} else {
1475094Slling 		source = ZPROP_SRC_DEFAULT;
1485094Slling 		value = zpool_prop_default_numeric(prop);
1495094Slling 	}
1505094Slling 
1515094Slling 	if (src)
1525094Slling 		*src = source;
1535094Slling 
1545094Slling 	return (value);
1555094Slling }
1565094Slling 
1575094Slling /*
1585094Slling  * Map VDEV STATE to printed strings.
1595094Slling  */
1605094Slling char *
1615094Slling zpool_state_to_name(vdev_state_t state, vdev_aux_t aux)
1625094Slling {
1635094Slling 	switch (state) {
1645094Slling 	case VDEV_STATE_CLOSED:
1655094Slling 	case VDEV_STATE_OFFLINE:
1665094Slling 		return (gettext("OFFLINE"));
1675094Slling 	case VDEV_STATE_REMOVED:
1685094Slling 		return (gettext("REMOVED"));
1695094Slling 	case VDEV_STATE_CANT_OPEN:
1705094Slling 		if (aux == VDEV_AUX_CORRUPT_DATA)
1715094Slling 			return (gettext("FAULTED"));
1725094Slling 		else
1735094Slling 			return (gettext("UNAVAIL"));
1745094Slling 	case VDEV_STATE_FAULTED:
1755094Slling 		return (gettext("FAULTED"));
1765094Slling 	case VDEV_STATE_DEGRADED:
1775094Slling 		return (gettext("DEGRADED"));
1785094Slling 	case VDEV_STATE_HEALTHY:
1795094Slling 		return (gettext("ONLINE"));
1805094Slling 	}
1815094Slling 
1825094Slling 	return (gettext("UNKNOWN"));
1835094Slling }
1845094Slling 
1855094Slling /*
1865094Slling  * Get a zpool property value for 'prop' and return the value in
1875094Slling  * a pre-allocated buffer.
1885094Slling  */
1895094Slling int
1905094Slling zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
1915094Slling     zprop_source_t *srctype)
1925094Slling {
1935094Slling 	uint64_t intval;
1945094Slling 	const char *strval;
1955094Slling 	zprop_source_t src = ZPROP_SRC_NONE;
1965094Slling 	nvlist_t *nvroot;
1975094Slling 	vdev_stat_t *vs;
1985094Slling 	uint_t vsc;
1995094Slling 
2005094Slling 	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
2015094Slling 		if (prop == ZPOOL_PROP_NAME)
2025094Slling 			(void) strlcpy(buf, zpool_get_name(zhp), len);
2035094Slling 		else if (prop == ZPOOL_PROP_HEALTH)
2045094Slling 			(void) strlcpy(buf, "FAULTED", len);
2055094Slling 		else
2065094Slling 			(void) strlcpy(buf, "-", len);
2075094Slling 		return (0);
2085094Slling 	}
2095094Slling 
2105094Slling 	if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) &&
2115094Slling 	    prop != ZPOOL_PROP_NAME)
2125094Slling 		return (-1);
2135094Slling 
2145094Slling 	switch (zpool_prop_get_type(prop)) {
2155094Slling 	case PROP_TYPE_STRING:
2165094Slling 		(void) strlcpy(buf, zpool_get_prop_string(zhp, prop, &src),
2175094Slling 		    len);
2185094Slling 		break;
2195094Slling 
2205094Slling 	case PROP_TYPE_NUMBER:
2215094Slling 		intval = zpool_get_prop_int(zhp, prop, &src);
2225094Slling 
2235094Slling 		switch (prop) {
2245094Slling 		case ZPOOL_PROP_SIZE:
2255094Slling 		case ZPOOL_PROP_USED:
2265094Slling 		case ZPOOL_PROP_AVAILABLE:
2275094Slling 			(void) zfs_nicenum(intval, buf, len);
2285094Slling 			break;
2295094Slling 
2305094Slling 		case ZPOOL_PROP_CAPACITY:
2315094Slling 			(void) snprintf(buf, len, "%llu%%",
2325094Slling 			    (u_longlong_t)intval);
2335094Slling 			break;
2345094Slling 
2355094Slling 		case ZPOOL_PROP_HEALTH:
2365094Slling 			verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
2375094Slling 			    ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
2385094Slling 			verify(nvlist_lookup_uint64_array(nvroot,
2395094Slling 			    ZPOOL_CONFIG_STATS, (uint64_t **)&vs, &vsc) == 0);
2405094Slling 
2415094Slling 			(void) strlcpy(buf, zpool_state_to_name(intval,
2425094Slling 			    vs->vs_aux), len);
2435094Slling 			break;
2445094Slling 		default:
2455094Slling 			(void) snprintf(buf, len, "%llu", intval);
2465094Slling 		}
2475094Slling 		break;
2485094Slling 
2495094Slling 	case PROP_TYPE_INDEX:
2505094Slling 		intval = zpool_get_prop_int(zhp, prop, &src);
2515094Slling 		if (zpool_prop_index_to_string(prop, intval, &strval)
2525094Slling 		    != 0)
2535094Slling 			return (-1);
2545094Slling 		(void) strlcpy(buf, strval, len);
2555094Slling 		break;
2565094Slling 
2575094Slling 	default:
2585094Slling 		abort();
2595094Slling 	}
2605094Slling 
2615094Slling 	if (srctype)
2625094Slling 		*srctype = src;
2635094Slling 
2645094Slling 	return (0);
2655094Slling }
2665094Slling 
2675094Slling /*
2685094Slling  * Check if the bootfs name has the same pool name as it is set to.
2695094Slling  * Assuming bootfs is a valid dataset name.
2705094Slling  */
2715094Slling static boolean_t
2725094Slling bootfs_name_valid(const char *pool, char *bootfs)
2735094Slling {
2745094Slling 	int len = strlen(pool);
2755094Slling 
2765094Slling 	if (!zfs_name_valid(bootfs, ZFS_TYPE_FILESYSTEM))
2775094Slling 		return (B_FALSE);
2785094Slling 
2795094Slling 	if (strncmp(pool, bootfs, len) == 0 &&
2805094Slling 	    (bootfs[len] == '/' || bootfs[len] == '\0'))
2815094Slling 		return (B_TRUE);
2825094Slling 
2835094Slling 	return (B_FALSE);
2845094Slling }
2855094Slling 
2865094Slling /*
2875094Slling  * Given an nvlist of zpool properties to be set, validate that they are
2885094Slling  * correct, and parse any numeric properties (index, boolean, etc) if they are
2895094Slling  * specified as strings.
2905094Slling  */
2915094Slling static nvlist_t *
2925094Slling zpool_validate_properties(libzfs_handle_t *hdl, const char *poolname,
2935094Slling     nvlist_t *props, uint64_t version, boolean_t create_or_import, char *errbuf)
2945094Slling {
2955094Slling 	nvpair_t *elem;
2965094Slling 	nvlist_t *retprops;
2975094Slling 	zpool_prop_t prop;
2985094Slling 	char *strval;
2995094Slling 	uint64_t intval;
300*5363Seschrock 	char *slash;
301*5363Seschrock 	struct stat64 statbuf;
3025094Slling 
3035094Slling 	if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) {
3045094Slling 		(void) no_memory(hdl);
3055094Slling 		return (NULL);
3065094Slling 	}
3075094Slling 
3085094Slling 	elem = NULL;
3095094Slling 	while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
3105094Slling 		const char *propname = nvpair_name(elem);
3115094Slling 
3125094Slling 		/*
3135094Slling 		 * Make sure this property is valid and applies to this type.
3145094Slling 		 */
3155094Slling 		if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
3165094Slling 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3175094Slling 			    "invalid property '%s'"), propname);
3185094Slling 			(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
3195094Slling 			goto error;
3205094Slling 		}
3215094Slling 
3225094Slling 		if (zpool_prop_readonly(prop)) {
3235094Slling 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
3245094Slling 			    "is readonly"), propname);
3255094Slling 			(void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
3265094Slling 			goto error;
3275094Slling 		}
3285094Slling 
3295094Slling 		if (zprop_parse_value(hdl, elem, prop, ZFS_TYPE_POOL, retprops,
3305094Slling 		    &strval, &intval, errbuf) != 0)
3315094Slling 			goto error;
3325094Slling 
3335094Slling 		/*
3345094Slling 		 * Perform additional checking for specific properties.
3355094Slling 		 */
3365094Slling 		switch (prop) {
3375094Slling 		case ZPOOL_PROP_VERSION:
3385094Slling 			if (intval < version || intval > SPA_VERSION) {
3395094Slling 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3405094Slling 				    "property '%s' number %d is invalid."),
3415094Slling 				    propname, intval);
3425094Slling 				(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
3435094Slling 				goto error;
3445094Slling 			}
3455094Slling 			break;
3465094Slling 
3475094Slling 		case ZPOOL_PROP_BOOTFS:
3485094Slling 			if (create_or_import) {
3495094Slling 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3505094Slling 				    "property '%s' cannot be set at creation "
3515094Slling 				    "or import time"), propname);
3525094Slling 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
3535094Slling 				goto error;
3545094Slling 			}
3555094Slling 
3565094Slling 			if (version < SPA_VERSION_BOOTFS) {
3575094Slling 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3585094Slling 				    "pool must be upgraded to support "
3595094Slling 				    "'%s' property"), propname);
3605094Slling 				(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
3615094Slling 				goto error;
3625094Slling 			}
3635094Slling 
3645094Slling 			/*
3655094Slling 			 * bootfs property value has to be a dataset name and
3665094Slling 			 * the dataset has to be in the same pool as it sets to.
3675094Slling 			 */
3685094Slling 			if (strval[0] != '\0' && !bootfs_name_valid(poolname,
3695094Slling 			    strval)) {
3705094Slling 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
3715094Slling 				    "is an invalid name"), strval);
3725094Slling 				(void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
3735094Slling 				goto error;
3745094Slling 			}
3755094Slling 			break;
3765094Slling 
3775094Slling 		case ZPOOL_PROP_ALTROOT:
3785094Slling 			if (!create_or_import) {
3795094Slling 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3805094Slling 				    "property '%s' can only be set during pool "
3815094Slling 				    "creation or import"), propname);
3825094Slling 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
3835094Slling 				goto error;
3845094Slling 			}
3855094Slling 
3865094Slling 			if (strval[0] != '/') {
3875094Slling 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3885094Slling 				    "bad alternate root '%s'"), strval);
3895094Slling 				(void) zfs_error(hdl, EZFS_BADPATH, errbuf);
3905094Slling 				goto error;
3915094Slling 			}
3925094Slling 			break;
393*5363Seschrock 
394*5363Seschrock 		case ZPOOL_PROP_CACHEFILE:
395*5363Seschrock 			if (strval[0] == '\0')
396*5363Seschrock 				break;
397*5363Seschrock 
398*5363Seschrock 			if (strcmp(strval, "none") == 0)
399*5363Seschrock 				break;
400*5363Seschrock 
401*5363Seschrock 			if (strval[0] != '/') {
402*5363Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
403*5363Seschrock 				    "property '%s' must be empty, an "
404*5363Seschrock 				    "absolute path, or 'none'"), propname);
405*5363Seschrock 				(void) zfs_error(hdl, EZFS_BADPATH, errbuf);
406*5363Seschrock 				goto error;
407*5363Seschrock 			}
408*5363Seschrock 
409*5363Seschrock 			slash = strrchr(strval, '/');
410*5363Seschrock 
411*5363Seschrock 			if (slash[1] == '\0' || strcmp(slash, "/.") == 0 ||
412*5363Seschrock 			    strcmp(slash, "/..") == 0) {
413*5363Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
414*5363Seschrock 				    "'%s' is not a valid file"), strval);
415*5363Seschrock 				(void) zfs_error(hdl, EZFS_BADPATH, errbuf);
416*5363Seschrock 				goto error;
417*5363Seschrock 			}
418*5363Seschrock 
419*5363Seschrock 			*slash = '\0';
420*5363Seschrock 
421*5363Seschrock 			if (stat64(strval, &statbuf) != 0 ||
422*5363Seschrock 			    !S_ISDIR(statbuf.st_mode)) {
423*5363Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
424*5363Seschrock 				    "'%s' is not a valid directory"),
425*5363Seschrock 				    strval);
426*5363Seschrock 				(void) zfs_error(hdl, EZFS_BADPATH, errbuf);
427*5363Seschrock 				goto error;
428*5363Seschrock 			}
429*5363Seschrock 
430*5363Seschrock 			*slash = '/';
431*5363Seschrock 			break;
4325094Slling 		}
4335094Slling 	}
4345094Slling 
4355094Slling 	return (retprops);
4365094Slling error:
4375094Slling 	nvlist_free(retprops);
4385094Slling 	return (NULL);
4395094Slling }
4405094Slling 
4415094Slling /*
4425094Slling  * Set zpool property : propname=propval.
4435094Slling  */
4445094Slling int
4455094Slling zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval)
4465094Slling {
4475094Slling 	zfs_cmd_t zc = { 0 };
4485094Slling 	int ret = -1;
4495094Slling 	char errbuf[1024];
4505094Slling 	nvlist_t *nvl = NULL;
4515094Slling 	nvlist_t *realprops;
4525094Slling 	uint64_t version;
4535094Slling 
4545094Slling 	(void) snprintf(errbuf, sizeof (errbuf),
4555094Slling 	    dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
4565094Slling 	    zhp->zpool_name);
4575094Slling 
4585094Slling 	if (zhp->zpool_props == NULL && zpool_get_all_props(zhp))
4595094Slling 		return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, errbuf));
4605094Slling 
4615094Slling 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
4625094Slling 		return (no_memory(zhp->zpool_hdl));
4635094Slling 
4645094Slling 	if (nvlist_add_string(nvl, propname, propval) != 0) {
4655094Slling 		nvlist_free(nvl);
4665094Slling 		return (no_memory(zhp->zpool_hdl));
4675094Slling 	}
4685094Slling 
4695094Slling 	version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
4705094Slling 	if ((realprops = zpool_validate_properties(zhp->zpool_hdl,
4715094Slling 	    zhp->zpool_name, nvl, version, B_FALSE, errbuf)) == NULL) {
4725094Slling 		nvlist_free(nvl);
4735094Slling 		return (-1);
4745094Slling 	}
4755094Slling 
4765094Slling 	nvlist_free(nvl);
4775094Slling 	nvl = realprops;
4785094Slling 
4795094Slling 	/*
4805094Slling 	 * Execute the corresponding ioctl() to set this property.
4815094Slling 	 */
4825094Slling 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4835094Slling 
4845094Slling 	if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl) != 0) {
4855094Slling 		nvlist_free(nvl);
4865094Slling 		return (-1);
4875094Slling 	}
4885094Slling 
4895094Slling 	ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SET_PROPS, &zc);
4905094Slling 
4915094Slling 	zcmd_free_nvlists(&zc);
4925094Slling 	nvlist_free(nvl);
4935094Slling 
4945094Slling 	if (ret)
4955094Slling 		(void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf);
4965094Slling 	else
4975094Slling 		(void) zpool_props_refresh(zhp);
4985094Slling 
4995094Slling 	return (ret);
5005094Slling }
5015094Slling 
5025094Slling int
5035094Slling zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
5045094Slling {
5055094Slling 	libzfs_handle_t *hdl = zhp->zpool_hdl;
5065094Slling 	zprop_list_t *entry;
5075094Slling 	char buf[ZFS_MAXPROPLEN];
5085094Slling 
5095094Slling 	if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0)
5105094Slling 		return (-1);
5115094Slling 
5125094Slling 	for (entry = *plp; entry != NULL; entry = entry->pl_next) {
5135094Slling 
5145094Slling 		if (entry->pl_fixed)
5155094Slling 			continue;
5165094Slling 
5175094Slling 		if (entry->pl_prop != ZPROP_INVAL &&
5185094Slling 		    zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf),
5195094Slling 		    NULL) == 0) {
5205094Slling 			if (strlen(buf) > entry->pl_width)
5215094Slling 				entry->pl_width = strlen(buf);
5225094Slling 		}
5235094Slling 	}
5245094Slling 
5255094Slling 	return (0);
5265094Slling }
5275094Slling 
5285094Slling 
529789Sahrens /*
530789Sahrens  * Validate the given pool name, optionally putting an extended error message in
531789Sahrens  * 'buf'.
532789Sahrens  */
5332082Seschrock static boolean_t
5342082Seschrock zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool)
535789Sahrens {
536789Sahrens 	namecheck_err_t why;
537789Sahrens 	char what;
5381773Seschrock 	int ret;
539789Sahrens 
5401773Seschrock 	ret = pool_namecheck(pool, &why, &what);
5411773Seschrock 
5421773Seschrock 	/*
5431773Seschrock 	 * The rules for reserved pool names were extended at a later point.
5441773Seschrock 	 * But we need to support users with existing pools that may now be
5451773Seschrock 	 * invalid.  So we only check for this expanded set of names during a
5461773Seschrock 	 * create (or import), and only in userland.
5471773Seschrock 	 */
5481773Seschrock 	if (ret == 0 && !isopen &&
5491773Seschrock 	    (strncmp(pool, "mirror", 6) == 0 ||
5501773Seschrock 	    strncmp(pool, "raidz", 5) == 0 ||
5514527Sperrin 	    strncmp(pool, "spare", 5) == 0 ||
5524527Sperrin 	    strcmp(pool, "log") == 0)) {
5532082Seschrock 		zfs_error_aux(hdl,
5542082Seschrock 		    dgettext(TEXT_DOMAIN, "name is reserved"));
5552082Seschrock 		return (B_FALSE);
5561773Seschrock 	}
5571773Seschrock 
5581773Seschrock 
5591773Seschrock 	if (ret != 0) {
5602082Seschrock 		if (hdl != NULL) {
561789Sahrens 			switch (why) {
5621003Slling 			case NAME_ERR_TOOLONG:
5632082Seschrock 				zfs_error_aux(hdl,
5641003Slling 				    dgettext(TEXT_DOMAIN, "name is too long"));
5651003Slling 				break;
5661003Slling 
567789Sahrens 			case NAME_ERR_INVALCHAR:
5682082Seschrock 				zfs_error_aux(hdl,
569789Sahrens 				    dgettext(TEXT_DOMAIN, "invalid character "
570789Sahrens 				    "'%c' in pool name"), what);
571789Sahrens 				break;
572789Sahrens 
573789Sahrens 			case NAME_ERR_NOLETTER:
5742082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5752082Seschrock 				    "name must begin with a letter"));
576789Sahrens 				break;
577789Sahrens 
578789Sahrens 			case NAME_ERR_RESERVED:
5792082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5802082Seschrock 				    "name is reserved"));
581789Sahrens 				break;
582789Sahrens 
583789Sahrens 			case NAME_ERR_DISKLIKE:
5842082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5852082Seschrock 				    "pool name is reserved"));
586789Sahrens 				break;
5872856Snd150628 
5882856Snd150628 			case NAME_ERR_LEADING_SLASH:
5892856Snd150628 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5902856Snd150628 				    "leading slash in name"));
5912856Snd150628 				break;
5922856Snd150628 
5932856Snd150628 			case NAME_ERR_EMPTY_COMPONENT:
5942856Snd150628 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5952856Snd150628 				    "empty component in name"));
5962856Snd150628 				break;
5972856Snd150628 
5982856Snd150628 			case NAME_ERR_TRAILING_SLASH:
5992856Snd150628 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
6002856Snd150628 				    "trailing slash in name"));
6012856Snd150628 				break;
6022856Snd150628 
6032856Snd150628 			case NAME_ERR_MULTIPLE_AT:
6042856Snd150628 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
6052856Snd150628 				    "multiple '@' delimiters in name"));
6062856Snd150628 				break;
6072856Snd150628 
608789Sahrens 			}
609789Sahrens 		}
6102082Seschrock 		return (B_FALSE);
611789Sahrens 	}
612789Sahrens 
6132082Seschrock 	return (B_TRUE);
614789Sahrens }
615789Sahrens 
616789Sahrens /*
617789Sahrens  * Open a handle to the given pool, even if the pool is currently in the FAULTED
618789Sahrens  * state.
619789Sahrens  */
620789Sahrens zpool_handle_t *
6212082Seschrock zpool_open_canfail(libzfs_handle_t *hdl, const char *pool)
622789Sahrens {
623789Sahrens 	zpool_handle_t *zhp;
6242142Seschrock 	boolean_t missing;
625789Sahrens 
626789Sahrens 	/*
627789Sahrens 	 * Make sure the pool name is valid.
628789Sahrens 	 */
6292082Seschrock 	if (!zpool_name_valid(hdl, B_TRUE, pool)) {
6303237Slling 		(void) zfs_error_fmt(hdl, EZFS_INVALIDNAME,
6312082Seschrock 		    dgettext(TEXT_DOMAIN, "cannot open '%s'"),
6322082Seschrock 		    pool);
633789Sahrens 		return (NULL);
634789Sahrens 	}
635789Sahrens 
6362082Seschrock 	if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
6372082Seschrock 		return (NULL);
638789Sahrens 
6392082Seschrock 	zhp->zpool_hdl = hdl;
640789Sahrens 	(void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
641789Sahrens 
6422142Seschrock 	if (zpool_refresh_stats(zhp, &missing) != 0) {
6432142Seschrock 		zpool_close(zhp);
6442142Seschrock 		return (NULL);
6452142Seschrock 	}
6462142Seschrock 
6472142Seschrock 	if (missing) {
6485094Slling 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "no such pool"));
6493237Slling 		(void) zfs_error_fmt(hdl, EZFS_NOENT,
6505094Slling 		    dgettext(TEXT_DOMAIN, "cannot open '%s'"), pool);
6512142Seschrock 		zpool_close(zhp);
6522142Seschrock 		return (NULL);
653789Sahrens 	}
654789Sahrens 
655789Sahrens 	return (zhp);
656789Sahrens }
657789Sahrens 
658789Sahrens /*
659789Sahrens  * Like the above, but silent on error.  Used when iterating over pools (because
660789Sahrens  * the configuration cache may be out of date).
661789Sahrens  */
6622142Seschrock int
6632142Seschrock zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret)
664789Sahrens {
665789Sahrens 	zpool_handle_t *zhp;
6662142Seschrock 	boolean_t missing;
667789Sahrens 
6682142Seschrock 	if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
6692142Seschrock 		return (-1);
670789Sahrens 
6712082Seschrock 	zhp->zpool_hdl = hdl;
672789Sahrens 	(void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
673789Sahrens 
6742142Seschrock 	if (zpool_refresh_stats(zhp, &missing) != 0) {
6752142Seschrock 		zpool_close(zhp);
6762142Seschrock 		return (-1);
677789Sahrens 	}
678789Sahrens 
6792142Seschrock 	if (missing) {
6802142Seschrock 		zpool_close(zhp);
6812142Seschrock 		*ret = NULL;
6822142Seschrock 		return (0);
6832142Seschrock 	}
6842142Seschrock 
6852142Seschrock 	*ret = zhp;
6862142Seschrock 	return (0);
687789Sahrens }
688789Sahrens 
689789Sahrens /*
690789Sahrens  * Similar to zpool_open_canfail(), but refuses to open pools in the faulted
691789Sahrens  * state.
692789Sahrens  */
693789Sahrens zpool_handle_t *
6942082Seschrock zpool_open(libzfs_handle_t *hdl, const char *pool)
695789Sahrens {
696789Sahrens 	zpool_handle_t *zhp;
697789Sahrens 
6982082Seschrock 	if ((zhp = zpool_open_canfail(hdl, pool)) == NULL)
699789Sahrens 		return (NULL);
700789Sahrens 
701789Sahrens 	if (zhp->zpool_state == POOL_STATE_UNAVAIL) {
7023237Slling 		(void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL,
7032082Seschrock 		    dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name);
704789Sahrens 		zpool_close(zhp);
705789Sahrens 		return (NULL);
706789Sahrens 	}
707789Sahrens 
708789Sahrens 	return (zhp);
709789Sahrens }
710789Sahrens 
711789Sahrens /*
712789Sahrens  * Close the handle.  Simply frees the memory associated with the handle.
713789Sahrens  */
714789Sahrens void
715789Sahrens zpool_close(zpool_handle_t *zhp)
716789Sahrens {
717789Sahrens 	if (zhp->zpool_config)
718789Sahrens 		nvlist_free(zhp->zpool_config);
719952Seschrock 	if (zhp->zpool_old_config)
720952Seschrock 		nvlist_free(zhp->zpool_old_config);
7213912Slling 	if (zhp->zpool_props)
7223912Slling 		nvlist_free(zhp->zpool_props);
723789Sahrens 	free(zhp);
724789Sahrens }
725789Sahrens 
726789Sahrens /*
727789Sahrens  * Return the name of the pool.
728789Sahrens  */
729789Sahrens const char *
730789Sahrens zpool_get_name(zpool_handle_t *zhp)
731789Sahrens {
732789Sahrens 	return (zhp->zpool_name);
733789Sahrens }
734789Sahrens 
735789Sahrens 
736789Sahrens /*
737789Sahrens  * Return the state of the pool (ACTIVE or UNAVAILABLE)
738789Sahrens  */
739789Sahrens int
740789Sahrens zpool_get_state(zpool_handle_t *zhp)
741789Sahrens {
742789Sahrens 	return (zhp->zpool_state);
743789Sahrens }
744789Sahrens 
745789Sahrens /*
746789Sahrens  * Create the named pool, using the provided vdev list.  It is assumed
747789Sahrens  * that the consumer has already validated the contents of the nvlist, so we
748789Sahrens  * don't have to worry about error semantics.
749789Sahrens  */
750789Sahrens int
7512082Seschrock zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
7525094Slling     nvlist_t *props)
753789Sahrens {
754789Sahrens 	zfs_cmd_t zc = { 0 };
7552082Seschrock 	char msg[1024];
7565094Slling 	char *altroot;
7572082Seschrock 
7582082Seschrock 	(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
7592082Seschrock 	    "cannot create '%s'"), pool);
760789Sahrens 
7612082Seschrock 	if (!zpool_name_valid(hdl, B_FALSE, pool))
7622082Seschrock 		return (zfs_error(hdl, EZFS_INVALIDNAME, msg));
7632082Seschrock 
7645320Slling 	if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
7655320Slling 		return (-1);
7665320Slling 
7675094Slling 	if (props && (props = zpool_validate_properties(hdl, pool, props,
7685094Slling 	    SPA_VERSION_1, B_TRUE, msg)) == NULL)
7695094Slling 		return (-1);
7705094Slling 
7715320Slling 	if (props && zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
7725320Slling 		nvlist_free(props);
7735094Slling 		return (-1);
7745320Slling 	}
775789Sahrens 
776789Sahrens 	(void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name));
777789Sahrens 
7784543Smarks 	if (zfs_ioctl(hdl, ZFS_IOC_POOL_CREATE, &zc) != 0) {
7795320Slling 
7802676Seschrock 		zcmd_free_nvlists(&zc);
7815320Slling 		nvlist_free(props);
7822082Seschrock 
783789Sahrens 		switch (errno) {
784789Sahrens 		case EBUSY:
785789Sahrens 			/*
786789Sahrens 			 * This can happen if the user has specified the same
787789Sahrens 			 * device multiple times.  We can't reliably detect this
788789Sahrens 			 * until we try to add it and see we already have a
789789Sahrens 			 * label.
790789Sahrens 			 */
7912082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
7922082Seschrock 			    "one or more vdevs refer to the same device"));
7932082Seschrock 			return (zfs_error(hdl, EZFS_BADDEV, msg));
794789Sahrens 
795789Sahrens 		case EOVERFLOW:
796789Sahrens 			/*
7972082Seschrock 			 * This occurs when one of the devices is below
798789Sahrens 			 * SPA_MINDEVSIZE.  Unfortunately, we can't detect which
799789Sahrens 			 * device was the problem device since there's no
800789Sahrens 			 * reliable way to determine device size from userland.
801789Sahrens 			 */
802789Sahrens 			{
803789Sahrens 				char buf[64];
804789Sahrens 
805789Sahrens 				zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
806789Sahrens 
8072082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
8082082Seschrock 				    "one or more devices is less than the "
8092082Seschrock 				    "minimum size (%s)"), buf);
810789Sahrens 			}
8112082Seschrock 			return (zfs_error(hdl, EZFS_BADDEV, msg));
812789Sahrens 
813789Sahrens 		case ENOSPC:
8142082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
8152082Seschrock 			    "one or more devices is out of space"));
8162082Seschrock 			return (zfs_error(hdl, EZFS_BADDEV, msg));
817789Sahrens 
818789Sahrens 		default:
8192082Seschrock 			return (zpool_standard_error(hdl, errno, msg));
820789Sahrens 		}
821789Sahrens 	}
822789Sahrens 
823789Sahrens 	/*
824789Sahrens 	 * If this is an alternate root pool, then we automatically set the
8252676Seschrock 	 * mountpoint of the root dataset to be '/'.
826789Sahrens 	 */
8275094Slling 	if (nvlist_lookup_string(props, zpool_prop_to_name(ZPOOL_PROP_ALTROOT),
8285094Slling 	    &altroot) == 0) {
829789Sahrens 		zfs_handle_t *zhp;
830789Sahrens 
8315094Slling 		verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_DATASET)) != NULL);
8322676Seschrock 		verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
8332676Seschrock 		    "/") == 0);
834789Sahrens 
835789Sahrens 		zfs_close(zhp);
836789Sahrens 	}
837789Sahrens 
8385320Slling 	zcmd_free_nvlists(&zc);
8395320Slling 	nvlist_free(props);
840789Sahrens 	return (0);
841789Sahrens }
842789Sahrens 
843789Sahrens /*
844789Sahrens  * Destroy the given pool.  It is up to the caller to ensure that there are no
845789Sahrens  * datasets left in the pool.
846789Sahrens  */
847789Sahrens int
848789Sahrens zpool_destroy(zpool_handle_t *zhp)
849789Sahrens {
850789Sahrens 	zfs_cmd_t zc = { 0 };
851789Sahrens 	zfs_handle_t *zfp = NULL;
8522082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
8532082Seschrock 	char msg[1024];
854789Sahrens 
855789Sahrens 	if (zhp->zpool_state == POOL_STATE_ACTIVE &&
8562082Seschrock 	    (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name,
8572082Seschrock 	    ZFS_TYPE_FILESYSTEM)) == NULL)
858789Sahrens 		return (-1);
859789Sahrens 
8602856Snd150628 	if (zpool_remove_zvol_links(zhp) != 0)
861789Sahrens 		return (-1);
862789Sahrens 
863789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
864789Sahrens 
8654543Smarks 	if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
8662082Seschrock 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
8672082Seschrock 		    "cannot destroy '%s'"), zhp->zpool_name);
868789Sahrens 
8692082Seschrock 		if (errno == EROFS) {
8702082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
8712082Seschrock 			    "one or more devices is read only"));
8722082Seschrock 			(void) zfs_error(hdl, EZFS_BADDEV, msg);
8732082Seschrock 		} else {
8742082Seschrock 			(void) zpool_standard_error(hdl, errno, msg);
875789Sahrens 		}
876789Sahrens 
877789Sahrens 		if (zfp)
878789Sahrens 			zfs_close(zfp);
879789Sahrens 		return (-1);
880789Sahrens 	}
881789Sahrens 
882789Sahrens 	if (zfp) {
883789Sahrens 		remove_mountpoint(zfp);
884789Sahrens 		zfs_close(zfp);
885789Sahrens 	}
886789Sahrens 
887789Sahrens 	return (0);
888789Sahrens }
889789Sahrens 
890789Sahrens /*
891789Sahrens  * Add the given vdevs to the pool.  The caller must have already performed the
892789Sahrens  * necessary verification to ensure that the vdev specification is well-formed.
893789Sahrens  */
894789Sahrens int
895789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
896789Sahrens {
8972676Seschrock 	zfs_cmd_t zc = { 0 };
8982082Seschrock 	int ret;
8992082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
9002082Seschrock 	char msg[1024];
9012082Seschrock 	nvlist_t **spares;
9022082Seschrock 	uint_t nspares;
9032082Seschrock 
9042082Seschrock 	(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
9052082Seschrock 	    "cannot add to '%s'"), zhp->zpool_name);
9062082Seschrock 
9075094Slling 	if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL)
9085094Slling 	    < SPA_VERSION_SPARES &&
9092082Seschrock 	    nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
9102082Seschrock 	    &spares, &nspares) == 0) {
9112082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
9122082Seschrock 		    "upgraded to add hot spares"));
9132082Seschrock 		return (zfs_error(hdl, EZFS_BADVERSION, msg));
9142082Seschrock 	}
915789Sahrens 
9165094Slling 	if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
9172082Seschrock 		return (-1);
918789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
919789Sahrens 
9204543Smarks 	if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_ADD, &zc) != 0) {
921789Sahrens 		switch (errno) {
922789Sahrens 		case EBUSY:
923789Sahrens 			/*
924789Sahrens 			 * This can happen if the user has specified the same
925789Sahrens 			 * device multiple times.  We can't reliably detect this
926789Sahrens 			 * until we try to add it and see we already have a
927789Sahrens 			 * label.
928789Sahrens 			 */
9292082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
9302082Seschrock 			    "one or more vdevs refer to the same device"));
9312082Seschrock 			(void) zfs_error(hdl, EZFS_BADDEV, msg);
932789Sahrens 			break;
933789Sahrens 
934789Sahrens 		case EOVERFLOW:
935789Sahrens 			/*
936789Sahrens 			 * This occurrs when one of the devices is below
937789Sahrens 			 * SPA_MINDEVSIZE.  Unfortunately, we can't detect which
938789Sahrens 			 * device was the problem device since there's no
939789Sahrens 			 * reliable way to determine device size from userland.
940789Sahrens 			 */
941789Sahrens 			{
942789Sahrens 				char buf[64];
943789Sahrens 
944789Sahrens 				zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
945789Sahrens 
9462082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
9472082Seschrock 				    "device is less than the minimum "
9482082Seschrock 				    "size (%s)"), buf);
949789Sahrens 			}
9502082Seschrock 			(void) zfs_error(hdl, EZFS_BADDEV, msg);
9512082Seschrock 			break;
9522082Seschrock 
9532082Seschrock 		case ENOTSUP:
9542082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
9554527Sperrin 			    "pool must be upgraded to add these vdevs"));
9562082Seschrock 			(void) zfs_error(hdl, EZFS_BADVERSION, msg);
957789Sahrens 			break;
958789Sahrens 
9593912Slling 		case EDOM:
9603912Slling 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
9614527Sperrin 			    "root pool can not have multiple vdevs"
9624527Sperrin 			    " or separate logs"));
9633912Slling 			(void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg);
9643912Slling 			break;
9653912Slling 
966789Sahrens 		default:
9672082Seschrock 			(void) zpool_standard_error(hdl, errno, msg);
968789Sahrens 		}
969789Sahrens 
9702082Seschrock 		ret = -1;
9712082Seschrock 	} else {
9722082Seschrock 		ret = 0;
973789Sahrens 	}
974789Sahrens 
9752676Seschrock 	zcmd_free_nvlists(&zc);
976789Sahrens 
9772082Seschrock 	return (ret);
978789Sahrens }
979789Sahrens 
980789Sahrens /*
981789Sahrens  * Exports the pool from the system.  The caller must ensure that there are no
982789Sahrens  * mounted datasets in the pool.
983789Sahrens  */
984789Sahrens int
985789Sahrens zpool_export(zpool_handle_t *zhp)
986789Sahrens {
987789Sahrens 	zfs_cmd_t zc = { 0 };
988789Sahrens 
989789Sahrens 	if (zpool_remove_zvol_links(zhp) != 0)
990789Sahrens 		return (-1);
991789Sahrens 
992789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
993789Sahrens 
9944543Smarks 	if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0)
9953237Slling 		return (zpool_standard_error_fmt(zhp->zpool_hdl, errno,
9962082Seschrock 		    dgettext(TEXT_DOMAIN, "cannot export '%s'"),
9972082Seschrock 		    zhp->zpool_name));
998789Sahrens 	return (0);
999789Sahrens }
1000789Sahrens 
1001789Sahrens /*
10025094Slling  * zpool_import() is a contracted interface. Should be kept the same
10035094Slling  * if possible.
10045094Slling  *
10055094Slling  * Applications should use zpool_import_props() to import a pool with
10065094Slling  * new properties value to be set.
1007789Sahrens  */
1008789Sahrens int
10092082Seschrock zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
10105094Slling     char *altroot)
10115094Slling {
10125094Slling 	nvlist_t *props = NULL;
10135094Slling 	int ret;
10145094Slling 
10155094Slling 	if (altroot != NULL) {
10165094Slling 		if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
10175094Slling 			return (zfs_error_fmt(hdl, EZFS_NOMEM,
10185094Slling 			    dgettext(TEXT_DOMAIN, "cannot import '%s'"),
10195094Slling 			    newname));
10205094Slling 		}
10215094Slling 
10225094Slling 		if (nvlist_add_string(props,
10235094Slling 		    zpool_prop_to_name(ZPOOL_PROP_ALTROOT), altroot) != 0) {
10245094Slling 			nvlist_free(props);
10255094Slling 			return (zfs_error_fmt(hdl, EZFS_NOMEM,
10265094Slling 			    dgettext(TEXT_DOMAIN, "cannot import '%s'"),
10275094Slling 			    newname));
10285094Slling 		}
10295094Slling 	}
10305094Slling 
10315094Slling 	ret = zpool_import_props(hdl, config, newname, props);
10325094Slling 	if (props)
10335094Slling 		nvlist_free(props);
10345094Slling 	return (ret);
10355094Slling }
10365094Slling 
10375094Slling /*
10385094Slling  * Import the given pool using the known configuration and a list of
10395094Slling  * properties to be set. The configuration should have come from
10405094Slling  * zpool_find_import(). The 'newname' parameters control whether the pool
10415094Slling  * is imported with a different name.
10425094Slling  */
10435094Slling int
10445094Slling zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
10455094Slling     nvlist_t *props)
1046789Sahrens {
10472676Seschrock 	zfs_cmd_t zc = { 0 };
1048789Sahrens 	char *thename;
1049789Sahrens 	char *origname;
1050789Sahrens 	int ret;
10515094Slling 	char errbuf[1024];
1052789Sahrens 
1053789Sahrens 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1054789Sahrens 	    &origname) == 0);
1055789Sahrens 
10565094Slling 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
10575094Slling 	    "cannot import pool '%s'"), origname);
10585094Slling 
1059789Sahrens 	if (newname != NULL) {
10602082Seschrock 		if (!zpool_name_valid(hdl, B_FALSE, newname))
10613237Slling 			return (zfs_error_fmt(hdl, EZFS_INVALIDNAME,
10622082Seschrock 			    dgettext(TEXT_DOMAIN, "cannot import '%s'"),
10632082Seschrock 			    newname));
1064789Sahrens 		thename = (char *)newname;
1065789Sahrens 	} else {
1066789Sahrens 		thename = origname;
1067789Sahrens 	}
1068789Sahrens 
10695094Slling 	if (props) {
10705094Slling 		uint64_t version;
10715094Slling 
10725094Slling 		verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
10735094Slling 		    &version) == 0);
10745094Slling 
10755094Slling 		if ((props = zpool_validate_properties(hdl, origname,
10765320Slling 		    props, version, B_TRUE, errbuf)) == NULL) {
10775094Slling 			return (-1);
10785320Slling 		} else if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
10795320Slling 			nvlist_free(props);
10805094Slling 			return (-1);
10815320Slling 		}
10825094Slling 	}
1083789Sahrens 
1084789Sahrens 	(void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name));
1085789Sahrens 
1086789Sahrens 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
10871544Seschrock 	    &zc.zc_guid) == 0);
1088789Sahrens 
10895320Slling 	if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0) {
10905320Slling 		nvlist_free(props);
10912082Seschrock 		return (-1);
10925320Slling 	}
1093789Sahrens 
1094789Sahrens 	ret = 0;
10954543Smarks 	if (zfs_ioctl(hdl, ZFS_IOC_POOL_IMPORT, &zc) != 0) {
1096789Sahrens 		char desc[1024];
1097789Sahrens 		if (newname == NULL)
1098789Sahrens 			(void) snprintf(desc, sizeof (desc),
1099789Sahrens 			    dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1100789Sahrens 			    thename);
1101789Sahrens 		else
1102789Sahrens 			(void) snprintf(desc, sizeof (desc),
1103789Sahrens 			    dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"),
1104789Sahrens 			    origname, thename);
1105789Sahrens 
1106789Sahrens 		switch (errno) {
11071544Seschrock 		case ENOTSUP:
11081544Seschrock 			/*
11091544Seschrock 			 * Unsupported version.
11101544Seschrock 			 */
11112082Seschrock 			(void) zfs_error(hdl, EZFS_BADVERSION, desc);
11121544Seschrock 			break;
11131544Seschrock 
11142174Seschrock 		case EINVAL:
11152174Seschrock 			(void) zfs_error(hdl, EZFS_INVALCONFIG, desc);
11162174Seschrock 			break;
11172174Seschrock 
1118789Sahrens 		default:
11192082Seschrock 			(void) zpool_standard_error(hdl, errno, desc);
1120789Sahrens 		}
1121789Sahrens 
1122789Sahrens 		ret = -1;
1123789Sahrens 	} else {
1124789Sahrens 		zpool_handle_t *zhp;
11254543Smarks 
1126789Sahrens 		/*
1127789Sahrens 		 * This should never fail, but play it safe anyway.
1128789Sahrens 		 */
11292142Seschrock 		if (zpool_open_silent(hdl, thename, &zhp) != 0) {
11302142Seschrock 			ret = -1;
11312142Seschrock 		} else if (zhp != NULL) {
1132789Sahrens 			ret = zpool_create_zvol_links(zhp);
1133789Sahrens 			zpool_close(zhp);
1134789Sahrens 		}
11354543Smarks 
1136789Sahrens 	}
1137789Sahrens 
11382676Seschrock 	zcmd_free_nvlists(&zc);
11395320Slling 	nvlist_free(props);
11405320Slling 
1141789Sahrens 	return (ret);
1142789Sahrens }
1143789Sahrens 
1144789Sahrens /*
1145789Sahrens  * Scrub the pool.
1146789Sahrens  */
1147789Sahrens int
1148789Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type)
1149789Sahrens {
1150789Sahrens 	zfs_cmd_t zc = { 0 };
1151789Sahrens 	char msg[1024];
11522082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1153789Sahrens 
1154789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1155789Sahrens 	zc.zc_cookie = type;
1156789Sahrens 
11574543Smarks 	if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SCRUB, &zc) == 0)
1158789Sahrens 		return (0);
1159789Sahrens 
1160789Sahrens 	(void) snprintf(msg, sizeof (msg),
1161789Sahrens 	    dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name);
1162789Sahrens 
11632082Seschrock 	if (errno == EBUSY)
11642082Seschrock 		return (zfs_error(hdl, EZFS_RESILVERING, msg));
11652082Seschrock 	else
11662082Seschrock 		return (zpool_standard_error(hdl, errno, msg));
1167789Sahrens }
1168789Sahrens 
11692468Sek110237 /*
11702468Sek110237  * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL
11712468Sek110237  * spare; but FALSE if its an INUSE spare.
11722468Sek110237  */
11732082Seschrock static nvlist_t *
11742082Seschrock vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid,
11752468Sek110237     boolean_t *avail_spare)
11761544Seschrock {
11771544Seschrock 	uint_t c, children;
11781544Seschrock 	nvlist_t **child;
11792082Seschrock 	uint64_t theguid, present;
11801544Seschrock 	char *path;
11811544Seschrock 	uint64_t wholedisk = 0;
11822082Seschrock 	nvlist_t *ret;
11831544Seschrock 
11842082Seschrock 	verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0);
11851544Seschrock 
11861544Seschrock 	if (search == NULL &&
11871544Seschrock 	    nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) {
11881544Seschrock 		/*
11891544Seschrock 		 * If the device has never been present since import, the only
11901544Seschrock 		 * reliable way to match the vdev is by GUID.
11911544Seschrock 		 */
11922082Seschrock 		if (theguid == guid)
11932082Seschrock 			return (nv);
11941544Seschrock 	} else if (search != NULL &&
11951544Seschrock 	    nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
11961544Seschrock 		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
11971544Seschrock 		    &wholedisk);
11981544Seschrock 		if (wholedisk) {
11991544Seschrock 			/*
12001544Seschrock 			 * For whole disks, the internal path has 's0', but the
12011544Seschrock 			 * path passed in by the user doesn't.
12021544Seschrock 			 */
12031544Seschrock 			if (strlen(search) == strlen(path) - 2 &&
12041544Seschrock 			    strncmp(search, path, strlen(search)) == 0)
12052082Seschrock 				return (nv);
12061544Seschrock 		} else if (strcmp(search, path) == 0) {
12072082Seschrock 			return (nv);
12081544Seschrock 		}
12091544Seschrock 	}
12101544Seschrock 
12111544Seschrock 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
12121544Seschrock 	    &child, &children) != 0)
12132082Seschrock 		return (NULL);
12141544Seschrock 
12151544Seschrock 	for (c = 0; c < children; c++)
12162082Seschrock 		if ((ret = vdev_to_nvlist_iter(child[c], search, guid,
12172468Sek110237 		    avail_spare)) != NULL)
12181544Seschrock 			return (ret);
12191544Seschrock 
12202082Seschrock 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
12212082Seschrock 	    &child, &children) == 0) {
12222082Seschrock 		for (c = 0; c < children; c++) {
12232082Seschrock 			if ((ret = vdev_to_nvlist_iter(child[c], search, guid,
12242468Sek110237 			    avail_spare)) != NULL) {
12252468Sek110237 				*avail_spare = B_TRUE;
12262082Seschrock 				return (ret);
12272082Seschrock 			}
12282082Seschrock 		}
12292082Seschrock 	}
12302082Seschrock 
12312082Seschrock 	return (NULL);
12321544Seschrock }
12331544Seschrock 
12342082Seschrock nvlist_t *
12352468Sek110237 zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare)
12361544Seschrock {
12371544Seschrock 	char buf[MAXPATHLEN];
12381544Seschrock 	const char *search;
12391544Seschrock 	char *end;
12401544Seschrock 	nvlist_t *nvroot;
12411544Seschrock 	uint64_t guid;
12421544Seschrock 
12431613Seschrock 	guid = strtoull(path, &end, 10);
12441544Seschrock 	if (guid != 0 && *end == '\0') {
12451544Seschrock 		search = NULL;
12461544Seschrock 	} else if (path[0] != '/') {
12471544Seschrock 		(void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path);
12481544Seschrock 		search = buf;
12491544Seschrock 	} else {
12501544Seschrock 		search = path;
12511544Seschrock 	}
12521544Seschrock 
12531544Seschrock 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
12541544Seschrock 	    &nvroot) == 0);
12551544Seschrock 
12562468Sek110237 	*avail_spare = B_FALSE;
12572468Sek110237 	return (vdev_to_nvlist_iter(nvroot, search, guid, avail_spare));
12582468Sek110237 }
12592468Sek110237 
12602468Sek110237 /*
12612468Sek110237  * Returns TRUE if the given guid corresponds to a spare (INUSE or not).
12622468Sek110237  */
12632468Sek110237 static boolean_t
12642468Sek110237 is_spare(zpool_handle_t *zhp, uint64_t guid)
12652468Sek110237 {
12662468Sek110237 	uint64_t spare_guid;
12672468Sek110237 	nvlist_t *nvroot;
12682468Sek110237 	nvlist_t **spares;
12692468Sek110237 	uint_t nspares;
12702468Sek110237 	int i;
12712468Sek110237 
12722468Sek110237 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
12732468Sek110237 	    &nvroot) == 0);
12742468Sek110237 	if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
12752468Sek110237 	    &spares, &nspares) == 0) {
12762468Sek110237 		for (i = 0; i < nspares; i++) {
12772468Sek110237 			verify(nvlist_lookup_uint64(spares[i],
12782468Sek110237 			    ZPOOL_CONFIG_GUID, &spare_guid) == 0);
12792468Sek110237 			if (guid == spare_guid)
12802468Sek110237 				return (B_TRUE);
12812468Sek110237 		}
12822468Sek110237 	}
12832468Sek110237 
12842468Sek110237 	return (B_FALSE);
12851544Seschrock }
12861544Seschrock 
1287789Sahrens /*
12884451Seschrock  * Bring the specified vdev online.   The 'flags' parameter is a set of the
12894451Seschrock  * ZFS_ONLINE_* flags.
1290789Sahrens  */
1291789Sahrens int
12924451Seschrock zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
12934451Seschrock     vdev_state_t *newstate)
1294789Sahrens {
1295789Sahrens 	zfs_cmd_t zc = { 0 };
1296789Sahrens 	char msg[1024];
12972082Seschrock 	nvlist_t *tgt;
12982468Sek110237 	boolean_t avail_spare;
12992082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1300789Sahrens 
13011544Seschrock 	(void) snprintf(msg, sizeof (msg),
13021544Seschrock 	    dgettext(TEXT_DOMAIN, "cannot online %s"), path);
1303789Sahrens 
13041544Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
13052468Sek110237 	if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL)
13062082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
1307789Sahrens 
13082468Sek110237 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
13092468Sek110237 
13102468Sek110237 	if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE)
13112082Seschrock 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
13122082Seschrock 
13134451Seschrock 	zc.zc_cookie = VDEV_STATE_ONLINE;
13144451Seschrock 	zc.zc_obj = flags;
13154451Seschrock 
1316789Sahrens 
13174543Smarks 	if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_SET_STATE, &zc) != 0)
13184451Seschrock 		return (zpool_standard_error(hdl, errno, msg));
13194451Seschrock 
13204451Seschrock 	*newstate = zc.zc_cookie;
13214451Seschrock 	return (0);
1322789Sahrens }
1323789Sahrens 
1324789Sahrens /*
1325789Sahrens  * Take the specified vdev offline
1326789Sahrens  */
1327789Sahrens int
13284451Seschrock zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
1329789Sahrens {
1330789Sahrens 	zfs_cmd_t zc = { 0 };
1331789Sahrens 	char msg[1024];
13322082Seschrock 	nvlist_t *tgt;
13332468Sek110237 	boolean_t avail_spare;
13342082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1335789Sahrens 
13361544Seschrock 	(void) snprintf(msg, sizeof (msg),
13371544Seschrock 	    dgettext(TEXT_DOMAIN, "cannot offline %s"), path);
13381544Seschrock 
1339789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
13402468Sek110237 	if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL)
13412082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
13422082Seschrock 
13432468Sek110237 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
13442468Sek110237 
13452468Sek110237 	if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE)
13462082Seschrock 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
13472082Seschrock 
13484451Seschrock 	zc.zc_cookie = VDEV_STATE_OFFLINE;
13494451Seschrock 	zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0;
13501485Slling 
13514543Smarks 	if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
1352789Sahrens 		return (0);
1353789Sahrens 
1354789Sahrens 	switch (errno) {
13552082Seschrock 	case EBUSY:
1356789Sahrens 
1357789Sahrens 		/*
1358789Sahrens 		 * There are no other replicas of this device.
1359789Sahrens 		 */
13602082Seschrock 		return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
13612082Seschrock 
13622082Seschrock 	default:
13632082Seschrock 		return (zpool_standard_error(hdl, errno, msg));
13642082Seschrock 	}
13652082Seschrock }
1366789Sahrens 
13672082Seschrock /*
13684451Seschrock  * Mark the given vdev faulted.
13694451Seschrock  */
13704451Seschrock int
13714451Seschrock zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid)
13724451Seschrock {
13734451Seschrock 	zfs_cmd_t zc = { 0 };
13744451Seschrock 	char msg[1024];
13754451Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
13764451Seschrock 
13774451Seschrock 	(void) snprintf(msg, sizeof (msg),
13784451Seschrock 	    dgettext(TEXT_DOMAIN, "cannot fault %llu"), guid);
13794451Seschrock 
13804451Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
13814451Seschrock 	zc.zc_guid = guid;
13824451Seschrock 	zc.zc_cookie = VDEV_STATE_FAULTED;
13834451Seschrock 
13844451Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
13854451Seschrock 		return (0);
13864451Seschrock 
13874451Seschrock 	switch (errno) {
13884451Seschrock 	case EBUSY:
13894451Seschrock 
13904451Seschrock 		/*
13914451Seschrock 		 * There are no other replicas of this device.
13924451Seschrock 		 */
13934451Seschrock 		return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
13944451Seschrock 
13954451Seschrock 	default:
13964451Seschrock 		return (zpool_standard_error(hdl, errno, msg));
13974451Seschrock 	}
13984451Seschrock 
13994451Seschrock }
14004451Seschrock 
14014451Seschrock /*
14024451Seschrock  * Mark the given vdev degraded.
14034451Seschrock  */
14044451Seschrock int
14054451Seschrock zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid)
14064451Seschrock {
14074451Seschrock 	zfs_cmd_t zc = { 0 };
14084451Seschrock 	char msg[1024];
14094451Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
14104451Seschrock 
14114451Seschrock 	(void) snprintf(msg, sizeof (msg),
14124451Seschrock 	    dgettext(TEXT_DOMAIN, "cannot degrade %llu"), guid);
14134451Seschrock 
14144451Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
14154451Seschrock 	zc.zc_guid = guid;
14164451Seschrock 	zc.zc_cookie = VDEV_STATE_DEGRADED;
14174451Seschrock 
14184451Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
14194451Seschrock 		return (0);
14204451Seschrock 
14214451Seschrock 	return (zpool_standard_error(hdl, errno, msg));
14224451Seschrock }
14234451Seschrock 
14244451Seschrock /*
14252082Seschrock  * Returns TRUE if the given nvlist is a vdev that was originally swapped in as
14262082Seschrock  * a hot spare.
14272082Seschrock  */
14282082Seschrock static boolean_t
14292082Seschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which)
14302082Seschrock {
14312082Seschrock 	nvlist_t **child;
14322082Seschrock 	uint_t c, children;
14332082Seschrock 	char *type;
14342082Seschrock 
14352082Seschrock 	if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child,
14362082Seschrock 	    &children) == 0) {
14372082Seschrock 		verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE,
14382082Seschrock 		    &type) == 0);
14392082Seschrock 
14402082Seschrock 		if (strcmp(type, VDEV_TYPE_SPARE) == 0 &&
14412082Seschrock 		    children == 2 && child[which] == tgt)
14422082Seschrock 			return (B_TRUE);
14432082Seschrock 
14442082Seschrock 		for (c = 0; c < children; c++)
14452082Seschrock 			if (is_replacing_spare(child[c], tgt, which))
14462082Seschrock 				return (B_TRUE);
1447789Sahrens 	}
14482082Seschrock 
14492082Seschrock 	return (B_FALSE);
1450789Sahrens }
1451789Sahrens 
1452789Sahrens /*
1453789Sahrens  * Attach new_disk (fully described by nvroot) to old_disk.
14544527Sperrin  * If 'replacing' is specified, the new disk will replace the old one.
1455789Sahrens  */
1456789Sahrens int
1457789Sahrens zpool_vdev_attach(zpool_handle_t *zhp,
1458789Sahrens     const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing)
1459789Sahrens {
1460789Sahrens 	zfs_cmd_t zc = { 0 };
1461789Sahrens 	char msg[1024];
1462789Sahrens 	int ret;
14632082Seschrock 	nvlist_t *tgt;
14642468Sek110237 	boolean_t avail_spare;
14654527Sperrin 	uint64_t val, is_log;
14662082Seschrock 	char *path;
14672082Seschrock 	nvlist_t **child;
14682082Seschrock 	uint_t children;
14692082Seschrock 	nvlist_t *config_root;
14702082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1471789Sahrens 
14721544Seschrock 	if (replacing)
14731544Seschrock 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
14741544Seschrock 		    "cannot replace %s with %s"), old_disk, new_disk);
14751544Seschrock 	else
14761544Seschrock 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
14771544Seschrock 		    "cannot attach %s to %s"), new_disk, old_disk);
14781544Seschrock 
1479789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
14802468Sek110237 	if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare)) == 0)
14812082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
14822082Seschrock 
14832468Sek110237 	if (avail_spare)
14842082Seschrock 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
14852082Seschrock 
14862082Seschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
14872082Seschrock 	zc.zc_cookie = replacing;
14882082Seschrock 
14892082Seschrock 	if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
14902082Seschrock 	    &child, &children) != 0 || children != 1) {
14912082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
14922082Seschrock 		    "new device must be a single disk"));
14932082Seschrock 		return (zfs_error(hdl, EZFS_INVALCONFIG, msg));
14941544Seschrock 	}
14952082Seschrock 
14962082Seschrock 	verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
14972082Seschrock 	    ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0);
14982082Seschrock 
14992082Seschrock 	/*
15002082Seschrock 	 * If the target is a hot spare that has been swapped in, we can only
15012082Seschrock 	 * replace it with another hot spare.
15022082Seschrock 	 */
15032082Seschrock 	if (replacing &&
15042082Seschrock 	    nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 &&
15052082Seschrock 	    nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 &&
15062468Sek110237 	    (zpool_find_vdev(zhp, path, &avail_spare) == NULL ||
15072468Sek110237 	    !avail_spare) && is_replacing_spare(config_root, tgt, 1)) {
15082082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
15092082Seschrock 		    "can only be replaced by another hot spare"));
15102082Seschrock 		return (zfs_error(hdl, EZFS_BADTARGET, msg));
15112082Seschrock 	}
15122082Seschrock 
15132082Seschrock 	/*
15142082Seschrock 	 * If we are attempting to replace a spare, it canot be applied to an
15152082Seschrock 	 * already spared device.
15162082Seschrock 	 */
15172082Seschrock 	if (replacing &&
15182082Seschrock 	    nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 &&
15192468Sek110237 	    zpool_find_vdev(zhp, path, &avail_spare) != NULL && avail_spare &&
15202082Seschrock 	    is_replacing_spare(config_root, tgt, 0)) {
15212082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
15222082Seschrock 		    "device has already been replaced with a spare"));
15232082Seschrock 		return (zfs_error(hdl, EZFS_BADTARGET, msg));
15242082Seschrock 	}
1525789Sahrens 
15265094Slling 	if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
15272082Seschrock 		return (-1);
1528789Sahrens 
15294543Smarks 	ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_ATTACH, &zc);
1530789Sahrens 
15312676Seschrock 	zcmd_free_nvlists(&zc);
1532789Sahrens 
1533789Sahrens 	if (ret == 0)
1534789Sahrens 		return (0);
1535789Sahrens 
1536789Sahrens 	switch (errno) {
15371544Seschrock 	case ENOTSUP:
1538789Sahrens 		/*
1539789Sahrens 		 * Can't attach to or replace this type of vdev.
1540789Sahrens 		 */
15414527Sperrin 		if (replacing) {
15424527Sperrin 			is_log = B_FALSE;
15434527Sperrin 			(void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_LOG,
15444527Sperrin 			    &is_log);
15454527Sperrin 			if (is_log)
15464527Sperrin 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
15474527Sperrin 				    "cannot replace a log with a spare"));
15484527Sperrin 			else
15494527Sperrin 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
15504527Sperrin 				    "cannot replace a replacing device"));
15514527Sperrin 		} else {
15522082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
15532082Seschrock 			    "can only attach to mirrors and top-level "
15542082Seschrock 			    "disks"));
15554527Sperrin 		}
15562082Seschrock 		(void) zfs_error(hdl, EZFS_BADTARGET, msg);
1557789Sahrens 		break;
1558789Sahrens 
15591544Seschrock 	case EINVAL:
1560789Sahrens 		/*
1561789Sahrens 		 * The new device must be a single disk.
1562789Sahrens 		 */
15632082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
15642082Seschrock 		    "new device must be a single disk"));
15652082Seschrock 		(void) zfs_error(hdl, EZFS_INVALCONFIG, msg);
1566789Sahrens 		break;
1567789Sahrens 
15681544Seschrock 	case EBUSY:
15692082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"),
15702082Seschrock 		    new_disk);
15712082Seschrock 		(void) zfs_error(hdl, EZFS_BADDEV, msg);
1572789Sahrens 		break;
1573789Sahrens 
15741544Seschrock 	case EOVERFLOW:
1575789Sahrens 		/*
1576789Sahrens 		 * The new device is too small.
1577789Sahrens 		 */
15782082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
15792082Seschrock 		    "device is too small"));
15802082Seschrock 		(void) zfs_error(hdl, EZFS_BADDEV, msg);
1581789Sahrens 		break;
1582789Sahrens 
15831544Seschrock 	case EDOM:
1584789Sahrens 		/*
1585789Sahrens 		 * The new device has a different alignment requirement.
1586789Sahrens 		 */
15872082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
15882082Seschrock 		    "devices have different sector alignment"));
15892082Seschrock 		(void) zfs_error(hdl, EZFS_BADDEV, msg);
1590789Sahrens 		break;
1591789Sahrens 
15921544Seschrock 	case ENAMETOOLONG:
1593789Sahrens 		/*
1594789Sahrens 		 * The resulting top-level vdev spec won't fit in the label.
1595789Sahrens 		 */
15962082Seschrock 		(void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg);
1597789Sahrens 		break;
1598789Sahrens 
15991544Seschrock 	default:
16002082Seschrock 		(void) zpool_standard_error(hdl, errno, msg);
1601789Sahrens 	}
1602789Sahrens 
16032082Seschrock 	return (-1);
1604789Sahrens }
1605789Sahrens 
1606789Sahrens /*
1607789Sahrens  * Detach the specified device.
1608789Sahrens  */
1609789Sahrens int
1610789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path)
1611789Sahrens {
1612789Sahrens 	zfs_cmd_t zc = { 0 };
1613789Sahrens 	char msg[1024];
16142082Seschrock 	nvlist_t *tgt;
16152468Sek110237 	boolean_t avail_spare;
16162082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1617789Sahrens 
16181544Seschrock 	(void) snprintf(msg, sizeof (msg),
16191544Seschrock 	    dgettext(TEXT_DOMAIN, "cannot detach %s"), path);
16201544Seschrock 
1621789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
16222468Sek110237 	if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0)
16232082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
1624789Sahrens 
16252468Sek110237 	if (avail_spare)
16262082Seschrock 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
16272082Seschrock 
16282082Seschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
16292082Seschrock 
16304543Smarks 	if (zfs_ioctl(hdl, ZFS_IOC_VDEV_DETACH, &zc) == 0)
1631789Sahrens 		return (0);
1632789Sahrens 
1633789Sahrens 	switch (errno) {
1634789Sahrens 
16351544Seschrock 	case ENOTSUP:
1636789Sahrens 		/*
1637789Sahrens 		 * Can't detach from this type of vdev.
1638789Sahrens 		 */
16392082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only "
16402082Seschrock 		    "applicable to mirror and replacing vdevs"));
16412082Seschrock 		(void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg);
1642789Sahrens 		break;
1643789Sahrens 
16441544Seschrock 	case EBUSY:
1645789Sahrens 		/*
1646789Sahrens 		 * There are no other replicas of this device.
1647789Sahrens 		 */
16482082Seschrock 		(void) zfs_error(hdl, EZFS_NOREPLICAS, msg);
1649789Sahrens 		break;
1650789Sahrens 
16511544Seschrock 	default:
16522082Seschrock 		(void) zpool_standard_error(hdl, errno, msg);
16531544Seschrock 	}
16541544Seschrock 
16552082Seschrock 	return (-1);
16562082Seschrock }
16572082Seschrock 
16582082Seschrock /*
16592082Seschrock  * Remove the given device.  Currently, this is supported only for hot spares.
16602082Seschrock  */
16612082Seschrock int
16622082Seschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path)
16632082Seschrock {
16642082Seschrock 	zfs_cmd_t zc = { 0 };
16652082Seschrock 	char msg[1024];
16662082Seschrock 	nvlist_t *tgt;
16672468Sek110237 	boolean_t avail_spare;
16682082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
16692082Seschrock 
16702082Seschrock 	(void) snprintf(msg, sizeof (msg),
16712082Seschrock 	    dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
16722082Seschrock 
16732082Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
16742468Sek110237 	if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0)
16752082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
16762082Seschrock 
16772468Sek110237 	if (!avail_spare) {
16782082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
16793377Seschrock 		    "only inactive hot spares can be removed"));
16802082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
16812082Seschrock 	}
16822082Seschrock 
16832082Seschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
16842082Seschrock 
16854543Smarks 	if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0)
16862082Seschrock 		return (0);
16872082Seschrock 
16882082Seschrock 	return (zpool_standard_error(hdl, errno, msg));
16891544Seschrock }
16901544Seschrock 
16911544Seschrock /*
16921544Seschrock  * Clear the errors for the pool, or the particular device if specified.
16931544Seschrock  */
16941544Seschrock int
16951544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path)
16961544Seschrock {
16971544Seschrock 	zfs_cmd_t zc = { 0 };
16981544Seschrock 	char msg[1024];
16992082Seschrock 	nvlist_t *tgt;
17002468Sek110237 	boolean_t avail_spare;
17012082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
17021544Seschrock 
17031544Seschrock 	if (path)
17041544Seschrock 		(void) snprintf(msg, sizeof (msg),
17051544Seschrock 		    dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
17062676Seschrock 		    path);
17071544Seschrock 	else
17081544Seschrock 		(void) snprintf(msg, sizeof (msg),
17091544Seschrock 		    dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
17101544Seschrock 		    zhp->zpool_name);
17111544Seschrock 
17121544Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
17132082Seschrock 	if (path) {
17142468Sek110237 		if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0)
17152082Seschrock 			return (zfs_error(hdl, EZFS_NODEVICE, msg));
17162082Seschrock 
17172468Sek110237 		if (avail_spare)
17182082Seschrock 			return (zfs_error(hdl, EZFS_ISSPARE, msg));
17192082Seschrock 
17202082Seschrock 		verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID,
17212082Seschrock 		    &zc.zc_guid) == 0);
17221544Seschrock 	}
17231544Seschrock 
17244543Smarks 	if (zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc) == 0)
17251544Seschrock 		return (0);
17261544Seschrock 
17272082Seschrock 	return (zpool_standard_error(hdl, errno, msg));
1728789Sahrens }
1729789Sahrens 
17303126Sahl /*
17314451Seschrock  * Similar to zpool_clear(), but takes a GUID (used by fmd).
17324451Seschrock  */
17334451Seschrock int
17344451Seschrock zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid)
17354451Seschrock {
17364451Seschrock 	zfs_cmd_t zc = { 0 };
17374451Seschrock 	char msg[1024];
17384451Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
17394451Seschrock 
17404451Seschrock 	(void) snprintf(msg, sizeof (msg),
17414451Seschrock 	    dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"),
17424451Seschrock 	    guid);
17434451Seschrock 
17444451Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
17454451Seschrock 	zc.zc_guid = guid;
17464451Seschrock 
17474451Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0)
17484451Seschrock 		return (0);
17494451Seschrock 
17504451Seschrock 	return (zpool_standard_error(hdl, errno, msg));
17514451Seschrock }
17524451Seschrock 
17534451Seschrock /*
17543126Sahl  * Iterate over all zvols in a given pool by walking the /dev/zvol/dsk/<pool>
17553126Sahl  * hierarchy.
17563126Sahl  */
17573126Sahl int
17583126Sahl zpool_iter_zvol(zpool_handle_t *zhp, int (*cb)(const char *, void *),
17593126Sahl     void *data)
1760789Sahrens {
17613126Sahl 	libzfs_handle_t *hdl = zhp->zpool_hdl;
17623126Sahl 	char (*paths)[MAXPATHLEN];
17633126Sahl 	size_t size = 4;
17643126Sahl 	int curr, fd, base, ret = 0;
17653126Sahl 	DIR *dirp;
17663126Sahl 	struct dirent *dp;
17673126Sahl 	struct stat st;
17683126Sahl 
17693126Sahl 	if ((base = open("/dev/zvol/dsk", O_RDONLY)) < 0)
17703126Sahl 		return (errno == ENOENT ? 0 : -1);
17713126Sahl 
17723126Sahl 	if (fstatat(base, zhp->zpool_name, &st, 0) != 0) {
17733126Sahl 		int err = errno;
17743126Sahl 		(void) close(base);
17753126Sahl 		return (err == ENOENT ? 0 : -1);
17763126Sahl 	}
1777789Sahrens 
1778789Sahrens 	/*
17793126Sahl 	 * Oddly this wasn't a directory -- ignore that failure since we
17803126Sahl 	 * know there are no links lower in the (non-existant) hierarchy.
1781789Sahrens 	 */
17823126Sahl 	if (!S_ISDIR(st.st_mode)) {
17833126Sahl 		(void) close(base);
17843126Sahl 		return (0);
17853126Sahl 	}
17863126Sahl 
17873126Sahl 	if ((paths = zfs_alloc(hdl, size * sizeof (paths[0]))) == NULL) {
17883126Sahl 		(void) close(base);
17893126Sahl 		return (-1);
1790789Sahrens 	}
1791789Sahrens 
17923126Sahl 	(void) strlcpy(paths[0], zhp->zpool_name, sizeof (paths[0]));
17933126Sahl 	curr = 0;
17943126Sahl 
17953126Sahl 	while (curr >= 0) {
17963126Sahl 		if (fstatat(base, paths[curr], &st, AT_SYMLINK_NOFOLLOW) != 0)
17973126Sahl 			goto err;
17983126Sahl 
17993126Sahl 		if (S_ISDIR(st.st_mode)) {
18003126Sahl 			if ((fd = openat(base, paths[curr], O_RDONLY)) < 0)
18013126Sahl 				goto err;
18023126Sahl 
18033126Sahl 			if ((dirp = fdopendir(fd)) == NULL) {
18043126Sahl 				(void) close(fd);
18053126Sahl 				goto err;
18063126Sahl 			}
18073126Sahl 
18083126Sahl 			while ((dp = readdir(dirp)) != NULL) {
18093126Sahl 				if (dp->d_name[0] == '.')
18103126Sahl 					continue;
18113126Sahl 
18123126Sahl 				if (curr + 1 == size) {
18133126Sahl 					paths = zfs_realloc(hdl, paths,
18143126Sahl 					    size * sizeof (paths[0]),
18153126Sahl 					    size * 2 * sizeof (paths[0]));
18163126Sahl 					if (paths == NULL) {
18173126Sahl 						(void) closedir(dirp);
18183126Sahl 						(void) close(fd);
18193126Sahl 						goto err;
18203126Sahl 					}
18213126Sahl 
18223126Sahl 					size *= 2;
18233126Sahl 				}
18243126Sahl 
18253126Sahl 				(void) strlcpy(paths[curr + 1], paths[curr],
18263126Sahl 				    sizeof (paths[curr + 1]));
18273126Sahl 				(void) strlcat(paths[curr], "/",
18283126Sahl 				    sizeof (paths[curr]));
18293126Sahl 				(void) strlcat(paths[curr], dp->d_name,
18303126Sahl 				    sizeof (paths[curr]));
18313126Sahl 				curr++;
18323126Sahl 			}
18333126Sahl 
18343126Sahl 			(void) closedir(dirp);
18353126Sahl 
18363126Sahl 		} else {
18373126Sahl 			if ((ret = cb(paths[curr], data)) != 0)
18383126Sahl 				break;
18393126Sahl 		}
18403126Sahl 
18413126Sahl 		curr--;
18423126Sahl 	}
18433126Sahl 
18443126Sahl 	free(paths);
18453126Sahl 	(void) close(base);
18463126Sahl 
18473126Sahl 	return (ret);
18483126Sahl 
18493126Sahl err:
18503126Sahl 	free(paths);
18513126Sahl 	(void) close(base);
18523126Sahl 	return (-1);
18533126Sahl }
18543126Sahl 
18553126Sahl typedef struct zvol_cb {
18563126Sahl 	zpool_handle_t *zcb_pool;
18573126Sahl 	boolean_t zcb_create;
18583126Sahl } zvol_cb_t;
18593126Sahl 
18603126Sahl /*ARGSUSED*/
18613126Sahl static int
18623126Sahl do_zvol_create(zfs_handle_t *zhp, void *data)
18633126Sahl {
18644657Sahrens 	int ret = 0;
18653126Sahl 
18664657Sahrens 	if (ZFS_IS_VOLUME(zhp)) {
18673126Sahl 		(void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name);
18684657Sahrens 		ret = zfs_iter_snapshots(zhp, do_zvol_create, NULL);
18694657Sahrens 	}
18703126Sahl 
18714657Sahrens 	if (ret == 0)
18724657Sahrens 		ret = zfs_iter_filesystems(zhp, do_zvol_create, NULL);
1873789Sahrens 
1874789Sahrens 	zfs_close(zhp);
18753126Sahl 
1876789Sahrens 	return (ret);
1877789Sahrens }
1878789Sahrens 
1879789Sahrens /*
1880789Sahrens  * Iterate over all zvols in the pool and make any necessary minor nodes.
1881789Sahrens  */
1882789Sahrens int
1883789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp)
1884789Sahrens {
1885789Sahrens 	zfs_handle_t *zfp;
1886789Sahrens 	int ret;
1887789Sahrens 
1888789Sahrens 	/*
1889789Sahrens 	 * If the pool is unavailable, just return success.
1890789Sahrens 	 */
18912082Seschrock 	if ((zfp = make_dataset_handle(zhp->zpool_hdl,
18922082Seschrock 	    zhp->zpool_name)) == NULL)
1893789Sahrens 		return (0);
1894789Sahrens 
18954657Sahrens 	ret = zfs_iter_filesystems(zfp, do_zvol_create, NULL);
1896789Sahrens 
1897789Sahrens 	zfs_close(zfp);
1898789Sahrens 	return (ret);
1899789Sahrens }
1900789Sahrens 
19013126Sahl static int
19023126Sahl do_zvol_remove(const char *dataset, void *data)
19033126Sahl {
19043126Sahl 	zpool_handle_t *zhp = data;
19053126Sahl 
19063126Sahl 	return (zvol_remove_link(zhp->zpool_hdl, dataset));
19073126Sahl }
19083126Sahl 
1909789Sahrens /*
19103126Sahl  * Iterate over all zvols in the pool and remove any minor nodes.  We iterate
19113126Sahl  * by examining the /dev links so that a corrupted pool doesn't impede this
19123126Sahl  * operation.
1913789Sahrens  */
1914789Sahrens int
1915789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp)
1916789Sahrens {
19173126Sahl 	return (zpool_iter_zvol(zhp, do_zvol_remove, zhp));
1918789Sahrens }
19191354Seschrock 
19201354Seschrock /*
19211354Seschrock  * Convert from a devid string to a path.
19221354Seschrock  */
19231354Seschrock static char *
19241354Seschrock devid_to_path(char *devid_str)
19251354Seschrock {
19261354Seschrock 	ddi_devid_t devid;
19271354Seschrock 	char *minor;
19281354Seschrock 	char *path;
19291354Seschrock 	devid_nmlist_t *list = NULL;
19301354Seschrock 	int ret;
19311354Seschrock 
19321354Seschrock 	if (devid_str_decode(devid_str, &devid, &minor) != 0)
19331354Seschrock 		return (NULL);
19341354Seschrock 
19351354Seschrock 	ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list);
19361354Seschrock 
19371354Seschrock 	devid_str_free(minor);
19381354Seschrock 	devid_free(devid);
19391354Seschrock 
19401354Seschrock 	if (ret != 0)
19411354Seschrock 		return (NULL);
19421354Seschrock 
19432082Seschrock 	if ((path = strdup(list[0].devname)) == NULL)
19442082Seschrock 		return (NULL);
19452082Seschrock 
19461354Seschrock 	devid_free_nmlist(list);
19471354Seschrock 
19481354Seschrock 	return (path);
19491354Seschrock }
19501354Seschrock 
19511354Seschrock /*
19521354Seschrock  * Convert from a path to a devid string.
19531354Seschrock  */
19541354Seschrock static char *
19551354Seschrock path_to_devid(const char *path)
19561354Seschrock {
19571354Seschrock 	int fd;
19581354Seschrock 	ddi_devid_t devid;
19591354Seschrock 	char *minor, *ret;
19601354Seschrock 
19611354Seschrock 	if ((fd = open(path, O_RDONLY)) < 0)
19621354Seschrock 		return (NULL);
19631354Seschrock 
19641354Seschrock 	minor = NULL;
19651354Seschrock 	ret = NULL;
19661354Seschrock 	if (devid_get(fd, &devid) == 0) {
19671354Seschrock 		if (devid_get_minor_name(fd, &minor) == 0)
19681354Seschrock 			ret = devid_str_encode(devid, minor);
19691354Seschrock 		if (minor != NULL)
19701354Seschrock 			devid_str_free(minor);
19711354Seschrock 		devid_free(devid);
19721354Seschrock 	}
19731354Seschrock 	(void) close(fd);
19741354Seschrock 
19751354Seschrock 	return (ret);
19761354Seschrock }
19771354Seschrock 
19781354Seschrock /*
19791354Seschrock  * Issue the necessary ioctl() to update the stored path value for the vdev.  We
19801354Seschrock  * ignore any failure here, since a common case is for an unprivileged user to
19811354Seschrock  * type 'zpool status', and we'll display the correct information anyway.
19821354Seschrock  */
19831354Seschrock static void
19841354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path)
19851354Seschrock {
19861354Seschrock 	zfs_cmd_t zc = { 0 };
19871354Seschrock 
19881354Seschrock 	(void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
19892676Seschrock 	(void) strncpy(zc.zc_value, path, sizeof (zc.zc_value));
19901354Seschrock 	verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
19911544Seschrock 	    &zc.zc_guid) == 0);
19921354Seschrock 
19932082Seschrock 	(void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc);
19941354Seschrock }
19951354Seschrock 
19961354Seschrock /*
19971354Seschrock  * Given a vdev, return the name to display in iostat.  If the vdev has a path,
19981354Seschrock  * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type.
19991354Seschrock  * We also check if this is a whole disk, in which case we strip off the
20001354Seschrock  * trailing 's0' slice name.
20011354Seschrock  *
20021354Seschrock  * This routine is also responsible for identifying when disks have been
20031354Seschrock  * reconfigured in a new location.  The kernel will have opened the device by
20041354Seschrock  * devid, but the path will still refer to the old location.  To catch this, we
20051354Seschrock  * first do a path -> devid translation (which is fast for the common case).  If
20061354Seschrock  * the devid matches, we're done.  If not, we do a reverse devid -> path
20071354Seschrock  * translation and issue the appropriate ioctl() to update the path of the vdev.
20081354Seschrock  * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any
20091354Seschrock  * of these checks.
20101354Seschrock  */
20111354Seschrock char *
20122082Seschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv)
20131354Seschrock {
20141354Seschrock 	char *path, *devid;
20151544Seschrock 	uint64_t value;
20161544Seschrock 	char buf[64];
20174451Seschrock 	vdev_stat_t *vs;
20184451Seschrock 	uint_t vsc;
20191354Seschrock 
20201544Seschrock 	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
20211544Seschrock 	    &value) == 0) {
20221544Seschrock 		verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
20231544Seschrock 		    &value) == 0);
20242856Snd150628 		(void) snprintf(buf, sizeof (buf), "%llu",
20252856Snd150628 		    (u_longlong_t)value);
20261544Seschrock 		path = buf;
20271544Seschrock 	} else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
20281354Seschrock 
20294451Seschrock 		/*
20304451Seschrock 		 * If the device is dead (faulted, offline, etc) then don't
20314451Seschrock 		 * bother opening it.  Otherwise we may be forcing the user to
20324451Seschrock 		 * open a misbehaving device, which can have undesirable
20334451Seschrock 		 * effects.
20344451Seschrock 		 */
20354451Seschrock 		if ((nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
20364451Seschrock 		    (uint64_t **)&vs, &vsc) != 0 ||
20374451Seschrock 		    vs->vs_state >= VDEV_STATE_DEGRADED) &&
20384451Seschrock 		    zhp != NULL &&
20391354Seschrock 		    nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) {
20401354Seschrock 			/*
20411354Seschrock 			 * Determine if the current path is correct.
20421354Seschrock 			 */
20431354Seschrock 			char *newdevid = path_to_devid(path);
20441354Seschrock 
20451354Seschrock 			if (newdevid == NULL ||
20461354Seschrock 			    strcmp(devid, newdevid) != 0) {
20471354Seschrock 				char *newpath;
20481354Seschrock 
20491354Seschrock 				if ((newpath = devid_to_path(devid)) != NULL) {
20501354Seschrock 					/*
20511354Seschrock 					 * Update the path appropriately.
20521354Seschrock 					 */
20531354Seschrock 					set_path(zhp, nv, newpath);
20542082Seschrock 					if (nvlist_add_string(nv,
20552082Seschrock 					    ZPOOL_CONFIG_PATH, newpath) == 0)
20562082Seschrock 						verify(nvlist_lookup_string(nv,
20572082Seschrock 						    ZPOOL_CONFIG_PATH,
20582082Seschrock 						    &path) == 0);
20591354Seschrock 					free(newpath);
20601354Seschrock 				}
20611354Seschrock 			}
20621354Seschrock 
20632082Seschrock 			if (newdevid)
20642082Seschrock 				devid_str_free(newdevid);
20651354Seschrock 		}
20661354Seschrock 
20671354Seschrock 		if (strncmp(path, "/dev/dsk/", 9) == 0)
20681354Seschrock 			path += 9;
20691354Seschrock 
20701354Seschrock 		if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
20711544Seschrock 		    &value) == 0 && value) {
20722082Seschrock 			char *tmp = zfs_strdup(hdl, path);
20732082Seschrock 			if (tmp == NULL)
20742082Seschrock 				return (NULL);
20751354Seschrock 			tmp[strlen(path) - 2] = '\0';
20761354Seschrock 			return (tmp);
20771354Seschrock 		}
20781354Seschrock 	} else {
20791354Seschrock 		verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0);
20802082Seschrock 
20812082Seschrock 		/*
20822082Seschrock 		 * If it's a raidz device, we need to stick in the parity level.
20832082Seschrock 		 */
20842082Seschrock 		if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) {
20852082Seschrock 			verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY,
20862082Seschrock 			    &value) == 0);
20872082Seschrock 			(void) snprintf(buf, sizeof (buf), "%s%llu", path,
20882856Snd150628 			    (u_longlong_t)value);
20892082Seschrock 			path = buf;
20902082Seschrock 		}
20911354Seschrock 	}
20921354Seschrock 
20932082Seschrock 	return (zfs_strdup(hdl, path));
20941354Seschrock }
20951544Seschrock 
20961544Seschrock static int
20971544Seschrock zbookmark_compare(const void *a, const void *b)
20981544Seschrock {
20991544Seschrock 	return (memcmp(a, b, sizeof (zbookmark_t)));
21001544Seschrock }
21011544Seschrock 
21021544Seschrock /*
21031544Seschrock  * Retrieve the persistent error log, uniquify the members, and return to the
21041544Seschrock  * caller.
21051544Seschrock  */
21061544Seschrock int
21073444Sek110237 zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
21081544Seschrock {
21091544Seschrock 	zfs_cmd_t zc = { 0 };
21101544Seschrock 	uint64_t count;
21112676Seschrock 	zbookmark_t *zb = NULL;
21123444Sek110237 	int i;
21131544Seschrock 
21141544Seschrock 	/*
21151544Seschrock 	 * Retrieve the raw error list from the kernel.  If the number of errors
21161544Seschrock 	 * has increased, allocate more space and continue until we get the
21171544Seschrock 	 * entire list.
21181544Seschrock 	 */
21191544Seschrock 	verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT,
21201544Seschrock 	    &count) == 0);
21214820Sek110237 	if (count == 0)
21224820Sek110237 		return (0);
21232676Seschrock 	if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl,
21242856Snd150628 	    count * sizeof (zbookmark_t))) == (uintptr_t)NULL)
21252082Seschrock 		return (-1);
21262676Seschrock 	zc.zc_nvlist_dst_size = count;
21271544Seschrock 	(void) strcpy(zc.zc_name, zhp->zpool_name);
21281544Seschrock 	for (;;) {
21292082Seschrock 		if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG,
21302082Seschrock 		    &zc) != 0) {
21312676Seschrock 			free((void *)(uintptr_t)zc.zc_nvlist_dst);
21321544Seschrock 			if (errno == ENOMEM) {
21333823Svb160487 				count = zc.zc_nvlist_dst_size;
21342676Seschrock 				if ((zc.zc_nvlist_dst = (uintptr_t)
21353823Svb160487 				    zfs_alloc(zhp->zpool_hdl, count *
21363823Svb160487 				    sizeof (zbookmark_t))) == (uintptr_t)NULL)
21372082Seschrock 					return (-1);
21381544Seschrock 			} else {
21391544Seschrock 				return (-1);
21401544Seschrock 			}
21411544Seschrock 		} else {
21421544Seschrock 			break;
21431544Seschrock 		}
21441544Seschrock 	}
21451544Seschrock 
21461544Seschrock 	/*
21471544Seschrock 	 * Sort the resulting bookmarks.  This is a little confusing due to the
21481544Seschrock 	 * implementation of ZFS_IOC_ERROR_LOG.  The bookmarks are copied last
21492676Seschrock 	 * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks
21501544Seschrock 	 * _not_ copied as part of the process.  So we point the start of our
21511544Seschrock 	 * array appropriate and decrement the total number of elements.
21521544Seschrock 	 */
21532676Seschrock 	zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) +
21542676Seschrock 	    zc.zc_nvlist_dst_size;
21552676Seschrock 	count -= zc.zc_nvlist_dst_size;
21561544Seschrock 
21571544Seschrock 	qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare);
21581544Seschrock 
21593444Sek110237 	verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0);
21601544Seschrock 
21611544Seschrock 	/*
21623444Sek110237 	 * Fill in the nverrlistp with nvlist's of dataset and object numbers.
21631544Seschrock 	 */
21641544Seschrock 	for (i = 0; i < count; i++) {
21651544Seschrock 		nvlist_t *nv;
21661544Seschrock 
21673700Sek110237 		/* ignoring zb_blkid and zb_level for now */
21683700Sek110237 		if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset &&
21693700Sek110237 		    zb[i-1].zb_object == zb[i].zb_object)
21701544Seschrock 			continue;
21711544Seschrock 
21723444Sek110237 		if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0)
21733444Sek110237 			goto nomem;
21743444Sek110237 		if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET,
21753444Sek110237 		    zb[i].zb_objset) != 0) {
21763444Sek110237 			nvlist_free(nv);
21772082Seschrock 			goto nomem;
21783444Sek110237 		}
21793444Sek110237 		if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT,
21803444Sek110237 		    zb[i].zb_object) != 0) {
21813444Sek110237 			nvlist_free(nv);
21823444Sek110237 			goto nomem;
21831544Seschrock 		}
21843444Sek110237 		if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) {
21853444Sek110237 			nvlist_free(nv);
21863444Sek110237 			goto nomem;
21873444Sek110237 		}
21883444Sek110237 		nvlist_free(nv);
21891544Seschrock 	}
21901544Seschrock 
21913265Sahrens 	free((void *)(uintptr_t)zc.zc_nvlist_dst);
21921544Seschrock 	return (0);
21932082Seschrock 
21942082Seschrock nomem:
21952676Seschrock 	free((void *)(uintptr_t)zc.zc_nvlist_dst);
21962082Seschrock 	return (no_memory(zhp->zpool_hdl));
21971544Seschrock }
21981760Seschrock 
21991760Seschrock /*
22001760Seschrock  * Upgrade a ZFS pool to the latest on-disk version.
22011760Seschrock  */
22021760Seschrock int
22035094Slling zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version)
22041760Seschrock {
22051760Seschrock 	zfs_cmd_t zc = { 0 };
22062082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
22071760Seschrock 
22081760Seschrock 	(void) strcpy(zc.zc_name, zhp->zpool_name);
22095094Slling 	zc.zc_cookie = new_version;
22105094Slling 
22114543Smarks 	if (zfs_ioctl(hdl, ZFS_IOC_POOL_UPGRADE, &zc) != 0)
22123237Slling 		return (zpool_standard_error_fmt(hdl, errno,
22132082Seschrock 		    dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"),
22142082Seschrock 		    zhp->zpool_name));
22151760Seschrock 	return (0);
22161760Seschrock }
22172926Sek110237 
22184988Sek110237 void
22194988Sek110237 zpool_set_history_str(const char *subcommand, int argc, char **argv,
22204988Sek110237     char *history_str)
22214988Sek110237 {
22224988Sek110237 	int i;
22234988Sek110237 
22244988Sek110237 	(void) strlcpy(history_str, subcommand, HIS_MAX_RECORD_LEN);
22254988Sek110237 	for (i = 1; i < argc; i++) {
22264988Sek110237 		if (strlen(history_str) + 1 + strlen(argv[i]) >
22274988Sek110237 		    HIS_MAX_RECORD_LEN)
22284988Sek110237 			break;
22294988Sek110237 		(void) strlcat(history_str, " ", HIS_MAX_RECORD_LEN);
22304988Sek110237 		(void) strlcat(history_str, argv[i], HIS_MAX_RECORD_LEN);
22314988Sek110237 	}
22324988Sek110237 }
22334988Sek110237 
22342926Sek110237 /*
22354988Sek110237  * Stage command history for logging.
22362926Sek110237  */
22374988Sek110237 int
22384988Sek110237 zpool_stage_history(libzfs_handle_t *hdl, const char *history_str)
22392926Sek110237 {
22404988Sek110237 	if (history_str == NULL)
22414988Sek110237 		return (EINVAL);
22424988Sek110237 
22434988Sek110237 	if (strlen(history_str) > HIS_MAX_RECORD_LEN)
22444988Sek110237 		return (EINVAL);
22452926Sek110237 
22464715Sek110237 	if (hdl->libzfs_log_str != NULL)
22474543Smarks 		free(hdl->libzfs_log_str);
22482926Sek110237 
22494988Sek110237 	if ((hdl->libzfs_log_str = strdup(history_str)) == NULL)
22504988Sek110237 		return (no_memory(hdl));
22514543Smarks 
22524988Sek110237 	return (0);
22532926Sek110237 }
22542926Sek110237 
22552926Sek110237 /*
22562926Sek110237  * Perform ioctl to get some command history of a pool.
22572926Sek110237  *
22582926Sek110237  * 'buf' is the buffer to fill up to 'len' bytes.  'off' is the
22592926Sek110237  * logical offset of the history buffer to start reading from.
22602926Sek110237  *
22612926Sek110237  * Upon return, 'off' is the next logical offset to read from and
22622926Sek110237  * 'len' is the actual amount of bytes read into 'buf'.
22632926Sek110237  */
22642926Sek110237 static int
22652926Sek110237 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len)
22662926Sek110237 {
22672926Sek110237 	zfs_cmd_t zc = { 0 };
22682926Sek110237 	libzfs_handle_t *hdl = zhp->zpool_hdl;
22692926Sek110237 
22702926Sek110237 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
22712926Sek110237 
22722926Sek110237 	zc.zc_history = (uint64_t)(uintptr_t)buf;
22732926Sek110237 	zc.zc_history_len = *len;
22742926Sek110237 	zc.zc_history_offset = *off;
22752926Sek110237 
22762926Sek110237 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) {
22772926Sek110237 		switch (errno) {
22782926Sek110237 		case EPERM:
22793237Slling 			return (zfs_error_fmt(hdl, EZFS_PERM,
22803237Slling 			    dgettext(TEXT_DOMAIN,
22812926Sek110237 			    "cannot show history for pool '%s'"),
22822926Sek110237 			    zhp->zpool_name));
22832926Sek110237 		case ENOENT:
22843237Slling 			return (zfs_error_fmt(hdl, EZFS_NOHISTORY,
22852926Sek110237 			    dgettext(TEXT_DOMAIN, "cannot get history for pool "
22862926Sek110237 			    "'%s'"), zhp->zpool_name));
22873863Sek110237 		case ENOTSUP:
22883863Sek110237 			return (zfs_error_fmt(hdl, EZFS_BADVERSION,
22893863Sek110237 			    dgettext(TEXT_DOMAIN, "cannot get history for pool "
22903863Sek110237 			    "'%s', pool must be upgraded"), zhp->zpool_name));
22912926Sek110237 		default:
22923237Slling 			return (zpool_standard_error_fmt(hdl, errno,
22932926Sek110237 			    dgettext(TEXT_DOMAIN,
22942926Sek110237 			    "cannot get history for '%s'"), zhp->zpool_name));
22952926Sek110237 		}
22962926Sek110237 	}
22972926Sek110237 
22982926Sek110237 	*len = zc.zc_history_len;
22992926Sek110237 	*off = zc.zc_history_offset;
23002926Sek110237 
23012926Sek110237 	return (0);
23022926Sek110237 }
23032926Sek110237 
23042926Sek110237 /*
23052926Sek110237  * Process the buffer of nvlists, unpacking and storing each nvlist record
23062926Sek110237  * into 'records'.  'leftover' is set to the number of bytes that weren't
23072926Sek110237  * processed as there wasn't a complete record.
23082926Sek110237  */
23092926Sek110237 static int
23102926Sek110237 zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover,
23112926Sek110237     nvlist_t ***records, uint_t *numrecords)
23122926Sek110237 {
23132926Sek110237 	uint64_t reclen;
23142926Sek110237 	nvlist_t *nv;
23152926Sek110237 	int i;
23162926Sek110237 
23172926Sek110237 	while (bytes_read > sizeof (reclen)) {
23182926Sek110237 
23192926Sek110237 		/* get length of packed record (stored as little endian) */
23202926Sek110237 		for (i = 0, reclen = 0; i < sizeof (reclen); i++)
23212926Sek110237 			reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i);
23222926Sek110237 
23232926Sek110237 		if (bytes_read < sizeof (reclen) + reclen)
23242926Sek110237 			break;
23252926Sek110237 
23262926Sek110237 		/* unpack record */
23272926Sek110237 		if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0)
23282926Sek110237 			return (ENOMEM);
23292926Sek110237 		bytes_read -= sizeof (reclen) + reclen;
23302926Sek110237 		buf += sizeof (reclen) + reclen;
23312926Sek110237 
23322926Sek110237 		/* add record to nvlist array */
23332926Sek110237 		(*numrecords)++;
23342926Sek110237 		if (ISP2(*numrecords + 1)) {
23352926Sek110237 			*records = realloc(*records,
23362926Sek110237 			    *numrecords * 2 * sizeof (nvlist_t *));
23372926Sek110237 		}
23382926Sek110237 		(*records)[*numrecords - 1] = nv;
23392926Sek110237 	}
23402926Sek110237 
23412926Sek110237 	*leftover = bytes_read;
23422926Sek110237 	return (0);
23432926Sek110237 }
23442926Sek110237 
23452926Sek110237 #define	HIS_BUF_LEN	(128*1024)
23462926Sek110237 
23472926Sek110237 /*
23482926Sek110237  * Retrieve the command history of a pool.
23492926Sek110237  */
23502926Sek110237 int
23512926Sek110237 zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
23522926Sek110237 {
23532926Sek110237 	char buf[HIS_BUF_LEN];
23542926Sek110237 	uint64_t off = 0;
23552926Sek110237 	nvlist_t **records = NULL;
23562926Sek110237 	uint_t numrecords = 0;
23572926Sek110237 	int err, i;
23582926Sek110237 
23592926Sek110237 	do {
23602926Sek110237 		uint64_t bytes_read = sizeof (buf);
23612926Sek110237 		uint64_t leftover;
23622926Sek110237 
23632926Sek110237 		if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0)
23642926Sek110237 			break;
23652926Sek110237 
23662926Sek110237 		/* if nothing else was read in, we're at EOF, just return */
23672926Sek110237 		if (!bytes_read)
23682926Sek110237 			break;
23692926Sek110237 
23702926Sek110237 		if ((err = zpool_history_unpack(buf, bytes_read,
23712926Sek110237 		    &leftover, &records, &numrecords)) != 0)
23722926Sek110237 			break;
23732926Sek110237 		off -= leftover;
23742926Sek110237 
23752926Sek110237 		/* CONSTCOND */
23762926Sek110237 	} while (1);
23772926Sek110237 
23782926Sek110237 	if (!err) {
23792926Sek110237 		verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0);
23802926Sek110237 		verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD,
23812926Sek110237 		    records, numrecords) == 0);
23822926Sek110237 	}
23832926Sek110237 	for (i = 0; i < numrecords; i++)
23842926Sek110237 		nvlist_free(records[i]);
23852926Sek110237 	free(records);
23862926Sek110237 
23872926Sek110237 	return (err);
23882926Sek110237 }
23893444Sek110237 
23903444Sek110237 void
23913444Sek110237 zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
23923444Sek110237     char *pathname, size_t len)
23933444Sek110237 {
23943444Sek110237 	zfs_cmd_t zc = { 0 };
23953444Sek110237 	boolean_t mounted = B_FALSE;
23963444Sek110237 	char *mntpnt = NULL;
23973444Sek110237 	char dsname[MAXNAMELEN];
23983444Sek110237 
23993444Sek110237 	if (dsobj == 0) {
24003444Sek110237 		/* special case for the MOS */
24013444Sek110237 		(void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj);
24023444Sek110237 		return;
24033444Sek110237 	}
24043444Sek110237 
24053444Sek110237 	/* get the dataset's name */
24063444Sek110237 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
24073444Sek110237 	zc.zc_obj = dsobj;
24083444Sek110237 	if (ioctl(zhp->zpool_hdl->libzfs_fd,
24093444Sek110237 	    ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) {
24103444Sek110237 		/* just write out a path of two object numbers */
24113444Sek110237 		(void) snprintf(pathname, len, "<0x%llx>:<0x%llx>",
24123444Sek110237 		    dsobj, obj);
24133444Sek110237 		return;
24143444Sek110237 	}
24153444Sek110237 	(void) strlcpy(dsname, zc.zc_value, sizeof (dsname));
24163444Sek110237 
24173444Sek110237 	/* find out if the dataset is mounted */
24183444Sek110237 	mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt);
24193444Sek110237 
24203444Sek110237 	/* get the corrupted object's path */
24213444Sek110237 	(void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name));
24223444Sek110237 	zc.zc_obj = obj;
24233444Sek110237 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH,
24243444Sek110237 	    &zc) == 0) {
24253444Sek110237 		if (mounted) {
24263444Sek110237 			(void) snprintf(pathname, len, "%s%s", mntpnt,
24273444Sek110237 			    zc.zc_value);
24283444Sek110237 		} else {
24293444Sek110237 			(void) snprintf(pathname, len, "%s:%s",
24303444Sek110237 			    dsname, zc.zc_value);
24313444Sek110237 		}
24323444Sek110237 	} else {
24333444Sek110237 		(void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj);
24343444Sek110237 	}
24353444Sek110237 	free(mntpnt);
24363444Sek110237 }
24373912Slling 
24384276Staylor #define	RDISK_ROOT	"/dev/rdsk"
24394276Staylor #define	BACKUP_SLICE	"s2"
24404276Staylor /*
24414276Staylor  * Don't start the slice at the default block of 34; many storage
24424276Staylor  * devices will use a stripe width of 128k, so start there instead.
24434276Staylor  */
24444276Staylor #define	NEW_START_BLOCK	256
24454276Staylor 
24464276Staylor /*
24474276Staylor  * determine where a partition starts on a disk in the current
24484276Staylor  * configuration
24494276Staylor  */
24504276Staylor static diskaddr_t
24514276Staylor find_start_block(nvlist_t *config)
24524276Staylor {
24534276Staylor 	nvlist_t **child;
24544276Staylor 	uint_t c, children;
24554276Staylor 	char *path;
24564276Staylor 	diskaddr_t sb = MAXOFFSET_T;
24574276Staylor 	int fd;
24584276Staylor 	char diskname[MAXPATHLEN];
24594276Staylor 	uint64_t wholedisk;
24604276Staylor 
24614276Staylor 	if (nvlist_lookup_nvlist_array(config,
24624276Staylor 	    ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) {
24634276Staylor 		if (nvlist_lookup_uint64(config,
24644276Staylor 		    ZPOOL_CONFIG_WHOLE_DISK,
24654276Staylor 		    &wholedisk) != 0 || !wholedisk) {
24664276Staylor 			return (MAXOFFSET_T);
24674276Staylor 		}
24684276Staylor 		if (nvlist_lookup_string(config,
24694276Staylor 		    ZPOOL_CONFIG_PATH, &path) != 0) {
24704276Staylor 			return (MAXOFFSET_T);
24714276Staylor 		}
24724276Staylor 
24734276Staylor 		(void) snprintf(diskname, sizeof (diskname), "%s%s",
24744276Staylor 		    RDISK_ROOT, strrchr(path, '/'));
24754276Staylor 		if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) {
24764276Staylor 			struct dk_gpt *vtoc;
24774276Staylor 			if (efi_alloc_and_read(fd, &vtoc) >= 0) {
24784276Staylor 				sb = vtoc->efi_parts[0].p_start;
24794276Staylor 				efi_free(vtoc);
24804276Staylor 			}
24814276Staylor 			(void) close(fd);
24824276Staylor 		}
24834276Staylor 		return (sb);
24844276Staylor 	}
24854276Staylor 
24864276Staylor 	for (c = 0; c < children; c++) {
24874276Staylor 		sb = find_start_block(child[c]);
24884276Staylor 		if (sb != MAXOFFSET_T) {
24894276Staylor 			return (sb);
24904276Staylor 		}
24914276Staylor 	}
24924276Staylor 	return (MAXOFFSET_T);
24934276Staylor }
24944276Staylor 
24954276Staylor /*
24964276Staylor  * Label an individual disk.  The name provided is the short name,
24974276Staylor  * stripped of any leading /dev path.
24984276Staylor  */
24994276Staylor int
25004276Staylor zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
25014276Staylor {
25024276Staylor 	char path[MAXPATHLEN];
25034276Staylor 	struct dk_gpt *vtoc;
25044276Staylor 	int fd;
25054276Staylor 	size_t resv = EFI_MIN_RESV_SIZE;
25064276Staylor 	uint64_t slice_size;
25074276Staylor 	diskaddr_t start_block;
25084276Staylor 	char errbuf[1024];
25094276Staylor 
25104276Staylor 	if (zhp) {
25114276Staylor 		nvlist_t *nvroot;
25124276Staylor 
25134276Staylor 		verify(nvlist_lookup_nvlist(zhp->zpool_config,
25144276Staylor 		    ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
25154276Staylor 
25164276Staylor 		if (zhp->zpool_start_block == 0)
25174276Staylor 			start_block = find_start_block(nvroot);
25184276Staylor 		else
25194276Staylor 			start_block = zhp->zpool_start_block;
25204276Staylor 		zhp->zpool_start_block = start_block;
25214276Staylor 	} else {
25224276Staylor 		/* new pool */
25234276Staylor 		start_block = NEW_START_BLOCK;
25244276Staylor 	}
25254276Staylor 
25264276Staylor 	(void) snprintf(path, sizeof (path), "%s/%s%s", RDISK_ROOT, name,
25274276Staylor 	    BACKUP_SLICE);
25284276Staylor 
25294276Staylor 	if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) {
25304276Staylor 		/*
25314276Staylor 		 * This shouldn't happen.  We've long since verified that this
25324276Staylor 		 * is a valid device.
25334276Staylor 		 */
25344276Staylor 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
25354276Staylor 		    "label '%s': unable to open device"), name);
25364276Staylor 		return (zfs_error(hdl, EZFS_OPENFAILED, errbuf));
25374276Staylor 	}
25384276Staylor 
25394276Staylor 	if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) {
25404276Staylor 		/*
25414276Staylor 		 * The only way this can fail is if we run out of memory, or we
25424276Staylor 		 * were unable to read the disk's capacity
25434276Staylor 		 */
25444276Staylor 		if (errno == ENOMEM)
25454276Staylor 			(void) no_memory(hdl);
25464276Staylor 
25474276Staylor 		(void) close(fd);
25484276Staylor 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
25494276Staylor 		    "label '%s': unable to read disk capacity"), name);
25504276Staylor 
25514276Staylor 		return (zfs_error(hdl, EZFS_NOCAP, errbuf));
25524276Staylor 	}
25534276Staylor 
25544276Staylor 	slice_size = vtoc->efi_last_u_lba + 1;
25554276Staylor 	slice_size -= EFI_MIN_RESV_SIZE;
25564276Staylor 	if (start_block == MAXOFFSET_T)
25574276Staylor 		start_block = NEW_START_BLOCK;
25584276Staylor 	slice_size -= start_block;
25594276Staylor 
25604276Staylor 	vtoc->efi_parts[0].p_start = start_block;
25614276Staylor 	vtoc->efi_parts[0].p_size = slice_size;
25624276Staylor 
25634276Staylor 	/*
25644276Staylor 	 * Why we use V_USR: V_BACKUP confuses users, and is considered
25654276Staylor 	 * disposable by some EFI utilities (since EFI doesn't have a backup
25664276Staylor 	 * slice).  V_UNASSIGNED is supposed to be used only for zero size
25674276Staylor 	 * partitions, and efi_write() will fail if we use it.  V_ROOT, V_BOOT,
25684276Staylor 	 * etc. were all pretty specific.  V_USR is as close to reality as we
25694276Staylor 	 * can get, in the absence of V_OTHER.
25704276Staylor 	 */
25714276Staylor 	vtoc->efi_parts[0].p_tag = V_USR;
25724276Staylor 	(void) strcpy(vtoc->efi_parts[0].p_name, "zfs");
25734276Staylor 
25744276Staylor 	vtoc->efi_parts[8].p_start = slice_size + start_block;
25754276Staylor 	vtoc->efi_parts[8].p_size = resv;
25764276Staylor 	vtoc->efi_parts[8].p_tag = V_RESERVED;
25774276Staylor 
25784276Staylor 	if (efi_write(fd, vtoc) != 0) {
25794276Staylor 		/*
25804276Staylor 		 * Some block drivers (like pcata) may not support EFI
25814276Staylor 		 * GPT labels.  Print out a helpful error message dir-
25824276Staylor 		 * ecting the user to manually label the disk and give
25834276Staylor 		 * a specific slice.
25844276Staylor 		 */
25854276Staylor 		(void) close(fd);
25864276Staylor 		efi_free(vtoc);
25874276Staylor 
25884276Staylor 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
25894276Staylor 		    "cannot label '%s': try using fdisk(1M) and then "
25904276Staylor 		    "provide a specific slice"), name);
25914276Staylor 		return (zfs_error(hdl, EZFS_LABELFAILED, errbuf));
25924276Staylor 	}
25934276Staylor 
25944276Staylor 	(void) close(fd);
25954276Staylor 	efi_free(vtoc);
25964276Staylor 	return (0);
25974276Staylor }
2598