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  */
21*2082Seschrock 
22789Sahrens /*
231354Seschrock  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24789Sahrens  * Use is subject to license terms.
25789Sahrens  */
26789Sahrens 
27789Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
28789Sahrens 
29789Sahrens #include <assert.h>
30789Sahrens #include <ctype.h>
31789Sahrens #include <errno.h>
32789Sahrens #include <devid.h>
33789Sahrens #include <fcntl.h>
34789Sahrens #include <libintl.h>
35789Sahrens #include <stdio.h>
36789Sahrens #include <stdlib.h>
37789Sahrens #include <string.h>
38789Sahrens #include <unistd.h>
39789Sahrens #include <sys/zfs_ioctl.h>
401544Seschrock #include <sys/zio.h>
41789Sahrens 
42789Sahrens #include "zfs_namecheck.h"
43789Sahrens #include "libzfs_impl.h"
44789Sahrens 
45789Sahrens /*
46789Sahrens  * Validate the given pool name, optionally putting an extended error message in
47789Sahrens  * 'buf'.
48789Sahrens  */
49*2082Seschrock static boolean_t
50*2082Seschrock zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool)
51789Sahrens {
52789Sahrens 	namecheck_err_t why;
53789Sahrens 	char what;
541773Seschrock 	int ret;
55789Sahrens 
561773Seschrock 	ret = pool_namecheck(pool, &why, &what);
571773Seschrock 
581773Seschrock 	/*
591773Seschrock 	 * The rules for reserved pool names were extended at a later point.
601773Seschrock 	 * But we need to support users with existing pools that may now be
611773Seschrock 	 * invalid.  So we only check for this expanded set of names during a
621773Seschrock 	 * create (or import), and only in userland.
631773Seschrock 	 */
641773Seschrock 	if (ret == 0 && !isopen &&
651773Seschrock 	    (strncmp(pool, "mirror", 6) == 0 ||
661773Seschrock 	    strncmp(pool, "raidz", 5) == 0 ||
671773Seschrock 	    strncmp(pool, "spare", 5) == 0)) {
68*2082Seschrock 		zfs_error_aux(hdl,
69*2082Seschrock 		    dgettext(TEXT_DOMAIN, "name is reserved"));
70*2082Seschrock 		return (B_FALSE);
711773Seschrock 	}
721773Seschrock 
731773Seschrock 
741773Seschrock 	if (ret != 0) {
75*2082Seschrock 		if (hdl != NULL) {
76789Sahrens 			switch (why) {
771003Slling 			case NAME_ERR_TOOLONG:
78*2082Seschrock 				zfs_error_aux(hdl,
791003Slling 				    dgettext(TEXT_DOMAIN, "name is too long"));
801003Slling 				break;
811003Slling 
82789Sahrens 			case NAME_ERR_INVALCHAR:
83*2082Seschrock 				zfs_error_aux(hdl,
84789Sahrens 				    dgettext(TEXT_DOMAIN, "invalid character "
85789Sahrens 				    "'%c' in pool name"), what);
86789Sahrens 				break;
87789Sahrens 
88789Sahrens 			case NAME_ERR_NOLETTER:
89*2082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
90*2082Seschrock 				    "name must begin with a letter"));
91789Sahrens 				break;
92789Sahrens 
93789Sahrens 			case NAME_ERR_RESERVED:
94*2082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
95*2082Seschrock 				    "name is reserved"));
96789Sahrens 				break;
97789Sahrens 
98789Sahrens 			case NAME_ERR_DISKLIKE:
99*2082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
100*2082Seschrock 				    "pool name is reserved"));
101789Sahrens 				break;
102789Sahrens 			}
103789Sahrens 		}
104*2082Seschrock 		return (B_FALSE);
105789Sahrens 	}
106789Sahrens 
107*2082Seschrock 	return (B_TRUE);
108789Sahrens }
109789Sahrens 
110789Sahrens /*
111789Sahrens  * Set the pool-wide health based on the vdev state of the root vdev.
112789Sahrens  */
113*2082Seschrock int
114789Sahrens set_pool_health(nvlist_t *config)
115789Sahrens {
116789Sahrens 	nvlist_t *nvroot;
117789Sahrens 	vdev_stat_t *vs;
118789Sahrens 	uint_t vsc;
119789Sahrens 	char *health;
120789Sahrens 
121789Sahrens 	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
122789Sahrens 	    &nvroot) == 0);
123789Sahrens 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
124789Sahrens 	    (uint64_t **)&vs, &vsc) == 0);
125789Sahrens 
126789Sahrens 	switch (vs->vs_state) {
127789Sahrens 
128789Sahrens 	case VDEV_STATE_CLOSED:
129789Sahrens 	case VDEV_STATE_CANT_OPEN:
130789Sahrens 	case VDEV_STATE_OFFLINE:
131789Sahrens 		health = dgettext(TEXT_DOMAIN, "FAULTED");
132789Sahrens 		break;
133789Sahrens 
134789Sahrens 	case VDEV_STATE_DEGRADED:
135789Sahrens 		health = dgettext(TEXT_DOMAIN, "DEGRADED");
136789Sahrens 		break;
137789Sahrens 
138789Sahrens 	case VDEV_STATE_HEALTHY:
139789Sahrens 		health = dgettext(TEXT_DOMAIN, "ONLINE");
140789Sahrens 		break;
141789Sahrens 
142789Sahrens 	default:
143*2082Seschrock 		abort();
144789Sahrens 	}
145789Sahrens 
146*2082Seschrock 	return (nvlist_add_string(config, ZPOOL_CONFIG_POOL_HEALTH, health));
147789Sahrens }
148789Sahrens 
149789Sahrens /*
150789Sahrens  * Open a handle to the given pool, even if the pool is currently in the FAULTED
151789Sahrens  * state.
152789Sahrens  */
153789Sahrens zpool_handle_t *
154*2082Seschrock zpool_open_canfail(libzfs_handle_t *hdl, const char *pool)
155789Sahrens {
156789Sahrens 	zpool_handle_t *zhp;
157789Sahrens 
158789Sahrens 	/*
159789Sahrens 	 * Make sure the pool name is valid.
160789Sahrens 	 */
161*2082Seschrock 	if (!zpool_name_valid(hdl, B_TRUE, pool)) {
162*2082Seschrock 		(void) zfs_error(hdl, EZFS_INVALIDNAME,
163*2082Seschrock 		    dgettext(TEXT_DOMAIN, "cannot open '%s'"),
164*2082Seschrock 		    pool);
165789Sahrens 		return (NULL);
166789Sahrens 	}
167789Sahrens 
168*2082Seschrock 	if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
169*2082Seschrock 		return (NULL);
170789Sahrens 
171*2082Seschrock 	zhp->zpool_hdl = hdl;
172789Sahrens 	(void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
173789Sahrens 
174*2082Seschrock 	if (zpool_refresh_stats(zhp) != 0) {
175*2082Seschrock 		if (errno == ENOENT || errno == EINVAL) {
176*2082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
177*2082Seschrock 			    "no such pool"));
178*2082Seschrock 			(void) zfs_error(hdl, EZFS_NOENT,
179*2082Seschrock 			    dgettext(TEXT_DOMAIN, "cannot open '%s'"),
180*2082Seschrock 			    pool);
181789Sahrens 			free(zhp);
182789Sahrens 			return (NULL);
183789Sahrens 		} else {
184789Sahrens 			zhp->zpool_state = POOL_STATE_UNAVAIL;
185789Sahrens 		}
186789Sahrens 	} else {
187789Sahrens 		zhp->zpool_state = POOL_STATE_ACTIVE;
188789Sahrens 	}
189789Sahrens 
190789Sahrens 	return (zhp);
191789Sahrens }
192789Sahrens 
193789Sahrens /*
194789Sahrens  * Like the above, but silent on error.  Used when iterating over pools (because
195789Sahrens  * the configuration cache may be out of date).
196789Sahrens  */
197789Sahrens zpool_handle_t *
198*2082Seschrock zpool_open_silent(libzfs_handle_t *hdl, const char *pool)
199789Sahrens {
200789Sahrens 	zpool_handle_t *zhp;
201789Sahrens 
202*2082Seschrock 	if ((zhp = calloc(sizeof (zpool_handle_t), 1)) == NULL)
203*2082Seschrock 		return (NULL);
204789Sahrens 
205*2082Seschrock 	zhp->zpool_hdl = hdl;
206789Sahrens 	(void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
207789Sahrens 
208*2082Seschrock 	if (zpool_refresh_stats(zhp) != 0) {
209*2082Seschrock 		if (errno == ENOENT || errno == EINVAL) {
210789Sahrens 			free(zhp);
211789Sahrens 			return (NULL);
212789Sahrens 		} else {
213789Sahrens 			zhp->zpool_state = POOL_STATE_UNAVAIL;
214789Sahrens 		}
215789Sahrens 	} else {
216789Sahrens 		zhp->zpool_state = POOL_STATE_ACTIVE;
217789Sahrens 	}
218789Sahrens 
219789Sahrens 	return (zhp);
220789Sahrens }
221789Sahrens 
222789Sahrens /*
223789Sahrens  * Similar to zpool_open_canfail(), but refuses to open pools in the faulted
224789Sahrens  * state.
225789Sahrens  */
226789Sahrens zpool_handle_t *
227*2082Seschrock zpool_open(libzfs_handle_t *hdl, const char *pool)
228789Sahrens {
229789Sahrens 	zpool_handle_t *zhp;
230789Sahrens 
231*2082Seschrock 	if ((zhp = zpool_open_canfail(hdl, pool)) == NULL)
232789Sahrens 		return (NULL);
233789Sahrens 
234789Sahrens 	if (zhp->zpool_state == POOL_STATE_UNAVAIL) {
235*2082Seschrock 		(void) zfs_error(hdl, EZFS_POOLUNAVAIL,
236*2082Seschrock 		    dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name);
237789Sahrens 		zpool_close(zhp);
238789Sahrens 		return (NULL);
239789Sahrens 	}
240789Sahrens 
241789Sahrens 	return (zhp);
242789Sahrens }
243789Sahrens 
244789Sahrens /*
245789Sahrens  * Close the handle.  Simply frees the memory associated with the handle.
246789Sahrens  */
247789Sahrens void
248789Sahrens zpool_close(zpool_handle_t *zhp)
249789Sahrens {
250789Sahrens 	if (zhp->zpool_config)
251789Sahrens 		nvlist_free(zhp->zpool_config);
252952Seschrock 	if (zhp->zpool_old_config)
253952Seschrock 		nvlist_free(zhp->zpool_old_config);
2541544Seschrock 	if (zhp->zpool_error_log) {
2551544Seschrock 		int i;
2561544Seschrock 		for (i = 0; i < zhp->zpool_error_count; i++)
257*2082Seschrock 			nvlist_free(zhp->zpool_error_log[i]);
2581544Seschrock 		free(zhp->zpool_error_log);
2591544Seschrock 	}
260789Sahrens 	free(zhp);
261789Sahrens }
262789Sahrens 
263789Sahrens /*
264789Sahrens  * Return the name of the pool.
265789Sahrens  */
266789Sahrens const char *
267789Sahrens zpool_get_name(zpool_handle_t *zhp)
268789Sahrens {
269789Sahrens 	return (zhp->zpool_name);
270789Sahrens }
271789Sahrens 
272789Sahrens /*
273789Sahrens  * Return the GUID of the pool.
274789Sahrens  */
275789Sahrens uint64_t
276789Sahrens zpool_get_guid(zpool_handle_t *zhp)
277789Sahrens {
278789Sahrens 	uint64_t guid;
279789Sahrens 
280789Sahrens 	verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID,
281789Sahrens 	    &guid) == 0);
282789Sahrens 	return (guid);
283789Sahrens }
284789Sahrens 
285789Sahrens /*
286*2082Seschrock  * Return the version of the pool.
287*2082Seschrock  */
288*2082Seschrock uint64_t
289*2082Seschrock zpool_get_version(zpool_handle_t *zhp)
290*2082Seschrock {
291*2082Seschrock 	uint64_t version;
292*2082Seschrock 
293*2082Seschrock 	verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_VERSION,
294*2082Seschrock 	    &version) == 0);
295*2082Seschrock 
296*2082Seschrock 	return (version);
297*2082Seschrock }
298*2082Seschrock 
299*2082Seschrock /*
300789Sahrens  * Return the amount of space currently consumed by the pool.
301789Sahrens  */
302789Sahrens uint64_t
303789Sahrens zpool_get_space_used(zpool_handle_t *zhp)
304789Sahrens {
305789Sahrens 	nvlist_t *nvroot;
306789Sahrens 	vdev_stat_t *vs;
307789Sahrens 	uint_t vsc;
308789Sahrens 
309789Sahrens 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
310789Sahrens 	    &nvroot) == 0);
311789Sahrens 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
312789Sahrens 	    (uint64_t **)&vs, &vsc) == 0);
313789Sahrens 
314789Sahrens 	return (vs->vs_alloc);
315789Sahrens }
316789Sahrens 
317789Sahrens /*
318789Sahrens  * Return the total space in the pool.
319789Sahrens  */
320789Sahrens uint64_t
321789Sahrens zpool_get_space_total(zpool_handle_t *zhp)
322789Sahrens {
323789Sahrens 	nvlist_t *nvroot;
324789Sahrens 	vdev_stat_t *vs;
325789Sahrens 	uint_t vsc;
326789Sahrens 
327789Sahrens 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
328789Sahrens 	    &nvroot) == 0);
329789Sahrens 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
330789Sahrens 	    (uint64_t **)&vs, &vsc) == 0);
331789Sahrens 
332789Sahrens 	return (vs->vs_space);
333789Sahrens }
334789Sahrens 
335789Sahrens /*
336789Sahrens  * Return the alternate root for this pool, if any.
337789Sahrens  */
338789Sahrens int
339789Sahrens zpool_get_root(zpool_handle_t *zhp, char *buf, size_t buflen)
340789Sahrens {
341789Sahrens 	zfs_cmd_t zc = { 0 };
342789Sahrens 
343789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
344*2082Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 ||
3451544Seschrock 	    zc.zc_root[0] == '\0')
346789Sahrens 		return (-1);
347789Sahrens 
3481544Seschrock 	(void) strlcpy(buf, zc.zc_root, buflen);
349789Sahrens 
350789Sahrens 	return (0);
351789Sahrens }
352789Sahrens 
353789Sahrens /*
354789Sahrens  * Return the state of the pool (ACTIVE or UNAVAILABLE)
355789Sahrens  */
356789Sahrens int
357789Sahrens zpool_get_state(zpool_handle_t *zhp)
358789Sahrens {
359789Sahrens 	return (zhp->zpool_state);
360789Sahrens }
361789Sahrens 
362789Sahrens /*
363789Sahrens  * Create the named pool, using the provided vdev list.  It is assumed
364789Sahrens  * that the consumer has already validated the contents of the nvlist, so we
365789Sahrens  * don't have to worry about error semantics.
366789Sahrens  */
367789Sahrens int
368*2082Seschrock zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
369*2082Seschrock     const char *altroot)
370789Sahrens {
371789Sahrens 	zfs_cmd_t zc = { 0 };
372789Sahrens 	char *packed;
373789Sahrens 	size_t len;
374*2082Seschrock 	char msg[1024];
375*2082Seschrock 
376*2082Seschrock 	(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
377*2082Seschrock 	    "cannot create '%s'"), pool);
378789Sahrens 
379*2082Seschrock 	if (!zpool_name_valid(hdl, B_FALSE, pool))
380*2082Seschrock 		return (zfs_error(hdl, EZFS_INVALIDNAME, msg));
381*2082Seschrock 
382*2082Seschrock 	if (altroot != NULL && altroot[0] != '/')
383*2082Seschrock 		return (zfs_error(hdl, EZFS_BADPATH,
384*2082Seschrock 		    dgettext(TEXT_DOMAIN, "bad alternate root '%s'"), altroot));
385789Sahrens 
386*2082Seschrock 	if (nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) != 0)
387*2082Seschrock 		return (no_memory(hdl));
388*2082Seschrock 
389*2082Seschrock 	if ((packed = zfs_alloc(hdl, len)) == NULL)
390789Sahrens 		return (-1);
391789Sahrens 
392*2082Seschrock 	if (nvlist_pack(nvroot, &packed, &len,
393*2082Seschrock 	    NV_ENCODE_NATIVE, 0) != 0) {
394*2082Seschrock 		free(packed);
395*2082Seschrock 		return (no_memory(hdl));
396*2082Seschrock 	}
397789Sahrens 
398789Sahrens 	(void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name));
399789Sahrens 	zc.zc_config_src = (uint64_t)(uintptr_t)packed;
400789Sahrens 	zc.zc_config_src_size = len;
401789Sahrens 
402789Sahrens 	if (altroot != NULL)
403789Sahrens 		(void) strlcpy(zc.zc_root, altroot, sizeof (zc.zc_root));
404789Sahrens 
405*2082Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) {
406*2082Seschrock 		free(packed);
407*2082Seschrock 
408789Sahrens 		switch (errno) {
409789Sahrens 		case EBUSY:
410789Sahrens 			/*
411789Sahrens 			 * This can happen if the user has specified the same
412789Sahrens 			 * device multiple times.  We can't reliably detect this
413789Sahrens 			 * until we try to add it and see we already have a
414789Sahrens 			 * label.
415789Sahrens 			 */
416*2082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
417*2082Seschrock 			    "one or more vdevs refer to the same device"));
418*2082Seschrock 			return (zfs_error(hdl, EZFS_BADDEV, msg));
419789Sahrens 
420789Sahrens 		case EOVERFLOW:
421789Sahrens 			/*
422*2082Seschrock 			 * This occurs when one of the devices is below
423789Sahrens 			 * SPA_MINDEVSIZE.  Unfortunately, we can't detect which
424789Sahrens 			 * device was the problem device since there's no
425789Sahrens 			 * reliable way to determine device size from userland.
426789Sahrens 			 */
427789Sahrens 			{
428789Sahrens 				char buf[64];
429789Sahrens 
430789Sahrens 				zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
431789Sahrens 
432*2082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
433*2082Seschrock 				    "one or more devices is less than the "
434*2082Seschrock 				    "minimum size (%s)"), buf);
435789Sahrens 			}
436*2082Seschrock 			return (zfs_error(hdl, EZFS_BADDEV, msg));
437789Sahrens 
438789Sahrens 		case ENOSPC:
439*2082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
440*2082Seschrock 			    "one or more devices is out of space"));
441*2082Seschrock 			return (zfs_error(hdl, EZFS_BADDEV, msg));
442789Sahrens 
443789Sahrens 		default:
444*2082Seschrock 			return (zpool_standard_error(hdl, errno, msg));
445789Sahrens 		}
446789Sahrens 	}
447789Sahrens 
448789Sahrens 	free(packed);
449789Sahrens 
450789Sahrens 	/*
451789Sahrens 	 * If this is an alternate root pool, then we automatically set the
452789Sahrens 	 * moutnpoint of the root dataset to be '/'.
453789Sahrens 	 */
454789Sahrens 	if (altroot != NULL) {
455789Sahrens 		zfs_handle_t *zhp;
456789Sahrens 
457*2082Seschrock 		verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_ANY)) != NULL);
458789Sahrens 		verify(zfs_prop_set(zhp, ZFS_PROP_MOUNTPOINT, "/") == 0);
459789Sahrens 
460789Sahrens 		zfs_close(zhp);
461789Sahrens 	}
462789Sahrens 
463789Sahrens 	return (0);
464789Sahrens }
465789Sahrens 
466789Sahrens /*
467789Sahrens  * Destroy the given pool.  It is up to the caller to ensure that there are no
468789Sahrens  * datasets left in the pool.
469789Sahrens  */
470789Sahrens int
471789Sahrens zpool_destroy(zpool_handle_t *zhp)
472789Sahrens {
473789Sahrens 	zfs_cmd_t zc = { 0 };
474789Sahrens 	zfs_handle_t *zfp = NULL;
475*2082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
476*2082Seschrock 	char msg[1024];
477789Sahrens 
478789Sahrens 	if (zhp->zpool_state == POOL_STATE_ACTIVE &&
479*2082Seschrock 	    (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name,
480*2082Seschrock 	    ZFS_TYPE_FILESYSTEM)) == NULL)
481789Sahrens 		return (-1);
482789Sahrens 
483789Sahrens 	if (zpool_remove_zvol_links(zhp) != NULL)
484789Sahrens 		return (-1);
485789Sahrens 
486789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
487789Sahrens 
488*2082Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
489*2082Seschrock 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
490*2082Seschrock 		    "cannot destroy '%s'"), zhp->zpool_name);
491789Sahrens 
492*2082Seschrock 		if (errno == EROFS) {
493*2082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
494*2082Seschrock 			    "one or more devices is read only"));
495*2082Seschrock 			(void) zfs_error(hdl, EZFS_BADDEV, msg);
496*2082Seschrock 		} else {
497*2082Seschrock 			(void) zpool_standard_error(hdl, errno, msg);
498789Sahrens 		}
499789Sahrens 
500789Sahrens 		if (zfp)
501789Sahrens 			zfs_close(zfp);
502789Sahrens 		return (-1);
503789Sahrens 	}
504789Sahrens 
505789Sahrens 	if (zfp) {
506789Sahrens 		remove_mountpoint(zfp);
507789Sahrens 		zfs_close(zfp);
508789Sahrens 	}
509789Sahrens 
510789Sahrens 	return (0);
511789Sahrens }
512789Sahrens 
513789Sahrens /*
514789Sahrens  * Add the given vdevs to the pool.  The caller must have already performed the
515789Sahrens  * necessary verification to ensure that the vdev specification is well-formed.
516789Sahrens  */
517789Sahrens int
518789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
519789Sahrens {
520789Sahrens 	char *packed;
521789Sahrens 	size_t len;
522789Sahrens 	zfs_cmd_t zc;
523*2082Seschrock 	int ret;
524*2082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
525*2082Seschrock 	char msg[1024];
526*2082Seschrock 	nvlist_t **spares;
527*2082Seschrock 	uint_t nspares;
528*2082Seschrock 
529*2082Seschrock 	(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
530*2082Seschrock 	    "cannot add to '%s'"), zhp->zpool_name);
531*2082Seschrock 
532*2082Seschrock 	if (zpool_get_version(zhp) < ZFS_VERSION_SPARES &&
533*2082Seschrock 	    nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
534*2082Seschrock 	    &spares, &nspares) == 0) {
535*2082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
536*2082Seschrock 		    "upgraded to add hot spares"));
537*2082Seschrock 		return (zfs_error(hdl, EZFS_BADVERSION, msg));
538*2082Seschrock 	}
539789Sahrens 
540789Sahrens 	verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0);
541789Sahrens 
542*2082Seschrock 	if ((packed = zfs_alloc(zhp->zpool_hdl, len)) == NULL)
543*2082Seschrock 		return (-1);
544789Sahrens 
545789Sahrens 	verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
546789Sahrens 
547789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
548789Sahrens 	zc.zc_config_src = (uint64_t)(uintptr_t)packed;
549789Sahrens 	zc.zc_config_src_size = len;
550789Sahrens 
551*2082Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) {
552789Sahrens 		switch (errno) {
553789Sahrens 		case EBUSY:
554789Sahrens 			/*
555789Sahrens 			 * This can happen if the user has specified the same
556789Sahrens 			 * device multiple times.  We can't reliably detect this
557789Sahrens 			 * until we try to add it and see we already have a
558789Sahrens 			 * label.
559789Sahrens 			 */
560*2082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
561*2082Seschrock 			    "one or more vdevs refer to the same device"));
562*2082Seschrock 			(void) zfs_error(hdl, EZFS_BADDEV, msg);
563789Sahrens 			break;
564789Sahrens 
565789Sahrens 		case EOVERFLOW:
566789Sahrens 			/*
567789Sahrens 			 * This occurrs when one of the devices is below
568789Sahrens 			 * SPA_MINDEVSIZE.  Unfortunately, we can't detect which
569789Sahrens 			 * device was the problem device since there's no
570789Sahrens 			 * reliable way to determine device size from userland.
571789Sahrens 			 */
572789Sahrens 			{
573789Sahrens 				char buf[64];
574789Sahrens 
575789Sahrens 				zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
576789Sahrens 
577*2082Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
578*2082Seschrock 				    "device is less than the minimum "
579*2082Seschrock 				    "size (%s)"), buf);
580789Sahrens 			}
581*2082Seschrock 			(void) zfs_error(hdl, EZFS_BADDEV, msg);
582*2082Seschrock 			break;
583*2082Seschrock 
584*2082Seschrock 		case ENOTSUP:
585*2082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
586*2082Seschrock 			    "pool must be upgraded to add raidz2 vdevs"));
587*2082Seschrock 			(void) zfs_error(hdl, EZFS_BADVERSION, msg);
588789Sahrens 			break;
589789Sahrens 
590789Sahrens 		default:
591*2082Seschrock 			(void) zpool_standard_error(hdl, errno, msg);
592789Sahrens 		}
593789Sahrens 
594*2082Seschrock 		ret = -1;
595*2082Seschrock 	} else {
596*2082Seschrock 		ret = 0;
597789Sahrens 	}
598789Sahrens 
599789Sahrens 	free(packed);
600789Sahrens 
601*2082Seschrock 	return (ret);
602789Sahrens }
603789Sahrens 
604789Sahrens /*
605789Sahrens  * Exports the pool from the system.  The caller must ensure that there are no
606789Sahrens  * mounted datasets in the pool.
607789Sahrens  */
608789Sahrens int
609789Sahrens zpool_export(zpool_handle_t *zhp)
610789Sahrens {
611789Sahrens 	zfs_cmd_t zc = { 0 };
612789Sahrens 
613789Sahrens 	if (zpool_remove_zvol_links(zhp) != 0)
614789Sahrens 		return (-1);
615789Sahrens 
616789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
617789Sahrens 
618*2082Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_EXPORT, &zc) != 0)
619*2082Seschrock 		return (zpool_standard_error(zhp->zpool_hdl, errno,
620*2082Seschrock 		    dgettext(TEXT_DOMAIN, "cannot export '%s'"),
621*2082Seschrock 		    zhp->zpool_name));
622789Sahrens 
623789Sahrens 	return (0);
624789Sahrens }
625789Sahrens 
626789Sahrens /*
627789Sahrens  * Import the given pool using the known configuration.  The configuration
628789Sahrens  * should have come from zpool_find_import().  The 'newname' and 'altroot'
629789Sahrens  * parameters control whether the pool is imported with a different name or with
630789Sahrens  * an alternate root, respectively.
631789Sahrens  */
632789Sahrens int
633*2082Seschrock zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
634*2082Seschrock     const char *altroot)
635789Sahrens {
636789Sahrens 	zfs_cmd_t zc;
637789Sahrens 	char *packed;
638789Sahrens 	size_t len;
639789Sahrens 	char *thename;
640789Sahrens 	char *origname;
641789Sahrens 	int ret;
642789Sahrens 
643789Sahrens 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
644789Sahrens 	    &origname) == 0);
645789Sahrens 
646789Sahrens 	if (newname != NULL) {
647*2082Seschrock 		if (!zpool_name_valid(hdl, B_FALSE, newname))
648*2082Seschrock 			return (zfs_error(hdl, EZFS_INVALIDNAME,
649*2082Seschrock 			    dgettext(TEXT_DOMAIN, "cannot import '%s'"),
650*2082Seschrock 			    newname));
651789Sahrens 		thename = (char *)newname;
652789Sahrens 	} else {
653789Sahrens 		thename = origname;
654789Sahrens 	}
655789Sahrens 
656*2082Seschrock 	if (altroot != NULL && altroot[0] != '/')
657*2082Seschrock 		return (zfs_error(hdl, EZFS_BADPATH,
658*2082Seschrock 		    dgettext(TEXT_DOMAIN, "bad alternate root '%s'"),
659*2082Seschrock 		    altroot));
660789Sahrens 
661789Sahrens 	(void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name));
662789Sahrens 
663789Sahrens 	if (altroot != NULL)
664789Sahrens 		(void) strlcpy(zc.zc_root, altroot, sizeof (zc.zc_root));
665789Sahrens 	else
666789Sahrens 		zc.zc_root[0] = '\0';
667789Sahrens 
668789Sahrens 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
6691544Seschrock 	    &zc.zc_guid) == 0);
670789Sahrens 
671789Sahrens 	verify(nvlist_size(config, &len, NV_ENCODE_NATIVE) == 0);
672789Sahrens 
673*2082Seschrock 	if ((packed = zfs_alloc(hdl, len)) == NULL)
674*2082Seschrock 		return (-1);
675789Sahrens 
676789Sahrens 	verify(nvlist_pack(config, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
677789Sahrens 
678789Sahrens 	zc.zc_config_src = (uint64_t)(uintptr_t)packed;
679789Sahrens 	zc.zc_config_src_size = len;
680789Sahrens 
681789Sahrens 	ret = 0;
682*2082Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) {
683789Sahrens 		char desc[1024];
684789Sahrens 		if (newname == NULL)
685789Sahrens 			(void) snprintf(desc, sizeof (desc),
686789Sahrens 			    dgettext(TEXT_DOMAIN, "cannot import '%s'"),
687789Sahrens 			    thename);
688789Sahrens 		else
689789Sahrens 			(void) snprintf(desc, sizeof (desc),
690789Sahrens 			    dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"),
691789Sahrens 			    origname, thename);
692789Sahrens 
693789Sahrens 		switch (errno) {
6941544Seschrock 		case ENOTSUP:
6951544Seschrock 			/*
6961544Seschrock 			 * Unsupported version.
6971544Seschrock 			 */
698*2082Seschrock 			(void) zfs_error(hdl, EZFS_BADVERSION, desc);
6991544Seschrock 			break;
7001544Seschrock 
701789Sahrens 		default:
702*2082Seschrock 			(void) zpool_standard_error(hdl, errno, desc);
703789Sahrens 		}
704789Sahrens 
705789Sahrens 		ret = -1;
706789Sahrens 	} else {
707789Sahrens 		zpool_handle_t *zhp;
708789Sahrens 		/*
709789Sahrens 		 * This should never fail, but play it safe anyway.
710789Sahrens 		 */
711*2082Seschrock 		if ((zhp = zpool_open_silent(hdl, thename)) != NULL) {
712789Sahrens 			ret = zpool_create_zvol_links(zhp);
713789Sahrens 			zpool_close(zhp);
714789Sahrens 		}
715789Sahrens 	}
716789Sahrens 
717789Sahrens 	free(packed);
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];
729*2082Seschrock 	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 
734*2082Seschrock 	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 
740*2082Seschrock 	if (errno == EBUSY)
741*2082Seschrock 		return (zfs_error(hdl, EZFS_RESILVERING, msg));
742*2082Seschrock 	else
743*2082Seschrock 		return (zpool_standard_error(hdl, errno, msg));
744789Sahrens }
745789Sahrens 
746*2082Seschrock static nvlist_t *
747*2082Seschrock vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid,
748*2082Seschrock     boolean_t *isspare)
7491544Seschrock {
7501544Seschrock 	uint_t c, children;
7511544Seschrock 	nvlist_t **child;
752*2082Seschrock 	uint64_t theguid, present;
7531544Seschrock 	char *path;
7541544Seschrock 	uint64_t wholedisk = 0;
755*2082Seschrock 	nvlist_t *ret;
7561544Seschrock 
757*2082Seschrock 	verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0);
7581544Seschrock 
7591544Seschrock 	if (search == NULL &&
7601544Seschrock 	    nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) {
7611544Seschrock 		/*
7621544Seschrock 		 * If the device has never been present since import, the only
7631544Seschrock 		 * reliable way to match the vdev is by GUID.
7641544Seschrock 		 */
765*2082Seschrock 		if (theguid == guid)
766*2082Seschrock 			return (nv);
7671544Seschrock 	} else if (search != NULL &&
7681544Seschrock 	    nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
7691544Seschrock 		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
7701544Seschrock 		    &wholedisk);
7711544Seschrock 		if (wholedisk) {
7721544Seschrock 			/*
7731544Seschrock 			 * For whole disks, the internal path has 's0', but the
7741544Seschrock 			 * path passed in by the user doesn't.
7751544Seschrock 			 */
7761544Seschrock 			if (strlen(search) == strlen(path) - 2 &&
7771544Seschrock 			    strncmp(search, path, strlen(search)) == 0)
778*2082Seschrock 				return (nv);
7791544Seschrock 		} else if (strcmp(search, path) == 0) {
780*2082Seschrock 			return (nv);
7811544Seschrock 		}
7821544Seschrock 	}
7831544Seschrock 
7841544Seschrock 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
7851544Seschrock 	    &child, &children) != 0)
786*2082Seschrock 		return (NULL);
7871544Seschrock 
7881544Seschrock 	for (c = 0; c < children; c++)
789*2082Seschrock 		if ((ret = vdev_to_nvlist_iter(child[c], search, guid,
790*2082Seschrock 		    isspare)) != NULL)
7911544Seschrock 			return (ret);
7921544Seschrock 
793*2082Seschrock 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
794*2082Seschrock 	    &child, &children) == 0) {
795*2082Seschrock 		for (c = 0; c < children; c++) {
796*2082Seschrock 			if ((ret = vdev_to_nvlist_iter(child[c], search, guid,
797*2082Seschrock 			    isspare)) != NULL) {
798*2082Seschrock 				*isspare = B_TRUE;
799*2082Seschrock 				return (ret);
800*2082Seschrock 			}
801*2082Seschrock 		}
802*2082Seschrock 	}
803*2082Seschrock 
804*2082Seschrock 	return (NULL);
8051544Seschrock }
8061544Seschrock 
807*2082Seschrock nvlist_t *
808*2082Seschrock zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *isspare)
8091544Seschrock {
8101544Seschrock 	char buf[MAXPATHLEN];
8111544Seschrock 	const char *search;
8121544Seschrock 	char *end;
8131544Seschrock 	nvlist_t *nvroot;
8141544Seschrock 	uint64_t guid;
8151544Seschrock 
8161613Seschrock 	guid = strtoull(path, &end, 10);
8171544Seschrock 	if (guid != 0 && *end == '\0') {
8181544Seschrock 		search = NULL;
8191544Seschrock 	} else if (path[0] != '/') {
8201544Seschrock 		(void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path);
8211544Seschrock 		search = buf;
8221544Seschrock 	} else {
8231544Seschrock 		search = path;
8241544Seschrock 	}
8251544Seschrock 
8261544Seschrock 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
8271544Seschrock 	    &nvroot) == 0);
8281544Seschrock 
829*2082Seschrock 	*isspare = B_FALSE;
830*2082Seschrock 	return (vdev_to_nvlist_iter(nvroot, search, guid, isspare));
8311544Seschrock }
8321544Seschrock 
833789Sahrens /*
834789Sahrens  * Bring the specified vdev online
835789Sahrens  */
836789Sahrens int
837789Sahrens zpool_vdev_online(zpool_handle_t *zhp, const char *path)
838789Sahrens {
839789Sahrens 	zfs_cmd_t zc = { 0 };
840789Sahrens 	char msg[1024];
841*2082Seschrock 	nvlist_t *tgt;
842*2082Seschrock 	boolean_t isspare;
843*2082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
844789Sahrens 
8451544Seschrock 	(void) snprintf(msg, sizeof (msg),
8461544Seschrock 	    dgettext(TEXT_DOMAIN, "cannot online %s"), path);
847789Sahrens 
8481544Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
849*2082Seschrock 	if ((tgt = zpool_find_vdev(zhp, path, &isspare)) == NULL)
850*2082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
851789Sahrens 
852*2082Seschrock 	if (isspare)
853*2082Seschrock 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
854*2082Seschrock 
855*2082Seschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
856*2082Seschrock 
857*2082Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ONLINE, &zc) == 0)
8581544Seschrock 		return (0);
859789Sahrens 
860*2082Seschrock 	return (zpool_standard_error(hdl, errno, msg));
861789Sahrens }
862789Sahrens 
863789Sahrens /*
864789Sahrens  * Take the specified vdev offline
865789Sahrens  */
866789Sahrens int
8671485Slling zpool_vdev_offline(zpool_handle_t *zhp, const char *path, int istmp)
868789Sahrens {
869789Sahrens 	zfs_cmd_t zc = { 0 };
870789Sahrens 	char msg[1024];
871*2082Seschrock 	nvlist_t *tgt;
872*2082Seschrock 	boolean_t isspare;
873*2082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
874789Sahrens 
8751544Seschrock 	(void) snprintf(msg, sizeof (msg),
8761544Seschrock 	    dgettext(TEXT_DOMAIN, "cannot offline %s"), path);
8771544Seschrock 
878789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
879*2082Seschrock 	if ((tgt = zpool_find_vdev(zhp, path, &isspare)) == NULL)
880*2082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
881*2082Seschrock 
882*2082Seschrock 	if (isspare)
883*2082Seschrock 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
884*2082Seschrock 
885*2082Seschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
886789Sahrens 
8871485Slling 	zc.zc_cookie = istmp;
8881485Slling 
889*2082Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_OFFLINE, &zc) == 0)
890789Sahrens 		return (0);
891789Sahrens 
892789Sahrens 	switch (errno) {
893*2082Seschrock 	case EBUSY:
894789Sahrens 
895789Sahrens 		/*
896789Sahrens 		 * There are no other replicas of this device.
897789Sahrens 		 */
898*2082Seschrock 		return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
899*2082Seschrock 
900*2082Seschrock 	default:
901*2082Seschrock 		return (zpool_standard_error(hdl, errno, msg));
902*2082Seschrock 	}
903*2082Seschrock }
904789Sahrens 
905*2082Seschrock /*
906*2082Seschrock  * Returns TRUE if the given nvlist is a vdev that was originally swapped in as
907*2082Seschrock  * a hot spare.
908*2082Seschrock  */
909*2082Seschrock static boolean_t
910*2082Seschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which)
911*2082Seschrock {
912*2082Seschrock 	nvlist_t **child;
913*2082Seschrock 	uint_t c, children;
914*2082Seschrock 	char *type;
915*2082Seschrock 
916*2082Seschrock 	if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child,
917*2082Seschrock 	    &children) == 0) {
918*2082Seschrock 		verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE,
919*2082Seschrock 		    &type) == 0);
920*2082Seschrock 
921*2082Seschrock 		if (strcmp(type, VDEV_TYPE_SPARE) == 0 &&
922*2082Seschrock 		    children == 2 && child[which] == tgt)
923*2082Seschrock 			return (B_TRUE);
924*2082Seschrock 
925*2082Seschrock 		for (c = 0; c < children; c++)
926*2082Seschrock 			if (is_replacing_spare(child[c], tgt, which))
927*2082Seschrock 				return (B_TRUE);
928789Sahrens 	}
929*2082Seschrock 
930*2082Seschrock 	return (B_FALSE);
931789Sahrens }
932789Sahrens 
933789Sahrens /*
934789Sahrens  * Attach new_disk (fully described by nvroot) to old_disk.
935789Sahrens  * If 'replacing' is specified, tne new disk will replace the old one.
936789Sahrens  */
937789Sahrens int
938789Sahrens zpool_vdev_attach(zpool_handle_t *zhp,
939789Sahrens     const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing)
940789Sahrens {
941789Sahrens 	zfs_cmd_t zc = { 0 };
942789Sahrens 	char msg[1024];
943789Sahrens 	char *packed;
944789Sahrens 	int ret;
945789Sahrens 	size_t len;
946*2082Seschrock 	nvlist_t *tgt;
947*2082Seschrock 	boolean_t isspare;
948*2082Seschrock 	uint64_t val;
949*2082Seschrock 	char *path;
950*2082Seschrock 	nvlist_t **child;
951*2082Seschrock 	uint_t children;
952*2082Seschrock 	nvlist_t *config_root;
953*2082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
954789Sahrens 
9551544Seschrock 	if (replacing)
9561544Seschrock 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
9571544Seschrock 		    "cannot replace %s with %s"), old_disk, new_disk);
9581544Seschrock 	else
9591544Seschrock 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
9601544Seschrock 		    "cannot attach %s to %s"), new_disk, old_disk);
9611544Seschrock 
962789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
963*2082Seschrock 	if ((tgt = zpool_find_vdev(zhp, old_disk, &isspare)) == 0)
964*2082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
965*2082Seschrock 
966*2082Seschrock 	if (isspare)
967*2082Seschrock 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
968*2082Seschrock 
969*2082Seschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
970*2082Seschrock 	zc.zc_cookie = replacing;
971*2082Seschrock 
972*2082Seschrock 	if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
973*2082Seschrock 	    &child, &children) != 0 || children != 1) {
974*2082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
975*2082Seschrock 		    "new device must be a single disk"));
976*2082Seschrock 		return (zfs_error(hdl, EZFS_INVALCONFIG, msg));
9771544Seschrock 	}
978*2082Seschrock 
979*2082Seschrock 	verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
980*2082Seschrock 	    ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0);
981*2082Seschrock 
982*2082Seschrock 	/*
983*2082Seschrock 	 * If the target is a hot spare that has been swapped in, we can only
984*2082Seschrock 	 * replace it with another hot spare.
985*2082Seschrock 	 */
986*2082Seschrock 	if (replacing &&
987*2082Seschrock 	    nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 &&
988*2082Seschrock 	    nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 &&
989*2082Seschrock 	    (zpool_find_vdev(zhp, path, &isspare) == NULL || !isspare) &&
990*2082Seschrock 	    is_replacing_spare(config_root, tgt, 1)) {
991*2082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
992*2082Seschrock 		    "can only be replaced by another hot spare"));
993*2082Seschrock 		return (zfs_error(hdl, EZFS_BADTARGET, msg));
994*2082Seschrock 	}
995*2082Seschrock 
996*2082Seschrock 	/*
997*2082Seschrock 	 * If we are attempting to replace a spare, it canot be applied to an
998*2082Seschrock 	 * already spared device.
999*2082Seschrock 	 */
1000*2082Seschrock 	if (replacing &&
1001*2082Seschrock 	    nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 &&
1002*2082Seschrock 	    zpool_find_vdev(zhp, path, &isspare) != NULL && isspare &&
1003*2082Seschrock 	    is_replacing_spare(config_root, tgt, 0)) {
1004*2082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1005*2082Seschrock 		    "device has already been replaced with a spare"));
1006*2082Seschrock 		return (zfs_error(hdl, EZFS_BADTARGET, msg));
1007*2082Seschrock 	}
1008789Sahrens 
1009789Sahrens 	verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0);
1010789Sahrens 
1011*2082Seschrock 	if ((packed = zfs_alloc(zhp->zpool_hdl, len)) == NULL)
1012*2082Seschrock 		return (-1);
1013789Sahrens 
1014789Sahrens 	verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
1015789Sahrens 
1016789Sahrens 	zc.zc_config_src = (uint64_t)(uintptr_t)packed;
1017789Sahrens 	zc.zc_config_src_size = len;
1018789Sahrens 
1019*2082Seschrock 	ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ATTACH, &zc);
1020789Sahrens 
1021789Sahrens 	free(packed);
1022789Sahrens 
1023789Sahrens 	if (ret == 0)
1024789Sahrens 		return (0);
1025789Sahrens 
1026789Sahrens 	switch (errno) {
10271544Seschrock 	case ENOTSUP:
1028789Sahrens 		/*
1029789Sahrens 		 * Can't attach to or replace this type of vdev.
1030789Sahrens 		 */
1031789Sahrens 		if (replacing)
1032*2082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1033*2082Seschrock 			    "cannot replace a replacing device"));
1034789Sahrens 		else
1035*2082Seschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1036*2082Seschrock 			    "can only attach to mirrors and top-level "
1037*2082Seschrock 			    "disks"));
1038*2082Seschrock 		(void) zfs_error(hdl, EZFS_BADTARGET, msg);
1039789Sahrens 		break;
1040789Sahrens 
10411544Seschrock 	case EINVAL:
1042789Sahrens 		/*
1043789Sahrens 		 * The new device must be a single disk.
1044789Sahrens 		 */
1045*2082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1046*2082Seschrock 		    "new device must be a single disk"));
1047*2082Seschrock 		(void) zfs_error(hdl, EZFS_INVALCONFIG, msg);
1048789Sahrens 		break;
1049789Sahrens 
10501544Seschrock 	case EBUSY:
1051*2082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"),
1052*2082Seschrock 		    new_disk);
1053*2082Seschrock 		(void) zfs_error(hdl, EZFS_BADDEV, msg);
1054789Sahrens 		break;
1055789Sahrens 
10561544Seschrock 	case EOVERFLOW:
1057789Sahrens 		/*
1058789Sahrens 		 * The new device is too small.
1059789Sahrens 		 */
1060*2082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1061*2082Seschrock 		    "device is too small"));
1062*2082Seschrock 		(void) zfs_error(hdl, EZFS_BADDEV, msg);
1063789Sahrens 		break;
1064789Sahrens 
10651544Seschrock 	case EDOM:
1066789Sahrens 		/*
1067789Sahrens 		 * The new device has a different alignment requirement.
1068789Sahrens 		 */
1069*2082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1070*2082Seschrock 		    "devices have different sector alignment"));
1071*2082Seschrock 		(void) zfs_error(hdl, EZFS_BADDEV, msg);
1072789Sahrens 		break;
1073789Sahrens 
10741544Seschrock 	case ENAMETOOLONG:
1075789Sahrens 		/*
1076789Sahrens 		 * The resulting top-level vdev spec won't fit in the label.
1077789Sahrens 		 */
1078*2082Seschrock 		(void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg);
1079789Sahrens 		break;
1080789Sahrens 
10811544Seschrock 	default:
1082*2082Seschrock 		(void) zpool_standard_error(hdl, errno, msg);
1083789Sahrens 	}
1084789Sahrens 
1085*2082Seschrock 	return (-1);
1086789Sahrens }
1087789Sahrens 
1088789Sahrens /*
1089789Sahrens  * Detach the specified device.
1090789Sahrens  */
1091789Sahrens int
1092789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path)
1093789Sahrens {
1094789Sahrens 	zfs_cmd_t zc = { 0 };
1095789Sahrens 	char msg[1024];
1096*2082Seschrock 	nvlist_t *tgt;
1097*2082Seschrock 	boolean_t isspare;
1098*2082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1099789Sahrens 
11001544Seschrock 	(void) snprintf(msg, sizeof (msg),
11011544Seschrock 	    dgettext(TEXT_DOMAIN, "cannot detach %s"), path);
11021544Seschrock 
1103789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1104*2082Seschrock 	if ((tgt = zpool_find_vdev(zhp, path, &isspare)) == 0)
1105*2082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
1106789Sahrens 
1107*2082Seschrock 	if (isspare)
1108*2082Seschrock 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
1109*2082Seschrock 
1110*2082Seschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
1111*2082Seschrock 
1112*2082Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_DETACH, &zc) == 0)
1113789Sahrens 		return (0);
1114789Sahrens 
1115789Sahrens 	switch (errno) {
1116789Sahrens 
11171544Seschrock 	case ENOTSUP:
1118789Sahrens 		/*
1119789Sahrens 		 * Can't detach from this type of vdev.
1120789Sahrens 		 */
1121*2082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only "
1122*2082Seschrock 		    "applicable to mirror and replacing vdevs"));
1123*2082Seschrock 		(void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg);
1124789Sahrens 		break;
1125789Sahrens 
11261544Seschrock 	case EBUSY:
1127789Sahrens 		/*
1128789Sahrens 		 * There are no other replicas of this device.
1129789Sahrens 		 */
1130*2082Seschrock 		(void) zfs_error(hdl, EZFS_NOREPLICAS, msg);
1131789Sahrens 		break;
1132789Sahrens 
11331544Seschrock 	default:
1134*2082Seschrock 		(void) zpool_standard_error(hdl, errno, msg);
11351544Seschrock 	}
11361544Seschrock 
1137*2082Seschrock 	return (-1);
1138*2082Seschrock }
1139*2082Seschrock 
1140*2082Seschrock /*
1141*2082Seschrock  * Remove the given device.  Currently, this is supported only for hot spares.
1142*2082Seschrock  */
1143*2082Seschrock int
1144*2082Seschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path)
1145*2082Seschrock {
1146*2082Seschrock 	zfs_cmd_t zc = { 0 };
1147*2082Seschrock 	char msg[1024];
1148*2082Seschrock 	nvlist_t *tgt;
1149*2082Seschrock 	boolean_t isspare;
1150*2082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1151*2082Seschrock 
1152*2082Seschrock 	(void) snprintf(msg, sizeof (msg),
1153*2082Seschrock 	    dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
1154*2082Seschrock 
1155*2082Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1156*2082Seschrock 	if ((tgt = zpool_find_vdev(zhp, path, &isspare)) == 0)
1157*2082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
1158*2082Seschrock 
1159*2082Seschrock 	if (!isspare) {
1160*2082Seschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1161*2082Seschrock 		    "only hot spares can be removed"));
1162*2082Seschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
1163*2082Seschrock 	}
1164*2082Seschrock 
1165*2082Seschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
1166*2082Seschrock 
1167*2082Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_REMOVE, &zc) == 0)
1168*2082Seschrock 		return (0);
1169*2082Seschrock 
1170*2082Seschrock 	return (zpool_standard_error(hdl, errno, msg));
11711544Seschrock }
11721544Seschrock 
11731544Seschrock /*
11741544Seschrock  * Clear the errors for the pool, or the particular device if specified.
11751544Seschrock  */
11761544Seschrock int
11771544Seschrock zpool_clear(zpool_handle_t *zhp, const char *path)
11781544Seschrock {
11791544Seschrock 	zfs_cmd_t zc = { 0 };
11801544Seschrock 	char msg[1024];
1181*2082Seschrock 	nvlist_t *tgt;
1182*2082Seschrock 	boolean_t isspare;
1183*2082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
11841544Seschrock 
11851544Seschrock 	if (path)
11861544Seschrock 		(void) snprintf(msg, sizeof (msg),
11871544Seschrock 		    dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
11881544Seschrock 		    zc.zc_prop_value);
11891544Seschrock 	else
11901544Seschrock 		(void) snprintf(msg, sizeof (msg),
11911544Seschrock 		    dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
11921544Seschrock 		    zhp->zpool_name);
11931544Seschrock 
11941544Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1195*2082Seschrock 	if (path) {
1196*2082Seschrock 		if ((tgt = zpool_find_vdev(zhp, path, &isspare)) == 0)
1197*2082Seschrock 			return (zfs_error(hdl, EZFS_NODEVICE, msg));
1198*2082Seschrock 
1199*2082Seschrock 		if (isspare)
1200*2082Seschrock 			return (zfs_error(hdl, EZFS_ISSPARE, msg));
1201*2082Seschrock 
1202*2082Seschrock 		verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID,
1203*2082Seschrock 		    &zc.zc_guid) == 0);
12041544Seschrock 	}
12051544Seschrock 
1206*2082Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0)
12071544Seschrock 		return (0);
12081544Seschrock 
1209*2082Seschrock 	return (zpool_standard_error(hdl, errno, msg));
1210789Sahrens }
1211789Sahrens 
1212789Sahrens static int
1213789Sahrens do_zvol(zfs_handle_t *zhp, void *data)
1214789Sahrens {
1215789Sahrens 	int linktype = (int)(uintptr_t)data;
1216789Sahrens 	int ret;
1217789Sahrens 
1218789Sahrens 	/*
1219789Sahrens 	 * We check for volblocksize intead of ZFS_TYPE_VOLUME so that we
1220789Sahrens 	 * correctly handle snapshots of volumes.
1221789Sahrens 	 */
1222789Sahrens 	if (zhp->zfs_volblocksize != 0) {
1223789Sahrens 		if (linktype)
1224*2082Seschrock 			ret = zvol_create_link(zhp->zfs_hdl, zhp->zfs_name);
1225789Sahrens 		else
1226*2082Seschrock 			ret = zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name);
1227789Sahrens 	}
1228789Sahrens 
1229789Sahrens 	ret = zfs_iter_children(zhp, do_zvol, data);
1230789Sahrens 
1231789Sahrens 	zfs_close(zhp);
1232789Sahrens 	return (ret);
1233789Sahrens }
1234789Sahrens 
1235789Sahrens /*
1236789Sahrens  * Iterate over all zvols in the pool and make any necessary minor nodes.
1237789Sahrens  */
1238789Sahrens int
1239789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp)
1240789Sahrens {
1241789Sahrens 	zfs_handle_t *zfp;
1242789Sahrens 	int ret;
1243789Sahrens 
1244789Sahrens 	/*
1245789Sahrens 	 * If the pool is unavailable, just return success.
1246789Sahrens 	 */
1247*2082Seschrock 	if ((zfp = make_dataset_handle(zhp->zpool_hdl,
1248*2082Seschrock 	    zhp->zpool_name)) == NULL)
1249789Sahrens 		return (0);
1250789Sahrens 
1251*2082Seschrock 	ret = zfs_iter_children(zfp, do_zvol, (void *)B_TRUE);
1252789Sahrens 
1253789Sahrens 	zfs_close(zfp);
1254789Sahrens 	return (ret);
1255789Sahrens }
1256789Sahrens 
1257789Sahrens /*
1258789Sahrens  * Iterate over all zvols in the poool and remove any minor nodes.
1259789Sahrens  */
1260789Sahrens int
1261789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp)
1262789Sahrens {
1263789Sahrens 	zfs_handle_t *zfp;
1264789Sahrens 	int ret;
1265789Sahrens 
1266789Sahrens 	/*
1267789Sahrens 	 * If the pool is unavailable, just return success.
1268789Sahrens 	 */
1269*2082Seschrock 	if ((zfp = make_dataset_handle(zhp->zpool_hdl,
1270*2082Seschrock 	    zhp->zpool_name)) == NULL)
1271789Sahrens 		return (0);
1272789Sahrens 
1273*2082Seschrock 	ret = zfs_iter_children(zfp, do_zvol, (void *)B_FALSE);
1274789Sahrens 
1275789Sahrens 	zfs_close(zfp);
1276789Sahrens 	return (ret);
1277789Sahrens }
12781354Seschrock 
12791354Seschrock /*
12801354Seschrock  * Convert from a devid string to a path.
12811354Seschrock  */
12821354Seschrock static char *
12831354Seschrock devid_to_path(char *devid_str)
12841354Seschrock {
12851354Seschrock 	ddi_devid_t devid;
12861354Seschrock 	char *minor;
12871354Seschrock 	char *path;
12881354Seschrock 	devid_nmlist_t *list = NULL;
12891354Seschrock 	int ret;
12901354Seschrock 
12911354Seschrock 	if (devid_str_decode(devid_str, &devid, &minor) != 0)
12921354Seschrock 		return (NULL);
12931354Seschrock 
12941354Seschrock 	ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list);
12951354Seschrock 
12961354Seschrock 	devid_str_free(minor);
12971354Seschrock 	devid_free(devid);
12981354Seschrock 
12991354Seschrock 	if (ret != 0)
13001354Seschrock 		return (NULL);
13011354Seschrock 
1302*2082Seschrock 	if ((path = strdup(list[0].devname)) == NULL)
1303*2082Seschrock 		return (NULL);
1304*2082Seschrock 
13051354Seschrock 	devid_free_nmlist(list);
13061354Seschrock 
13071354Seschrock 	return (path);
13081354Seschrock }
13091354Seschrock 
13101354Seschrock /*
13111354Seschrock  * Convert from a path to a devid string.
13121354Seschrock  */
13131354Seschrock static char *
13141354Seschrock path_to_devid(const char *path)
13151354Seschrock {
13161354Seschrock 	int fd;
13171354Seschrock 	ddi_devid_t devid;
13181354Seschrock 	char *minor, *ret;
13191354Seschrock 
13201354Seschrock 	if ((fd = open(path, O_RDONLY)) < 0)
13211354Seschrock 		return (NULL);
13221354Seschrock 
13231354Seschrock 	minor = NULL;
13241354Seschrock 	ret = NULL;
13251354Seschrock 	if (devid_get(fd, &devid) == 0) {
13261354Seschrock 		if (devid_get_minor_name(fd, &minor) == 0)
13271354Seschrock 			ret = devid_str_encode(devid, minor);
13281354Seschrock 		if (minor != NULL)
13291354Seschrock 			devid_str_free(minor);
13301354Seschrock 		devid_free(devid);
13311354Seschrock 	}
13321354Seschrock 	(void) close(fd);
13331354Seschrock 
13341354Seschrock 	return (ret);
13351354Seschrock }
13361354Seschrock 
13371354Seschrock /*
13381354Seschrock  * Issue the necessary ioctl() to update the stored path value for the vdev.  We
13391354Seschrock  * ignore any failure here, since a common case is for an unprivileged user to
13401354Seschrock  * type 'zpool status', and we'll display the correct information anyway.
13411354Seschrock  */
13421354Seschrock static void
13431354Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path)
13441354Seschrock {
13451354Seschrock 	zfs_cmd_t zc = { 0 };
13461354Seschrock 
13471354Seschrock 	(void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
13481354Seschrock 	(void) strncpy(zc.zc_prop_value, path, sizeof (zc.zc_prop_value));
13491354Seschrock 	verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
13501544Seschrock 	    &zc.zc_guid) == 0);
13511354Seschrock 
1352*2082Seschrock 	(void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc);
13531354Seschrock }
13541354Seschrock 
13551354Seschrock /*
13561354Seschrock  * Given a vdev, return the name to display in iostat.  If the vdev has a path,
13571354Seschrock  * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type.
13581354Seschrock  * We also check if this is a whole disk, in which case we strip off the
13591354Seschrock  * trailing 's0' slice name.
13601354Seschrock  *
13611354Seschrock  * This routine is also responsible for identifying when disks have been
13621354Seschrock  * reconfigured in a new location.  The kernel will have opened the device by
13631354Seschrock  * devid, but the path will still refer to the old location.  To catch this, we
13641354Seschrock  * first do a path -> devid translation (which is fast for the common case).  If
13651354Seschrock  * the devid matches, we're done.  If not, we do a reverse devid -> path
13661354Seschrock  * translation and issue the appropriate ioctl() to update the path of the vdev.
13671354Seschrock  * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any
13681354Seschrock  * of these checks.
13691354Seschrock  */
13701354Seschrock char *
1371*2082Seschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv)
13721354Seschrock {
13731354Seschrock 	char *path, *devid;
13741544Seschrock 	uint64_t value;
13751544Seschrock 	char buf[64];
13761354Seschrock 
13771544Seschrock 	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
13781544Seschrock 	    &value) == 0) {
13791544Seschrock 		verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
13801544Seschrock 		    &value) == 0);
13811613Seschrock 		(void) snprintf(buf, sizeof (buf), "%llu", value);
13821544Seschrock 		path = buf;
13831544Seschrock 	} else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
13841354Seschrock 
13851354Seschrock 		if (zhp != NULL &&
13861354Seschrock 		    nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) {
13871354Seschrock 			/*
13881354Seschrock 			 * Determine if the current path is correct.
13891354Seschrock 			 */
13901354Seschrock 			char *newdevid = path_to_devid(path);
13911354Seschrock 
13921354Seschrock 			if (newdevid == NULL ||
13931354Seschrock 			    strcmp(devid, newdevid) != 0) {
13941354Seschrock 				char *newpath;
13951354Seschrock 
13961354Seschrock 				if ((newpath = devid_to_path(devid)) != NULL) {
13971354Seschrock 					/*
13981354Seschrock 					 * Update the path appropriately.
13991354Seschrock 					 */
14001354Seschrock 					set_path(zhp, nv, newpath);
1401*2082Seschrock 					if (nvlist_add_string(nv,
1402*2082Seschrock 					    ZPOOL_CONFIG_PATH, newpath) == 0)
1403*2082Seschrock 						verify(nvlist_lookup_string(nv,
1404*2082Seschrock 						    ZPOOL_CONFIG_PATH,
1405*2082Seschrock 						    &path) == 0);
14061354Seschrock 					free(newpath);
14071354Seschrock 				}
14081354Seschrock 			}
14091354Seschrock 
1410*2082Seschrock 			if (newdevid)
1411*2082Seschrock 				devid_str_free(newdevid);
14121354Seschrock 		}
14131354Seschrock 
14141354Seschrock 		if (strncmp(path, "/dev/dsk/", 9) == 0)
14151354Seschrock 			path += 9;
14161354Seschrock 
14171354Seschrock 		if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
14181544Seschrock 		    &value) == 0 && value) {
1419*2082Seschrock 			char *tmp = zfs_strdup(hdl, path);
1420*2082Seschrock 			if (tmp == NULL)
1421*2082Seschrock 				return (NULL);
14221354Seschrock 			tmp[strlen(path) - 2] = '\0';
14231354Seschrock 			return (tmp);
14241354Seschrock 		}
14251354Seschrock 	} else {
14261354Seschrock 		verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0);
1427*2082Seschrock 
1428*2082Seschrock 		/*
1429*2082Seschrock 		 * If it's a raidz device, we need to stick in the parity level.
1430*2082Seschrock 		 */
1431*2082Seschrock 		if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) {
1432*2082Seschrock 			verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY,
1433*2082Seschrock 			    &value) == 0);
1434*2082Seschrock 			(void) snprintf(buf, sizeof (buf), "%s%llu", path,
1435*2082Seschrock 			    value);
1436*2082Seschrock 			path = buf;
1437*2082Seschrock 		}
14381354Seschrock 	}
14391354Seschrock 
1440*2082Seschrock 	return (zfs_strdup(hdl, path));
14411354Seschrock }
14421544Seschrock 
14431544Seschrock static int
14441544Seschrock zbookmark_compare(const void *a, const void *b)
14451544Seschrock {
14461544Seschrock 	return (memcmp(a, b, sizeof (zbookmark_t)));
14471544Seschrock }
14481544Seschrock 
14491544Seschrock /*
14501544Seschrock  * Retrieve the persistent error log, uniquify the members, and return to the
14511544Seschrock  * caller.
14521544Seschrock  */
14531544Seschrock int
14541544Seschrock zpool_get_errlog(zpool_handle_t *zhp, nvlist_t ***list, size_t *nelem)
14551544Seschrock {
14561544Seschrock 	zfs_cmd_t zc = { 0 };
14571544Seschrock 	uint64_t count;
14581544Seschrock 	zbookmark_t *zb;
14591544Seschrock 	int i, j;
14601544Seschrock 
14611544Seschrock 	if (zhp->zpool_error_log != NULL) {
14621544Seschrock 		*list = zhp->zpool_error_log;
14631544Seschrock 		*nelem = zhp->zpool_error_count;
14641544Seschrock 		return (0);
14651544Seschrock 	}
14661544Seschrock 
14671544Seschrock 	/*
14681544Seschrock 	 * Retrieve the raw error list from the kernel.  If the number of errors
14691544Seschrock 	 * has increased, allocate more space and continue until we get the
14701544Seschrock 	 * entire list.
14711544Seschrock 	 */
14721544Seschrock 	verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT,
14731544Seschrock 	    &count) == 0);
1474*2082Seschrock 	if ((zc.zc_config_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl,
1475*2082Seschrock 	    count * sizeof (zbookmark_t))) == NULL)
1476*2082Seschrock 		return (-1);
14771544Seschrock 	zc.zc_config_dst_size = count;
14781544Seschrock 	(void) strcpy(zc.zc_name, zhp->zpool_name);
14791544Seschrock 	for (;;) {
1480*2082Seschrock 		if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG,
1481*2082Seschrock 		    &zc) != 0) {
1482*2082Seschrock 			free((void *)(uintptr_t)zc.zc_config_dst);
14831544Seschrock 			if (errno == ENOMEM) {
1484*2082Seschrock 				if ((zc.zc_config_dst = (uintptr_t)
1485*2082Seschrock 				    zfs_alloc(zhp->zpool_hdl,
1486*2082Seschrock 				    zc.zc_config_dst_size)) == NULL)
1487*2082Seschrock 					return (-1);
14881544Seschrock 			} else {
14891544Seschrock 				return (-1);
14901544Seschrock 			}
14911544Seschrock 		} else {
14921544Seschrock 			break;
14931544Seschrock 		}
14941544Seschrock 	}
14951544Seschrock 
14961544Seschrock 	/*
14971544Seschrock 	 * Sort the resulting bookmarks.  This is a little confusing due to the
14981544Seschrock 	 * implementation of ZFS_IOC_ERROR_LOG.  The bookmarks are copied last
14991544Seschrock 	 * to first, and 'zc_config_dst_size' indicates the number of boomarks
15001544Seschrock 	 * _not_ copied as part of the process.  So we point the start of our
15011544Seschrock 	 * array appropriate and decrement the total number of elements.
15021544Seschrock 	 */
15031544Seschrock 	zb = ((zbookmark_t *)(uintptr_t)zc.zc_config_dst) +
15041544Seschrock 	    zc.zc_config_dst_size;
15051544Seschrock 	count -= zc.zc_config_dst_size;
15061544Seschrock 
15071544Seschrock 	qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare);
15081544Seschrock 
15091544Seschrock 	/*
15101544Seschrock 	 * Count the number of unique elements
15111544Seschrock 	 */
15121544Seschrock 	j = 0;
15131544Seschrock 	for (i = 0; i < count; i++) {
15141544Seschrock 		if (i > 0 && memcmp(&zb[i - 1], &zb[i],
15151544Seschrock 		    sizeof (zbookmark_t)) == 0)
15161544Seschrock 			continue;
15171544Seschrock 		j++;
15181544Seschrock 	}
15191544Seschrock 
15201544Seschrock 	/*
15211544Seschrock 	 * If the user has only requested the number of items, return it now
15221544Seschrock 	 * without bothering with the extra work.
15231544Seschrock 	 */
15241544Seschrock 	if (list == NULL) {
15251544Seschrock 		*nelem = j;
1526*2082Seschrock 		free((void *)(uintptr_t)zc.zc_config_dst);
15271544Seschrock 		return (0);
15281544Seschrock 	}
15291544Seschrock 
15301544Seschrock 	zhp->zpool_error_count = j;
15311544Seschrock 
15321544Seschrock 	/*
15331544Seschrock 	 * Allocate an array of nvlists to hold the results
15341544Seschrock 	 */
1535*2082Seschrock 	if ((zhp->zpool_error_log = zfs_alloc(zhp->zpool_hdl,
1536*2082Seschrock 	    j * sizeof (nvlist_t *))) == NULL) {
1537*2082Seschrock 		free((void *)(uintptr_t)zc.zc_config_dst);
1538*2082Seschrock 		return (-1);
1539*2082Seschrock 	}
15401544Seschrock 
15411544Seschrock 	/*
15421544Seschrock 	 * Fill in the results with names from the kernel.
15431544Seschrock 	 */
15441544Seschrock 	j = 0;
15451544Seschrock 	for (i = 0; i < count; i++) {
15461544Seschrock 		char buf[64];
15471544Seschrock 		nvlist_t *nv;
15481544Seschrock 
15491544Seschrock 		if (i > 0 && memcmp(&zb[i - 1], &zb[i],
15501544Seschrock 		    sizeof (zbookmark_t)) == 0)
15511544Seschrock 			continue;
15521544Seschrock 
1553*2082Seschrock 		if (nvlist_alloc(&nv, NV_UNIQUE_NAME,
1554*2082Seschrock 		    0) != 0)
1555*2082Seschrock 			goto nomem;
15561544Seschrock 		zhp->zpool_error_log[j] = nv;
15571544Seschrock 
15581544Seschrock 		zc.zc_bookmark = zb[i];
1559*2082Seschrock 		if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_BOOKMARK_NAME,
1560*2082Seschrock 		    &zc) == 0) {
1561*2082Seschrock 			if (nvlist_add_string(nv, ZPOOL_ERR_DATASET,
1562*2082Seschrock 			    zc.zc_prop_name) != 0 ||
1563*2082Seschrock 			    nvlist_add_string(nv, ZPOOL_ERR_OBJECT,
1564*2082Seschrock 			    zc.zc_prop_value) != 0 ||
1565*2082Seschrock 			    nvlist_add_string(nv, ZPOOL_ERR_RANGE,
1566*2082Seschrock 			    zc.zc_filename) != 0)
1567*2082Seschrock 				goto nomem;
15681544Seschrock 		} else {
15691544Seschrock 			(void) snprintf(buf, sizeof (buf), "%llx",
15701544Seschrock 			    zb[i].zb_objset);
1571*2082Seschrock 			if (nvlist_add_string(nv,
1572*2082Seschrock 			    ZPOOL_ERR_DATASET, buf) != 0)
1573*2082Seschrock 				goto nomem;
15741544Seschrock 			(void) snprintf(buf, sizeof (buf), "%llx",
15751544Seschrock 			    zb[i].zb_object);
1576*2082Seschrock 			if (nvlist_add_string(nv, ZPOOL_ERR_OBJECT,
1577*2082Seschrock 			    buf) != 0)
1578*2082Seschrock 				goto nomem;
15791544Seschrock 			(void) snprintf(buf, sizeof (buf), "lvl=%u blkid=%llu",
15801544Seschrock 			    (int)zb[i].zb_level, (long long)zb[i].zb_blkid);
1581*2082Seschrock 			if (nvlist_add_string(nv, ZPOOL_ERR_RANGE,
1582*2082Seschrock 			    buf) != 0)
1583*2082Seschrock 				goto nomem;
15841544Seschrock 		}
15851544Seschrock 
15861544Seschrock 		j++;
15871544Seschrock 	}
15881544Seschrock 
15891544Seschrock 	*list = zhp->zpool_error_log;
15901544Seschrock 	*nelem = zhp->zpool_error_count;
15911544Seschrock 
15921544Seschrock 	free((void *)(uintptr_t)zc.zc_config_dst);
15931544Seschrock 
15941544Seschrock 	return (0);
1595*2082Seschrock 
1596*2082Seschrock nomem:
1597*2082Seschrock 	free((void *)(uintptr_t)zc.zc_config_dst);
1598*2082Seschrock 	for (i = 0; i < zhp->zpool_error_count; i++) {
1599*2082Seschrock 		if (zhp->zpool_error_log[i])
1600*2082Seschrock 			free(zhp->zpool_error_log[i]);
1601*2082Seschrock 	}
1602*2082Seschrock 	free(zhp->zpool_error_log);
1603*2082Seschrock 	zhp->zpool_error_log = NULL;
1604*2082Seschrock 	return (no_memory(zhp->zpool_hdl));
16051544Seschrock }
16061760Seschrock 
16071760Seschrock /*
16081760Seschrock  * Upgrade a ZFS pool to the latest on-disk version.
16091760Seschrock  */
16101760Seschrock int
16111760Seschrock zpool_upgrade(zpool_handle_t *zhp)
16121760Seschrock {
16131760Seschrock 	zfs_cmd_t zc = { 0 };
1614*2082Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
16151760Seschrock 
16161760Seschrock 	(void) strcpy(zc.zc_name, zhp->zpool_name);
1617*2082Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_UPGRADE, &zc) != 0)
1618*2082Seschrock 		return (zpool_standard_error(hdl, errno,
1619*2082Seschrock 		    dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"),
1620*2082Seschrock 		    zhp->zpool_name));
16211760Seschrock 
16221760Seschrock 	return (0);
16231760Seschrock }
1624