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 
51789Sahrens /*
52789Sahrens  * Validate the given pool name, optionally putting an extended error message in
53789Sahrens  * 'buf'.
54789Sahrens  */
552082Seschrock static boolean_t
562082Seschrock zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool)
57789Sahrens {
58789Sahrens 	namecheck_err_t why;
59789Sahrens 	char what;
601773Seschrock 	int ret;
61789Sahrens 
621773Seschrock 	ret = pool_namecheck(pool, &why, &what);
631773Seschrock 
641773Seschrock 	/*
651773Seschrock 	 * The rules for reserved pool names were extended at a later point.
661773Seschrock 	 * But we need to support users with existing pools that may now be
671773Seschrock 	 * invalid.  So we only check for this expanded set of names during a
681773Seschrock 	 * create (or import), and only in userland.
691773Seschrock 	 */
701773Seschrock 	if (ret == 0 && !isopen &&
711773Seschrock 	    (strncmp(pool, "mirror", 6) == 0 ||
721773Seschrock 	    strncmp(pool, "raidz", 5) == 0 ||
731773Seschrock 	    strncmp(pool, "spare", 5) == 0)) {
742082Seschrock 		zfs_error_aux(hdl,
752082Seschrock 		    dgettext(TEXT_DOMAIN, "name is reserved"));
762082Seschrock 		return (B_FALSE);
771773Seschrock 	}
781773Seschrock 
791773Seschrock 
801773Seschrock 	if (ret != 0) {
812082Seschrock 		if (hdl != NULL) {
82789Sahrens 			switch (why) {
831003Slling 			case NAME_ERR_TOOLONG:
842082Seschrock 				zfs_error_aux(hdl,
851003Slling 				    dgettext(TEXT_DOMAIN, "name is too long"));
861003Slling 				break;
871003Slling 
88789Sahrens 			case NAME_ERR_INVALCHAR:
892082Seschrock 				zfs_error_aux(hdl,
90789Sahrens 				    dgettext(TEXT_DOMAIN, "invalid character "
91789Sahrens 				    "'%c' in pool name"), what);
92789Sahrens 				break;
93789Sahrens 
94789Sahrens 			case NAME_ERR_NOLETTER:
952082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
962082Seschrock 				    "name must begin with a letter"));
97789Sahrens 				break;
98789Sahrens 
99789Sahrens 			case NAME_ERR_RESERVED:
1002082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1012082Seschrock 				    "name is reserved"));
102789Sahrens 				break;
103789Sahrens 
104789Sahrens 			case NAME_ERR_DISKLIKE:
1052082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1062082Seschrock 				    "pool name is reserved"));
107789Sahrens 				break;
1082856Snd150628 
1092856Snd150628 			case NAME_ERR_LEADING_SLASH:
1102856Snd150628 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1112856Snd150628 				    "leading slash in name"));
1122856Snd150628 				break;
1132856Snd150628 
1142856Snd150628 			case NAME_ERR_EMPTY_COMPONENT:
1152856Snd150628 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1162856Snd150628 				    "empty component in name"));
1172856Snd150628 				break;
1182856Snd150628 
1192856Snd150628 			case NAME_ERR_TRAILING_SLASH:
1202856Snd150628 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1212856Snd150628 				    "trailing slash in name"));
1222856Snd150628 				break;
1232856Snd150628 
1242856Snd150628 			case NAME_ERR_MULTIPLE_AT:
1252856Snd150628 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1262856Snd150628 				    "multiple '@' delimiters in name"));
1272856Snd150628 				break;
1282856Snd150628 
129789Sahrens 			}
130789Sahrens 		}
1312082Seschrock 		return (B_FALSE);
132789Sahrens 	}
133789Sahrens 
1342082Seschrock 	return (B_TRUE);
135789Sahrens }
136789Sahrens 
1373912Slling static int
1383912Slling zpool_get_all_props(zpool_handle_t *zhp)
1393912Slling {
1403912Slling 	zfs_cmd_t zc = { 0 };
1413912Slling 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1423912Slling 
1433912Slling 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1443912Slling 
1453912Slling 	if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0)
1463912Slling 		return (-1);
1473912Slling 
1483912Slling 	while (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) {
1493912Slling 		if (errno == ENOMEM) {
1503912Slling 			if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
1513912Slling 				zcmd_free_nvlists(&zc);
1523912Slling 				return (-1);
1533912Slling 			}
1543912Slling 		} else {
1553912Slling 			zcmd_free_nvlists(&zc);
1563912Slling 			return (-1);
1573912Slling 		}
1583912Slling 	}
1593912Slling 
1603912Slling 	if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) {
1613912Slling 		zcmd_free_nvlists(&zc);
1623912Slling 		return (-1);
1633912Slling 	}
1643912Slling 
1653912Slling 	zcmd_free_nvlists(&zc);
1663912Slling 
1673912Slling 	return (0);
1683912Slling }
1693912Slling 
170789Sahrens /*
171789Sahrens  * Open a handle to the given pool, even if the pool is currently in the FAULTED
172789Sahrens  * state.
173789Sahrens  */
174789Sahrens zpool_handle_t *
1752082Seschrock zpool_open_canfail(libzfs_handle_t *hdl, const char *pool)
176789Sahrens {
177789Sahrens 	zpool_handle_t *zhp;
1782142Seschrock 	boolean_t missing;
179789Sahrens 
180789Sahrens 	/*
181789Sahrens 	 * Make sure the pool name is valid.
182789Sahrens 	 */
1832082Seschrock 	if (!zpool_name_valid(hdl, B_TRUE, pool)) {
1843237Slling 		(void) zfs_error_fmt(hdl, EZFS_INVALIDNAME,
1852082Seschrock 		    dgettext(TEXT_DOMAIN, "cannot open '%s'"),
1862082Seschrock 		    pool);
187789Sahrens 		return (NULL);
188789Sahrens 	}
189789Sahrens 
1902082Seschrock 	if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
1912082Seschrock 		return (NULL);
192789Sahrens 
1932082Seschrock 	zhp->zpool_hdl = hdl;
194789Sahrens 	(void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
195789Sahrens 
1962142Seschrock 	if (zpool_refresh_stats(zhp, &missing) != 0) {
1972142Seschrock 		zpool_close(zhp);
1982142Seschrock 		return (NULL);
1992142Seschrock 	}
2002142Seschrock 
2012142Seschrock 	if (missing) {
2022142Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2032142Seschrock 		    "no such pool"));
2043237Slling 		(void) zfs_error_fmt(hdl, EZFS_NOENT,
2052142Seschrock 		    dgettext(TEXT_DOMAIN, "cannot open '%s'"),
2062142Seschrock 		    pool);
2072142Seschrock 		zpool_close(zhp);
2082142Seschrock 		return (NULL);
209789Sahrens 	}
210789Sahrens 
211789Sahrens 	return (zhp);
212789Sahrens }
213789Sahrens 
214789Sahrens /*
215789Sahrens  * Like the above, but silent on error.  Used when iterating over pools (because
216789Sahrens  * the configuration cache may be out of date).
217789Sahrens  */
2182142Seschrock int
2192142Seschrock zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret)
220789Sahrens {
221789Sahrens 	zpool_handle_t *zhp;
2222142Seschrock 	boolean_t missing;
223789Sahrens 
2242142Seschrock 	if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
2252142Seschrock 		return (-1);
226789Sahrens 
2272082Seschrock 	zhp->zpool_hdl = hdl;
228789Sahrens 	(void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
229789Sahrens 
2302142Seschrock 	if (zpool_refresh_stats(zhp, &missing) != 0) {
2312142Seschrock 		zpool_close(zhp);
2322142Seschrock 		return (-1);
233789Sahrens 	}
234789Sahrens 
2352142Seschrock 	if (missing) {
2362142Seschrock 		zpool_close(zhp);
2372142Seschrock 		*ret = NULL;
2382142Seschrock 		return (0);
2392142Seschrock 	}
2402142Seschrock 
2412142Seschrock 	*ret = zhp;
2422142Seschrock 	return (0);
243789Sahrens }
244789Sahrens 
245789Sahrens /*
246789Sahrens  * Similar to zpool_open_canfail(), but refuses to open pools in the faulted
247789Sahrens  * state.
248789Sahrens  */
249789Sahrens zpool_handle_t *
2502082Seschrock zpool_open(libzfs_handle_t *hdl, const char *pool)
251789Sahrens {
252789Sahrens 	zpool_handle_t *zhp;
253789Sahrens 
2542082Seschrock 	if ((zhp = zpool_open_canfail(hdl, pool)) == NULL)
255789Sahrens 		return (NULL);
256789Sahrens 
257789Sahrens 	if (zhp->zpool_state == POOL_STATE_UNAVAIL) {
2583237Slling 		(void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL,
2592082Seschrock 		    dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name);
260789Sahrens 		zpool_close(zhp);
261789Sahrens 		return (NULL);
262789Sahrens 	}
263789Sahrens 
264789Sahrens 	return (zhp);
265789Sahrens }
266789Sahrens 
267789Sahrens /*
268789Sahrens  * Close the handle.  Simply frees the memory associated with the handle.
269789Sahrens  */
270789Sahrens void
271789Sahrens zpool_close(zpool_handle_t *zhp)
272789Sahrens {
273789Sahrens 	if (zhp->zpool_config)
274789Sahrens 		nvlist_free(zhp->zpool_config);
275952Seschrock 	if (zhp->zpool_old_config)
276952Seschrock 		nvlist_free(zhp->zpool_old_config);
2773912Slling 	if (zhp->zpool_props)
2783912Slling 		nvlist_free(zhp->zpool_props);
279789Sahrens 	free(zhp);
280789Sahrens }
281789Sahrens 
282789Sahrens /*
283789Sahrens  * Return the name of the pool.
284789Sahrens  */
285789Sahrens const char *
286789Sahrens zpool_get_name(zpool_handle_t *zhp)
287789Sahrens {
288789Sahrens 	return (zhp->zpool_name);
289789Sahrens }
290789Sahrens 
291789Sahrens /*
292789Sahrens  * Return the GUID of the pool.
293789Sahrens  */
294789Sahrens uint64_t
295789Sahrens zpool_get_guid(zpool_handle_t *zhp)
296789Sahrens {
297789Sahrens 	uint64_t guid;
298789Sahrens 
299789Sahrens 	verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID,
300789Sahrens 	    &guid) == 0);
301789Sahrens 	return (guid);
302789Sahrens }
303789Sahrens 
304789Sahrens /*
3052082Seschrock  * Return the version of the pool.
3062082Seschrock  */
3072082Seschrock uint64_t
3082082Seschrock zpool_get_version(zpool_handle_t *zhp)
3092082Seschrock {
3102082Seschrock 	uint64_t version;
3112082Seschrock 
3122082Seschrock 	verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_VERSION,
3132082Seschrock 	    &version) == 0);
3142082Seschrock 
3152082Seschrock 	return (version);
3162082Seschrock }
3172082Seschrock 
3182082Seschrock /*
319789Sahrens  * Return the amount of space currently consumed by the pool.
320789Sahrens  */
321789Sahrens uint64_t
322789Sahrens zpool_get_space_used(zpool_handle_t *zhp)
323789Sahrens {
324789Sahrens 	nvlist_t *nvroot;
325789Sahrens 	vdev_stat_t *vs;
326789Sahrens 	uint_t vsc;
327789Sahrens 
328789Sahrens 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
329789Sahrens 	    &nvroot) == 0);
330789Sahrens 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
331789Sahrens 	    (uint64_t **)&vs, &vsc) == 0);
332789Sahrens 
333789Sahrens 	return (vs->vs_alloc);
334789Sahrens }
335789Sahrens 
336789Sahrens /*
337789Sahrens  * Return the total space in the pool.
338789Sahrens  */
339789Sahrens uint64_t
340789Sahrens zpool_get_space_total(zpool_handle_t *zhp)
341789Sahrens {
342789Sahrens 	nvlist_t *nvroot;
343789Sahrens 	vdev_stat_t *vs;
344789Sahrens 	uint_t vsc;
345789Sahrens 
346789Sahrens 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
347789Sahrens 	    &nvroot) == 0);
348789Sahrens 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
349789Sahrens 	    (uint64_t **)&vs, &vsc) == 0);
350789Sahrens 
351789Sahrens 	return (vs->vs_space);
352789Sahrens }
353789Sahrens 
354789Sahrens /*
355789Sahrens  * Return the alternate root for this pool, if any.
356789Sahrens  */
357789Sahrens int
358789Sahrens zpool_get_root(zpool_handle_t *zhp, char *buf, size_t buflen)
359789Sahrens {
360789Sahrens 	zfs_cmd_t zc = { 0 };
361789Sahrens 
362789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3632082Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 ||
3642676Seschrock 	    zc.zc_value[0] == '\0')
365789Sahrens 		return (-1);
366789Sahrens 
3672676Seschrock 	(void) strlcpy(buf, zc.zc_value, buflen);
368789Sahrens 
369789Sahrens 	return (0);
370789Sahrens }
371789Sahrens 
372789Sahrens /*
373789Sahrens  * Return the state of the pool (ACTIVE or UNAVAILABLE)
374789Sahrens  */
375789Sahrens int
376789Sahrens zpool_get_state(zpool_handle_t *zhp)
377789Sahrens {
378789Sahrens 	return (zhp->zpool_state);
379789Sahrens }
380789Sahrens 
381789Sahrens /*
382789Sahrens  * Create the named pool, using the provided vdev list.  It is assumed
383789Sahrens  * that the consumer has already validated the contents of the nvlist, so we
384789Sahrens  * don't have to worry about error semantics.
385789Sahrens  */
386789Sahrens int
3872082Seschrock zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
3882082Seschrock     const char *altroot)
389789Sahrens {
390789Sahrens 	zfs_cmd_t zc = { 0 };
3912082Seschrock 	char msg[1024];
3922082Seschrock 
3932082Seschrock 	(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
3942082Seschrock 	    "cannot create '%s'"), pool);
395789Sahrens 
3962082Seschrock 	if (!zpool_name_valid(hdl, B_FALSE, pool))
3972082Seschrock 		return (zfs_error(hdl, EZFS_INVALIDNAME, msg));
3982082Seschrock 
3992082Seschrock 	if (altroot != NULL && altroot[0] != '/')
4003237Slling 		return (zfs_error_fmt(hdl, EZFS_BADPATH,
4012082Seschrock 		    dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), altroot));
402789Sahrens 
4032676Seschrock 	if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0)
404789Sahrens 		return (-1);
405789Sahrens 
406789Sahrens 	(void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name));
407789Sahrens 
408789Sahrens 	if (altroot != NULL)
4092676Seschrock 		(void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value));
410789Sahrens 
4112082Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) {
4122676Seschrock 		zcmd_free_nvlists(&zc);
4132082Seschrock 
414789Sahrens 		switch (errno) {
415789Sahrens 		case EBUSY:
416789Sahrens 			/*
417789Sahrens 			 * This can happen if the user has specified the same
418789Sahrens 			 * device multiple times.  We can't reliably detect this
419789Sahrens 			 * until we try to add it and see we already have a
420789Sahrens 			 * label.
421789Sahrens 			 */
4222082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4232082Seschrock 			    "one or more vdevs refer to the same device"));
4242082Seschrock 			return (zfs_error(hdl, EZFS_BADDEV, msg));
425789Sahrens 
426789Sahrens 		case EOVERFLOW:
427789Sahrens 			/*
4282082Seschrock 			 * This occurs when one of the devices is below
429789Sahrens 			 * SPA_MINDEVSIZE.  Unfortunately, we can't detect which
430789Sahrens 			 * device was the problem device since there's no
431789Sahrens 			 * reliable way to determine device size from userland.
432789Sahrens 			 */
433789Sahrens 			{
434789Sahrens 				char buf[64];
435789Sahrens 
436789Sahrens 				zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
437789Sahrens 
4382082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4392082Seschrock 				    "one or more devices is less than the "
4402082Seschrock 				    "minimum size (%s)"), buf);
441789Sahrens 			}
4422082Seschrock 			return (zfs_error(hdl, EZFS_BADDEV, msg));
443789Sahrens 
444789Sahrens 		case ENOSPC:
4452082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4462082Seschrock 			    "one or more devices is out of space"));
4472082Seschrock 			return (zfs_error(hdl, EZFS_BADDEV, msg));
448789Sahrens 
449789Sahrens 		default:
4502082Seschrock 			return (zpool_standard_error(hdl, errno, msg));
451789Sahrens 		}
452789Sahrens 	}
453789Sahrens 
4542676Seschrock 	zcmd_free_nvlists(&zc);
455789Sahrens 
456789Sahrens 	/*
457789Sahrens 	 * If this is an alternate root pool, then we automatically set the
4582676Seschrock 	 * mountpoint of the root dataset to be '/'.
459789Sahrens 	 */
460789Sahrens 	if (altroot != NULL) {
461789Sahrens 		zfs_handle_t *zhp;
462789Sahrens 
4632082Seschrock 		verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_ANY)) != NULL);
4642676Seschrock 		verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
4652676Seschrock 		    "/") == 0);
466789Sahrens 
467789Sahrens 		zfs_close(zhp);
468789Sahrens 	}
469789Sahrens 
470789Sahrens 	return (0);
471789Sahrens }
472789Sahrens 
473789Sahrens /*
474789Sahrens  * Destroy the given pool.  It is up to the caller to ensure that there are no
475789Sahrens  * datasets left in the pool.
476789Sahrens  */
477789Sahrens int
478789Sahrens zpool_destroy(zpool_handle_t *zhp)
479789Sahrens {
480789Sahrens 	zfs_cmd_t zc = { 0 };
481789Sahrens 	zfs_handle_t *zfp = NULL;
4822082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
4832082Seschrock 	char msg[1024];
484789Sahrens 
485789Sahrens 	if (zhp->zpool_state == POOL_STATE_ACTIVE &&
4862082Seschrock 	    (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name,
4872082Seschrock 	    ZFS_TYPE_FILESYSTEM)) == NULL)
488789Sahrens 		return (-1);
489789Sahrens 
4902856Snd150628 	if (zpool_remove_zvol_links(zhp) != 0)
491789Sahrens 		return (-1);
492789Sahrens 
493789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
494789Sahrens 
4952082Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
4962082Seschrock 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
4972082Seschrock 		    "cannot destroy '%s'"), zhp->zpool_name);
498789Sahrens 
4992082Seschrock 		if (errno == EROFS) {
5002082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5012082Seschrock 			    "one or more devices is read only"));
5022082Seschrock 			(void) zfs_error(hdl, EZFS_BADDEV, msg);
5032082Seschrock 		} else {
5042082Seschrock 			(void) zpool_standard_error(hdl, errno, msg);
505789Sahrens 		}
506789Sahrens 
507789Sahrens 		if (zfp)
508789Sahrens 			zfs_close(zfp);
509789Sahrens 		return (-1);
510789Sahrens 	}
511789Sahrens 
512789Sahrens 	if (zfp) {
513789Sahrens 		remove_mountpoint(zfp);
514789Sahrens 		zfs_close(zfp);
515789Sahrens 	}
516789Sahrens 
517789Sahrens 	return (0);
518789Sahrens }
519789Sahrens 
520789Sahrens /*
521789Sahrens  * Add the given vdevs to the pool.  The caller must have already performed the
522789Sahrens  * necessary verification to ensure that the vdev specification is well-formed.
523789Sahrens  */
524789Sahrens int
525789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
526789Sahrens {
5272676Seschrock 	zfs_cmd_t zc = { 0 };
5282082Seschrock 	int ret;
5292082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
5302082Seschrock 	char msg[1024];
5312082Seschrock 	nvlist_t **spares;
5322082Seschrock 	uint_t nspares;
5332082Seschrock 
5342082Seschrock 	(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
5352082Seschrock 	    "cannot add to '%s'"), zhp->zpool_name);
5362082Seschrock 
5372082Seschrock 	if (zpool_get_version(zhp) < ZFS_VERSION_SPARES &&
5382082Seschrock 	    nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
5392082Seschrock 	    &spares, &nspares) == 0) {
5402082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
5412082Seschrock 		    "upgraded to add hot spares"));
5422082Seschrock 		return (zfs_error(hdl, EZFS_BADVERSION, msg));
5432082Seschrock 	}
544789Sahrens 
5452676Seschrock 	if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0)
5462082Seschrock 		return (-1);
547789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
548789Sahrens 
5492082Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) {
550789Sahrens 		switch (errno) {
551789Sahrens 		case EBUSY:
552789Sahrens 			/*
553789Sahrens 			 * This can happen if the user has specified the same
554789Sahrens 			 * device multiple times.  We can't reliably detect this
555789Sahrens 			 * until we try to add it and see we already have a
556789Sahrens 			 * label.
557789Sahrens 			 */
5582082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5592082Seschrock 			    "one or more vdevs refer to the same device"));
5602082Seschrock 			(void) zfs_error(hdl, EZFS_BADDEV, msg);
561789Sahrens 			break;
562789Sahrens 
563789Sahrens 		case EOVERFLOW:
564789Sahrens 			/*
565789Sahrens 			 * This occurrs when one of the devices is below
566789Sahrens 			 * SPA_MINDEVSIZE.  Unfortunately, we can't detect which
567789Sahrens 			 * device was the problem device since there's no
568789Sahrens 			 * reliable way to determine device size from userland.
569789Sahrens 			 */
570789Sahrens 			{
571789Sahrens 				char buf[64];
572789Sahrens 
573789Sahrens 				zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
574789Sahrens 
5752082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5762082Seschrock 				    "device is less than the minimum "
5772082Seschrock 				    "size (%s)"), buf);
578789Sahrens 			}
5792082Seschrock 			(void) zfs_error(hdl, EZFS_BADDEV, msg);
5802082Seschrock 			break;
5812082Seschrock 
5822082Seschrock 		case ENOTSUP:
5832082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5842082Seschrock 			    "pool must be upgraded to add raidz2 vdevs"));
5852082Seschrock 			(void) zfs_error(hdl, EZFS_BADVERSION, msg);
586789Sahrens 			break;
587789Sahrens 
5883912Slling 		case EDOM:
5893912Slling 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5904295Slling 			    "root pool can not have multiple vdevs"));
5913912Slling 			(void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg);
5923912Slling 			break;
5933912Slling 
594789Sahrens 		default:
5952082Seschrock 			(void) zpool_standard_error(hdl, errno, msg);
596789Sahrens 		}
597789Sahrens 
5982082Seschrock 		ret = -1;
5992082Seschrock 	} else {
6002082Seschrock 		ret = 0;
601789Sahrens 	}
602789Sahrens 
6032676Seschrock 	zcmd_free_nvlists(&zc);
604789Sahrens 
6052082Seschrock 	return (ret);
606789Sahrens }
607789Sahrens 
608789Sahrens /*
609789Sahrens  * Exports the pool from the system.  The caller must ensure that there are no
610789Sahrens  * mounted datasets in the pool.
611789Sahrens  */
612789Sahrens int
613789Sahrens zpool_export(zpool_handle_t *zhp)
614789Sahrens {
615789Sahrens 	zfs_cmd_t zc = { 0 };
616789Sahrens 
617789Sahrens 	if (zpool_remove_zvol_links(zhp) != 0)
618789Sahrens 		return (-1);
619789Sahrens 
620789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
621789Sahrens 
6222082Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_EXPORT, &zc) != 0)
6233237Slling 		return (zpool_standard_error_fmt(zhp->zpool_hdl, errno,
6242082Seschrock 		    dgettext(TEXT_DOMAIN, "cannot export '%s'"),
6252082Seschrock 		    zhp->zpool_name));
626789Sahrens 	return (0);
627789Sahrens }
628789Sahrens 
629789Sahrens /*
630789Sahrens  * Import the given pool using the known configuration.  The configuration
631789Sahrens  * should have come from zpool_find_import().  The 'newname' and 'altroot'
632789Sahrens  * parameters control whether the pool is imported with a different name or with
633789Sahrens  * an alternate root, respectively.
634789Sahrens  */
635789Sahrens int
6362082Seschrock zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
6372082Seschrock     const char *altroot)
638789Sahrens {
6392676Seschrock 	zfs_cmd_t zc = { 0 };
640789Sahrens 	char *thename;
641789Sahrens 	char *origname;
642789Sahrens 	int ret;
643789Sahrens 
644789Sahrens 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
645789Sahrens 	    &origname) == 0);
646789Sahrens 
647789Sahrens 	if (newname != NULL) {
6482082Seschrock 		if (!zpool_name_valid(hdl, B_FALSE, newname))
6493237Slling 			return (zfs_error_fmt(hdl, EZFS_INVALIDNAME,
6502082Seschrock 			    dgettext(TEXT_DOMAIN, "cannot import '%s'"),
6512082Seschrock 			    newname));
652789Sahrens 		thename = (char *)newname;
653789Sahrens 	} else {
654789Sahrens 		thename = origname;
655789Sahrens 	}
656789Sahrens 
6572082Seschrock 	if (altroot != NULL && altroot[0] != '/')
6583237Slling 		return (zfs_error_fmt(hdl, EZFS_BADPATH,
6592082Seschrock 		    dgettext(TEXT_DOMAIN, "bad alternate root '%s'"),
6602082Seschrock 		    altroot));
661789Sahrens 
662789Sahrens 	(void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name));
663789Sahrens 
664789Sahrens 	if (altroot != NULL)
6652676Seschrock 		(void) strlcpy(zc.zc_value, altroot, sizeof (zc.zc_value));
666789Sahrens 	else
6672676Seschrock 		zc.zc_value[0] = '\0';
668789Sahrens 
669789Sahrens 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
6701544Seschrock 	    &zc.zc_guid) == 0);
671789Sahrens 
6722676Seschrock 	if (zcmd_write_src_nvlist(hdl, &zc, config, NULL) != 0)
6732082Seschrock 		return (-1);
674789Sahrens 
675789Sahrens 	ret = 0;
6762082Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) {
677789Sahrens 		char desc[1024];
678789Sahrens 		if (newname == NULL)
679789Sahrens 			(void) snprintf(desc, sizeof (desc),
680789Sahrens 			    dgettext(TEXT_DOMAIN, "cannot import '%s'"),
681789Sahrens 			    thename);
682789Sahrens 		else
683789Sahrens 			(void) snprintf(desc, sizeof (desc),
684789Sahrens 			    dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"),
685789Sahrens 			    origname, thename);
686789Sahrens 
687789Sahrens 		switch (errno) {
6881544Seschrock 		case ENOTSUP:
6891544Seschrock 			/*
6901544Seschrock 			 * Unsupported version.
6911544Seschrock 			 */
6922082Seschrock 			(void) zfs_error(hdl, EZFS_BADVERSION, desc);
6931544Seschrock 			break;
6941544Seschrock 
6952174Seschrock 		case EINVAL:
6962174Seschrock 			(void) zfs_error(hdl, EZFS_INVALCONFIG, desc);
6972174Seschrock 			break;
6982174Seschrock 
699789Sahrens 		default:
7002082Seschrock 			(void) zpool_standard_error(hdl, errno, desc);
701789Sahrens 		}
702789Sahrens 
703789Sahrens 		ret = -1;
704789Sahrens 	} else {
705789Sahrens 		zpool_handle_t *zhp;
706789Sahrens 		/*
707789Sahrens 		 * This should never fail, but play it safe anyway.
708789Sahrens 		 */
7092142Seschrock 		if (zpool_open_silent(hdl, thename, &zhp) != 0) {
7102142Seschrock 			ret = -1;
7112142Seschrock 		} else if (zhp != NULL) {
712789Sahrens 			ret = zpool_create_zvol_links(zhp);
713789Sahrens 			zpool_close(zhp);
714789Sahrens 		}
715789Sahrens 	}
716789Sahrens 
7172676Seschrock 	zcmd_free_nvlists(&zc);
718789Sahrens 	return (ret);
719789Sahrens }
720789Sahrens 
721789Sahrens /*
722789Sahrens  * Scrub the pool.
723789Sahrens  */
724789Sahrens int
725789Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type)
726789Sahrens {
727789Sahrens 	zfs_cmd_t zc = { 0 };
728789Sahrens 	char msg[1024];
7292082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
730789Sahrens 
731789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
732789Sahrens 	zc.zc_cookie = type;
733789Sahrens 
7342082Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_SCRUB, &zc) == 0)
735789Sahrens 		return (0);
736789Sahrens 
737789Sahrens 	(void) snprintf(msg, sizeof (msg),
738789Sahrens 	    dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name);
739789Sahrens 
7402082Seschrock 	if (errno == EBUSY)
7412082Seschrock 		return (zfs_error(hdl, EZFS_RESILVERING, msg));
7422082Seschrock 	else
7432082Seschrock 		return (zpool_standard_error(hdl, errno, msg));
744789Sahrens }
745789Sahrens 
7462468Sek110237 /*
7472468Sek110237  * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL
7482468Sek110237  * spare; but FALSE if its an INUSE spare.
7492468Sek110237  */
7502082Seschrock static nvlist_t *
7512082Seschrock vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid,
7522468Sek110237     boolean_t *avail_spare)
7531544Seschrock {
7541544Seschrock 	uint_t c, children;
7551544Seschrock 	nvlist_t **child;
7562082Seschrock 	uint64_t theguid, present;
7571544Seschrock 	char *path;
7581544Seschrock 	uint64_t wholedisk = 0;
7592082Seschrock 	nvlist_t *ret;
7601544Seschrock 
7612082Seschrock 	verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0);
7621544Seschrock 
7631544Seschrock 	if (search == NULL &&
7641544Seschrock 	    nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) {
7651544Seschrock 		/*
7661544Seschrock 		 * If the device has never been present since import, the only
7671544Seschrock 		 * reliable way to match the vdev is by GUID.
7681544Seschrock 		 */
7692082Seschrock 		if (theguid == guid)
7702082Seschrock 			return (nv);
7711544Seschrock 	} else if (search != NULL &&
7721544Seschrock 	    nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
7731544Seschrock 		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
7741544Seschrock 		    &wholedisk);
7751544Seschrock 		if (wholedisk) {
7761544Seschrock 			/*
7771544Seschrock 			 * For whole disks, the internal path has 's0', but the
7781544Seschrock 			 * path passed in by the user doesn't.
7791544Seschrock 			 */
7801544Seschrock 			if (strlen(search) == strlen(path) - 2 &&
7811544Seschrock 			    strncmp(search, path, strlen(search)) == 0)
7822082Seschrock 				return (nv);
7831544Seschrock 		} else if (strcmp(search, path) == 0) {
7842082Seschrock 			return (nv);
7851544Seschrock 		}
7861544Seschrock 	}
7871544Seschrock 
7881544Seschrock 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
7891544Seschrock 	    &child, &children) != 0)
7902082Seschrock 		return (NULL);
7911544Seschrock 
7921544Seschrock 	for (c = 0; c < children; c++)
7932082Seschrock 		if ((ret = vdev_to_nvlist_iter(child[c], search, guid,
7942468Sek110237 		    avail_spare)) != NULL)
7951544Seschrock 			return (ret);
7961544Seschrock 
7972082Seschrock 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
7982082Seschrock 	    &child, &children) == 0) {
7992082Seschrock 		for (c = 0; c < children; c++) {
8002082Seschrock 			if ((ret = vdev_to_nvlist_iter(child[c], search, guid,
8012468Sek110237 			    avail_spare)) != NULL) {
8022468Sek110237 				*avail_spare = B_TRUE;
8032082Seschrock 				return (ret);
8042082Seschrock 			}
8052082Seschrock 		}
8062082Seschrock 	}
8072082Seschrock 
8082082Seschrock 	return (NULL);
8091544Seschrock }
8101544Seschrock 
8112082Seschrock nvlist_t *
8122468Sek110237 zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare)
8131544Seschrock {
8141544Seschrock 	char buf[MAXPATHLEN];
8151544Seschrock 	const char *search;
8161544Seschrock 	char *end;
8171544Seschrock 	nvlist_t *nvroot;
8181544Seschrock 	uint64_t guid;
8191544Seschrock 
8201613Seschrock 	guid = strtoull(path, &end, 10);
8211544Seschrock 	if (guid != 0 && *end == '\0') {
8221544Seschrock 		search = NULL;
8231544Seschrock 	} else if (path[0] != '/') {
8241544Seschrock 		(void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path);
8251544Seschrock 		search = buf;
8261544Seschrock 	} else {
8271544Seschrock 		search = path;
8281544Seschrock 	}
8291544Seschrock 
8301544Seschrock 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
8311544Seschrock 	    &nvroot) == 0);
8321544Seschrock 
8332468Sek110237 	*avail_spare = B_FALSE;
8342468Sek110237 	return (vdev_to_nvlist_iter(nvroot, search, guid, avail_spare));
8352468Sek110237 }
8362468Sek110237 
8372468Sek110237 /*
8382468Sek110237  * Returns TRUE if the given guid corresponds to a spare (INUSE or not).
8392468Sek110237  */
8402468Sek110237 static boolean_t
8412468Sek110237 is_spare(zpool_handle_t *zhp, uint64_t guid)
8422468Sek110237 {
8432468Sek110237 	uint64_t spare_guid;
8442468Sek110237 	nvlist_t *nvroot;
8452468Sek110237 	nvlist_t **spares;
8462468Sek110237 	uint_t nspares;
8472468Sek110237 	int i;
8482468Sek110237 
8492468Sek110237 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
8502468Sek110237 	    &nvroot) == 0);
8512468Sek110237 	if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
8522468Sek110237 	    &spares, &nspares) == 0) {
8532468Sek110237 		for (i = 0; i < nspares; i++) {
8542468Sek110237 			verify(nvlist_lookup_uint64(spares[i],
8552468Sek110237 			    ZPOOL_CONFIG_GUID, &spare_guid) == 0);
8562468Sek110237 			if (guid == spare_guid)
8572468Sek110237 				return (B_TRUE);
8582468Sek110237 		}
8592468Sek110237 	}
8602468Sek110237 
8612468Sek110237 	return (B_FALSE);
8621544Seschrock }
8631544Seschrock 
864789Sahrens /*
865*4451Seschrock  * Bring the specified vdev online.   The 'flags' parameter is a set of the
866*4451Seschrock  * ZFS_ONLINE_* flags.
867789Sahrens  */
868789Sahrens int
869*4451Seschrock zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
870*4451Seschrock     vdev_state_t *newstate)
871789Sahrens {
872789Sahrens 	zfs_cmd_t zc = { 0 };
873789Sahrens 	char msg[1024];
8742082Seschrock 	nvlist_t *tgt;
8752468Sek110237 	boolean_t avail_spare;
8762082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
877789Sahrens 
8781544Seschrock 	(void) snprintf(msg, sizeof (msg),
8791544Seschrock 	    dgettext(TEXT_DOMAIN, "cannot online %s"), path);
880789Sahrens 
8811544Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
8822468Sek110237 	if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL)
8832082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
884789Sahrens 
8852468Sek110237 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
8862468Sek110237 
8872468Sek110237 	if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE)
8882082Seschrock 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
8892082Seschrock 
890*4451Seschrock 	zc.zc_cookie = VDEV_STATE_ONLINE;
891*4451Seschrock 	zc.zc_obj = flags;
892*4451Seschrock 
893789Sahrens 
894*4451Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) != 0)
895*4451Seschrock 		return (zpool_standard_error(hdl, errno, msg));
896*4451Seschrock 
897*4451Seschrock 	*newstate = zc.zc_cookie;
898*4451Seschrock 	return (0);
899789Sahrens }
900789Sahrens 
901789Sahrens /*
902789Sahrens  * Take the specified vdev offline
903789Sahrens  */
904789Sahrens int
905*4451Seschrock zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
906789Sahrens {
907789Sahrens 	zfs_cmd_t zc = { 0 };
908789Sahrens 	char msg[1024];
9092082Seschrock 	nvlist_t *tgt;
9102468Sek110237 	boolean_t avail_spare;
9112082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
912789Sahrens 
9131544Seschrock 	(void) snprintf(msg, sizeof (msg),
9141544Seschrock 	    dgettext(TEXT_DOMAIN, "cannot offline %s"), path);
9151544Seschrock 
916789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
9172468Sek110237 	if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == NULL)
9182082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
9192082Seschrock 
9202468Sek110237 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
9212468Sek110237 
9222468Sek110237 	if (avail_spare || is_spare(zhp, zc.zc_guid) == B_TRUE)
9232082Seschrock 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
9242082Seschrock 
925*4451Seschrock 	zc.zc_cookie = VDEV_STATE_OFFLINE;
926*4451Seschrock 	zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0;
9271485Slling 
928*4451Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
929789Sahrens 		return (0);
930789Sahrens 
931789Sahrens 	switch (errno) {
9322082Seschrock 	case EBUSY:
933789Sahrens 
934789Sahrens 		/*
935789Sahrens 		 * There are no other replicas of this device.
936789Sahrens 		 */
9372082Seschrock 		return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
9382082Seschrock 
9392082Seschrock 	default:
9402082Seschrock 		return (zpool_standard_error(hdl, errno, msg));
9412082Seschrock 	}
9422082Seschrock }
943789Sahrens 
9442082Seschrock /*
945*4451Seschrock  * Mark the given vdev faulted.
946*4451Seschrock  */
947*4451Seschrock int
948*4451Seschrock zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid)
949*4451Seschrock {
950*4451Seschrock 	zfs_cmd_t zc = { 0 };
951*4451Seschrock 	char msg[1024];
952*4451Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
953*4451Seschrock 
954*4451Seschrock 	(void) snprintf(msg, sizeof (msg),
955*4451Seschrock 	    dgettext(TEXT_DOMAIN, "cannot fault %llu"), guid);
956*4451Seschrock 
957*4451Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
958*4451Seschrock 	zc.zc_guid = guid;
959*4451Seschrock 	zc.zc_cookie = VDEV_STATE_FAULTED;
960*4451Seschrock 
961*4451Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
962*4451Seschrock 		return (0);
963*4451Seschrock 
964*4451Seschrock 	switch (errno) {
965*4451Seschrock 	case EBUSY:
966*4451Seschrock 
967*4451Seschrock 		/*
968*4451Seschrock 		 * There are no other replicas of this device.
969*4451Seschrock 		 */
970*4451Seschrock 		return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
971*4451Seschrock 
972*4451Seschrock 	default:
973*4451Seschrock 		return (zpool_standard_error(hdl, errno, msg));
974*4451Seschrock 	}
975*4451Seschrock 
976*4451Seschrock }
977*4451Seschrock 
978*4451Seschrock /*
979*4451Seschrock  * Mark the given vdev degraded.
980*4451Seschrock  */
981*4451Seschrock int
982*4451Seschrock zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid)
983*4451Seschrock {
984*4451Seschrock 	zfs_cmd_t zc = { 0 };
985*4451Seschrock 	char msg[1024];
986*4451Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
987*4451Seschrock 
988*4451Seschrock 	(void) snprintf(msg, sizeof (msg),
989*4451Seschrock 	    dgettext(TEXT_DOMAIN, "cannot degrade %llu"), guid);
990*4451Seschrock 
991*4451Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
992*4451Seschrock 	zc.zc_guid = guid;
993*4451Seschrock 	zc.zc_cookie = VDEV_STATE_DEGRADED;
994*4451Seschrock 
995*4451Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
996*4451Seschrock 		return (0);
997*4451Seschrock 
998*4451Seschrock 	return (zpool_standard_error(hdl, errno, msg));
999*4451Seschrock }
1000*4451Seschrock 
1001*4451Seschrock /*
10022082Seschrock  * Returns TRUE if the given nvlist is a vdev that was originally swapped in as
10032082Seschrock  * a hot spare.
10042082Seschrock  */
10052082Seschrock static boolean_t
10062082Seschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which)
10072082Seschrock {
10082082Seschrock 	nvlist_t **child;
10092082Seschrock 	uint_t c, children;
10102082Seschrock 	char *type;
10112082Seschrock 
10122082Seschrock 	if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child,
10132082Seschrock 	    &children) == 0) {
10142082Seschrock 		verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE,
10152082Seschrock 		    &type) == 0);
10162082Seschrock 
10172082Seschrock 		if (strcmp(type, VDEV_TYPE_SPARE) == 0 &&
10182082Seschrock 		    children == 2 && child[which] == tgt)
10192082Seschrock 			return (B_TRUE);
10202082Seschrock 
10212082Seschrock 		for (c = 0; c < children; c++)
10222082Seschrock 			if (is_replacing_spare(child[c], tgt, which))
10232082Seschrock 				return (B_TRUE);
1024789Sahrens 	}
10252082Seschrock 
10262082Seschrock 	return (B_FALSE);
1027789Sahrens }
1028789Sahrens 
1029789Sahrens /*
1030789Sahrens  * Attach new_disk (fully described by nvroot) to old_disk.
1031789Sahrens  * If 'replacing' is specified, tne new disk will replace the old one.
1032789Sahrens  */
1033789Sahrens int
1034789Sahrens zpool_vdev_attach(zpool_handle_t *zhp,
1035789Sahrens     const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing)
1036789Sahrens {
1037789Sahrens 	zfs_cmd_t zc = { 0 };
1038789Sahrens 	char msg[1024];
1039789Sahrens 	int ret;
10402082Seschrock 	nvlist_t *tgt;
10412468Sek110237 	boolean_t avail_spare;
10422082Seschrock 	uint64_t val;
10432082Seschrock 	char *path;
10442082Seschrock 	nvlist_t **child;
10452082Seschrock 	uint_t children;
10462082Seschrock 	nvlist_t *config_root;
10472082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1048789Sahrens 
10491544Seschrock 	if (replacing)
10501544Seschrock 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
10511544Seschrock 		    "cannot replace %s with %s"), old_disk, new_disk);
10521544Seschrock 	else
10531544Seschrock 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
10541544Seschrock 		    "cannot attach %s to %s"), new_disk, old_disk);
10551544Seschrock 
1056789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
10572468Sek110237 	if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare)) == 0)
10582082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
10592082Seschrock 
10602468Sek110237 	if (avail_spare)
10612082Seschrock 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
10622082Seschrock 
10632082Seschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
10642082Seschrock 	zc.zc_cookie = replacing;
10652082Seschrock 
10662082Seschrock 	if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
10672082Seschrock 	    &child, &children) != 0 || children != 1) {
10682082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
10692082Seschrock 		    "new device must be a single disk"));
10702082Seschrock 		return (zfs_error(hdl, EZFS_INVALCONFIG, msg));
10711544Seschrock 	}
10722082Seschrock 
10732082Seschrock 	verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
10742082Seschrock 	    ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0);
10752082Seschrock 
10762082Seschrock 	/*
10772082Seschrock 	 * If the target is a hot spare that has been swapped in, we can only
10782082Seschrock 	 * replace it with another hot spare.
10792082Seschrock 	 */
10802082Seschrock 	if (replacing &&
10812082Seschrock 	    nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 &&
10822082Seschrock 	    nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 &&
10832468Sek110237 	    (zpool_find_vdev(zhp, path, &avail_spare) == NULL ||
10842468Sek110237 	    !avail_spare) && is_replacing_spare(config_root, tgt, 1)) {
10852082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
10862082Seschrock 		    "can only be replaced by another hot spare"));
10872082Seschrock 		return (zfs_error(hdl, EZFS_BADTARGET, msg));
10882082Seschrock 	}
10892082Seschrock 
10902082Seschrock 	/*
10912082Seschrock 	 * If we are attempting to replace a spare, it canot be applied to an
10922082Seschrock 	 * already spared device.
10932082Seschrock 	 */
10942082Seschrock 	if (replacing &&
10952082Seschrock 	    nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 &&
10962468Sek110237 	    zpool_find_vdev(zhp, path, &avail_spare) != NULL && avail_spare &&
10972082Seschrock 	    is_replacing_spare(config_root, tgt, 0)) {
10982082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
10992082Seschrock 		    "device has already been replaced with a spare"));
11002082Seschrock 		return (zfs_error(hdl, EZFS_BADTARGET, msg));
11012082Seschrock 	}
1102789Sahrens 
11032676Seschrock 	if (zcmd_write_src_nvlist(hdl, &zc, nvroot, NULL) != 0)
11042082Seschrock 		return (-1);
1105789Sahrens 
11062082Seschrock 	ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ATTACH, &zc);
1107789Sahrens 
11082676Seschrock 	zcmd_free_nvlists(&zc);
1109789Sahrens 
1110789Sahrens 	if (ret == 0)
1111789Sahrens 		return (0);
1112789Sahrens 
1113789Sahrens 	switch (errno) {
11141544Seschrock 	case ENOTSUP:
1115789Sahrens 		/*
1116789Sahrens 		 * Can't attach to or replace this type of vdev.
1117789Sahrens 		 */
1118789Sahrens 		if (replacing)
11192082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
11202082Seschrock 			    "cannot replace a replacing device"));
1121789Sahrens 		else
11222082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
11232082Seschrock 			    "can only attach to mirrors and top-level "
11242082Seschrock 			    "disks"));
11252082Seschrock 		(void) zfs_error(hdl, EZFS_BADTARGET, msg);
1126789Sahrens 		break;
1127789Sahrens 
11281544Seschrock 	case EINVAL:
1129789Sahrens 		/*
1130789Sahrens 		 * The new device must be a single disk.
1131789Sahrens 		 */
11322082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
11332082Seschrock 		    "new device must be a single disk"));
11342082Seschrock 		(void) zfs_error(hdl, EZFS_INVALCONFIG, msg);
1135789Sahrens 		break;
1136789Sahrens 
11371544Seschrock 	case EBUSY:
11382082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"),
11392082Seschrock 		    new_disk);
11402082Seschrock 		(void) zfs_error(hdl, EZFS_BADDEV, msg);
1141789Sahrens 		break;
1142789Sahrens 
11431544Seschrock 	case EOVERFLOW:
1144789Sahrens 		/*
1145789Sahrens 		 * The new device is too small.
1146789Sahrens 		 */
11472082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
11482082Seschrock 		    "device is too small"));
11492082Seschrock 		(void) zfs_error(hdl, EZFS_BADDEV, msg);
1150789Sahrens 		break;
1151789Sahrens 
11521544Seschrock 	case EDOM:
1153789Sahrens 		/*
1154789Sahrens 		 * The new device has a different alignment requirement.
1155789Sahrens 		 */
11562082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
11572082Seschrock 		    "devices have different sector alignment"));
11582082Seschrock 		(void) zfs_error(hdl, EZFS_BADDEV, msg);
1159789Sahrens 		break;
1160789Sahrens 
11611544Seschrock 	case ENAMETOOLONG:
1162789Sahrens 		/*
1163789Sahrens 		 * The resulting top-level vdev spec won't fit in the label.
1164789Sahrens 		 */
11652082Seschrock 		(void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg);
1166789Sahrens 		break;
1167789Sahrens 
11681544Seschrock 	default:
11692082Seschrock 		(void) zpool_standard_error(hdl, errno, msg);
1170789Sahrens 	}
1171789Sahrens 
11722082Seschrock 	return (-1);
1173789Sahrens }
1174789Sahrens 
1175789Sahrens /*
1176789Sahrens  * Detach the specified device.
1177789Sahrens  */
1178789Sahrens int
1179789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path)
1180789Sahrens {
1181789Sahrens 	zfs_cmd_t zc = { 0 };
1182789Sahrens 	char msg[1024];
11832082Seschrock 	nvlist_t *tgt;
11842468Sek110237 	boolean_t avail_spare;
11852082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1186789Sahrens 
11871544Seschrock 	(void) snprintf(msg, sizeof (msg),
11881544Seschrock 	    dgettext(TEXT_DOMAIN, "cannot detach %s"), path);
11891544Seschrock 
1190789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
11912468Sek110237 	if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0)
11922082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
1193789Sahrens 
11942468Sek110237 	if (avail_spare)
11952082Seschrock 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
11962082Seschrock 
11972082Seschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
11982082Seschrock 
11992082Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_DETACH, &zc) == 0)
1200789Sahrens 		return (0);
1201789Sahrens 
1202789Sahrens 	switch (errno) {
1203789Sahrens 
12041544Seschrock 	case ENOTSUP:
1205789Sahrens 		/*
1206789Sahrens 		 * Can't detach from this type of vdev.
1207789Sahrens 		 */
12082082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only "
12092082Seschrock 		    "applicable to mirror and replacing vdevs"));
12102082Seschrock 		(void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg);
1211789Sahrens 		break;
1212789Sahrens 
12131544Seschrock 	case EBUSY:
1214789Sahrens 		/*
1215789Sahrens 		 * There are no other replicas of this device.
1216789Sahrens 		 */
12172082Seschrock 		(void) zfs_error(hdl, EZFS_NOREPLICAS, msg);
1218789Sahrens 		break;
1219789Sahrens 
12201544Seschrock 	default:
12212082Seschrock 		(void) zpool_standard_error(hdl, errno, msg);
12221544Seschrock 	}
12231544Seschrock 
12242082Seschrock 	return (-1);
12252082Seschrock }
12262082Seschrock 
12272082Seschrock /*
12282082Seschrock  * Remove the given device.  Currently, this is supported only for hot spares.
12292082Seschrock  */
12302082Seschrock int
12312082Seschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path)
12322082Seschrock {
12332082Seschrock 	zfs_cmd_t zc = { 0 };
12342082Seschrock 	char msg[1024];
12352082Seschrock 	nvlist_t *tgt;
12362468Sek110237 	boolean_t avail_spare;
12372082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
12382082Seschrock 
12392082Seschrock 	(void) snprintf(msg, sizeof (msg),
12402082Seschrock 	    dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
12412082Seschrock 
12422082Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
12432468Sek110237 	if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0)
12442082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
12452082Seschrock 
12462468Sek110237 	if (!avail_spare) {
12472082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
12483377Seschrock 		    "only inactive hot spares can be removed"));
12492082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
12502082Seschrock 	}
12512082Seschrock 
12522082Seschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
12532082Seschrock 
12542082Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_REMOVE, &zc) == 0)
12552082Seschrock 		return (0);
12562082Seschrock 
12572082Seschrock 	return (zpool_standard_error(hdl, errno, msg));
12581544Seschrock }
12591544Seschrock 
12601544Seschrock /*
12611544Seschrock  * Clear the errors for the pool, or the particular device if specified.
12621544Seschrock  */
12631544Seschrock int
12641544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path)
12651544Seschrock {
12661544Seschrock 	zfs_cmd_t zc = { 0 };
12671544Seschrock 	char msg[1024];
12682082Seschrock 	nvlist_t *tgt;
12692468Sek110237 	boolean_t avail_spare;
12702082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
12711544Seschrock 
12721544Seschrock 	if (path)
12731544Seschrock 		(void) snprintf(msg, sizeof (msg),
12741544Seschrock 		    dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
12752676Seschrock 		    path);
12761544Seschrock 	else
12771544Seschrock 		(void) snprintf(msg, sizeof (msg),
12781544Seschrock 		    dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
12791544Seschrock 		    zhp->zpool_name);
12801544Seschrock 
12811544Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
12822082Seschrock 	if (path) {
12832468Sek110237 		if ((tgt = zpool_find_vdev(zhp, path, &avail_spare)) == 0)
12842082Seschrock 			return (zfs_error(hdl, EZFS_NODEVICE, msg));
12852082Seschrock 
12862468Sek110237 		if (avail_spare)
12872082Seschrock 			return (zfs_error(hdl, EZFS_ISSPARE, msg));
12882082Seschrock 
12892082Seschrock 		verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID,
12902082Seschrock 		    &zc.zc_guid) == 0);
12911544Seschrock 	}
12921544Seschrock 
12932082Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0)
12941544Seschrock 		return (0);
12951544Seschrock 
12962082Seschrock 	return (zpool_standard_error(hdl, errno, msg));
1297789Sahrens }
1298789Sahrens 
12993126Sahl /*
1300*4451Seschrock  * Similar to zpool_clear(), but takes a GUID (used by fmd).
1301*4451Seschrock  */
1302*4451Seschrock int
1303*4451Seschrock zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid)
1304*4451Seschrock {
1305*4451Seschrock 	zfs_cmd_t zc = { 0 };
1306*4451Seschrock 	char msg[1024];
1307*4451Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1308*4451Seschrock 
1309*4451Seschrock 	(void) snprintf(msg, sizeof (msg),
1310*4451Seschrock 	    dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"),
1311*4451Seschrock 	    guid);
1312*4451Seschrock 
1313*4451Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1314*4451Seschrock 	zc.zc_guid = guid;
1315*4451Seschrock 
1316*4451Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0)
1317*4451Seschrock 		return (0);
1318*4451Seschrock 
1319*4451Seschrock 	return (zpool_standard_error(hdl, errno, msg));
1320*4451Seschrock }
1321*4451Seschrock 
1322*4451Seschrock /*
13233126Sahl  * Iterate over all zvols in a given pool by walking the /dev/zvol/dsk/<pool>
13243126Sahl  * hierarchy.
13253126Sahl  */
13263126Sahl int
13273126Sahl zpool_iter_zvol(zpool_handle_t *zhp, int (*cb)(const char *, void *),
13283126Sahl     void *data)
1329789Sahrens {
13303126Sahl 	libzfs_handle_t *hdl = zhp->zpool_hdl;
13313126Sahl 	char (*paths)[MAXPATHLEN];
13323126Sahl 	size_t size = 4;
13333126Sahl 	int curr, fd, base, ret = 0;
13343126Sahl 	DIR *dirp;
13353126Sahl 	struct dirent *dp;
13363126Sahl 	struct stat st;
13373126Sahl 
13383126Sahl 	if ((base = open("/dev/zvol/dsk", O_RDONLY)) < 0)
13393126Sahl 		return (errno == ENOENT ? 0 : -1);
13403126Sahl 
13413126Sahl 	if (fstatat(base, zhp->zpool_name, &st, 0) != 0) {
13423126Sahl 		int err = errno;
13433126Sahl 		(void) close(base);
13443126Sahl 		return (err == ENOENT ? 0 : -1);
13453126Sahl 	}
1346789Sahrens 
1347789Sahrens 	/*
13483126Sahl 	 * Oddly this wasn't a directory -- ignore that failure since we
13493126Sahl 	 * know there are no links lower in the (non-existant) hierarchy.
1350789Sahrens 	 */
13513126Sahl 	if (!S_ISDIR(st.st_mode)) {
13523126Sahl 		(void) close(base);
13533126Sahl 		return (0);
13543126Sahl 	}
13553126Sahl 
13563126Sahl 	if ((paths = zfs_alloc(hdl, size * sizeof (paths[0]))) == NULL) {
13573126Sahl 		(void) close(base);
13583126Sahl 		return (-1);
1359789Sahrens 	}
1360789Sahrens 
13613126Sahl 	(void) strlcpy(paths[0], zhp->zpool_name, sizeof (paths[0]));
13623126Sahl 	curr = 0;
13633126Sahl 
13643126Sahl 	while (curr >= 0) {
13653126Sahl 		if (fstatat(base, paths[curr], &st, AT_SYMLINK_NOFOLLOW) != 0)
13663126Sahl 			goto err;
13673126Sahl 
13683126Sahl 		if (S_ISDIR(st.st_mode)) {
13693126Sahl 			if ((fd = openat(base, paths[curr], O_RDONLY)) < 0)
13703126Sahl 				goto err;
13713126Sahl 
13723126Sahl 			if ((dirp = fdopendir(fd)) == NULL) {
13733126Sahl 				(void) close(fd);
13743126Sahl 				goto err;
13753126Sahl 			}
13763126Sahl 
13773126Sahl 			while ((dp = readdir(dirp)) != NULL) {
13783126Sahl 				if (dp->d_name[0] == '.')
13793126Sahl 					continue;
13803126Sahl 
13813126Sahl 				if (curr + 1 == size) {
13823126Sahl 					paths = zfs_realloc(hdl, paths,
13833126Sahl 					    size * sizeof (paths[0]),
13843126Sahl 					    size * 2 * sizeof (paths[0]));
13853126Sahl 					if (paths == NULL) {
13863126Sahl 						(void) closedir(dirp);
13873126Sahl 						(void) close(fd);
13883126Sahl 						goto err;
13893126Sahl 					}
13903126Sahl 
13913126Sahl 					size *= 2;
13923126Sahl 				}
13933126Sahl 
13943126Sahl 				(void) strlcpy(paths[curr + 1], paths[curr],
13953126Sahl 				    sizeof (paths[curr + 1]));
13963126Sahl 				(void) strlcat(paths[curr], "/",
13973126Sahl 				    sizeof (paths[curr]));
13983126Sahl 				(void) strlcat(paths[curr], dp->d_name,
13993126Sahl 				    sizeof (paths[curr]));
14003126Sahl 				curr++;
14013126Sahl 			}
14023126Sahl 
14033126Sahl 			(void) closedir(dirp);
14043126Sahl 
14053126Sahl 		} else {
14063126Sahl 			if ((ret = cb(paths[curr], data)) != 0)
14073126Sahl 				break;
14083126Sahl 		}
14093126Sahl 
14103126Sahl 		curr--;
14113126Sahl 	}
14123126Sahl 
14133126Sahl 	free(paths);
14143126Sahl 	(void) close(base);
14153126Sahl 
14163126Sahl 	return (ret);
14173126Sahl 
14183126Sahl err:
14193126Sahl 	free(paths);
14203126Sahl 	(void) close(base);
14213126Sahl 	return (-1);
14223126Sahl }
14233126Sahl 
14243126Sahl typedef struct zvol_cb {
14253126Sahl 	zpool_handle_t *zcb_pool;
14263126Sahl 	boolean_t zcb_create;
14273126Sahl } zvol_cb_t;
14283126Sahl 
14293126Sahl /*ARGSUSED*/
14303126Sahl static int
14313126Sahl do_zvol_create(zfs_handle_t *zhp, void *data)
14323126Sahl {
14333126Sahl 	int ret;
14343126Sahl 
14353126Sahl 	if (ZFS_IS_VOLUME(zhp))
14363126Sahl 		(void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name);
14373126Sahl 
14383126Sahl 	ret = zfs_iter_children(zhp, do_zvol_create, NULL);
1439789Sahrens 
1440789Sahrens 	zfs_close(zhp);
14413126Sahl 
1442789Sahrens 	return (ret);
1443789Sahrens }
1444789Sahrens 
1445789Sahrens /*
1446789Sahrens  * Iterate over all zvols in the pool and make any necessary minor nodes.
1447789Sahrens  */
1448789Sahrens int
1449789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp)
1450789Sahrens {
1451789Sahrens 	zfs_handle_t *zfp;
1452789Sahrens 	int ret;
1453789Sahrens 
1454789Sahrens 	/*
1455789Sahrens 	 * If the pool is unavailable, just return success.
1456789Sahrens 	 */
14572082Seschrock 	if ((zfp = make_dataset_handle(zhp->zpool_hdl,
14582082Seschrock 	    zhp->zpool_name)) == NULL)
1459789Sahrens 		return (0);
1460789Sahrens 
14613126Sahl 	ret = zfs_iter_children(zfp, do_zvol_create, NULL);
1462789Sahrens 
1463789Sahrens 	zfs_close(zfp);
1464789Sahrens 	return (ret);
1465789Sahrens }
1466789Sahrens 
14673126Sahl static int
14683126Sahl do_zvol_remove(const char *dataset, void *data)
14693126Sahl {
14703126Sahl 	zpool_handle_t *zhp = data;
14713126Sahl 
14723126Sahl 	return (zvol_remove_link(zhp->zpool_hdl, dataset));
14733126Sahl }
14743126Sahl 
1475789Sahrens /*
14763126Sahl  * Iterate over all zvols in the pool and remove any minor nodes.  We iterate
14773126Sahl  * by examining the /dev links so that a corrupted pool doesn't impede this
14783126Sahl  * operation.
1479789Sahrens  */
1480789Sahrens int
1481789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp)
1482789Sahrens {
14833126Sahl 	return (zpool_iter_zvol(zhp, do_zvol_remove, zhp));
1484789Sahrens }
14851354Seschrock 
14861354Seschrock /*
14871354Seschrock  * Convert from a devid string to a path.
14881354Seschrock  */
14891354Seschrock static char *
14901354Seschrock devid_to_path(char *devid_str)
14911354Seschrock {
14921354Seschrock 	ddi_devid_t devid;
14931354Seschrock 	char *minor;
14941354Seschrock 	char *path;
14951354Seschrock 	devid_nmlist_t *list = NULL;
14961354Seschrock 	int ret;
14971354Seschrock 
14981354Seschrock 	if (devid_str_decode(devid_str, &devid, &minor) != 0)
14991354Seschrock 		return (NULL);
15001354Seschrock 
15011354Seschrock 	ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list);
15021354Seschrock 
15031354Seschrock 	devid_str_free(minor);
15041354Seschrock 	devid_free(devid);
15051354Seschrock 
15061354Seschrock 	if (ret != 0)
15071354Seschrock 		return (NULL);
15081354Seschrock 
15092082Seschrock 	if ((path = strdup(list[0].devname)) == NULL)
15102082Seschrock 		return (NULL);
15112082Seschrock 
15121354Seschrock 	devid_free_nmlist(list);
15131354Seschrock 
15141354Seschrock 	return (path);
15151354Seschrock }
15161354Seschrock 
15171354Seschrock /*
15181354Seschrock  * Convert from a path to a devid string.
15191354Seschrock  */
15201354Seschrock static char *
15211354Seschrock path_to_devid(const char *path)
15221354Seschrock {
15231354Seschrock 	int fd;
15241354Seschrock 	ddi_devid_t devid;
15251354Seschrock 	char *minor, *ret;
15261354Seschrock 
15271354Seschrock 	if ((fd = open(path, O_RDONLY)) < 0)
15281354Seschrock 		return (NULL);
15291354Seschrock 
15301354Seschrock 	minor = NULL;
15311354Seschrock 	ret = NULL;
15321354Seschrock 	if (devid_get(fd, &devid) == 0) {
15331354Seschrock 		if (devid_get_minor_name(fd, &minor) == 0)
15341354Seschrock 			ret = devid_str_encode(devid, minor);
15351354Seschrock 		if (minor != NULL)
15361354Seschrock 			devid_str_free(minor);
15371354Seschrock 		devid_free(devid);
15381354Seschrock 	}
15391354Seschrock 	(void) close(fd);
15401354Seschrock 
15411354Seschrock 	return (ret);
15421354Seschrock }
15431354Seschrock 
15441354Seschrock /*
15451354Seschrock  * Issue the necessary ioctl() to update the stored path value for the vdev.  We
15461354Seschrock  * ignore any failure here, since a common case is for an unprivileged user to
15471354Seschrock  * type 'zpool status', and we'll display the correct information anyway.
15481354Seschrock  */
15491354Seschrock static void
15501354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path)
15511354Seschrock {
15521354Seschrock 	zfs_cmd_t zc = { 0 };
15531354Seschrock 
15541354Seschrock 	(void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
15552676Seschrock 	(void) strncpy(zc.zc_value, path, sizeof (zc.zc_value));
15561354Seschrock 	verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
15571544Seschrock 	    &zc.zc_guid) == 0);
15581354Seschrock 
15592082Seschrock 	(void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc);
15601354Seschrock }
15611354Seschrock 
15621354Seschrock /*
15631354Seschrock  * Given a vdev, return the name to display in iostat.  If the vdev has a path,
15641354Seschrock  * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type.
15651354Seschrock  * We also check if this is a whole disk, in which case we strip off the
15661354Seschrock  * trailing 's0' slice name.
15671354Seschrock  *
15681354Seschrock  * This routine is also responsible for identifying when disks have been
15691354Seschrock  * reconfigured in a new location.  The kernel will have opened the device by
15701354Seschrock  * devid, but the path will still refer to the old location.  To catch this, we
15711354Seschrock  * first do a path -> devid translation (which is fast for the common case).  If
15721354Seschrock  * the devid matches, we're done.  If not, we do a reverse devid -> path
15731354Seschrock  * translation and issue the appropriate ioctl() to update the path of the vdev.
15741354Seschrock  * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any
15751354Seschrock  * of these checks.
15761354Seschrock  */
15771354Seschrock char *
15782082Seschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv)
15791354Seschrock {
15801354Seschrock 	char *path, *devid;
15811544Seschrock 	uint64_t value;
15821544Seschrock 	char buf[64];
1583*4451Seschrock 	vdev_stat_t *vs;
1584*4451Seschrock 	uint_t vsc;
15851354Seschrock 
15861544Seschrock 	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
15871544Seschrock 	    &value) == 0) {
15881544Seschrock 		verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
15891544Seschrock 		    &value) == 0);
15902856Snd150628 		(void) snprintf(buf, sizeof (buf), "%llu",
15912856Snd150628 		    (u_longlong_t)value);
15921544Seschrock 		path = buf;
15931544Seschrock 	} else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
15941354Seschrock 
1595*4451Seschrock 		/*
1596*4451Seschrock 		 * If the device is dead (faulted, offline, etc) then don't
1597*4451Seschrock 		 * bother opening it.  Otherwise we may be forcing the user to
1598*4451Seschrock 		 * open a misbehaving device, which can have undesirable
1599*4451Seschrock 		 * effects.
1600*4451Seschrock 		 */
1601*4451Seschrock 		if ((nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
1602*4451Seschrock 		    (uint64_t **)&vs, &vsc) != 0 ||
1603*4451Seschrock 		    vs->vs_state >= VDEV_STATE_DEGRADED) &&
1604*4451Seschrock 		    zhp != NULL &&
16051354Seschrock 		    nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) {
16061354Seschrock 			/*
16071354Seschrock 			 * Determine if the current path is correct.
16081354Seschrock 			 */
16091354Seschrock 			char *newdevid = path_to_devid(path);
16101354Seschrock 
16111354Seschrock 			if (newdevid == NULL ||
16121354Seschrock 			    strcmp(devid, newdevid) != 0) {
16131354Seschrock 				char *newpath;
16141354Seschrock 
16151354Seschrock 				if ((newpath = devid_to_path(devid)) != NULL) {
16161354Seschrock 					/*
16171354Seschrock 					 * Update the path appropriately.
16181354Seschrock 					 */
16191354Seschrock 					set_path(zhp, nv, newpath);
16202082Seschrock 					if (nvlist_add_string(nv,
16212082Seschrock 					    ZPOOL_CONFIG_PATH, newpath) == 0)
16222082Seschrock 						verify(nvlist_lookup_string(nv,
16232082Seschrock 						    ZPOOL_CONFIG_PATH,
16242082Seschrock 						    &path) == 0);
16251354Seschrock 					free(newpath);
16261354Seschrock 				}
16271354Seschrock 			}
16281354Seschrock 
16292082Seschrock 			if (newdevid)
16302082Seschrock 				devid_str_free(newdevid);
16311354Seschrock 		}
16321354Seschrock 
16331354Seschrock 		if (strncmp(path, "/dev/dsk/", 9) == 0)
16341354Seschrock 			path += 9;
16351354Seschrock 
16361354Seschrock 		if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
16371544Seschrock 		    &value) == 0 && value) {
16382082Seschrock 			char *tmp = zfs_strdup(hdl, path);
16392082Seschrock 			if (tmp == NULL)
16402082Seschrock 				return (NULL);
16411354Seschrock 			tmp[strlen(path) - 2] = '\0';
16421354Seschrock 			return (tmp);
16431354Seschrock 		}
16441354Seschrock 	} else {
16451354Seschrock 		verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0);
16462082Seschrock 
16472082Seschrock 		/*
16482082Seschrock 		 * If it's a raidz device, we need to stick in the parity level.
16492082Seschrock 		 */
16502082Seschrock 		if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) {
16512082Seschrock 			verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY,
16522082Seschrock 			    &value) == 0);
16532082Seschrock 			(void) snprintf(buf, sizeof (buf), "%s%llu", path,
16542856Snd150628 			    (u_longlong_t)value);
16552082Seschrock 			path = buf;
16562082Seschrock 		}
16571354Seschrock 	}
16581354Seschrock 
16592082Seschrock 	return (zfs_strdup(hdl, path));
16601354Seschrock }
16611544Seschrock 
16621544Seschrock static int
16631544Seschrock zbookmark_compare(const void *a, const void *b)
16641544Seschrock {
16651544Seschrock 	return (memcmp(a, b, sizeof (zbookmark_t)));
16661544Seschrock }
16671544Seschrock 
16681544Seschrock /*
16691544Seschrock  * Retrieve the persistent error log, uniquify the members, and return to the
16701544Seschrock  * caller.
16711544Seschrock  */
16721544Seschrock int
16733444Sek110237 zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
16741544Seschrock {
16751544Seschrock 	zfs_cmd_t zc = { 0 };
16761544Seschrock 	uint64_t count;
16772676Seschrock 	zbookmark_t *zb = NULL;
16783444Sek110237 	int i;
16791544Seschrock 
16801544Seschrock 	/*
16811544Seschrock 	 * Retrieve the raw error list from the kernel.  If the number of errors
16821544Seschrock 	 * has increased, allocate more space and continue until we get the
16831544Seschrock 	 * entire list.
16841544Seschrock 	 */
16851544Seschrock 	verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT,
16861544Seschrock 	    &count) == 0);
16872676Seschrock 	if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl,
16882856Snd150628 	    count * sizeof (zbookmark_t))) == (uintptr_t)NULL)
16892082Seschrock 		return (-1);
16902676Seschrock 	zc.zc_nvlist_dst_size = count;
16911544Seschrock 	(void) strcpy(zc.zc_name, zhp->zpool_name);
16921544Seschrock 	for (;;) {
16932082Seschrock 		if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG,
16942082Seschrock 		    &zc) != 0) {
16952676Seschrock 			free((void *)(uintptr_t)zc.zc_nvlist_dst);
16961544Seschrock 			if (errno == ENOMEM) {
16973823Svb160487 				count = zc.zc_nvlist_dst_size;
16982676Seschrock 				if ((zc.zc_nvlist_dst = (uintptr_t)
16993823Svb160487 				    zfs_alloc(zhp->zpool_hdl, count *
17003823Svb160487 				    sizeof (zbookmark_t))) == (uintptr_t)NULL)
17012082Seschrock 					return (-1);
17021544Seschrock 			} else {
17031544Seschrock 				return (-1);
17041544Seschrock 			}
17051544Seschrock 		} else {
17061544Seschrock 			break;
17071544Seschrock 		}
17081544Seschrock 	}
17091544Seschrock 
17101544Seschrock 	/*
17111544Seschrock 	 * Sort the resulting bookmarks.  This is a little confusing due to the
17121544Seschrock 	 * implementation of ZFS_IOC_ERROR_LOG.  The bookmarks are copied last
17132676Seschrock 	 * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks
17141544Seschrock 	 * _not_ copied as part of the process.  So we point the start of our
17151544Seschrock 	 * array appropriate and decrement the total number of elements.
17161544Seschrock 	 */
17172676Seschrock 	zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) +
17182676Seschrock 	    zc.zc_nvlist_dst_size;
17192676Seschrock 	count -= zc.zc_nvlist_dst_size;
17201544Seschrock 
17211544Seschrock 	qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare);
17221544Seschrock 
17233444Sek110237 	verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0);
17241544Seschrock 
17251544Seschrock 	/*
17263444Sek110237 	 * Fill in the nverrlistp with nvlist's of dataset and object numbers.
17271544Seschrock 	 */
17281544Seschrock 	for (i = 0; i < count; i++) {
17291544Seschrock 		nvlist_t *nv;
17301544Seschrock 
17313700Sek110237 		/* ignoring zb_blkid and zb_level for now */
17323700Sek110237 		if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset &&
17333700Sek110237 		    zb[i-1].zb_object == zb[i].zb_object)
17341544Seschrock 			continue;
17351544Seschrock 
17363444Sek110237 		if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0)
17373444Sek110237 			goto nomem;
17383444Sek110237 		if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET,
17393444Sek110237 		    zb[i].zb_objset) != 0) {
17403444Sek110237 			nvlist_free(nv);
17412082Seschrock 			goto nomem;
17423444Sek110237 		}
17433444Sek110237 		if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT,
17443444Sek110237 		    zb[i].zb_object) != 0) {
17453444Sek110237 			nvlist_free(nv);
17463444Sek110237 			goto nomem;
17471544Seschrock 		}
17483444Sek110237 		if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) {
17493444Sek110237 			nvlist_free(nv);
17503444Sek110237 			goto nomem;
17513444Sek110237 		}
17523444Sek110237 		nvlist_free(nv);
17531544Seschrock 	}
17541544Seschrock 
17553265Sahrens 	free((void *)(uintptr_t)zc.zc_nvlist_dst);
17561544Seschrock 	return (0);
17572082Seschrock 
17582082Seschrock nomem:
17592676Seschrock 	free((void *)(uintptr_t)zc.zc_nvlist_dst);
17602082Seschrock 	return (no_memory(zhp->zpool_hdl));
17611544Seschrock }
17621760Seschrock 
17631760Seschrock /*
17641760Seschrock  * Upgrade a ZFS pool to the latest on-disk version.
17651760Seschrock  */
17661760Seschrock int
17671760Seschrock zpool_upgrade(zpool_handle_t *zhp)
17681760Seschrock {
17691760Seschrock 	zfs_cmd_t zc = { 0 };
17702082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
17711760Seschrock 
17721760Seschrock 	(void) strcpy(zc.zc_name, zhp->zpool_name);
17732082Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_UPGRADE, &zc) != 0)
17743237Slling 		return (zpool_standard_error_fmt(hdl, errno,
17752082Seschrock 		    dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"),
17762082Seschrock 		    zhp->zpool_name));
17771760Seschrock 
17781760Seschrock 	return (0);
17791760Seschrock }
17802926Sek110237 
17812926Sek110237 /*
17822926Sek110237  * Log command history.
17832926Sek110237  *
17842926Sek110237  * 'pool' is B_TRUE if we are logging a command for 'zpool'; B_FALSE
17852926Sek110237  * otherwise ('zfs').  'pool_create' is B_TRUE if we are logging the creation
1786*4451Seschrock  * of the pool; B_FALSE otherwise.  'path' is the pathname containing the
17872926Sek110237  * poolname.  'argc' and 'argv' are used to construct the command string.
17882926Sek110237  */
17892926Sek110237 void
17902926Sek110237 zpool_log_history(libzfs_handle_t *hdl, int argc, char **argv, const char *path,
17913912Slling 	boolean_t pool, boolean_t pool_create)
17922926Sek110237 {
17932926Sek110237 	char cmd_buf[HIS_MAX_RECORD_LEN];
17942926Sek110237 	char *dspath;
17952926Sek110237 	zfs_cmd_t zc = { 0 };
17962926Sek110237 	int i;
17972926Sek110237 
17982926Sek110237 	/* construct the command string */
17992926Sek110237 	(void) strcpy(cmd_buf, pool ? "zpool" : "zfs");
18002926Sek110237 	for (i = 0; i < argc; i++) {
18012926Sek110237 		if (strlen(cmd_buf) + 1 + strlen(argv[i]) > HIS_MAX_RECORD_LEN)
18022926Sek110237 			break;
18032926Sek110237 		(void) strcat(cmd_buf, " ");
18042926Sek110237 		(void) strcat(cmd_buf, argv[i]);
18052926Sek110237 	}
18062926Sek110237 
18072926Sek110237 	/* figure out the poolname */
18082926Sek110237 	dspath = strpbrk(path, "/@");
18092926Sek110237 	if (dspath == NULL) {
18102926Sek110237 		(void) strcpy(zc.zc_name, path);
18112926Sek110237 	} else {
18122926Sek110237 		(void) strncpy(zc.zc_name, path, dspath - path);
18132926Sek110237 		zc.zc_name[dspath-path] = '\0';
18142926Sek110237 	}
18152926Sek110237 
18162926Sek110237 	zc.zc_history = (uint64_t)(uintptr_t)cmd_buf;
18172926Sek110237 	zc.zc_history_len = strlen(cmd_buf);
18182926Sek110237 
18192926Sek110237 	/* overloading zc_history_offset */
18202926Sek110237 	zc.zc_history_offset = pool_create;
18212926Sek110237 
18222926Sek110237 	(void) ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_LOG_HISTORY, &zc);
18232926Sek110237 }
18242926Sek110237 
18252926Sek110237 /*
18262926Sek110237  * Perform ioctl to get some command history of a pool.
18272926Sek110237  *
18282926Sek110237  * 'buf' is the buffer to fill up to 'len' bytes.  'off' is the
18292926Sek110237  * logical offset of the history buffer to start reading from.
18302926Sek110237  *
18312926Sek110237  * Upon return, 'off' is the next logical offset to read from and
18322926Sek110237  * 'len' is the actual amount of bytes read into 'buf'.
18332926Sek110237  */
18342926Sek110237 static int
18352926Sek110237 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len)
18362926Sek110237 {
18372926Sek110237 	zfs_cmd_t zc = { 0 };
18382926Sek110237 	libzfs_handle_t *hdl = zhp->zpool_hdl;
18392926Sek110237 
18402926Sek110237 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
18412926Sek110237 
18422926Sek110237 	zc.zc_history = (uint64_t)(uintptr_t)buf;
18432926Sek110237 	zc.zc_history_len = *len;
18442926Sek110237 	zc.zc_history_offset = *off;
18452926Sek110237 
18462926Sek110237 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) {
18472926Sek110237 		switch (errno) {
18482926Sek110237 		case EPERM:
18493237Slling 			return (zfs_error_fmt(hdl, EZFS_PERM,
18503237Slling 			    dgettext(TEXT_DOMAIN,
18512926Sek110237 			    "cannot show history for pool '%s'"),
18522926Sek110237 			    zhp->zpool_name));
18532926Sek110237 		case ENOENT:
18543237Slling 			return (zfs_error_fmt(hdl, EZFS_NOHISTORY,
18552926Sek110237 			    dgettext(TEXT_DOMAIN, "cannot get history for pool "
18562926Sek110237 			    "'%s'"), zhp->zpool_name));
18573863Sek110237 		case ENOTSUP:
18583863Sek110237 			return (zfs_error_fmt(hdl, EZFS_BADVERSION,
18593863Sek110237 			    dgettext(TEXT_DOMAIN, "cannot get history for pool "
18603863Sek110237 			    "'%s', pool must be upgraded"), zhp->zpool_name));
18612926Sek110237 		default:
18623237Slling 			return (zpool_standard_error_fmt(hdl, errno,
18632926Sek110237 			    dgettext(TEXT_DOMAIN,
18642926Sek110237 			    "cannot get history for '%s'"), zhp->zpool_name));
18652926Sek110237 		}
18662926Sek110237 	}
18672926Sek110237 
18682926Sek110237 	*len = zc.zc_history_len;
18692926Sek110237 	*off = zc.zc_history_offset;
18702926Sek110237 
18712926Sek110237 	return (0);
18722926Sek110237 }
18732926Sek110237 
18742926Sek110237 /*
18752926Sek110237  * Process the buffer of nvlists, unpacking and storing each nvlist record
18762926Sek110237  * into 'records'.  'leftover' is set to the number of bytes that weren't
18772926Sek110237  * processed as there wasn't a complete record.
18782926Sek110237  */
18792926Sek110237 static int
18802926Sek110237 zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover,
18812926Sek110237     nvlist_t ***records, uint_t *numrecords)
18822926Sek110237 {
18832926Sek110237 	uint64_t reclen;
18842926Sek110237 	nvlist_t *nv;
18852926Sek110237 	int i;
18862926Sek110237 
18872926Sek110237 	while (bytes_read > sizeof (reclen)) {
18882926Sek110237 
18892926Sek110237 		/* get length of packed record (stored as little endian) */
18902926Sek110237 		for (i = 0, reclen = 0; i < sizeof (reclen); i++)
18912926Sek110237 			reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i);
18922926Sek110237 
18932926Sek110237 		if (bytes_read < sizeof (reclen) + reclen)
18942926Sek110237 			break;
18952926Sek110237 
18962926Sek110237 		/* unpack record */
18972926Sek110237 		if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0)
18982926Sek110237 			return (ENOMEM);
18992926Sek110237 		bytes_read -= sizeof (reclen) + reclen;
19002926Sek110237 		buf += sizeof (reclen) + reclen;
19012926Sek110237 
19022926Sek110237 		/* add record to nvlist array */
19032926Sek110237 		(*numrecords)++;
19042926Sek110237 		if (ISP2(*numrecords + 1)) {
19052926Sek110237 			*records = realloc(*records,
19062926Sek110237 			    *numrecords * 2 * sizeof (nvlist_t *));
19072926Sek110237 		}
19082926Sek110237 		(*records)[*numrecords - 1] = nv;
19092926Sek110237 	}
19102926Sek110237 
19112926Sek110237 	*leftover = bytes_read;
19122926Sek110237 	return (0);
19132926Sek110237 }
19142926Sek110237 
19152926Sek110237 #define	HIS_BUF_LEN	(128*1024)
19162926Sek110237 
19172926Sek110237 /*
19182926Sek110237  * Retrieve the command history of a pool.
19192926Sek110237  */
19202926Sek110237 int
19212926Sek110237 zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
19222926Sek110237 {
19232926Sek110237 	char buf[HIS_BUF_LEN];
19242926Sek110237 	uint64_t off = 0;
19252926Sek110237 	nvlist_t **records = NULL;
19262926Sek110237 	uint_t numrecords = 0;
19272926Sek110237 	int err, i;
19282926Sek110237 
19292926Sek110237 	do {
19302926Sek110237 		uint64_t bytes_read = sizeof (buf);
19312926Sek110237 		uint64_t leftover;
19322926Sek110237 
19332926Sek110237 		if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0)
19342926Sek110237 			break;
19352926Sek110237 
19362926Sek110237 		/* if nothing else was read in, we're at EOF, just return */
19372926Sek110237 		if (!bytes_read)
19382926Sek110237 			break;
19392926Sek110237 
19402926Sek110237 		if ((err = zpool_history_unpack(buf, bytes_read,
19412926Sek110237 		    &leftover, &records, &numrecords)) != 0)
19422926Sek110237 			break;
19432926Sek110237 		off -= leftover;
19442926Sek110237 
19452926Sek110237 		/* CONSTCOND */
19462926Sek110237 	} while (1);
19472926Sek110237 
19482926Sek110237 	if (!err) {
19492926Sek110237 		verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0);
19502926Sek110237 		verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD,
19512926Sek110237 		    records, numrecords) == 0);
19522926Sek110237 	}
19532926Sek110237 	for (i = 0; i < numrecords; i++)
19542926Sek110237 		nvlist_free(records[i]);
19552926Sek110237 	free(records);
19562926Sek110237 
19572926Sek110237 	return (err);
19582926Sek110237 }
19593444Sek110237 
19603444Sek110237 void
19613444Sek110237 zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
19623444Sek110237     char *pathname, size_t len)
19633444Sek110237 {
19643444Sek110237 	zfs_cmd_t zc = { 0 };
19653444Sek110237 	boolean_t mounted = B_FALSE;
19663444Sek110237 	char *mntpnt = NULL;
19673444Sek110237 	char dsname[MAXNAMELEN];
19683444Sek110237 
19693444Sek110237 	if (dsobj == 0) {
19703444Sek110237 		/* special case for the MOS */
19713444Sek110237 		(void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj);
19723444Sek110237 		return;
19733444Sek110237 	}
19743444Sek110237 
19753444Sek110237 	/* get the dataset's name */
19763444Sek110237 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
19773444Sek110237 	zc.zc_obj = dsobj;
19783444Sek110237 	if (ioctl(zhp->zpool_hdl->libzfs_fd,
19793444Sek110237 	    ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) {
19803444Sek110237 		/* just write out a path of two object numbers */
19813444Sek110237 		(void) snprintf(pathname, len, "<0x%llx>:<0x%llx>",
19823444Sek110237 		    dsobj, obj);
19833444Sek110237 		return;
19843444Sek110237 	}
19853444Sek110237 	(void) strlcpy(dsname, zc.zc_value, sizeof (dsname));
19863444Sek110237 
19873444Sek110237 	/* find out if the dataset is mounted */
19883444Sek110237 	mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt);
19893444Sek110237 
19903444Sek110237 	/* get the corrupted object's path */
19913444Sek110237 	(void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name));
19923444Sek110237 	zc.zc_obj = obj;
19933444Sek110237 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH,
19943444Sek110237 	    &zc) == 0) {
19953444Sek110237 		if (mounted) {
19963444Sek110237 			(void) snprintf(pathname, len, "%s%s", mntpnt,
19973444Sek110237 			    zc.zc_value);
19983444Sek110237 		} else {
19993444Sek110237 			(void) snprintf(pathname, len, "%s:%s",
20003444Sek110237 			    dsname, zc.zc_value);
20013444Sek110237 		}
20023444Sek110237 	} else {
20033444Sek110237 		(void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj);
20043444Sek110237 	}
20053444Sek110237 	free(mntpnt);
20063444Sek110237 }
20073912Slling 
20084276Staylor #define	RDISK_ROOT	"/dev/rdsk"
20094276Staylor #define	BACKUP_SLICE	"s2"
20104276Staylor /*
20114276Staylor  * Don't start the slice at the default block of 34; many storage
20124276Staylor  * devices will use a stripe width of 128k, so start there instead.
20134276Staylor  */
20144276Staylor #define	NEW_START_BLOCK	256
20154276Staylor 
20164276Staylor /*
20174276Staylor  * determine where a partition starts on a disk in the current
20184276Staylor  * configuration
20194276Staylor  */
20204276Staylor static diskaddr_t
20214276Staylor find_start_block(nvlist_t *config)
20224276Staylor {
20234276Staylor 	nvlist_t **child;
20244276Staylor 	uint_t c, children;
20254276Staylor 	char *path;
20264276Staylor 	diskaddr_t sb = MAXOFFSET_T;
20274276Staylor 	int fd;
20284276Staylor 	char diskname[MAXPATHLEN];
20294276Staylor 	uint64_t wholedisk;
20304276Staylor 
20314276Staylor 	if (nvlist_lookup_nvlist_array(config,
20324276Staylor 	    ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) {
20334276Staylor 		if (nvlist_lookup_uint64(config,
20344276Staylor 		    ZPOOL_CONFIG_WHOLE_DISK,
20354276Staylor 		    &wholedisk) != 0 || !wholedisk) {
20364276Staylor 			return (MAXOFFSET_T);
20374276Staylor 		}
20384276Staylor 		if (nvlist_lookup_string(config,
20394276Staylor 		    ZPOOL_CONFIG_PATH, &path) != 0) {
20404276Staylor 			return (MAXOFFSET_T);
20414276Staylor 		}
20424276Staylor 
20434276Staylor 		(void) snprintf(diskname, sizeof (diskname), "%s%s",
20444276Staylor 		    RDISK_ROOT, strrchr(path, '/'));
20454276Staylor 		if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) {
20464276Staylor 			struct dk_gpt *vtoc;
20474276Staylor 			if (efi_alloc_and_read(fd, &vtoc) >= 0) {
20484276Staylor 				sb = vtoc->efi_parts[0].p_start;
20494276Staylor 				efi_free(vtoc);
20504276Staylor 			}
20514276Staylor 			(void) close(fd);
20524276Staylor 		}
20534276Staylor 		return (sb);
20544276Staylor 	}
20554276Staylor 
20564276Staylor 	for (c = 0; c < children; c++) {
20574276Staylor 		sb = find_start_block(child[c]);
20584276Staylor 		if (sb != MAXOFFSET_T) {
20594276Staylor 			return (sb);
20604276Staylor 		}
20614276Staylor 	}
20624276Staylor 	return (MAXOFFSET_T);
20634276Staylor }
20644276Staylor 
20654276Staylor /*
20664276Staylor  * Label an individual disk.  The name provided is the short name,
20674276Staylor  * stripped of any leading /dev path.
20684276Staylor  */
20694276Staylor int
20704276Staylor zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
20714276Staylor {
20724276Staylor 	char path[MAXPATHLEN];
20734276Staylor 	struct dk_gpt *vtoc;
20744276Staylor 	int fd;
20754276Staylor 	size_t resv = EFI_MIN_RESV_SIZE;
20764276Staylor 	uint64_t slice_size;
20774276Staylor 	diskaddr_t start_block;
20784276Staylor 	char errbuf[1024];
20794276Staylor 
20804276Staylor 	if (zhp) {
20814276Staylor 		nvlist_t *nvroot;
20824276Staylor 
20834276Staylor 		verify(nvlist_lookup_nvlist(zhp->zpool_config,
20844276Staylor 		    ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
20854276Staylor 
20864276Staylor 		if (zhp->zpool_start_block == 0)
20874276Staylor 			start_block = find_start_block(nvroot);
20884276Staylor 		else
20894276Staylor 			start_block = zhp->zpool_start_block;
20904276Staylor 		zhp->zpool_start_block = start_block;
20914276Staylor 	} else {
20924276Staylor 		/* new pool */
20934276Staylor 		start_block = NEW_START_BLOCK;
20944276Staylor 	}
20954276Staylor 
20964276Staylor 	(void) snprintf(path, sizeof (path), "%s/%s%s", RDISK_ROOT, name,
20974276Staylor 	    BACKUP_SLICE);
20984276Staylor 
20994276Staylor 	if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) {
21004276Staylor 		/*
21014276Staylor 		 * This shouldn't happen.  We've long since verified that this
21024276Staylor 		 * is a valid device.
21034276Staylor 		 */
21044276Staylor 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
21054276Staylor 		    "label '%s': unable to open device"), name);
21064276Staylor 		return (zfs_error(hdl, EZFS_OPENFAILED, errbuf));
21074276Staylor 	}
21084276Staylor 
21094276Staylor 	if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) {
21104276Staylor 		/*
21114276Staylor 		 * The only way this can fail is if we run out of memory, or we
21124276Staylor 		 * were unable to read the disk's capacity
21134276Staylor 		 */
21144276Staylor 		if (errno == ENOMEM)
21154276Staylor 			(void) no_memory(hdl);
21164276Staylor 
21174276Staylor 		(void) close(fd);
21184276Staylor 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
21194276Staylor 		    "label '%s': unable to read disk capacity"), name);
21204276Staylor 
21214276Staylor 		return (zfs_error(hdl, EZFS_NOCAP, errbuf));
21224276Staylor 	}
21234276Staylor 
21244276Staylor 	slice_size = vtoc->efi_last_u_lba + 1;
21254276Staylor 	slice_size -= EFI_MIN_RESV_SIZE;
21264276Staylor 	if (start_block == MAXOFFSET_T)
21274276Staylor 		start_block = NEW_START_BLOCK;
21284276Staylor 	slice_size -= start_block;
21294276Staylor 
21304276Staylor 	vtoc->efi_parts[0].p_start = start_block;
21314276Staylor 	vtoc->efi_parts[0].p_size = slice_size;
21324276Staylor 
21334276Staylor 	/*
21344276Staylor 	 * Why we use V_USR: V_BACKUP confuses users, and is considered
21354276Staylor 	 * disposable by some EFI utilities (since EFI doesn't have a backup
21364276Staylor 	 * slice).  V_UNASSIGNED is supposed to be used only for zero size
21374276Staylor 	 * partitions, and efi_write() will fail if we use it.  V_ROOT, V_BOOT,
21384276Staylor 	 * etc. were all pretty specific.  V_USR is as close to reality as we
21394276Staylor 	 * can get, in the absence of V_OTHER.
21404276Staylor 	 */
21414276Staylor 	vtoc->efi_parts[0].p_tag = V_USR;
21424276Staylor 	(void) strcpy(vtoc->efi_parts[0].p_name, "zfs");
21434276Staylor 
21444276Staylor 	vtoc->efi_parts[8].p_start = slice_size + start_block;
21454276Staylor 	vtoc->efi_parts[8].p_size = resv;
21464276Staylor 	vtoc->efi_parts[8].p_tag = V_RESERVED;
21474276Staylor 
21484276Staylor 	if (efi_write(fd, vtoc) != 0) {
21494276Staylor 		/*
21504276Staylor 		 * Some block drivers (like pcata) may not support EFI
21514276Staylor 		 * GPT labels.  Print out a helpful error message dir-
21524276Staylor 		 * ecting the user to manually label the disk and give
21534276Staylor 		 * a specific slice.
21544276Staylor 		 */
21554276Staylor 		(void) close(fd);
21564276Staylor 		efi_free(vtoc);
21574276Staylor 
21584276Staylor 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
21594276Staylor 		    "cannot label '%s': try using fdisk(1M) and then "
21604276Staylor 		    "provide a specific slice"), name);
21614276Staylor 		return (zfs_error(hdl, EZFS_LABELFAILED, errbuf));
21624276Staylor 	}
21634276Staylor 
21644276Staylor 	(void) close(fd);
21654276Staylor 	efi_free(vtoc);
21664276Staylor 	return (0);
21674276Staylor }
21684276Staylor 
21693912Slling int
21703912Slling zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval)
21713912Slling {
21723912Slling 	zfs_cmd_t zc = { 0 };
21733912Slling 	int ret = -1;
21743912Slling 	char errbuf[1024];
21753912Slling 	nvlist_t *nvl = NULL;
21763912Slling 	nvlist_t *realprops;
21773912Slling 
21783912Slling 	(void) snprintf(errbuf, sizeof (errbuf),
21793912Slling 	    dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
21803912Slling 	    zhp->zpool_name);
21813912Slling 
21823912Slling 	if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) {
21833912Slling 		zfs_error_aux(zhp->zpool_hdl,
21843912Slling 		    dgettext(TEXT_DOMAIN, "pool must be "
21853912Slling 		    "upgraded to support pool properties"));
21863912Slling 		return (zfs_error(zhp->zpool_hdl, EZFS_BADVERSION, errbuf));
21873912Slling 	}
21883912Slling 
21893912Slling 	if (zhp->zpool_props == NULL && zpool_get_all_props(zhp))
21903912Slling 		return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, errbuf));
21913912Slling 
21923912Slling 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 ||
21933912Slling 	    nvlist_add_string(nvl, propname, propval) != 0) {
21943912Slling 		return (no_memory(zhp->zpool_hdl));
21953912Slling 	}
21963912Slling 
21973912Slling 	if ((realprops = zfs_validate_properties(zhp->zpool_hdl, ZFS_TYPE_POOL,
21983912Slling 	    zhp->zpool_name, nvl, 0, NULL, errbuf)) == NULL) {
21993912Slling 		nvlist_free(nvl);
22003912Slling 		return (-1);
22013912Slling 	}
22023912Slling 
22033912Slling 	nvlist_free(nvl);
22043912Slling 	nvl = realprops;
22053912Slling 
22063912Slling 	/*
22073912Slling 	 * Execute the corresponding ioctl() to set this property.
22083912Slling 	 */
22093912Slling 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
22103912Slling 
22113912Slling 	if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl, NULL) != 0)
22123912Slling 		return (-1);
22133912Slling 
22143912Slling 	ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_SET_PROPS, &zc);
22153912Slling 	zcmd_free_nvlists(&zc);
22163912Slling 
22173912Slling 	if (ret)
22183912Slling 		(void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf);
22193912Slling 
22203912Slling 	return (ret);
22213912Slling }
22223912Slling 
2223*4451Seschrock uint64_t
2224*4451Seschrock zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop)
2225*4451Seschrock {
2226*4451Seschrock 	uint64_t value;
2227*4451Seschrock 	nvlist_t *nvp;
2228*4451Seschrock 
2229*4451Seschrock 	if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS)
2230*4451Seschrock 		return (0);
2231*4451Seschrock 
2232*4451Seschrock 	if (zhp->zpool_props == NULL && zpool_get_all_props(zhp))
2233*4451Seschrock 		return (zpool_prop_default_numeric(prop));
2234*4451Seschrock 
2235*4451Seschrock 	switch (prop) {
2236*4451Seschrock 	case ZPOOL_PROP_AUTOREPLACE:
2237*4451Seschrock 		if (nvlist_lookup_nvlist(zhp->zpool_props,
2238*4451Seschrock 		    zpool_prop_to_name(prop), &nvp) != 0) {
2239*4451Seschrock 			value = zpool_prop_default_numeric(prop);
2240*4451Seschrock 		} else {
2241*4451Seschrock 			VERIFY(nvlist_lookup_uint64(nvp, ZFS_PROP_VALUE,
2242*4451Seschrock 			    &value) == 0);
2243*4451Seschrock 		}
2244*4451Seschrock 		return (value);
2245*4451Seschrock 		break;
2246*4451Seschrock 
2247*4451Seschrock 	default:
2248*4451Seschrock 		assert(0);
2249*4451Seschrock 	}
2250*4451Seschrock 
2251*4451Seschrock 	return (0);
2252*4451Seschrock }
2253*4451Seschrock 
22543912Slling int
22553912Slling zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *propbuf,
22563912Slling     size_t proplen, zfs_source_t *srctype)
22573912Slling {
22583912Slling 	uint64_t value;
22593912Slling 	char msg[1024], *strvalue;
22603912Slling 	nvlist_t *nvp;
22613912Slling 	zfs_source_t src = ZFS_SRC_NONE;
22623912Slling 
22633912Slling 	(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
22643912Slling 	    "cannot get property '%s'"), zpool_prop_to_name(prop));
22653912Slling 
22663912Slling 	if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) {
22673912Slling 		zfs_error_aux(zhp->zpool_hdl,
22683912Slling 		    dgettext(TEXT_DOMAIN, "pool must be "
22693912Slling 		    "upgraded to support pool properties"));
22703912Slling 		return (zfs_error(zhp->zpool_hdl, EZFS_BADVERSION, msg));
22713912Slling 	}
22723912Slling 
2273*4451Seschrock 	if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) &&
2274*4451Seschrock 	    prop != ZPOOL_PROP_NAME)
22753912Slling 		return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, msg));
22763912Slling 
22773912Slling 	switch (prop) {
2278*4451Seschrock 	case ZPOOL_PROP_NAME:
22793912Slling 		(void) strlcpy(propbuf, zhp->zpool_name, proplen);
22803912Slling 		break;
22813912Slling 
2282*4451Seschrock 	case ZPOOL_PROP_BOOTFS:
22833912Slling 		if (nvlist_lookup_nvlist(zhp->zpool_props,
22843912Slling 		    zpool_prop_to_name(prop), &nvp) != 0) {
22853912Slling 			strvalue = (char *)zfs_prop_default_string(prop);
22863912Slling 			if (strvalue == NULL)
22873912Slling 				strvalue = "-";
22883912Slling 			src = ZFS_SRC_DEFAULT;
22893912Slling 		} else {
22903912Slling 			VERIFY(nvlist_lookup_uint64(nvp,
22913912Slling 			    ZFS_PROP_SOURCE, &value) == 0);
22923912Slling 			src = value;
22933912Slling 			VERIFY(nvlist_lookup_string(nvp, ZFS_PROP_VALUE,
22943912Slling 			    &strvalue) == 0);
22953912Slling 			if (strlen(strvalue) >= proplen)
22963912Slling 				return (-1);
22973912Slling 		}
2298*4451Seschrock 		(void) strlcpy(propbuf, strvalue, proplen);
2299*4451Seschrock 		break;
2300*4451Seschrock 
2301*4451Seschrock 	case ZPOOL_PROP_AUTOREPLACE:
2302*4451Seschrock 		if (nvlist_lookup_nvlist(zhp->zpool_props,
2303*4451Seschrock 		    zpool_prop_to_name(prop), &nvp) != 0) {
2304*4451Seschrock 			value = zpool_prop_default_numeric(prop);
2305*4451Seschrock 			src = ZFS_SRC_DEFAULT;
2306*4451Seschrock 		} else {
2307*4451Seschrock 			VERIFY(nvlist_lookup_uint64(nvp,
2308*4451Seschrock 			    ZFS_PROP_SOURCE, &value) == 0);
2309*4451Seschrock 			src = value;
2310*4451Seschrock 			VERIFY(nvlist_lookup_uint64(nvp, ZFS_PROP_VALUE,
2311*4451Seschrock 			    &value) == 0);
2312*4451Seschrock 		}
2313*4451Seschrock 		(void) strlcpy(propbuf, value ? "on" : "off", proplen);
23143912Slling 		break;
23153912Slling 
23163912Slling 	default:
23173912Slling 		return (-1);
23183912Slling 	}
23193912Slling 	if (srctype)
23203912Slling 		*srctype = src;
23213912Slling 	return (0);
23223912Slling }
23233912Slling 
23243912Slling int
23253912Slling zpool_get_proplist(libzfs_handle_t *hdl, char *fields, zpool_proplist_t **listp)
23263912Slling {
23273912Slling 	return (zfs_get_proplist_common(hdl, fields, listp, ZFS_TYPE_POOL));
23283912Slling }
23293912Slling 
23303912Slling 
23313912Slling int
23323912Slling zpool_expand_proplist(zpool_handle_t *zhp, zpool_proplist_t **plp)
23333912Slling {
23343912Slling 	libzfs_handle_t *hdl = zhp->zpool_hdl;
23353912Slling 	zpool_proplist_t *entry;
23363912Slling 	char buf[ZFS_MAXPROPLEN];
23373912Slling 
23383912Slling 	if (zfs_expand_proplist_common(hdl, plp, ZFS_TYPE_POOL) != 0)
23393912Slling 		return (-1);
23403912Slling 
23413912Slling 	for (entry = *plp; entry != NULL; entry = entry->pl_next) {
23423912Slling 
23433912Slling 		if (entry->pl_fixed)
23443912Slling 			continue;
23453912Slling 
23463912Slling 		if (entry->pl_prop != ZFS_PROP_INVAL &&
23473912Slling 		    zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf),
23483912Slling 		    NULL) == 0) {
23493912Slling 			if (strlen(buf) > entry->pl_width)
23503912Slling 				entry->pl_width = strlen(buf);
23513912Slling 		}
23523912Slling 	}
23533912Slling 
23543912Slling 	return (0);
23553912Slling }
2356