xref: /illumos-gate/usr/src/lib/libzfs/common/libzfs_pool.c (revision 379c004d1f26b343f034bba8a350290691d00d38)
1fa9e4066Sahrens /*
2fa9e4066Sahrens  * CDDL HEADER START
3fa9e4066Sahrens  *
4fa9e4066Sahrens  * The contents of this file are subject to the terms of the
5441d80aaSlling  * Common Development and Distribution License (the "License").
6441d80aaSlling  * You may not use this file except in compliance with the License.
7fa9e4066Sahrens  *
8fa9e4066Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e4066Sahrens  * or http://www.opensolaris.org/os/licensing.
10fa9e4066Sahrens  * See the License for the specific language governing permissions
11fa9e4066Sahrens  * and limitations under the License.
12fa9e4066Sahrens  *
13fa9e4066Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14fa9e4066Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e4066Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16fa9e4066Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e4066Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e4066Sahrens  *
19fa9e4066Sahrens  * CDDL HEADER END
20fa9e4066Sahrens  */
2199653d4eSeschrock 
22fa9e4066Sahrens /*
23*379c004dSEric Schrock  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24fa9e4066Sahrens  * Use is subject to license terms.
25fa9e4066Sahrens  */
26fa9e4066Sahrens 
27f3861e1aSahl #include <alloca.h>
28fa9e4066Sahrens #include <assert.h>
29fa9e4066Sahrens #include <ctype.h>
30fa9e4066Sahrens #include <errno.h>
31fa9e4066Sahrens #include <devid.h>
32f3861e1aSahl #include <dirent.h>
33fa9e4066Sahrens #include <fcntl.h>
34fa9e4066Sahrens #include <libintl.h>
35fa9e4066Sahrens #include <stdio.h>
36fa9e4066Sahrens #include <stdlib.h>
37f3861e1aSahl #include <strings.h>
38fa9e4066Sahrens #include <unistd.h>
390a48a24eStimh #include <zone.h>
408488aeb5Staylor #include <sys/efi_partition.h>
418488aeb5Staylor #include <sys/vtoc.h>
42fa9e4066Sahrens #include <sys/zfs_ioctl.h>
43ea8dc4b6Seschrock #include <sys/zio.h>
4406eeb2adSek #include <strings.h>
45fa9e4066Sahrens 
46fa9e4066Sahrens #include "zfs_namecheck.h"
47b1b8ab34Slling #include "zfs_prop.h"
48fa9e4066Sahrens #include "libzfs_impl.h"
49fa9e4066Sahrens 
5015e6edf1Sgw static int read_efi_label(nvlist_t *config, diskaddr_t *sb);
51990b4856Slling 
52b5b76fecSGeorge Wilson #if defined(__i386) || defined(__amd64)
53b5b76fecSGeorge Wilson #define	BOOTCMD	"installgrub(1M)"
54b5b76fecSGeorge Wilson #else
55b5b76fecSGeorge Wilson #define	BOOTCMD	"installboot(1M)"
56b5b76fecSGeorge Wilson #endif
57b5b76fecSGeorge Wilson 
58990b4856Slling /*
59990b4856Slling  * ====================================================================
60990b4856Slling  *   zpool property functions
61990b4856Slling  * ====================================================================
62990b4856Slling  */
63990b4856Slling 
64990b4856Slling static int
65990b4856Slling zpool_get_all_props(zpool_handle_t *zhp)
66990b4856Slling {
67990b4856Slling 	zfs_cmd_t zc = { 0 };
68990b4856Slling 	libzfs_handle_t *hdl = zhp->zpool_hdl;
69990b4856Slling 
70990b4856Slling 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
71990b4856Slling 
72990b4856Slling 	if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0)
73990b4856Slling 		return (-1);
74990b4856Slling 
75990b4856Slling 	while (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) {
76990b4856Slling 		if (errno == ENOMEM) {
77990b4856Slling 			if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
78990b4856Slling 				zcmd_free_nvlists(&zc);
79990b4856Slling 				return (-1);
80990b4856Slling 			}
81990b4856Slling 		} else {
82990b4856Slling 			zcmd_free_nvlists(&zc);
83990b4856Slling 			return (-1);
84990b4856Slling 		}
85990b4856Slling 	}
86990b4856Slling 
87990b4856Slling 	if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) {
88990b4856Slling 		zcmd_free_nvlists(&zc);
89990b4856Slling 		return (-1);
90990b4856Slling 	}
91990b4856Slling 
92990b4856Slling 	zcmd_free_nvlists(&zc);
93990b4856Slling 
94990b4856Slling 	return (0);
95990b4856Slling }
96990b4856Slling 
97990b4856Slling static int
98990b4856Slling zpool_props_refresh(zpool_handle_t *zhp)
99990b4856Slling {
100990b4856Slling 	nvlist_t *old_props;
101990b4856Slling 
102990b4856Slling 	old_props = zhp->zpool_props;
103990b4856Slling 
104990b4856Slling 	if (zpool_get_all_props(zhp) != 0)
105990b4856Slling 		return (-1);
106990b4856Slling 
107990b4856Slling 	nvlist_free(old_props);
108990b4856Slling 	return (0);
109990b4856Slling }
110990b4856Slling 
111990b4856Slling static char *
112990b4856Slling zpool_get_prop_string(zpool_handle_t *zhp, zpool_prop_t prop,
113990b4856Slling     zprop_source_t *src)
114990b4856Slling {
115990b4856Slling 	nvlist_t *nv, *nvl;
116990b4856Slling 	uint64_t ival;
117990b4856Slling 	char *value;
118990b4856Slling 	zprop_source_t source;
119990b4856Slling 
120990b4856Slling 	nvl = zhp->zpool_props;
121990b4856Slling 	if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) {
122990b4856Slling 		verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &ival) == 0);
123990b4856Slling 		source = ival;
124990b4856Slling 		verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
125990b4856Slling 	} else {
126990b4856Slling 		source = ZPROP_SRC_DEFAULT;
127990b4856Slling 		if ((value = (char *)zpool_prop_default_string(prop)) == NULL)
128990b4856Slling 			value = "-";
129990b4856Slling 	}
130990b4856Slling 
131990b4856Slling 	if (src)
132990b4856Slling 		*src = source;
133990b4856Slling 
134990b4856Slling 	return (value);
135990b4856Slling }
136990b4856Slling 
137990b4856Slling uint64_t
138990b4856Slling zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop, zprop_source_t *src)
139990b4856Slling {
140990b4856Slling 	nvlist_t *nv, *nvl;
141990b4856Slling 	uint64_t value;
142990b4856Slling 	zprop_source_t source;
143990b4856Slling 
144b87f3af3Sperrin 	if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) {
145b87f3af3Sperrin 		/*
146b87f3af3Sperrin 		 * zpool_get_all_props() has most likely failed because
147b87f3af3Sperrin 		 * the pool is faulted, but if all we need is the top level
148b87f3af3Sperrin 		 * vdev's guid then get it from the zhp config nvlist.
149b87f3af3Sperrin 		 */
150b87f3af3Sperrin 		if ((prop == ZPOOL_PROP_GUID) &&
151b87f3af3Sperrin 		    (nvlist_lookup_nvlist(zhp->zpool_config,
152b87f3af3Sperrin 		    ZPOOL_CONFIG_VDEV_TREE, &nv) == 0) &&
153b87f3af3Sperrin 		    (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &value)
154b87f3af3Sperrin 		    == 0)) {
155b87f3af3Sperrin 			return (value);
156b87f3af3Sperrin 		}
157990b4856Slling 		return (zpool_prop_default_numeric(prop));
158b87f3af3Sperrin 	}
159990b4856Slling 
160990b4856Slling 	nvl = zhp->zpool_props;
161990b4856Slling 	if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) {
162990b4856Slling 		verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &value) == 0);
163990b4856Slling 		source = value;
164990b4856Slling 		verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0);
165990b4856Slling 	} else {
166990b4856Slling 		source = ZPROP_SRC_DEFAULT;
167990b4856Slling 		value = zpool_prop_default_numeric(prop);
168990b4856Slling 	}
169990b4856Slling 
170990b4856Slling 	if (src)
171990b4856Slling 		*src = source;
172990b4856Slling 
173990b4856Slling 	return (value);
174990b4856Slling }
175990b4856Slling 
176990b4856Slling /*
177990b4856Slling  * Map VDEV STATE to printed strings.
178990b4856Slling  */
179990b4856Slling char *
180990b4856Slling zpool_state_to_name(vdev_state_t state, vdev_aux_t aux)
181990b4856Slling {
182990b4856Slling 	switch (state) {
183990b4856Slling 	case VDEV_STATE_CLOSED:
184990b4856Slling 	case VDEV_STATE_OFFLINE:
185990b4856Slling 		return (gettext("OFFLINE"));
186990b4856Slling 	case VDEV_STATE_REMOVED:
187990b4856Slling 		return (gettext("REMOVED"));
188990b4856Slling 	case VDEV_STATE_CANT_OPEN:
189b87f3af3Sperrin 		if (aux == VDEV_AUX_CORRUPT_DATA || aux == VDEV_AUX_BAD_LOG)
190990b4856Slling 			return (gettext("FAULTED"));
191990b4856Slling 		else
192990b4856Slling 			return (gettext("UNAVAIL"));
193990b4856Slling 	case VDEV_STATE_FAULTED:
194990b4856Slling 		return (gettext("FAULTED"));
195990b4856Slling 	case VDEV_STATE_DEGRADED:
196990b4856Slling 		return (gettext("DEGRADED"));
197990b4856Slling 	case VDEV_STATE_HEALTHY:
198990b4856Slling 		return (gettext("ONLINE"));
199990b4856Slling 	}
200990b4856Slling 
201990b4856Slling 	return (gettext("UNKNOWN"));
202990b4856Slling }
203990b4856Slling 
204990b4856Slling /*
205990b4856Slling  * Get a zpool property value for 'prop' and return the value in
206990b4856Slling  * a pre-allocated buffer.
207990b4856Slling  */
208990b4856Slling int
209990b4856Slling zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
210990b4856Slling     zprop_source_t *srctype)
211990b4856Slling {
212990b4856Slling 	uint64_t intval;
213990b4856Slling 	const char *strval;
214990b4856Slling 	zprop_source_t src = ZPROP_SRC_NONE;
215990b4856Slling 	nvlist_t *nvroot;
216990b4856Slling 	vdev_stat_t *vs;
217990b4856Slling 	uint_t vsc;
218990b4856Slling 
219990b4856Slling 	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
220*379c004dSEric Schrock 		switch (prop) {
221*379c004dSEric Schrock 		case ZPOOL_PROP_NAME:
222990b4856Slling 			(void) strlcpy(buf, zpool_get_name(zhp), len);
223*379c004dSEric Schrock 			break;
224*379c004dSEric Schrock 
225*379c004dSEric Schrock 		case ZPOOL_PROP_HEALTH:
226990b4856Slling 			(void) strlcpy(buf, "FAULTED", len);
227*379c004dSEric Schrock 			break;
228*379c004dSEric Schrock 
229*379c004dSEric Schrock 		case ZPOOL_PROP_GUID:
230*379c004dSEric Schrock 			intval = zpool_get_prop_int(zhp, prop, &src);
231*379c004dSEric Schrock 			(void) snprintf(buf, len, "%llu", intval);
232*379c004dSEric Schrock 			break;
233*379c004dSEric Schrock 
234*379c004dSEric Schrock 		case ZPOOL_PROP_ALTROOT:
235*379c004dSEric Schrock 		case ZPOOL_PROP_CACHEFILE:
236*379c004dSEric Schrock 			if (zhp->zpool_props != NULL ||
237*379c004dSEric Schrock 			    zpool_get_all_props(zhp) == 0) {
238*379c004dSEric Schrock 				(void) strlcpy(buf,
239*379c004dSEric Schrock 				    zpool_get_prop_string(zhp, prop, &src),
240*379c004dSEric Schrock 				    len);
241*379c004dSEric Schrock 				if (srctype != NULL)
242*379c004dSEric Schrock 					*srctype = src;
243*379c004dSEric Schrock 				return (0);
244*379c004dSEric Schrock 			}
245*379c004dSEric Schrock 			/* FALLTHROUGH */
246*379c004dSEric Schrock 		default:
247990b4856Slling 			(void) strlcpy(buf, "-", len);
248*379c004dSEric Schrock 			break;
249*379c004dSEric Schrock 		}
250*379c004dSEric Schrock 
251*379c004dSEric Schrock 		if (srctype != NULL)
252*379c004dSEric Schrock 			*srctype = src;
253990b4856Slling 		return (0);
254990b4856Slling 	}
255990b4856Slling 
256990b4856Slling 	if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) &&
257990b4856Slling 	    prop != ZPOOL_PROP_NAME)
258990b4856Slling 		return (-1);
259990b4856Slling 
260990b4856Slling 	switch (zpool_prop_get_type(prop)) {
261990b4856Slling 	case PROP_TYPE_STRING:
262990b4856Slling 		(void) strlcpy(buf, zpool_get_prop_string(zhp, prop, &src),
263990b4856Slling 		    len);
264990b4856Slling 		break;
265990b4856Slling 
266990b4856Slling 	case PROP_TYPE_NUMBER:
267990b4856Slling 		intval = zpool_get_prop_int(zhp, prop, &src);
268990b4856Slling 
269990b4856Slling 		switch (prop) {
270990b4856Slling 		case ZPOOL_PROP_SIZE:
271990b4856Slling 		case ZPOOL_PROP_USED:
272990b4856Slling 		case ZPOOL_PROP_AVAILABLE:
273990b4856Slling 			(void) zfs_nicenum(intval, buf, len);
274990b4856Slling 			break;
275990b4856Slling 
276990b4856Slling 		case ZPOOL_PROP_CAPACITY:
277990b4856Slling 			(void) snprintf(buf, len, "%llu%%",
278990b4856Slling 			    (u_longlong_t)intval);
279990b4856Slling 			break;
280990b4856Slling 
281990b4856Slling 		case ZPOOL_PROP_HEALTH:
282990b4856Slling 			verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
283990b4856Slling 			    ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
284990b4856Slling 			verify(nvlist_lookup_uint64_array(nvroot,
285990b4856Slling 			    ZPOOL_CONFIG_STATS, (uint64_t **)&vs, &vsc) == 0);
286990b4856Slling 
287990b4856Slling 			(void) strlcpy(buf, zpool_state_to_name(intval,
288990b4856Slling 			    vs->vs_aux), len);
289990b4856Slling 			break;
290990b4856Slling 		default:
291990b4856Slling 			(void) snprintf(buf, len, "%llu", intval);
292990b4856Slling 		}
293990b4856Slling 		break;
294990b4856Slling 
295990b4856Slling 	case PROP_TYPE_INDEX:
296990b4856Slling 		intval = zpool_get_prop_int(zhp, prop, &src);
297990b4856Slling 		if (zpool_prop_index_to_string(prop, intval, &strval)
298990b4856Slling 		    != 0)
299990b4856Slling 			return (-1);
300990b4856Slling 		(void) strlcpy(buf, strval, len);
301990b4856Slling 		break;
302990b4856Slling 
303990b4856Slling 	default:
304990b4856Slling 		abort();
305990b4856Slling 	}
306990b4856Slling 
307990b4856Slling 	if (srctype)
308990b4856Slling 		*srctype = src;
309990b4856Slling 
310990b4856Slling 	return (0);
311990b4856Slling }
312990b4856Slling 
313990b4856Slling /*
314990b4856Slling  * Check if the bootfs name has the same pool name as it is set to.
315990b4856Slling  * Assuming bootfs is a valid dataset name.
316990b4856Slling  */
317990b4856Slling static boolean_t
318990b4856Slling bootfs_name_valid(const char *pool, char *bootfs)
319990b4856Slling {
320990b4856Slling 	int len = strlen(pool);
321990b4856Slling 
322fe3e2633SEric Taylor 	if (!zfs_name_valid(bootfs, ZFS_TYPE_FILESYSTEM|ZFS_TYPE_SNAPSHOT))
323990b4856Slling 		return (B_FALSE);
324990b4856Slling 
325990b4856Slling 	if (strncmp(pool, bootfs, len) == 0 &&
326990b4856Slling 	    (bootfs[len] == '/' || bootfs[len] == '\0'))
327990b4856Slling 		return (B_TRUE);
328990b4856Slling 
329990b4856Slling 	return (B_FALSE);
330990b4856Slling }
331990b4856Slling 
33215e6edf1Sgw /*
33315e6edf1Sgw  * Inspect the configuration to determine if any of the devices contain
33415e6edf1Sgw  * an EFI label.
33515e6edf1Sgw  */
33615e6edf1Sgw static boolean_t
33715e6edf1Sgw pool_uses_efi(nvlist_t *config)
33815e6edf1Sgw {
33915e6edf1Sgw 	nvlist_t **child;
34015e6edf1Sgw 	uint_t c, children;
34115e6edf1Sgw 
34215e6edf1Sgw 	if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN,
34315e6edf1Sgw 	    &child, &children) != 0)
34415e6edf1Sgw 		return (read_efi_label(config, NULL) >= 0);
34515e6edf1Sgw 
34615e6edf1Sgw 	for (c = 0; c < children; c++) {
34715e6edf1Sgw 		if (pool_uses_efi(child[c]))
34815e6edf1Sgw 			return (B_TRUE);
34915e6edf1Sgw 	}
35015e6edf1Sgw 	return (B_FALSE);
35115e6edf1Sgw }
35215e6edf1Sgw 
353b5b76fecSGeorge Wilson static boolean_t
354b5b76fecSGeorge Wilson pool_is_bootable(zpool_handle_t *zhp)
355b5b76fecSGeorge Wilson {
356b5b76fecSGeorge Wilson 	char bootfs[ZPOOL_MAXNAMELEN];
357b5b76fecSGeorge Wilson 
358b5b76fecSGeorge Wilson 	return (zpool_get_prop(zhp, ZPOOL_PROP_BOOTFS, bootfs,
359b5b76fecSGeorge Wilson 	    sizeof (bootfs), NULL) == 0 && strncmp(bootfs, "-",
360b5b76fecSGeorge Wilson 	    sizeof (bootfs)) != 0);
361b5b76fecSGeorge Wilson }
362b5b76fecSGeorge Wilson 
363b5b76fecSGeorge Wilson 
364990b4856Slling /*
365990b4856Slling  * Given an nvlist of zpool properties to be set, validate that they are
366990b4856Slling  * correct, and parse any numeric properties (index, boolean, etc) if they are
367990b4856Slling  * specified as strings.
368990b4856Slling  */
369990b4856Slling static nvlist_t *
3700a48a24eStimh zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
371990b4856Slling     nvlist_t *props, uint64_t version, boolean_t create_or_import, char *errbuf)
372990b4856Slling {
373990b4856Slling 	nvpair_t *elem;
374990b4856Slling 	nvlist_t *retprops;
375990b4856Slling 	zpool_prop_t prop;
376990b4856Slling 	char *strval;
377990b4856Slling 	uint64_t intval;
3782f8aaab3Seschrock 	char *slash;
3792f8aaab3Seschrock 	struct stat64 statbuf;
38015e6edf1Sgw 	zpool_handle_t *zhp;
38115e6edf1Sgw 	nvlist_t *nvroot;
382990b4856Slling 
383990b4856Slling 	if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) {
384990b4856Slling 		(void) no_memory(hdl);
385990b4856Slling 		return (NULL);
386990b4856Slling 	}
387990b4856Slling 
388990b4856Slling 	elem = NULL;
389990b4856Slling 	while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
390990b4856Slling 		const char *propname = nvpair_name(elem);
391990b4856Slling 
392990b4856Slling 		/*
393990b4856Slling 		 * Make sure this property is valid and applies to this type.
394990b4856Slling 		 */
395990b4856Slling 		if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
396990b4856Slling 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
397990b4856Slling 			    "invalid property '%s'"), propname);
398990b4856Slling 			(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
399990b4856Slling 			goto error;
400990b4856Slling 		}
401990b4856Slling 
402990b4856Slling 		if (zpool_prop_readonly(prop)) {
403990b4856Slling 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
404990b4856Slling 			    "is readonly"), propname);
405990b4856Slling 			(void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
406990b4856Slling 			goto error;
407990b4856Slling 		}
408990b4856Slling 
409990b4856Slling 		if (zprop_parse_value(hdl, elem, prop, ZFS_TYPE_POOL, retprops,
410990b4856Slling 		    &strval, &intval, errbuf) != 0)
411990b4856Slling 			goto error;
412990b4856Slling 
413990b4856Slling 		/*
414990b4856Slling 		 * Perform additional checking for specific properties.
415990b4856Slling 		 */
416990b4856Slling 		switch (prop) {
417990b4856Slling 		case ZPOOL_PROP_VERSION:
418990b4856Slling 			if (intval < version || intval > SPA_VERSION) {
419990b4856Slling 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
420990b4856Slling 				    "property '%s' number %d is invalid."),
421990b4856Slling 				    propname, intval);
422990b4856Slling 				(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
423990b4856Slling 				goto error;
424990b4856Slling 			}
425990b4856Slling 			break;
426990b4856Slling 
427990b4856Slling 		case ZPOOL_PROP_BOOTFS:
428990b4856Slling 			if (create_or_import) {
429990b4856Slling 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
430990b4856Slling 				    "property '%s' cannot be set at creation "
431990b4856Slling 				    "or import time"), propname);
432990b4856Slling 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
433990b4856Slling 				goto error;
434990b4856Slling 			}
435990b4856Slling 
436990b4856Slling 			if (version < SPA_VERSION_BOOTFS) {
437990b4856Slling 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
438990b4856Slling 				    "pool must be upgraded to support "
439990b4856Slling 				    "'%s' property"), propname);
440990b4856Slling 				(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
441990b4856Slling 				goto error;
442990b4856Slling 			}
443990b4856Slling 
444990b4856Slling 			/*
445990b4856Slling 			 * bootfs property value has to be a dataset name and
446990b4856Slling 			 * the dataset has to be in the same pool as it sets to.
447990b4856Slling 			 */
448990b4856Slling 			if (strval[0] != '\0' && !bootfs_name_valid(poolname,
449990b4856Slling 			    strval)) {
450990b4856Slling 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
451990b4856Slling 				    "is an invalid name"), strval);
452990b4856Slling 				(void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
453990b4856Slling 				goto error;
454990b4856Slling 			}
45515e6edf1Sgw 
45615e6edf1Sgw 			if ((zhp = zpool_open_canfail(hdl, poolname)) == NULL) {
45715e6edf1Sgw 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
45815e6edf1Sgw 				    "could not open pool '%s'"), poolname);
45915e6edf1Sgw 				(void) zfs_error(hdl, EZFS_OPENFAILED, errbuf);
46015e6edf1Sgw 				goto error;
46115e6edf1Sgw 			}
46215e6edf1Sgw 			verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
46315e6edf1Sgw 			    ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
46415e6edf1Sgw 
46515e6edf1Sgw 			/*
46615e6edf1Sgw 			 * bootfs property cannot be set on a disk which has
46715e6edf1Sgw 			 * been EFI labeled.
46815e6edf1Sgw 			 */
46915e6edf1Sgw 			if (pool_uses_efi(nvroot)) {
47015e6edf1Sgw 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
47115e6edf1Sgw 				    "property '%s' not supported on "
47215e6edf1Sgw 				    "EFI labeled devices"), propname);
47315e6edf1Sgw 				(void) zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf);
47415e6edf1Sgw 				zpool_close(zhp);
47515e6edf1Sgw 				goto error;
47615e6edf1Sgw 			}
47715e6edf1Sgw 			zpool_close(zhp);
478990b4856Slling 			break;
479990b4856Slling 
4802f8aaab3Seschrock 		case ZPOOL_PROP_ALTROOT:
481990b4856Slling 			if (!create_or_import) {
482990b4856Slling 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
483990b4856Slling 				    "property '%s' can only be set during pool "
484990b4856Slling 				    "creation or import"), propname);
485990b4856Slling 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
486990b4856Slling 				goto error;
487990b4856Slling 			}
488990b4856Slling 
4892f8aaab3Seschrock 			if (strval[0] != '/') {
490990b4856Slling 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4912f8aaab3Seschrock 				    "bad alternate root '%s'"), strval);
4922f8aaab3Seschrock 				(void) zfs_error(hdl, EZFS_BADPATH, errbuf);
493990b4856Slling 				goto error;
494990b4856Slling 			}
4952f8aaab3Seschrock 			break;
4962f8aaab3Seschrock 
4972f8aaab3Seschrock 		case ZPOOL_PROP_CACHEFILE:
4982f8aaab3Seschrock 			if (strval[0] == '\0')
4992f8aaab3Seschrock 				break;
5002f8aaab3Seschrock 
5012f8aaab3Seschrock 			if (strcmp(strval, "none") == 0)
5022f8aaab3Seschrock 				break;
503990b4856Slling 
504990b4856Slling 			if (strval[0] != '/') {
505990b4856Slling 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5062f8aaab3Seschrock 				    "property '%s' must be empty, an "
5072f8aaab3Seschrock 				    "absolute path, or 'none'"), propname);
508990b4856Slling 				(void) zfs_error(hdl, EZFS_BADPATH, errbuf);
509990b4856Slling 				goto error;
510990b4856Slling 			}
511990b4856Slling 
5122f8aaab3Seschrock 			slash = strrchr(strval, '/');
513990b4856Slling 
5142f8aaab3Seschrock 			if (slash[1] == '\0' || strcmp(slash, "/.") == 0 ||
5152f8aaab3Seschrock 			    strcmp(slash, "/..") == 0) {
5162f8aaab3Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5172f8aaab3Seschrock 				    "'%s' is not a valid file"), strval);
5182f8aaab3Seschrock 				(void) zfs_error(hdl, EZFS_BADPATH, errbuf);
5192f8aaab3Seschrock 				goto error;
5202f8aaab3Seschrock 			}
521990b4856Slling 
5222f8aaab3Seschrock 			*slash = '\0';
5232f8aaab3Seschrock 
5242c32020fSeschrock 			if (strval[0] != '\0' &&
5252c32020fSeschrock 			    (stat64(strval, &statbuf) != 0 ||
5262c32020fSeschrock 			    !S_ISDIR(statbuf.st_mode))) {
5272f8aaab3Seschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5282f8aaab3Seschrock 				    "'%s' is not a valid directory"),
5292f8aaab3Seschrock 				    strval);
5302f8aaab3Seschrock 				(void) zfs_error(hdl, EZFS_BADPATH, errbuf);
5312f8aaab3Seschrock 				goto error;
5322f8aaab3Seschrock 			}
5332f8aaab3Seschrock 
5342f8aaab3Seschrock 			*slash = '/';
5352f8aaab3Seschrock 			break;
536990b4856Slling 		}
537990b4856Slling 	}
538990b4856Slling 
539990b4856Slling 	return (retprops);
540990b4856Slling error:
541990b4856Slling 	nvlist_free(retprops);
542990b4856Slling 	return (NULL);
543990b4856Slling }
544990b4856Slling 
545990b4856Slling /*
546990b4856Slling  * Set zpool property : propname=propval.
547990b4856Slling  */
548990b4856Slling int
549990b4856Slling zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval)
550990b4856Slling {
551990b4856Slling 	zfs_cmd_t zc = { 0 };
552990b4856Slling 	int ret = -1;
553990b4856Slling 	char errbuf[1024];
554990b4856Slling 	nvlist_t *nvl = NULL;
555990b4856Slling 	nvlist_t *realprops;
556990b4856Slling 	uint64_t version;
557990b4856Slling 
558990b4856Slling 	(void) snprintf(errbuf, sizeof (errbuf),
559990b4856Slling 	    dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
560990b4856Slling 	    zhp->zpool_name);
561990b4856Slling 
562990b4856Slling 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
563990b4856Slling 		return (no_memory(zhp->zpool_hdl));
564990b4856Slling 
565990b4856Slling 	if (nvlist_add_string(nvl, propname, propval) != 0) {
566990b4856Slling 		nvlist_free(nvl);
567990b4856Slling 		return (no_memory(zhp->zpool_hdl));
568990b4856Slling 	}
569990b4856Slling 
570990b4856Slling 	version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
5710a48a24eStimh 	if ((realprops = zpool_valid_proplist(zhp->zpool_hdl,
572990b4856Slling 	    zhp->zpool_name, nvl, version, B_FALSE, errbuf)) == NULL) {
573990b4856Slling 		nvlist_free(nvl);
574990b4856Slling 		return (-1);
575990b4856Slling 	}
576990b4856Slling 
577990b4856Slling 	nvlist_free(nvl);
578990b4856Slling 	nvl = realprops;
579990b4856Slling 
580990b4856Slling 	/*
581990b4856Slling 	 * Execute the corresponding ioctl() to set this property.
582990b4856Slling 	 */
583990b4856Slling 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
584990b4856Slling 
585990b4856Slling 	if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl) != 0) {
586990b4856Slling 		nvlist_free(nvl);
587990b4856Slling 		return (-1);
588990b4856Slling 	}
589990b4856Slling 
590990b4856Slling 	ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SET_PROPS, &zc);
591990b4856Slling 
592990b4856Slling 	zcmd_free_nvlists(&zc);
593990b4856Slling 	nvlist_free(nvl);
594990b4856Slling 
595990b4856Slling 	if (ret)
596990b4856Slling 		(void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf);
597990b4856Slling 	else
598990b4856Slling 		(void) zpool_props_refresh(zhp);
599990b4856Slling 
600990b4856Slling 	return (ret);
601990b4856Slling }
602990b4856Slling 
603990b4856Slling int
604990b4856Slling zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
605990b4856Slling {
606990b4856Slling 	libzfs_handle_t *hdl = zhp->zpool_hdl;
607990b4856Slling 	zprop_list_t *entry;
608990b4856Slling 	char buf[ZFS_MAXPROPLEN];
609990b4856Slling 
610990b4856Slling 	if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0)
611990b4856Slling 		return (-1);
612990b4856Slling 
613990b4856Slling 	for (entry = *plp; entry != NULL; entry = entry->pl_next) {
614990b4856Slling 
615990b4856Slling 		if (entry->pl_fixed)
616990b4856Slling 			continue;
617990b4856Slling 
618990b4856Slling 		if (entry->pl_prop != ZPROP_INVAL &&
619990b4856Slling 		    zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf),
620990b4856Slling 		    NULL) == 0) {
621990b4856Slling 			if (strlen(buf) > entry->pl_width)
622990b4856Slling 				entry->pl_width = strlen(buf);
623990b4856Slling 		}
624990b4856Slling 	}
625990b4856Slling 
626990b4856Slling 	return (0);
627990b4856Slling }
628990b4856Slling 
629990b4856Slling 
630fa9e4066Sahrens /*
631fa9e4066Sahrens  * Validate the given pool name, optionally putting an extended error message in
632fa9e4066Sahrens  * 'buf'.
633fa9e4066Sahrens  */
634e7cbe64fSgw boolean_t
63599653d4eSeschrock zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool)
636fa9e4066Sahrens {
637fa9e4066Sahrens 	namecheck_err_t why;
638fa9e4066Sahrens 	char what;
639b468a217Seschrock 	int ret;
640b468a217Seschrock 
641b468a217Seschrock 	ret = pool_namecheck(pool, &why, &what);
642b468a217Seschrock 
643b468a217Seschrock 	/*
644b468a217Seschrock 	 * The rules for reserved pool names were extended at a later point.
645b468a217Seschrock 	 * But we need to support users with existing pools that may now be
646b468a217Seschrock 	 * invalid.  So we only check for this expanded set of names during a
647b468a217Seschrock 	 * create (or import), and only in userland.
648b468a217Seschrock 	 */
649b468a217Seschrock 	if (ret == 0 && !isopen &&
650b468a217Seschrock 	    (strncmp(pool, "mirror", 6) == 0 ||
651b468a217Seschrock 	    strncmp(pool, "raidz", 5) == 0 ||
6528654d025Sperrin 	    strncmp(pool, "spare", 5) == 0 ||
6538654d025Sperrin 	    strcmp(pool, "log") == 0)) {
654e7cbe64fSgw 		if (hdl != NULL)
655e7cbe64fSgw 			zfs_error_aux(hdl,
656e7cbe64fSgw 			    dgettext(TEXT_DOMAIN, "name is reserved"));
65799653d4eSeschrock 		return (B_FALSE);
658b468a217Seschrock 	}
659b468a217Seschrock 
660fa9e4066Sahrens 
661b468a217Seschrock 	if (ret != 0) {
66299653d4eSeschrock 		if (hdl != NULL) {
663fa9e4066Sahrens 			switch (why) {
664b81d61a6Slling 			case NAME_ERR_TOOLONG:
66599653d4eSeschrock 				zfs_error_aux(hdl,
666b81d61a6Slling 				    dgettext(TEXT_DOMAIN, "name is too long"));
667b81d61a6Slling 				break;
668b81d61a6Slling 
669fa9e4066Sahrens 			case NAME_ERR_INVALCHAR:
67099653d4eSeschrock 				zfs_error_aux(hdl,
671fa9e4066Sahrens 				    dgettext(TEXT_DOMAIN, "invalid character "
672fa9e4066Sahrens 				    "'%c' in pool name"), what);
673fa9e4066Sahrens 				break;
674fa9e4066Sahrens 
675fa9e4066Sahrens 			case NAME_ERR_NOLETTER:
67699653d4eSeschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
67799653d4eSeschrock 				    "name must begin with a letter"));
678fa9e4066Sahrens 				break;
679fa9e4066Sahrens 
680fa9e4066Sahrens 			case NAME_ERR_RESERVED:
68199653d4eSeschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
68299653d4eSeschrock 				    "name is reserved"));
683fa9e4066Sahrens 				break;
684fa9e4066Sahrens 
685fa9e4066Sahrens 			case NAME_ERR_DISKLIKE:
68699653d4eSeschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
68799653d4eSeschrock 				    "pool name is reserved"));
688fa9e4066Sahrens 				break;
6895ad82045Snd 
6905ad82045Snd 			case NAME_ERR_LEADING_SLASH:
6915ad82045Snd 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
6925ad82045Snd 				    "leading slash in name"));
6935ad82045Snd 				break;
6945ad82045Snd 
6955ad82045Snd 			case NAME_ERR_EMPTY_COMPONENT:
6965ad82045Snd 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
6975ad82045Snd 				    "empty component in name"));
6985ad82045Snd 				break;
6995ad82045Snd 
7005ad82045Snd 			case NAME_ERR_TRAILING_SLASH:
7015ad82045Snd 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
7025ad82045Snd 				    "trailing slash in name"));
7035ad82045Snd 				break;
7045ad82045Snd 
7055ad82045Snd 			case NAME_ERR_MULTIPLE_AT:
7065ad82045Snd 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
7075ad82045Snd 				    "multiple '@' delimiters in name"));
7085ad82045Snd 				break;
7095ad82045Snd 
710fa9e4066Sahrens 			}
711fa9e4066Sahrens 		}
71299653d4eSeschrock 		return (B_FALSE);
713fa9e4066Sahrens 	}
714fa9e4066Sahrens 
71599653d4eSeschrock 	return (B_TRUE);
716fa9e4066Sahrens }
717fa9e4066Sahrens 
718fa9e4066Sahrens /*
719fa9e4066Sahrens  * Open a handle to the given pool, even if the pool is currently in the FAULTED
720fa9e4066Sahrens  * state.
721fa9e4066Sahrens  */
722fa9e4066Sahrens zpool_handle_t *
72399653d4eSeschrock zpool_open_canfail(libzfs_handle_t *hdl, const char *pool)
724fa9e4066Sahrens {
725fa9e4066Sahrens 	zpool_handle_t *zhp;
72694de1d4cSeschrock 	boolean_t missing;
727fa9e4066Sahrens 
728fa9e4066Sahrens 	/*
729fa9e4066Sahrens 	 * Make sure the pool name is valid.
730fa9e4066Sahrens 	 */
73199653d4eSeschrock 	if (!zpool_name_valid(hdl, B_TRUE, pool)) {
732ece3d9b3Slling 		(void) zfs_error_fmt(hdl, EZFS_INVALIDNAME,
73399653d4eSeschrock 		    dgettext(TEXT_DOMAIN, "cannot open '%s'"),
73499653d4eSeschrock 		    pool);
735fa9e4066Sahrens 		return (NULL);
736fa9e4066Sahrens 	}
737fa9e4066Sahrens 
73899653d4eSeschrock 	if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
73999653d4eSeschrock 		return (NULL);
740fa9e4066Sahrens 
74199653d4eSeschrock 	zhp->zpool_hdl = hdl;
742fa9e4066Sahrens 	(void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
743fa9e4066Sahrens 
74494de1d4cSeschrock 	if (zpool_refresh_stats(zhp, &missing) != 0) {
74594de1d4cSeschrock 		zpool_close(zhp);
74694de1d4cSeschrock 		return (NULL);
74794de1d4cSeschrock 	}
74894de1d4cSeschrock 
74994de1d4cSeschrock 	if (missing) {
750990b4856Slling 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "no such pool"));
751ece3d9b3Slling 		(void) zfs_error_fmt(hdl, EZFS_NOENT,
752990b4856Slling 		    dgettext(TEXT_DOMAIN, "cannot open '%s'"), pool);
75394de1d4cSeschrock 		zpool_close(zhp);
75494de1d4cSeschrock 		return (NULL);
755fa9e4066Sahrens 	}
756fa9e4066Sahrens 
757fa9e4066Sahrens 	return (zhp);
758fa9e4066Sahrens }
759fa9e4066Sahrens 
760fa9e4066Sahrens /*
761fa9e4066Sahrens  * Like the above, but silent on error.  Used when iterating over pools (because
762fa9e4066Sahrens  * the configuration cache may be out of date).
763fa9e4066Sahrens  */
76494de1d4cSeschrock int
76594de1d4cSeschrock zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret)
766fa9e4066Sahrens {
767fa9e4066Sahrens 	zpool_handle_t *zhp;
76894de1d4cSeschrock 	boolean_t missing;
769fa9e4066Sahrens 
77094de1d4cSeschrock 	if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
77194de1d4cSeschrock 		return (-1);
772fa9e4066Sahrens 
77399653d4eSeschrock 	zhp->zpool_hdl = hdl;
774fa9e4066Sahrens 	(void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
775fa9e4066Sahrens 
77694de1d4cSeschrock 	if (zpool_refresh_stats(zhp, &missing) != 0) {
77794de1d4cSeschrock 		zpool_close(zhp);
77894de1d4cSeschrock 		return (-1);
779fa9e4066Sahrens 	}
780fa9e4066Sahrens 
78194de1d4cSeschrock 	if (missing) {
78294de1d4cSeschrock 		zpool_close(zhp);
78394de1d4cSeschrock 		*ret = NULL;
78494de1d4cSeschrock 		return (0);
78594de1d4cSeschrock 	}
78694de1d4cSeschrock 
78794de1d4cSeschrock 	*ret = zhp;
78894de1d4cSeschrock 	return (0);
789fa9e4066Sahrens }
790fa9e4066Sahrens 
791fa9e4066Sahrens /*
792fa9e4066Sahrens  * Similar to zpool_open_canfail(), but refuses to open pools in the faulted
793fa9e4066Sahrens  * state.
794fa9e4066Sahrens  */
795fa9e4066Sahrens zpool_handle_t *
79699653d4eSeschrock zpool_open(libzfs_handle_t *hdl, const char *pool)
797fa9e4066Sahrens {
798fa9e4066Sahrens 	zpool_handle_t *zhp;
799fa9e4066Sahrens 
80099653d4eSeschrock 	if ((zhp = zpool_open_canfail(hdl, pool)) == NULL)
801fa9e4066Sahrens 		return (NULL);
802fa9e4066Sahrens 
803fa9e4066Sahrens 	if (zhp->zpool_state == POOL_STATE_UNAVAIL) {
804ece3d9b3Slling 		(void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL,
80599653d4eSeschrock 		    dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name);
806fa9e4066Sahrens 		zpool_close(zhp);
807fa9e4066Sahrens 		return (NULL);
808fa9e4066Sahrens 	}
809fa9e4066Sahrens 
810fa9e4066Sahrens 	return (zhp);
811fa9e4066Sahrens }
812fa9e4066Sahrens 
813fa9e4066Sahrens /*
814fa9e4066Sahrens  * Close the handle.  Simply frees the memory associated with the handle.
815fa9e4066Sahrens  */
816fa9e4066Sahrens void
817fa9e4066Sahrens zpool_close(zpool_handle_t *zhp)
818fa9e4066Sahrens {
819fa9e4066Sahrens 	if (zhp->zpool_config)
820fa9e4066Sahrens 		nvlist_free(zhp->zpool_config);
821088e9d47Seschrock 	if (zhp->zpool_old_config)
822088e9d47Seschrock 		nvlist_free(zhp->zpool_old_config);
823b1b8ab34Slling 	if (zhp->zpool_props)
824b1b8ab34Slling 		nvlist_free(zhp->zpool_props);
825fa9e4066Sahrens 	free(zhp);
826fa9e4066Sahrens }
827fa9e4066Sahrens 
828fa9e4066Sahrens /*
829fa9e4066Sahrens  * Return the name of the pool.
830fa9e4066Sahrens  */
831fa9e4066Sahrens const char *
832fa9e4066Sahrens zpool_get_name(zpool_handle_t *zhp)
833fa9e4066Sahrens {
834fa9e4066Sahrens 	return (zhp->zpool_name);
835fa9e4066Sahrens }
836fa9e4066Sahrens 
837fa9e4066Sahrens 
838fa9e4066Sahrens /*
839fa9e4066Sahrens  * Return the state of the pool (ACTIVE or UNAVAILABLE)
840fa9e4066Sahrens  */
841fa9e4066Sahrens int
842fa9e4066Sahrens zpool_get_state(zpool_handle_t *zhp)
843fa9e4066Sahrens {
844fa9e4066Sahrens 	return (zhp->zpool_state);
845fa9e4066Sahrens }
846fa9e4066Sahrens 
847fa9e4066Sahrens /*
848fa9e4066Sahrens  * Create the named pool, using the provided vdev list.  It is assumed
849fa9e4066Sahrens  * that the consumer has already validated the contents of the nvlist, so we
850fa9e4066Sahrens  * don't have to worry about error semantics.
851fa9e4066Sahrens  */
852fa9e4066Sahrens int
85399653d4eSeschrock zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
8540a48a24eStimh     nvlist_t *props, nvlist_t *fsprops)
855fa9e4066Sahrens {
856fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
8570a48a24eStimh 	nvlist_t *zc_fsprops = NULL;
8580a48a24eStimh 	nvlist_t *zc_props = NULL;
85999653d4eSeschrock 	char msg[1024];
860990b4856Slling 	char *altroot;
8610a48a24eStimh 	int ret = -1;
862fa9e4066Sahrens 
86399653d4eSeschrock 	(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
86499653d4eSeschrock 	    "cannot create '%s'"), pool);
865fa9e4066Sahrens 
86699653d4eSeschrock 	if (!zpool_name_valid(hdl, B_FALSE, pool))
86799653d4eSeschrock 		return (zfs_error(hdl, EZFS_INVALIDNAME, msg));
868fa9e4066Sahrens 
869351420b3Slling 	if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
870990b4856Slling 		return (-1);
871fa9e4066Sahrens 
8720a48a24eStimh 	if (props) {
8730a48a24eStimh 		if ((zc_props = zpool_valid_proplist(hdl, pool, props,
8740a48a24eStimh 		    SPA_VERSION_1, B_TRUE, msg)) == NULL) {
8750a48a24eStimh 			goto create_failed;
8760a48a24eStimh 		}
8770a48a24eStimh 	}
87899653d4eSeschrock 
8790a48a24eStimh 	if (fsprops) {
8800a48a24eStimh 		uint64_t zoned;
8810a48a24eStimh 		char *zonestr;
8820a48a24eStimh 
8830a48a24eStimh 		zoned = ((nvlist_lookup_string(fsprops,
8840a48a24eStimh 		    zfs_prop_to_name(ZFS_PROP_ZONED), &zonestr) == 0) &&
8850a48a24eStimh 		    strcmp(zonestr, "on") == 0);
8860a48a24eStimh 
8870a48a24eStimh 		if ((zc_fsprops = zfs_valid_proplist(hdl,
8880a48a24eStimh 		    ZFS_TYPE_FILESYSTEM, fsprops, zoned, NULL, msg)) == NULL) {
8890a48a24eStimh 			goto create_failed;
8900a48a24eStimh 		}
8910a48a24eStimh 		if (!zc_props &&
8920a48a24eStimh 		    (nvlist_alloc(&zc_props, NV_UNIQUE_NAME, 0) != 0)) {
8930a48a24eStimh 			goto create_failed;
8940a48a24eStimh 		}
8950a48a24eStimh 		if (nvlist_add_nvlist(zc_props,
8960a48a24eStimh 		    ZPOOL_ROOTFS_PROPS, zc_fsprops) != 0) {
8970a48a24eStimh 			goto create_failed;
8980a48a24eStimh 		}
899351420b3Slling 	}
900fa9e4066Sahrens 
9010a48a24eStimh 	if (zc_props && zcmd_write_src_nvlist(hdl, &zc, zc_props) != 0)
9020a48a24eStimh 		goto create_failed;
9030a48a24eStimh 
904990b4856Slling 	(void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name));
905fa9e4066Sahrens 
9060a48a24eStimh 	if ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_CREATE, &zc)) != 0) {
907351420b3Slling 
908e9dbad6fSeschrock 		zcmd_free_nvlists(&zc);
9090a48a24eStimh 		nvlist_free(zc_props);
9100a48a24eStimh 		nvlist_free(zc_fsprops);
911fa9e4066Sahrens 
91299653d4eSeschrock 		switch (errno) {
913fa9e4066Sahrens 		case EBUSY:
914fa9e4066Sahrens 			/*
915fa9e4066Sahrens 			 * This can happen if the user has specified the same
916fa9e4066Sahrens 			 * device multiple times.  We can't reliably detect this
917fa9e4066Sahrens 			 * until we try to add it and see we already have a
918fa9e4066Sahrens 			 * label.
919fa9e4066Sahrens 			 */
92099653d4eSeschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
92199653d4eSeschrock 			    "one or more vdevs refer to the same device"));
92299653d4eSeschrock 			return (zfs_error(hdl, EZFS_BADDEV, msg));
923fa9e4066Sahrens 
924fa9e4066Sahrens 		case EOVERFLOW:
925fa9e4066Sahrens 			/*
92699653d4eSeschrock 			 * This occurs when one of the devices is below
927fa9e4066Sahrens 			 * SPA_MINDEVSIZE.  Unfortunately, we can't detect which
928fa9e4066Sahrens 			 * device was the problem device since there's no
929fa9e4066Sahrens 			 * reliable way to determine device size from userland.
930fa9e4066Sahrens 			 */
931fa9e4066Sahrens 			{
932fa9e4066Sahrens 				char buf[64];
933fa9e4066Sahrens 
934fa9e4066Sahrens 				zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
935fa9e4066Sahrens 
93699653d4eSeschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
93799653d4eSeschrock 				    "one or more devices is less than the "
93899653d4eSeschrock 				    "minimum size (%s)"), buf);
939fa9e4066Sahrens 			}
94099653d4eSeschrock 			return (zfs_error(hdl, EZFS_BADDEV, msg));
941fa9e4066Sahrens 
942fa9e4066Sahrens 		case ENOSPC:
94399653d4eSeschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
94499653d4eSeschrock 			    "one or more devices is out of space"));
94599653d4eSeschrock 			return (zfs_error(hdl, EZFS_BADDEV, msg));
946fa9e4066Sahrens 
947fa94a07fSbrendan 		case ENOTBLK:
948fa94a07fSbrendan 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
949fa94a07fSbrendan 			    "cache device must be a disk or disk slice"));
950fa94a07fSbrendan 			return (zfs_error(hdl, EZFS_BADDEV, msg));
951fa94a07fSbrendan 
952fa9e4066Sahrens 		default:
95399653d4eSeschrock 			return (zpool_standard_error(hdl, errno, msg));
954fa9e4066Sahrens 		}
955fa9e4066Sahrens 	}
956fa9e4066Sahrens 
957fa9e4066Sahrens 	/*
958fa9e4066Sahrens 	 * If this is an alternate root pool, then we automatically set the
959e9dbad6fSeschrock 	 * mountpoint of the root dataset to be '/'.
960fa9e4066Sahrens 	 */
961990b4856Slling 	if (nvlist_lookup_string(props, zpool_prop_to_name(ZPOOL_PROP_ALTROOT),
962990b4856Slling 	    &altroot) == 0) {
963fa9e4066Sahrens 		zfs_handle_t *zhp;
964fa9e4066Sahrens 
965990b4856Slling 		verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_DATASET)) != NULL);
966e9dbad6fSeschrock 		verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
967e9dbad6fSeschrock 		    "/") == 0);
968fa9e4066Sahrens 
969fa9e4066Sahrens 		zfs_close(zhp);
970fa9e4066Sahrens 	}
971fa9e4066Sahrens 
9720a48a24eStimh create_failed:
973351420b3Slling 	zcmd_free_nvlists(&zc);
9740a48a24eStimh 	nvlist_free(zc_props);
9750a48a24eStimh 	nvlist_free(zc_fsprops);
9760a48a24eStimh 	return (ret);
977fa9e4066Sahrens }
978fa9e4066Sahrens 
979fa9e4066Sahrens /*
980fa9e4066Sahrens  * Destroy the given pool.  It is up to the caller to ensure that there are no
981fa9e4066Sahrens  * datasets left in the pool.
982fa9e4066Sahrens  */
983fa9e4066Sahrens int
984fa9e4066Sahrens zpool_destroy(zpool_handle_t *zhp)
985fa9e4066Sahrens {
986fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
987fa9e4066Sahrens 	zfs_handle_t *zfp = NULL;
98899653d4eSeschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
98999653d4eSeschrock 	char msg[1024];
990fa9e4066Sahrens 
991fa9e4066Sahrens 	if (zhp->zpool_state == POOL_STATE_ACTIVE &&
99299653d4eSeschrock 	    (zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name,
99399653d4eSeschrock 	    ZFS_TYPE_FILESYSTEM)) == NULL)
994fa9e4066Sahrens 		return (-1);
995fa9e4066Sahrens 
9965ad82045Snd 	if (zpool_remove_zvol_links(zhp) != 0)
997fa9e4066Sahrens 		return (-1);
998fa9e4066Sahrens 
999fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1000fa9e4066Sahrens 
1001ecd6cf80Smarks 	if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
100299653d4eSeschrock 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
100399653d4eSeschrock 		    "cannot destroy '%s'"), zhp->zpool_name);
1004fa9e4066Sahrens 
100599653d4eSeschrock 		if (errno == EROFS) {
100699653d4eSeschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
100799653d4eSeschrock 			    "one or more devices is read only"));
100899653d4eSeschrock 			(void) zfs_error(hdl, EZFS_BADDEV, msg);
100999653d4eSeschrock 		} else {
101099653d4eSeschrock 			(void) zpool_standard_error(hdl, errno, msg);
1011fa9e4066Sahrens 		}
1012fa9e4066Sahrens 
1013fa9e4066Sahrens 		if (zfp)
1014fa9e4066Sahrens 			zfs_close(zfp);
1015fa9e4066Sahrens 		return (-1);
1016fa9e4066Sahrens 	}
1017fa9e4066Sahrens 
1018fa9e4066Sahrens 	if (zfp) {
1019fa9e4066Sahrens 		remove_mountpoint(zfp);
1020fa9e4066Sahrens 		zfs_close(zfp);
1021fa9e4066Sahrens 	}
1022fa9e4066Sahrens 
1023fa9e4066Sahrens 	return (0);
1024fa9e4066Sahrens }
1025fa9e4066Sahrens 
1026fa9e4066Sahrens /*
1027fa9e4066Sahrens  * Add the given vdevs to the pool.  The caller must have already performed the
1028fa9e4066Sahrens  * necessary verification to ensure that the vdev specification is well-formed.
1029fa9e4066Sahrens  */
1030fa9e4066Sahrens int
1031fa9e4066Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
1032fa9e4066Sahrens {
1033e9dbad6fSeschrock 	zfs_cmd_t zc = { 0 };
103499653d4eSeschrock 	int ret;
103599653d4eSeschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
103699653d4eSeschrock 	char msg[1024];
1037fa94a07fSbrendan 	nvlist_t **spares, **l2cache;
1038fa94a07fSbrendan 	uint_t nspares, nl2cache;
103999653d4eSeschrock 
104099653d4eSeschrock 	(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
104199653d4eSeschrock 	    "cannot add to '%s'"), zhp->zpool_name);
104299653d4eSeschrock 
1043fa94a07fSbrendan 	if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
1044fa94a07fSbrendan 	    SPA_VERSION_SPARES &&
104599653d4eSeschrock 	    nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
104699653d4eSeschrock 	    &spares, &nspares) == 0) {
104799653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
104899653d4eSeschrock 		    "upgraded to add hot spares"));
104999653d4eSeschrock 		return (zfs_error(hdl, EZFS_BADVERSION, msg));
105099653d4eSeschrock 	}
1051fa9e4066Sahrens 
1052b5b76fecSGeorge Wilson 	if (pool_is_bootable(zhp) && nvlist_lookup_nvlist_array(nvroot,
1053b5b76fecSGeorge Wilson 	    ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0) {
1054b5b76fecSGeorge Wilson 		uint64_t s;
1055b5b76fecSGeorge Wilson 
1056b5b76fecSGeorge Wilson 		for (s = 0; s < nspares; s++) {
1057b5b76fecSGeorge Wilson 			char *path;
1058b5b76fecSGeorge Wilson 
1059b5b76fecSGeorge Wilson 			if (nvlist_lookup_string(spares[s], ZPOOL_CONFIG_PATH,
1060b5b76fecSGeorge Wilson 			    &path) == 0 && pool_uses_efi(spares[s])) {
1061b5b76fecSGeorge Wilson 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1062b5b76fecSGeorge Wilson 				    "device '%s' contains an EFI label and "
1063b5b76fecSGeorge Wilson 				    "cannot be used on root pools."),
1064b5b76fecSGeorge Wilson 				    zpool_vdev_name(hdl, NULL, spares[s]));
1065b5b76fecSGeorge Wilson 				return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg));
1066b5b76fecSGeorge Wilson 			}
1067b5b76fecSGeorge Wilson 		}
1068b5b76fecSGeorge Wilson 	}
1069b5b76fecSGeorge Wilson 
1070fa94a07fSbrendan 	if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
1071fa94a07fSbrendan 	    SPA_VERSION_L2CACHE &&
1072fa94a07fSbrendan 	    nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
1073fa94a07fSbrendan 	    &l2cache, &nl2cache) == 0) {
1074fa94a07fSbrendan 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
1075fa94a07fSbrendan 		    "upgraded to add cache devices"));
1076fa94a07fSbrendan 		return (zfs_error(hdl, EZFS_BADVERSION, msg));
1077fa94a07fSbrendan 	}
1078fa94a07fSbrendan 
1079990b4856Slling 	if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
108099653d4eSeschrock 		return (-1);
1081fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1082fa9e4066Sahrens 
1083ecd6cf80Smarks 	if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_ADD, &zc) != 0) {
1084fa9e4066Sahrens 		switch (errno) {
1085fa9e4066Sahrens 		case EBUSY:
1086fa9e4066Sahrens 			/*
1087fa9e4066Sahrens 			 * This can happen if the user has specified the same
1088fa9e4066Sahrens 			 * device multiple times.  We can't reliably detect this
1089fa9e4066Sahrens 			 * until we try to add it and see we already have a
1090fa9e4066Sahrens 			 * label.
1091fa9e4066Sahrens 			 */
109299653d4eSeschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
109399653d4eSeschrock 			    "one or more vdevs refer to the same device"));
109499653d4eSeschrock 			(void) zfs_error(hdl, EZFS_BADDEV, msg);
1095fa9e4066Sahrens 			break;
1096fa9e4066Sahrens 
1097fa9e4066Sahrens 		case EOVERFLOW:
1098fa9e4066Sahrens 			/*
1099fa9e4066Sahrens 			 * This occurrs when one of the devices is below
1100fa9e4066Sahrens 			 * SPA_MINDEVSIZE.  Unfortunately, we can't detect which
1101fa9e4066Sahrens 			 * device was the problem device since there's no
1102fa9e4066Sahrens 			 * reliable way to determine device size from userland.
1103fa9e4066Sahrens 			 */
1104fa9e4066Sahrens 			{
1105fa9e4066Sahrens 				char buf[64];
1106fa9e4066Sahrens 
1107fa9e4066Sahrens 				zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
1108fa9e4066Sahrens 
110999653d4eSeschrock 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
111099653d4eSeschrock 				    "device is less than the minimum "
111199653d4eSeschrock 				    "size (%s)"), buf);
1112fa9e4066Sahrens 			}
111399653d4eSeschrock 			(void) zfs_error(hdl, EZFS_BADDEV, msg);
111499653d4eSeschrock 			break;
111599653d4eSeschrock 
111699653d4eSeschrock 		case ENOTSUP:
111799653d4eSeschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
11188654d025Sperrin 			    "pool must be upgraded to add these vdevs"));
111999653d4eSeschrock 			(void) zfs_error(hdl, EZFS_BADVERSION, msg);
1120fa9e4066Sahrens 			break;
1121fa9e4066Sahrens 
1122b1b8ab34Slling 		case EDOM:
1123b1b8ab34Slling 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
11248654d025Sperrin 			    "root pool can not have multiple vdevs"
11258654d025Sperrin 			    " or separate logs"));
1126b1b8ab34Slling 			(void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg);
1127b1b8ab34Slling 			break;
1128b1b8ab34Slling 
1129fa94a07fSbrendan 		case ENOTBLK:
1130fa94a07fSbrendan 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1131fa94a07fSbrendan 			    "cache device must be a disk or disk slice"));
1132fa94a07fSbrendan 			(void) zfs_error(hdl, EZFS_BADDEV, msg);
1133fa94a07fSbrendan 			break;
1134fa94a07fSbrendan 
1135fa9e4066Sahrens 		default:
113699653d4eSeschrock 			(void) zpool_standard_error(hdl, errno, msg);
1137fa9e4066Sahrens 		}
1138fa9e4066Sahrens 
113999653d4eSeschrock 		ret = -1;
114099653d4eSeschrock 	} else {
114199653d4eSeschrock 		ret = 0;
1142fa9e4066Sahrens 	}
1143fa9e4066Sahrens 
1144e9dbad6fSeschrock 	zcmd_free_nvlists(&zc);
1145fa9e4066Sahrens 
114699653d4eSeschrock 	return (ret);
1147fa9e4066Sahrens }
1148fa9e4066Sahrens 
1149fa9e4066Sahrens /*
1150fa9e4066Sahrens  * Exports the pool from the system.  The caller must ensure that there are no
1151fa9e4066Sahrens  * mounted datasets in the pool.
1152fa9e4066Sahrens  */
1153fa9e4066Sahrens int
1154394ab0cbSGeorge Wilson zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce)
1155fa9e4066Sahrens {
1156fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
115789a89ebfSlling 	char msg[1024];
1158fa9e4066Sahrens 
1159fa9e4066Sahrens 	if (zpool_remove_zvol_links(zhp) != 0)
1160fa9e4066Sahrens 		return (-1);
1161fa9e4066Sahrens 
116289a89ebfSlling 	(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
116389a89ebfSlling 	    "cannot export '%s'"), zhp->zpool_name);
116489a89ebfSlling 
1165fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
116689a89ebfSlling 	zc.zc_cookie = force;
1167394ab0cbSGeorge Wilson 	zc.zc_guid = hardforce;
116889a89ebfSlling 
116989a89ebfSlling 	if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) {
117089a89ebfSlling 		switch (errno) {
117189a89ebfSlling 		case EXDEV:
117289a89ebfSlling 			zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
117389a89ebfSlling 			    "use '-f' to override the following errors:\n"
117489a89ebfSlling 			    "'%s' has an active shared spare which could be"
117589a89ebfSlling 			    " used by other pools once '%s' is exported."),
117689a89ebfSlling 			    zhp->zpool_name, zhp->zpool_name);
117789a89ebfSlling 			return (zfs_error(zhp->zpool_hdl, EZFS_ACTIVE_SPARE,
117889a89ebfSlling 			    msg));
117989a89ebfSlling 		default:
118089a89ebfSlling 			return (zpool_standard_error_fmt(zhp->zpool_hdl, errno,
118189a89ebfSlling 			    msg));
118289a89ebfSlling 		}
118389a89ebfSlling 	}
1184fa9e4066Sahrens 
1185fa9e4066Sahrens 	return (0);
1186fa9e4066Sahrens }
1187fa9e4066Sahrens 
1188394ab0cbSGeorge Wilson int
1189394ab0cbSGeorge Wilson zpool_export(zpool_handle_t *zhp, boolean_t force)
1190394ab0cbSGeorge Wilson {
1191394ab0cbSGeorge Wilson 	return (zpool_export_common(zhp, force, B_FALSE));
1192394ab0cbSGeorge Wilson }
1193394ab0cbSGeorge Wilson 
1194394ab0cbSGeorge Wilson int
1195394ab0cbSGeorge Wilson zpool_export_force(zpool_handle_t *zhp)
1196394ab0cbSGeorge Wilson {
1197394ab0cbSGeorge Wilson 	return (zpool_export_common(zhp, B_TRUE, B_TRUE));
1198394ab0cbSGeorge Wilson }
1199394ab0cbSGeorge Wilson 
1200fa9e4066Sahrens /*
1201990b4856Slling  * zpool_import() is a contracted interface. Should be kept the same
1202990b4856Slling  * if possible.
1203990b4856Slling  *
1204990b4856Slling  * Applications should use zpool_import_props() to import a pool with
1205990b4856Slling  * new properties value to be set.
1206fa9e4066Sahrens  */
1207fa9e4066Sahrens int
120899653d4eSeschrock zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
1209990b4856Slling     char *altroot)
1210990b4856Slling {
1211990b4856Slling 	nvlist_t *props = NULL;
1212990b4856Slling 	int ret;
1213990b4856Slling 
1214990b4856Slling 	if (altroot != NULL) {
1215990b4856Slling 		if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
1216990b4856Slling 			return (zfs_error_fmt(hdl, EZFS_NOMEM,
1217990b4856Slling 			    dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1218990b4856Slling 			    newname));
1219990b4856Slling 		}
1220990b4856Slling 
1221990b4856Slling 		if (nvlist_add_string(props,
1222352d8027SGeorge Wilson 		    zpool_prop_to_name(ZPOOL_PROP_ALTROOT), altroot) != 0 ||
1223352d8027SGeorge Wilson 		    nvlist_add_string(props,
1224352d8027SGeorge Wilson 		    zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), "none") != 0) {
1225990b4856Slling 			nvlist_free(props);
1226990b4856Slling 			return (zfs_error_fmt(hdl, EZFS_NOMEM,
1227990b4856Slling 			    dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1228990b4856Slling 			    newname));
1229990b4856Slling 		}
1230990b4856Slling 	}
1231990b4856Slling 
1232c5904d13Seschrock 	ret = zpool_import_props(hdl, config, newname, props, B_FALSE);
1233990b4856Slling 	if (props)
1234990b4856Slling 		nvlist_free(props);
1235990b4856Slling 	return (ret);
1236990b4856Slling }
1237990b4856Slling 
1238990b4856Slling /*
1239990b4856Slling  * Import the given pool using the known configuration and a list of
1240990b4856Slling  * properties to be set. The configuration should have come from
1241990b4856Slling  * zpool_find_import(). The 'newname' parameters control whether the pool
1242990b4856Slling  * is imported with a different name.
1243990b4856Slling  */
1244990b4856Slling int
1245990b4856Slling zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
1246c5904d13Seschrock     nvlist_t *props, boolean_t importfaulted)
1247fa9e4066Sahrens {
1248e9dbad6fSeschrock 	zfs_cmd_t zc = { 0 };
1249fa9e4066Sahrens 	char *thename;
1250fa9e4066Sahrens 	char *origname;
1251fa9e4066Sahrens 	int ret;
1252990b4856Slling 	char errbuf[1024];
1253fa9e4066Sahrens 
1254fa9e4066Sahrens 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1255fa9e4066Sahrens 	    &origname) == 0);
1256fa9e4066Sahrens 
1257990b4856Slling 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1258990b4856Slling 	    "cannot import pool '%s'"), origname);
1259990b4856Slling 
1260fa9e4066Sahrens 	if (newname != NULL) {
126199653d4eSeschrock 		if (!zpool_name_valid(hdl, B_FALSE, newname))
1262ece3d9b3Slling 			return (zfs_error_fmt(hdl, EZFS_INVALIDNAME,
126399653d4eSeschrock 			    dgettext(TEXT_DOMAIN, "cannot import '%s'"),
126499653d4eSeschrock 			    newname));
1265fa9e4066Sahrens 		thename = (char *)newname;
1266fa9e4066Sahrens 	} else {
1267fa9e4066Sahrens 		thename = origname;
1268fa9e4066Sahrens 	}
1269fa9e4066Sahrens 
1270990b4856Slling 	if (props) {
1271990b4856Slling 		uint64_t version;
1272fa9e4066Sahrens 
1273990b4856Slling 		verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
1274990b4856Slling 		    &version) == 0);
1275fa9e4066Sahrens 
12760a48a24eStimh 		if ((props = zpool_valid_proplist(hdl, origname,
1277351420b3Slling 		    props, version, B_TRUE, errbuf)) == NULL) {
1278990b4856Slling 			return (-1);
1279351420b3Slling 		} else if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
1280351420b3Slling 			nvlist_free(props);
1281990b4856Slling 			return (-1);
1282351420b3Slling 		}
1283990b4856Slling 	}
1284990b4856Slling 
1285990b4856Slling 	(void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name));
1286fa9e4066Sahrens 
1287fa9e4066Sahrens 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1288ea8dc4b6Seschrock 	    &zc.zc_guid) == 0);
1289fa9e4066Sahrens 
1290351420b3Slling 	if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0) {
1291351420b3Slling 		nvlist_free(props);
129299653d4eSeschrock 		return (-1);
1293351420b3Slling 	}
1294fa9e4066Sahrens 
1295c5904d13Seschrock 	zc.zc_cookie = (uint64_t)importfaulted;
1296fa9e4066Sahrens 	ret = 0;
1297ecd6cf80Smarks 	if (zfs_ioctl(hdl, ZFS_IOC_POOL_IMPORT, &zc) != 0) {
1298fa9e4066Sahrens 		char desc[1024];
1299fa9e4066Sahrens 		if (newname == NULL)
1300fa9e4066Sahrens 			(void) snprintf(desc, sizeof (desc),
1301fa9e4066Sahrens 			    dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1302fa9e4066Sahrens 			    thename);
1303fa9e4066Sahrens 		else
1304fa9e4066Sahrens 			(void) snprintf(desc, sizeof (desc),
1305fa9e4066Sahrens 			    dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"),
1306fa9e4066Sahrens 			    origname, thename);
1307fa9e4066Sahrens 
1308fa9e4066Sahrens 		switch (errno) {
1309ea8dc4b6Seschrock 		case ENOTSUP:
1310ea8dc4b6Seschrock 			/*
1311ea8dc4b6Seschrock 			 * Unsupported version.
1312ea8dc4b6Seschrock 			 */
131399653d4eSeschrock 			(void) zfs_error(hdl, EZFS_BADVERSION, desc);
1314ea8dc4b6Seschrock 			break;
1315ea8dc4b6Seschrock 
1316b5989ec7Seschrock 		case EINVAL:
1317b5989ec7Seschrock 			(void) zfs_error(hdl, EZFS_INVALCONFIG, desc);
1318b5989ec7Seschrock 			break;
1319b5989ec7Seschrock 
1320fa9e4066Sahrens 		default:
132199653d4eSeschrock 			(void) zpool_standard_error(hdl, errno, desc);
1322fa9e4066Sahrens 		}
1323fa9e4066Sahrens 
1324fa9e4066Sahrens 		ret = -1;
1325fa9e4066Sahrens 	} else {
1326fa9e4066Sahrens 		zpool_handle_t *zhp;
1327ecd6cf80Smarks 
1328fa9e4066Sahrens 		/*
1329fa9e4066Sahrens 		 * This should never fail, but play it safe anyway.
1330fa9e4066Sahrens 		 */
133194de1d4cSeschrock 		if (zpool_open_silent(hdl, thename, &zhp) != 0) {
133294de1d4cSeschrock 			ret = -1;
133394de1d4cSeschrock 		} else if (zhp != NULL) {
1334fa9e4066Sahrens 			ret = zpool_create_zvol_links(zhp);
1335fa9e4066Sahrens 			zpool_close(zhp);
1336fa9e4066Sahrens 		}
1337ecd6cf80Smarks 
1338fa9e4066Sahrens 	}
1339fa9e4066Sahrens 
1340e9dbad6fSeschrock 	zcmd_free_nvlists(&zc);
1341351420b3Slling 	nvlist_free(props);
1342351420b3Slling 
1343fa9e4066Sahrens 	return (ret);
1344fa9e4066Sahrens }
1345fa9e4066Sahrens 
1346fa9e4066Sahrens /*
1347fa9e4066Sahrens  * Scrub the pool.
1348fa9e4066Sahrens  */
1349fa9e4066Sahrens int
1350fa9e4066Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type)
1351fa9e4066Sahrens {
1352fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
1353fa9e4066Sahrens 	char msg[1024];
135499653d4eSeschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1355fa9e4066Sahrens 
1356fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1357fa9e4066Sahrens 	zc.zc_cookie = type;
1358fa9e4066Sahrens 
1359ecd6cf80Smarks 	if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SCRUB, &zc) == 0)
1360fa9e4066Sahrens 		return (0);
1361fa9e4066Sahrens 
1362fa9e4066Sahrens 	(void) snprintf(msg, sizeof (msg),
1363fa9e4066Sahrens 	    dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name);
1364fa9e4066Sahrens 
136599653d4eSeschrock 	if (errno == EBUSY)
136699653d4eSeschrock 		return (zfs_error(hdl, EZFS_RESILVERING, msg));
136799653d4eSeschrock 	else
136899653d4eSeschrock 		return (zpool_standard_error(hdl, errno, msg));
1369fa9e4066Sahrens }
1370fa9e4066Sahrens 
1371a43d325bSek /*
1372a43d325bSek  * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL
1373a43d325bSek  * spare; but FALSE if its an INUSE spare.
1374a43d325bSek  */
137599653d4eSeschrock static nvlist_t *
137699653d4eSeschrock vdev_to_nvlist_iter(nvlist_t *nv, const char *search, uint64_t guid,
1377ee0eb9f2SEric Schrock     boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log)
1378ea8dc4b6Seschrock {
1379ea8dc4b6Seschrock 	uint_t c, children;
1380ea8dc4b6Seschrock 	nvlist_t **child;
138199653d4eSeschrock 	uint64_t theguid, present;
1382ea8dc4b6Seschrock 	char *path;
1383ea8dc4b6Seschrock 	uint64_t wholedisk = 0;
138499653d4eSeschrock 	nvlist_t *ret;
1385ee0eb9f2SEric Schrock 	uint64_t is_log;
1386ea8dc4b6Seschrock 
138799653d4eSeschrock 	verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &theguid) == 0);
1388ea8dc4b6Seschrock 
1389ea8dc4b6Seschrock 	if (search == NULL &&
1390ea8dc4b6Seschrock 	    nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &present) == 0) {
1391ea8dc4b6Seschrock 		/*
1392ea8dc4b6Seschrock 		 * If the device has never been present since import, the only
1393ea8dc4b6Seschrock 		 * reliable way to match the vdev is by GUID.
1394ea8dc4b6Seschrock 		 */
139599653d4eSeschrock 		if (theguid == guid)
139699653d4eSeschrock 			return (nv);
1397ea8dc4b6Seschrock 	} else if (search != NULL &&
1398ea8dc4b6Seschrock 	    nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
1399ea8dc4b6Seschrock 		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
1400ea8dc4b6Seschrock 		    &wholedisk);
1401ea8dc4b6Seschrock 		if (wholedisk) {
1402ea8dc4b6Seschrock 			/*
1403ea8dc4b6Seschrock 			 * For whole disks, the internal path has 's0', but the
1404ea8dc4b6Seschrock 			 * path passed in by the user doesn't.
1405ea8dc4b6Seschrock 			 */
1406ea8dc4b6Seschrock 			if (strlen(search) == strlen(path) - 2 &&
1407ea8dc4b6Seschrock 			    strncmp(search, path, strlen(search)) == 0)
140899653d4eSeschrock 				return (nv);
1409ea8dc4b6Seschrock 		} else if (strcmp(search, path) == 0) {
141099653d4eSeschrock 			return (nv);
1411ea8dc4b6Seschrock 		}
1412ea8dc4b6Seschrock 	}
1413ea8dc4b6Seschrock 
1414ea8dc4b6Seschrock 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1415ea8dc4b6Seschrock 	    &child, &children) != 0)
141699653d4eSeschrock 		return (NULL);
1417ea8dc4b6Seschrock 
1418ee0eb9f2SEric Schrock 	for (c = 0; c < children; c++) {
141999653d4eSeschrock 		if ((ret = vdev_to_nvlist_iter(child[c], search, guid,
1420ee0eb9f2SEric Schrock 		    avail_spare, l2cache, NULL)) != NULL) {
1421ee0eb9f2SEric Schrock 			/*
1422ee0eb9f2SEric Schrock 			 * The 'is_log' value is only set for the toplevel
1423ee0eb9f2SEric Schrock 			 * vdev, not the leaf vdevs.  So we always lookup the
1424ee0eb9f2SEric Schrock 			 * log device from the root of the vdev tree (where
1425ee0eb9f2SEric Schrock 			 * 'log' is non-NULL).
1426ee0eb9f2SEric Schrock 			 */
1427ee0eb9f2SEric Schrock 			if (log != NULL &&
1428ee0eb9f2SEric Schrock 			    nvlist_lookup_uint64(child[c],
1429ee0eb9f2SEric Schrock 			    ZPOOL_CONFIG_IS_LOG, &is_log) == 0 &&
1430ee0eb9f2SEric Schrock 			    is_log) {
1431ee0eb9f2SEric Schrock 				*log = B_TRUE;
1432ee0eb9f2SEric Schrock 			}
1433ea8dc4b6Seschrock 			return (ret);
1434ee0eb9f2SEric Schrock 		}
1435ee0eb9f2SEric Schrock 	}
1436ea8dc4b6Seschrock 
143799653d4eSeschrock 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
143899653d4eSeschrock 	    &child, &children) == 0) {
143999653d4eSeschrock 		for (c = 0; c < children; c++) {
144099653d4eSeschrock 			if ((ret = vdev_to_nvlist_iter(child[c], search, guid,
1441ee0eb9f2SEric Schrock 			    avail_spare, l2cache, NULL)) != NULL) {
1442a43d325bSek 				*avail_spare = B_TRUE;
144399653d4eSeschrock 				return (ret);
144499653d4eSeschrock 			}
144599653d4eSeschrock 		}
144699653d4eSeschrock 	}
144799653d4eSeschrock 
1448fa94a07fSbrendan 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1449fa94a07fSbrendan 	    &child, &children) == 0) {
1450fa94a07fSbrendan 		for (c = 0; c < children; c++) {
1451fa94a07fSbrendan 			if ((ret = vdev_to_nvlist_iter(child[c], search, guid,
1452ee0eb9f2SEric Schrock 			    avail_spare, l2cache, NULL)) != NULL) {
1453fa94a07fSbrendan 				*l2cache = B_TRUE;
1454fa94a07fSbrendan 				return (ret);
1455fa94a07fSbrendan 			}
1456fa94a07fSbrendan 		}
1457fa94a07fSbrendan 	}
1458fa94a07fSbrendan 
145999653d4eSeschrock 	return (NULL);
1460ea8dc4b6Seschrock }
1461ea8dc4b6Seschrock 
146299653d4eSeschrock nvlist_t *
1463fa94a07fSbrendan zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
1464ee0eb9f2SEric Schrock     boolean_t *l2cache, boolean_t *log)
1465ea8dc4b6Seschrock {
1466ea8dc4b6Seschrock 	char buf[MAXPATHLEN];
1467ea8dc4b6Seschrock 	const char *search;
1468ea8dc4b6Seschrock 	char *end;
1469ea8dc4b6Seschrock 	nvlist_t *nvroot;
1470ea8dc4b6Seschrock 	uint64_t guid;
1471ea8dc4b6Seschrock 
14720917b783Seschrock 	guid = strtoull(path, &end, 10);
1473ea8dc4b6Seschrock 	if (guid != 0 && *end == '\0') {
1474ea8dc4b6Seschrock 		search = NULL;
1475ea8dc4b6Seschrock 	} else if (path[0] != '/') {
1476ea8dc4b6Seschrock 		(void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path);
1477ea8dc4b6Seschrock 		search = buf;
1478ea8dc4b6Seschrock 	} else {
1479ea8dc4b6Seschrock 		search = path;
1480ea8dc4b6Seschrock 	}
1481ea8dc4b6Seschrock 
1482ea8dc4b6Seschrock 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
1483ea8dc4b6Seschrock 	    &nvroot) == 0);
1484ea8dc4b6Seschrock 
1485a43d325bSek 	*avail_spare = B_FALSE;
1486fa94a07fSbrendan 	*l2cache = B_FALSE;
1487ee0eb9f2SEric Schrock 	if (log != NULL)
1488ee0eb9f2SEric Schrock 		*log = B_FALSE;
1489fa94a07fSbrendan 	return (vdev_to_nvlist_iter(nvroot, search, guid, avail_spare,
1490ee0eb9f2SEric Schrock 	    l2cache, log));
1491a43d325bSek }
1492a43d325bSek 
149319397407SSherry Moore static int
149419397407SSherry Moore vdev_online(nvlist_t *nv)
149519397407SSherry Moore {
149619397407SSherry Moore 	uint64_t ival;
149719397407SSherry Moore 
149819397407SSherry Moore 	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_OFFLINE, &ival) == 0 ||
149919397407SSherry Moore 	    nvlist_lookup_uint64(nv, ZPOOL_CONFIG_FAULTED, &ival) == 0 ||
150019397407SSherry Moore 	    nvlist_lookup_uint64(nv, ZPOOL_CONFIG_REMOVED, &ival) == 0)
150119397407SSherry Moore 		return (0);
150219397407SSherry Moore 
150319397407SSherry Moore 	return (1);
150419397407SSherry Moore }
150519397407SSherry Moore 
150619397407SSherry Moore /*
150719397407SSherry Moore  * Get phys_path for a root pool
150819397407SSherry Moore  * Return 0 on success; non-zeron on failure.
150919397407SSherry Moore  */
151019397407SSherry Moore int
151119397407SSherry Moore zpool_get_physpath(zpool_handle_t *zhp, char *physpath)
151219397407SSherry Moore {
151319397407SSherry Moore 	nvlist_t *vdev_root;
151419397407SSherry Moore 	nvlist_t **child;
151519397407SSherry Moore 	uint_t count;
151619397407SSherry Moore 	int i;
151719397407SSherry Moore 
151819397407SSherry Moore 	/*
151919397407SSherry Moore 	 * Make sure this is a root pool, as phys_path doesn't mean
152019397407SSherry Moore 	 * anything to a non-root pool.
152119397407SSherry Moore 	 */
1522b5b76fecSGeorge Wilson 	if (!pool_is_bootable(zhp))
152319397407SSherry Moore 		return (-1);
152419397407SSherry Moore 
152519397407SSherry Moore 	verify(nvlist_lookup_nvlist(zhp->zpool_config,
152619397407SSherry Moore 	    ZPOOL_CONFIG_VDEV_TREE, &vdev_root) == 0);
152719397407SSherry Moore 
152819397407SSherry Moore 	if (nvlist_lookup_nvlist_array(vdev_root, ZPOOL_CONFIG_CHILDREN,
152919397407SSherry Moore 	    &child, &count) != 0)
153019397407SSherry Moore 		return (-2);
153119397407SSherry Moore 
153219397407SSherry Moore 	for (i = 0; i < count; i++) {
153319397407SSherry Moore 		nvlist_t **child2;
153419397407SSherry Moore 		uint_t count2;
153519397407SSherry Moore 		char *type;
153619397407SSherry Moore 		char *tmppath;
153719397407SSherry Moore 		int j;
153819397407SSherry Moore 
153919397407SSherry Moore 		if (nvlist_lookup_string(child[i], ZPOOL_CONFIG_TYPE, &type)
154019397407SSherry Moore 		    != 0)
154119397407SSherry Moore 			return (-3);
154219397407SSherry Moore 
154319397407SSherry Moore 		if (strcmp(type, VDEV_TYPE_DISK) == 0) {
154419397407SSherry Moore 			if (!vdev_online(child[i]))
154519397407SSherry Moore 				return (-8);
154619397407SSherry Moore 			verify(nvlist_lookup_string(child[i],
154719397407SSherry Moore 			    ZPOOL_CONFIG_PHYS_PATH, &tmppath) == 0);
154819397407SSherry Moore 			(void) strncpy(physpath, tmppath, strlen(tmppath));
154919397407SSherry Moore 		} else if (strcmp(type, VDEV_TYPE_MIRROR) == 0) {
155019397407SSherry Moore 			if (nvlist_lookup_nvlist_array(child[i],
155119397407SSherry Moore 			    ZPOOL_CONFIG_CHILDREN, &child2, &count2) != 0)
155219397407SSherry Moore 				return (-4);
155319397407SSherry Moore 
155419397407SSherry Moore 			for (j = 0; j < count2; j++) {
155519397407SSherry Moore 				if (!vdev_online(child2[j]))
155619397407SSherry Moore 					return (-8);
155719397407SSherry Moore 				if (nvlist_lookup_string(child2[j],
155819397407SSherry Moore 				    ZPOOL_CONFIG_PHYS_PATH, &tmppath) != 0)
155919397407SSherry Moore 					return (-5);
156019397407SSherry Moore 
156119397407SSherry Moore 				if ((strlen(physpath) + strlen(tmppath)) >
156219397407SSherry Moore 				    MAXNAMELEN)
156319397407SSherry Moore 					return (-6);
156419397407SSherry Moore 
156519397407SSherry Moore 				if (strlen(physpath) == 0) {
156619397407SSherry Moore 					(void) strncpy(physpath, tmppath,
156719397407SSherry Moore 					    strlen(tmppath));
156819397407SSherry Moore 				} else {
156919397407SSherry Moore 					(void) strcat(physpath, " ");
157019397407SSherry Moore 					(void) strcat(physpath, tmppath);
157119397407SSherry Moore 				}
157219397407SSherry Moore 			}
157319397407SSherry Moore 		} else {
157419397407SSherry Moore 			return (-7);
157519397407SSherry Moore 		}
157619397407SSherry Moore 	}
157719397407SSherry Moore 
157819397407SSherry Moore 	return (0);
157919397407SSherry Moore }
158019397407SSherry Moore 
1581a43d325bSek /*
1582fa94a07fSbrendan  * Returns TRUE if the given guid corresponds to the given type.
1583fa94a07fSbrendan  * This is used to check for hot spares (INUSE or not), and level 2 cache
1584fa94a07fSbrendan  * devices.
1585a43d325bSek  */
1586a43d325bSek static boolean_t
1587fa94a07fSbrendan is_guid_type(zpool_handle_t *zhp, uint64_t guid, const char *type)
1588a43d325bSek {
1589fa94a07fSbrendan 	uint64_t target_guid;
1590a43d325bSek 	nvlist_t *nvroot;
1591fa94a07fSbrendan 	nvlist_t **list;
1592fa94a07fSbrendan 	uint_t count;
1593a43d325bSek 	int i;
1594a43d325bSek 
1595a43d325bSek 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
1596a43d325bSek 	    &nvroot) == 0);
1597fa94a07fSbrendan 	if (nvlist_lookup_nvlist_array(nvroot, type, &list, &count) == 0) {
1598fa94a07fSbrendan 		for (i = 0; i < count; i++) {
1599fa94a07fSbrendan 			verify(nvlist_lookup_uint64(list[i], ZPOOL_CONFIG_GUID,
1600fa94a07fSbrendan 			    &target_guid) == 0);
1601fa94a07fSbrendan 			if (guid == target_guid)
1602a43d325bSek 				return (B_TRUE);
1603a43d325bSek 		}
1604a43d325bSek 	}
1605a43d325bSek 
1606a43d325bSek 	return (B_FALSE);
1607ea8dc4b6Seschrock }
1608ea8dc4b6Seschrock 
1609fa9e4066Sahrens /*
16103d7072f8Seschrock  * Bring the specified vdev online.   The 'flags' parameter is a set of the
16113d7072f8Seschrock  * ZFS_ONLINE_* flags.
1612fa9e4066Sahrens  */
1613fa9e4066Sahrens int
16143d7072f8Seschrock zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
16153d7072f8Seschrock     vdev_state_t *newstate)
1616fa9e4066Sahrens {
1617fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
1618fa9e4066Sahrens 	char msg[1024];
161999653d4eSeschrock 	nvlist_t *tgt;
1620fa94a07fSbrendan 	boolean_t avail_spare, l2cache;
162199653d4eSeschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1622fa9e4066Sahrens 
1623ea8dc4b6Seschrock 	(void) snprintf(msg, sizeof (msg),
1624ea8dc4b6Seschrock 	    dgettext(TEXT_DOMAIN, "cannot online %s"), path);
1625ea8dc4b6Seschrock 
1626fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1627ee0eb9f2SEric Schrock 	if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
1628ee0eb9f2SEric Schrock 	    NULL)) == NULL)
162999653d4eSeschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
1630fa9e4066Sahrens 
163199653d4eSeschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
1632fa9e4066Sahrens 
1633fa94a07fSbrendan 	if (avail_spare ||
1634fa94a07fSbrendan 	    is_guid_type(zhp, zc.zc_guid, ZPOOL_CONFIG_SPARES) == B_TRUE)
1635a43d325bSek 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
1636a43d325bSek 
16373d7072f8Seschrock 	zc.zc_cookie = VDEV_STATE_ONLINE;
16383d7072f8Seschrock 	zc.zc_obj = flags;
1639fa9e4066Sahrens 
1640ecd6cf80Smarks 	if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_SET_STATE, &zc) != 0)
16413d7072f8Seschrock 		return (zpool_standard_error(hdl, errno, msg));
16423d7072f8Seschrock 
16433d7072f8Seschrock 	*newstate = zc.zc_cookie;
16443d7072f8Seschrock 	return (0);
1645fa9e4066Sahrens }
1646fa9e4066Sahrens 
1647fa9e4066Sahrens /*
1648fa9e4066Sahrens  * Take the specified vdev offline
1649fa9e4066Sahrens  */
1650fa9e4066Sahrens int
16513d7072f8Seschrock zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
1652fa9e4066Sahrens {
1653fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
1654fa9e4066Sahrens 	char msg[1024];
165599653d4eSeschrock 	nvlist_t *tgt;
1656fa94a07fSbrendan 	boolean_t avail_spare, l2cache;
165799653d4eSeschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1658fa9e4066Sahrens 
1659ea8dc4b6Seschrock 	(void) snprintf(msg, sizeof (msg),
1660ea8dc4b6Seschrock 	    dgettext(TEXT_DOMAIN, "cannot offline %s"), path);
1661ea8dc4b6Seschrock 
1662fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1663ee0eb9f2SEric Schrock 	if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
1664ee0eb9f2SEric Schrock 	    NULL)) == NULL)
166599653d4eSeschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
166699653d4eSeschrock 
166799653d4eSeschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
1668fa9e4066Sahrens 
1669fa94a07fSbrendan 	if (avail_spare ||
1670fa94a07fSbrendan 	    is_guid_type(zhp, zc.zc_guid, ZPOOL_CONFIG_SPARES) == B_TRUE)
1671a43d325bSek 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
1672a43d325bSek 
16733d7072f8Seschrock 	zc.zc_cookie = VDEV_STATE_OFFLINE;
16743d7072f8Seschrock 	zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0;
16753d7072f8Seschrock 
1676ecd6cf80Smarks 	if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
16773d7072f8Seschrock 		return (0);
16783d7072f8Seschrock 
16793d7072f8Seschrock 	switch (errno) {
16803d7072f8Seschrock 	case EBUSY:
16813d7072f8Seschrock 
16823d7072f8Seschrock 		/*
16833d7072f8Seschrock 		 * There are no other replicas of this device.
16843d7072f8Seschrock 		 */
16853d7072f8Seschrock 		return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
16863d7072f8Seschrock 
16873d7072f8Seschrock 	default:
16883d7072f8Seschrock 		return (zpool_standard_error(hdl, errno, msg));
16893d7072f8Seschrock 	}
16903d7072f8Seschrock }
16913d7072f8Seschrock 
16923d7072f8Seschrock /*
16933d7072f8Seschrock  * Mark the given vdev faulted.
16943d7072f8Seschrock  */
16953d7072f8Seschrock int
16963d7072f8Seschrock zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid)
16973d7072f8Seschrock {
16983d7072f8Seschrock 	zfs_cmd_t zc = { 0 };
16993d7072f8Seschrock 	char msg[1024];
17003d7072f8Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
17013d7072f8Seschrock 
17023d7072f8Seschrock 	(void) snprintf(msg, sizeof (msg),
17033d7072f8Seschrock 	    dgettext(TEXT_DOMAIN, "cannot fault %llu"), guid);
1704441d80aaSlling 
17053d7072f8Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
17063d7072f8Seschrock 	zc.zc_guid = guid;
17073d7072f8Seschrock 	zc.zc_cookie = VDEV_STATE_FAULTED;
17083d7072f8Seschrock 
17093d7072f8Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
1710fa9e4066Sahrens 		return (0);
1711fa9e4066Sahrens 
1712fa9e4066Sahrens 	switch (errno) {
171399653d4eSeschrock 	case EBUSY:
1714fa9e4066Sahrens 
1715fa9e4066Sahrens 		/*
1716fa9e4066Sahrens 		 * There are no other replicas of this device.
1717fa9e4066Sahrens 		 */
171899653d4eSeschrock 		return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
1719fa9e4066Sahrens 
172099653d4eSeschrock 	default:
172199653d4eSeschrock 		return (zpool_standard_error(hdl, errno, msg));
1722fa9e4066Sahrens 	}
17233d7072f8Seschrock 
17243d7072f8Seschrock }
17253d7072f8Seschrock 
17263d7072f8Seschrock /*
17273d7072f8Seschrock  * Mark the given vdev degraded.
17283d7072f8Seschrock  */
17293d7072f8Seschrock int
17303d7072f8Seschrock zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid)
17313d7072f8Seschrock {
17323d7072f8Seschrock 	zfs_cmd_t zc = { 0 };
17333d7072f8Seschrock 	char msg[1024];
17343d7072f8Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
17353d7072f8Seschrock 
17363d7072f8Seschrock 	(void) snprintf(msg, sizeof (msg),
17373d7072f8Seschrock 	    dgettext(TEXT_DOMAIN, "cannot degrade %llu"), guid);
17383d7072f8Seschrock 
17393d7072f8Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
17403d7072f8Seschrock 	zc.zc_guid = guid;
17413d7072f8Seschrock 	zc.zc_cookie = VDEV_STATE_DEGRADED;
17423d7072f8Seschrock 
17433d7072f8Seschrock 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
17443d7072f8Seschrock 		return (0);
17453d7072f8Seschrock 
17463d7072f8Seschrock 	return (zpool_standard_error(hdl, errno, msg));
174799653d4eSeschrock }
174899653d4eSeschrock 
174999653d4eSeschrock /*
175099653d4eSeschrock  * Returns TRUE if the given nvlist is a vdev that was originally swapped in as
175199653d4eSeschrock  * a hot spare.
175299653d4eSeschrock  */
175399653d4eSeschrock static boolean_t
175499653d4eSeschrock is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which)
175599653d4eSeschrock {
175699653d4eSeschrock 	nvlist_t **child;
175799653d4eSeschrock 	uint_t c, children;
175899653d4eSeschrock 	char *type;
175999653d4eSeschrock 
176099653d4eSeschrock 	if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child,
176199653d4eSeschrock 	    &children) == 0) {
176299653d4eSeschrock 		verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE,
176399653d4eSeschrock 		    &type) == 0);
176499653d4eSeschrock 
176599653d4eSeschrock 		if (strcmp(type, VDEV_TYPE_SPARE) == 0 &&
176699653d4eSeschrock 		    children == 2 && child[which] == tgt)
176799653d4eSeschrock 			return (B_TRUE);
176899653d4eSeschrock 
176999653d4eSeschrock 		for (c = 0; c < children; c++)
177099653d4eSeschrock 			if (is_replacing_spare(child[c], tgt, which))
177199653d4eSeschrock 				return (B_TRUE);
177299653d4eSeschrock 	}
177399653d4eSeschrock 
177499653d4eSeschrock 	return (B_FALSE);
1775fa9e4066Sahrens }
1776fa9e4066Sahrens 
1777fa9e4066Sahrens /*
1778fa9e4066Sahrens  * Attach new_disk (fully described by nvroot) to old_disk.
17798654d025Sperrin  * If 'replacing' is specified, the new disk will replace the old one.
1780fa9e4066Sahrens  */
1781fa9e4066Sahrens int
1782fa9e4066Sahrens zpool_vdev_attach(zpool_handle_t *zhp,
1783fa9e4066Sahrens     const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing)
1784fa9e4066Sahrens {
1785fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
1786fa9e4066Sahrens 	char msg[1024];
1787fa9e4066Sahrens 	int ret;
178899653d4eSeschrock 	nvlist_t *tgt;
1789ee0eb9f2SEric Schrock 	boolean_t avail_spare, l2cache, islog;
1790ee0eb9f2SEric Schrock 	uint64_t val;
17910430f8daSeschrock 	char *path, *newname;
179299653d4eSeschrock 	nvlist_t **child;
179399653d4eSeschrock 	uint_t children;
179499653d4eSeschrock 	nvlist_t *config_root;
179599653d4eSeschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1796b5b76fecSGeorge Wilson 	boolean_t rootpool = pool_is_bootable(zhp);
1797fa9e4066Sahrens 
1798ea8dc4b6Seschrock 	if (replacing)
1799ea8dc4b6Seschrock 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1800ea8dc4b6Seschrock 		    "cannot replace %s with %s"), old_disk, new_disk);
1801ea8dc4b6Seschrock 	else
1802ea8dc4b6Seschrock 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1803ea8dc4b6Seschrock 		    "cannot attach %s to %s"), new_disk, old_disk);
1804ea8dc4b6Seschrock 
1805b5b76fecSGeorge Wilson 	/*
1806b5b76fecSGeorge Wilson 	 * If this is a root pool, make sure that we're not attaching an
1807b5b76fecSGeorge Wilson 	 * EFI labeled device.
1808b5b76fecSGeorge Wilson 	 */
1809b5b76fecSGeorge Wilson 	if (rootpool && pool_uses_efi(nvroot)) {
1810b5b76fecSGeorge Wilson 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1811b5b76fecSGeorge Wilson 		    "EFI labeled devices are not supported on root pools."));
1812b5b76fecSGeorge Wilson 		return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg));
1813b5b76fecSGeorge Wilson 	}
1814b5b76fecSGeorge Wilson 
1815fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1816ee0eb9f2SEric Schrock 	if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare, &l2cache,
1817ee0eb9f2SEric Schrock 	    &islog)) == 0)
181899653d4eSeschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
181999653d4eSeschrock 
1820a43d325bSek 	if (avail_spare)
182199653d4eSeschrock 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
182299653d4eSeschrock 
1823fa94a07fSbrendan 	if (l2cache)
1824fa94a07fSbrendan 		return (zfs_error(hdl, EZFS_ISL2CACHE, msg));
1825fa94a07fSbrendan 
182699653d4eSeschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
1827fa9e4066Sahrens 	zc.zc_cookie = replacing;
1828fa9e4066Sahrens 
182999653d4eSeschrock 	if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
183099653d4eSeschrock 	    &child, &children) != 0 || children != 1) {
183199653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
183299653d4eSeschrock 		    "new device must be a single disk"));
183399653d4eSeschrock 		return (zfs_error(hdl, EZFS_INVALCONFIG, msg));
183499653d4eSeschrock 	}
183599653d4eSeschrock 
183699653d4eSeschrock 	verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
183799653d4eSeschrock 	    ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0);
183899653d4eSeschrock 
18390430f8daSeschrock 	if ((newname = zpool_vdev_name(NULL, NULL, child[0])) == NULL)
18400430f8daSeschrock 		return (-1);
18410430f8daSeschrock 
184299653d4eSeschrock 	/*
184399653d4eSeschrock 	 * If the target is a hot spare that has been swapped in, we can only
184499653d4eSeschrock 	 * replace it with another hot spare.
184599653d4eSeschrock 	 */
184699653d4eSeschrock 	if (replacing &&
184799653d4eSeschrock 	    nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 &&
1848ee0eb9f2SEric Schrock 	    (zpool_find_vdev(zhp, newname, &avail_spare, &l2cache,
1849ee0eb9f2SEric Schrock 	    NULL) == NULL || !avail_spare) &&
1850ee0eb9f2SEric Schrock 	    is_replacing_spare(config_root, tgt, 1)) {
185199653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
185299653d4eSeschrock 		    "can only be replaced by another hot spare"));
18530430f8daSeschrock 		free(newname);
185499653d4eSeschrock 		return (zfs_error(hdl, EZFS_BADTARGET, msg));
185599653d4eSeschrock 	}
185699653d4eSeschrock 
185799653d4eSeschrock 	/*
185899653d4eSeschrock 	 * If we are attempting to replace a spare, it canot be applied to an
185999653d4eSeschrock 	 * already spared device.
186099653d4eSeschrock 	 */
186199653d4eSeschrock 	if (replacing &&
186299653d4eSeschrock 	    nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 &&
1863ee0eb9f2SEric Schrock 	    zpool_find_vdev(zhp, newname, &avail_spare,
1864ee0eb9f2SEric Schrock 	    &l2cache, NULL) != NULL && avail_spare &&
1865ee0eb9f2SEric Schrock 	    is_replacing_spare(config_root, tgt, 0)) {
186699653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
186799653d4eSeschrock 		    "device has already been replaced with a spare"));
18680430f8daSeschrock 		free(newname);
186999653d4eSeschrock 		return (zfs_error(hdl, EZFS_BADTARGET, msg));
187099653d4eSeschrock 	}
187199653d4eSeschrock 
18720430f8daSeschrock 	free(newname);
18730430f8daSeschrock 
1874990b4856Slling 	if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
187599653d4eSeschrock 		return (-1);
1876fa9e4066Sahrens 
1877ecd6cf80Smarks 	ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_ATTACH, &zc);
1878fa9e4066Sahrens 
1879e9dbad6fSeschrock 	zcmd_free_nvlists(&zc);
1880fa9e4066Sahrens 
1881b5b76fecSGeorge Wilson 	if (ret == 0) {
1882b5b76fecSGeorge Wilson 		if (rootpool) {
1883b5b76fecSGeorge Wilson 			/*
1884b5b76fecSGeorge Wilson 			 * XXX - This should be removed once we can
1885b5b76fecSGeorge Wilson 			 * automatically install the bootblocks on the
1886b5b76fecSGeorge Wilson 			 * newly attached disk.
1887b5b76fecSGeorge Wilson 			 */
1888b5b76fecSGeorge Wilson 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Please "
1889b5b76fecSGeorge Wilson 			    "be sure to invoke %s to make '%s' bootable.\n"),
1890b5b76fecSGeorge Wilson 			    BOOTCMD, new_disk);
1891b5b76fecSGeorge Wilson 		}
1892fa9e4066Sahrens 		return (0);
1893b5b76fecSGeorge Wilson 	}
1894fa9e4066Sahrens 
1895fa9e4066Sahrens 	switch (errno) {
1896ea8dc4b6Seschrock 	case ENOTSUP:
1897fa9e4066Sahrens 		/*
1898fa9e4066Sahrens 		 * Can't attach to or replace this type of vdev.
1899fa9e4066Sahrens 		 */
19008654d025Sperrin 		if (replacing) {
1901ee0eb9f2SEric Schrock 			if (islog)
19028654d025Sperrin 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
19038654d025Sperrin 				    "cannot replace a log with a spare"));
19048654d025Sperrin 			else
19058654d025Sperrin 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
19068654d025Sperrin 				    "cannot replace a replacing device"));
19078654d025Sperrin 		} else {
190899653d4eSeschrock 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
190999653d4eSeschrock 			    "can only attach to mirrors and top-level "
191099653d4eSeschrock 			    "disks"));
19118654d025Sperrin 		}
191299653d4eSeschrock 		(void) zfs_error(hdl, EZFS_BADTARGET, msg);
1913fa9e4066Sahrens 		break;
1914fa9e4066Sahrens 
1915ea8dc4b6Seschrock 	case EINVAL:
1916fa9e4066Sahrens 		/*
1917fa9e4066Sahrens 		 * The new device must be a single disk.
1918fa9e4066Sahrens 		 */
191999653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
192099653d4eSeschrock 		    "new device must be a single disk"));
192199653d4eSeschrock 		(void) zfs_error(hdl, EZFS_INVALCONFIG, msg);
1922fa9e4066Sahrens 		break;
1923fa9e4066Sahrens 
1924ea8dc4b6Seschrock 	case EBUSY:
192599653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"),
192699653d4eSeschrock 		    new_disk);
192799653d4eSeschrock 		(void) zfs_error(hdl, EZFS_BADDEV, msg);
1928fa9e4066Sahrens 		break;
1929fa9e4066Sahrens 
1930ea8dc4b6Seschrock 	case EOVERFLOW:
1931fa9e4066Sahrens 		/*
1932fa9e4066Sahrens 		 * The new device is too small.
1933fa9e4066Sahrens 		 */
193499653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
193599653d4eSeschrock 		    "device is too small"));
193699653d4eSeschrock 		(void) zfs_error(hdl, EZFS_BADDEV, msg);
1937fa9e4066Sahrens 		break;
1938fa9e4066Sahrens 
1939ea8dc4b6Seschrock 	case EDOM:
1940fa9e4066Sahrens 		/*
1941fa9e4066Sahrens 		 * The new device has a different alignment requirement.
1942fa9e4066Sahrens 		 */
194399653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
194499653d4eSeschrock 		    "devices have different sector alignment"));
194599653d4eSeschrock 		(void) zfs_error(hdl, EZFS_BADDEV, msg);
1946fa9e4066Sahrens 		break;
1947fa9e4066Sahrens 
1948ea8dc4b6Seschrock 	case ENAMETOOLONG:
1949fa9e4066Sahrens 		/*
1950fa9e4066Sahrens 		 * The resulting top-level vdev spec won't fit in the label.
1951fa9e4066Sahrens 		 */
195299653d4eSeschrock 		(void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg);
1953fa9e4066Sahrens 		break;
1954fa9e4066Sahrens 
1955ea8dc4b6Seschrock 	default:
195699653d4eSeschrock 		(void) zpool_standard_error(hdl, errno, msg);
1957fa9e4066Sahrens 	}
1958fa9e4066Sahrens 
195999653d4eSeschrock 	return (-1);
1960fa9e4066Sahrens }
1961fa9e4066Sahrens 
1962fa9e4066Sahrens /*
1963fa9e4066Sahrens  * Detach the specified device.
1964fa9e4066Sahrens  */
1965fa9e4066Sahrens int
1966fa9e4066Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path)
1967fa9e4066Sahrens {
1968fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
1969fa9e4066Sahrens 	char msg[1024];
197099653d4eSeschrock 	nvlist_t *tgt;
1971fa94a07fSbrendan 	boolean_t avail_spare, l2cache;
197299653d4eSeschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
1973fa9e4066Sahrens 
1974ea8dc4b6Seschrock 	(void) snprintf(msg, sizeof (msg),
1975ea8dc4b6Seschrock 	    dgettext(TEXT_DOMAIN, "cannot detach %s"), path);
1976ea8dc4b6Seschrock 
1977fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1978ee0eb9f2SEric Schrock 	if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
1979ee0eb9f2SEric Schrock 	    NULL)) == 0)
198099653d4eSeschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
1981fa9e4066Sahrens 
1982a43d325bSek 	if (avail_spare)
198399653d4eSeschrock 		return (zfs_error(hdl, EZFS_ISSPARE, msg));
198499653d4eSeschrock 
1985fa94a07fSbrendan 	if (l2cache)
1986fa94a07fSbrendan 		return (zfs_error(hdl, EZFS_ISL2CACHE, msg));
1987fa94a07fSbrendan 
198899653d4eSeschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
198999653d4eSeschrock 
1990ecd6cf80Smarks 	if (zfs_ioctl(hdl, ZFS_IOC_VDEV_DETACH, &zc) == 0)
1991fa9e4066Sahrens 		return (0);
1992fa9e4066Sahrens 
1993fa9e4066Sahrens 	switch (errno) {
1994fa9e4066Sahrens 
1995ea8dc4b6Seschrock 	case ENOTSUP:
1996fa9e4066Sahrens 		/*
1997fa9e4066Sahrens 		 * Can't detach from this type of vdev.
1998fa9e4066Sahrens 		 */
199999653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only "
200099653d4eSeschrock 		    "applicable to mirror and replacing vdevs"));
200199653d4eSeschrock 		(void) zfs_error(zhp->zpool_hdl, EZFS_BADTARGET, msg);
2002fa9e4066Sahrens 		break;
2003fa9e4066Sahrens 
2004ea8dc4b6Seschrock 	case EBUSY:
2005fa9e4066Sahrens 		/*
2006fa9e4066Sahrens 		 * There are no other replicas of this device.
2007fa9e4066Sahrens 		 */
200899653d4eSeschrock 		(void) zfs_error(hdl, EZFS_NOREPLICAS, msg);
2009fa9e4066Sahrens 		break;
2010fa9e4066Sahrens 
2011ea8dc4b6Seschrock 	default:
201299653d4eSeschrock 		(void) zpool_standard_error(hdl, errno, msg);
2013ea8dc4b6Seschrock 	}
2014ea8dc4b6Seschrock 
201599653d4eSeschrock 	return (-1);
201699653d4eSeschrock }
201799653d4eSeschrock 
201899653d4eSeschrock /*
2019fa94a07fSbrendan  * Remove the given device.  Currently, this is supported only for hot spares
2020fa94a07fSbrendan  * and level 2 cache devices.
202199653d4eSeschrock  */
202299653d4eSeschrock int
202399653d4eSeschrock zpool_vdev_remove(zpool_handle_t *zhp, const char *path)
202499653d4eSeschrock {
202599653d4eSeschrock 	zfs_cmd_t zc = { 0 };
202699653d4eSeschrock 	char msg[1024];
202799653d4eSeschrock 	nvlist_t *tgt;
2028fa94a07fSbrendan 	boolean_t avail_spare, l2cache;
202999653d4eSeschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
203099653d4eSeschrock 
203199653d4eSeschrock 	(void) snprintf(msg, sizeof (msg),
203299653d4eSeschrock 	    dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
203399653d4eSeschrock 
203499653d4eSeschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2035ee0eb9f2SEric Schrock 	if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
2036ee0eb9f2SEric Schrock 	    NULL)) == 0)
203799653d4eSeschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
203899653d4eSeschrock 
2039fa94a07fSbrendan 	if (!avail_spare && !l2cache) {
204099653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2041fa94a07fSbrendan 		    "only inactive hot spares or cache devices "
2042fa94a07fSbrendan 		    "can be removed"));
204399653d4eSeschrock 		return (zfs_error(hdl, EZFS_NODEVICE, msg));
204499653d4eSeschrock 	}
204599653d4eSeschrock 
204699653d4eSeschrock 	verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
204799653d4eSeschrock 
2048ecd6cf80Smarks 	if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0)
204999653d4eSeschrock 		return (0);
205099653d4eSeschrock 
205199653d4eSeschrock 	return (zpool_standard_error(hdl, errno, msg));
2052ea8dc4b6Seschrock }
2053ea8dc4b6Seschrock 
2054ea8dc4b6Seschrock /*
2055ea8dc4b6Seschrock  * Clear the errors for the pool, or the particular device if specified.
2056ea8dc4b6Seschrock  */
2057ea8dc4b6Seschrock int
2058ea8dc4b6Seschrock zpool_clear(zpool_handle_t *zhp, const char *path)
2059ea8dc4b6Seschrock {
2060ea8dc4b6Seschrock 	zfs_cmd_t zc = { 0 };
2061ea8dc4b6Seschrock 	char msg[1024];
206299653d4eSeschrock 	nvlist_t *tgt;
2063fa94a07fSbrendan 	boolean_t avail_spare, l2cache;
206499653d4eSeschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
2065ea8dc4b6Seschrock 
2066ea8dc4b6Seschrock 	if (path)
2067ea8dc4b6Seschrock 		(void) snprintf(msg, sizeof (msg),
2068ea8dc4b6Seschrock 		    dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
2069e9dbad6fSeschrock 		    path);
2070ea8dc4b6Seschrock 	else
2071ea8dc4b6Seschrock 		(void) snprintf(msg, sizeof (msg),
2072ea8dc4b6Seschrock 		    dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
2073ea8dc4b6Seschrock 		    zhp->zpool_name);
2074ea8dc4b6Seschrock 
2075ea8dc4b6Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
207699653d4eSeschrock 	if (path) {
2077fa94a07fSbrendan 		if ((tgt = zpool_find_vdev(zhp, path, &avail_spare,
2078ee0eb9f2SEric Schrock 		    &l2cache, NULL)) == 0)
207999653d4eSeschrock 			return (zfs_error(hdl, EZFS_NODEVICE, msg));
2080ea8dc4b6Seschrock 
2081fa94a07fSbrendan 		/*
2082fa94a07fSbrendan 		 * Don't allow error clearing for hot spares.  Do allow
2083fa94a07fSbrendan 		 * error clearing for l2cache devices.
2084fa94a07fSbrendan 		 */
2085a43d325bSek 		if (avail_spare)
208699653d4eSeschrock 			return (zfs_error(hdl, EZFS_ISSPARE, msg));
2087ea8dc4b6Seschrock 
208899653d4eSeschrock 		verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID,
208999653d4eSeschrock 		    &zc.zc_guid) == 0);
2090fa9e4066Sahrens 	}
2091fa9e4066Sahrens 
2092ecd6cf80Smarks 	if (zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc) == 0)
209399653d4eSeschrock 		return (0);
209499653d4eSeschrock 
209599653d4eSeschrock 	return (zpool_standard_error(hdl, errno, msg));
2096fa9e4066Sahrens }
2097fa9e4066Sahrens 
20983d7072f8Seschrock /*
20993d7072f8Seschrock  * Similar to zpool_clear(), but takes a GUID (used by fmd).
21003d7072f8Seschrock  */
21013d7072f8Seschrock int
21023d7072f8Seschrock zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid)
21033d7072f8Seschrock {
21043d7072f8Seschrock 	zfs_cmd_t zc = { 0 };
21053d7072f8Seschrock 	char msg[1024];
21063d7072f8Seschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
21073d7072f8Seschrock 
21083d7072f8Seschrock 	(void) snprintf(msg, sizeof (msg),
21093d7072f8Seschrock 	    dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"),
21103d7072f8Seschrock 	    guid);
21113d7072f8Seschrock 
21123d7072f8Seschrock 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
21133d7072f8Seschrock 	zc.zc_guid = guid;
21143d7072f8Seschrock 
21153d7072f8Seschrock 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0)
21163d7072f8Seschrock 		return (0);
21173d7072f8Seschrock 
21183d7072f8Seschrock 	return (zpool_standard_error(hdl, errno, msg));
21193d7072f8Seschrock }
21203d7072f8Seschrock 
2121f3861e1aSahl /*
2122f3861e1aSahl  * Iterate over all zvols in a given pool by walking the /dev/zvol/dsk/<pool>
2123f3861e1aSahl  * hierarchy.
2124f3861e1aSahl  */
2125f3861e1aSahl int
2126f3861e1aSahl zpool_iter_zvol(zpool_handle_t *zhp, int (*cb)(const char *, void *),
2127f3861e1aSahl     void *data)
2128fa9e4066Sahrens {
2129f3861e1aSahl 	libzfs_handle_t *hdl = zhp->zpool_hdl;
2130f3861e1aSahl 	char (*paths)[MAXPATHLEN];
2131f3861e1aSahl 	size_t size = 4;
2132f3861e1aSahl 	int curr, fd, base, ret = 0;
2133f3861e1aSahl 	DIR *dirp;
2134f3861e1aSahl 	struct dirent *dp;
2135f3861e1aSahl 	struct stat st;
2136f3861e1aSahl 
2137f3861e1aSahl 	if ((base = open("/dev/zvol/dsk", O_RDONLY)) < 0)
2138f3861e1aSahl 		return (errno == ENOENT ? 0 : -1);
2139f3861e1aSahl 
2140f3861e1aSahl 	if (fstatat(base, zhp->zpool_name, &st, 0) != 0) {
2141f3861e1aSahl 		int err = errno;
2142f3861e1aSahl 		(void) close(base);
2143f3861e1aSahl 		return (err == ENOENT ? 0 : -1);
2144f3861e1aSahl 	}
2145fa9e4066Sahrens 
2146fa9e4066Sahrens 	/*
2147f3861e1aSahl 	 * Oddly this wasn't a directory -- ignore that failure since we
2148f3861e1aSahl 	 * know there are no links lower in the (non-existant) hierarchy.
2149fa9e4066Sahrens 	 */
2150f3861e1aSahl 	if (!S_ISDIR(st.st_mode)) {
2151f3861e1aSahl 		(void) close(base);
2152f3861e1aSahl 		return (0);
2153fa9e4066Sahrens 	}
2154fa9e4066Sahrens 
2155f3861e1aSahl 	if ((paths = zfs_alloc(hdl, size * sizeof (paths[0]))) == NULL) {
2156f3861e1aSahl 		(void) close(base);
2157f3861e1aSahl 		return (-1);
2158f3861e1aSahl 	}
2159f3861e1aSahl 
2160f3861e1aSahl 	(void) strlcpy(paths[0], zhp->zpool_name, sizeof (paths[0]));
2161f3861e1aSahl 	curr = 0;
2162f3861e1aSahl 
2163f3861e1aSahl 	while (curr >= 0) {
2164f3861e1aSahl 		if (fstatat(base, paths[curr], &st, AT_SYMLINK_NOFOLLOW) != 0)
2165f3861e1aSahl 			goto err;
2166f3861e1aSahl 
2167f3861e1aSahl 		if (S_ISDIR(st.st_mode)) {
2168f3861e1aSahl 			if ((fd = openat(base, paths[curr], O_RDONLY)) < 0)
2169f3861e1aSahl 				goto err;
2170f3861e1aSahl 
2171f3861e1aSahl 			if ((dirp = fdopendir(fd)) == NULL) {
2172f3861e1aSahl 				(void) close(fd);
2173f3861e1aSahl 				goto err;
2174f3861e1aSahl 			}
2175f3861e1aSahl 
2176f3861e1aSahl 			while ((dp = readdir(dirp)) != NULL) {
2177f3861e1aSahl 				if (dp->d_name[0] == '.')
2178f3861e1aSahl 					continue;
2179f3861e1aSahl 
2180f3861e1aSahl 				if (curr + 1 == size) {
2181f3861e1aSahl 					paths = zfs_realloc(hdl, paths,
2182f3861e1aSahl 					    size * sizeof (paths[0]),
2183f3861e1aSahl 					    size * 2 * sizeof (paths[0]));
2184f3861e1aSahl 					if (paths == NULL) {
2185f3861e1aSahl 						(void) closedir(dirp);
2186f3861e1aSahl 						(void) close(fd);
2187f3861e1aSahl 						goto err;
2188f3861e1aSahl 					}
2189f3861e1aSahl 
2190f3861e1aSahl 					size *= 2;
2191f3861e1aSahl 				}
2192f3861e1aSahl 
2193f3861e1aSahl 				(void) strlcpy(paths[curr + 1], paths[curr],
2194f3861e1aSahl 				    sizeof (paths[curr + 1]));
2195f3861e1aSahl 				(void) strlcat(paths[curr], "/",
2196f3861e1aSahl 				    sizeof (paths[curr]));
2197f3861e1aSahl 				(void) strlcat(paths[curr], dp->d_name,
2198f3861e1aSahl 				    sizeof (paths[curr]));
2199f3861e1aSahl 				curr++;
2200f3861e1aSahl 			}
2201f3861e1aSahl 
2202f3861e1aSahl 			(void) closedir(dirp);
2203f3861e1aSahl 
2204f3861e1aSahl 		} else {
2205f3861e1aSahl 			if ((ret = cb(paths[curr], data)) != 0)
2206f3861e1aSahl 				break;
2207f3861e1aSahl 		}
2208f3861e1aSahl 
2209f3861e1aSahl 		curr--;
2210f3861e1aSahl 	}
2211f3861e1aSahl 
2212f3861e1aSahl 	free(paths);
2213f3861e1aSahl 	(void) close(base);
2214f3861e1aSahl 
2215f3861e1aSahl 	return (ret);
2216f3861e1aSahl 
2217f3861e1aSahl err:
2218f3861e1aSahl 	free(paths);
2219f3861e1aSahl 	(void) close(base);
2220f3861e1aSahl 	return (-1);
2221f3861e1aSahl }
2222f3861e1aSahl 
2223f3861e1aSahl typedef struct zvol_cb {
2224f3861e1aSahl 	zpool_handle_t *zcb_pool;
2225f3861e1aSahl 	boolean_t zcb_create;
2226f3861e1aSahl } zvol_cb_t;
2227f3861e1aSahl 
2228f3861e1aSahl /*ARGSUSED*/
2229f3861e1aSahl static int
2230f3861e1aSahl do_zvol_create(zfs_handle_t *zhp, void *data)
2231f3861e1aSahl {
22323aefe2c7Sahrens 	int ret = 0;
2233f3861e1aSahl 
22343aefe2c7Sahrens 	if (ZFS_IS_VOLUME(zhp)) {
2235f3861e1aSahl 		(void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name);
22363aefe2c7Sahrens 		ret = zfs_iter_snapshots(zhp, do_zvol_create, NULL);
22373aefe2c7Sahrens 	}
2238f3861e1aSahl 
22393aefe2c7Sahrens 	if (ret == 0)
22403aefe2c7Sahrens 		ret = zfs_iter_filesystems(zhp, do_zvol_create, NULL);
2241fa9e4066Sahrens 
2242fa9e4066Sahrens 	zfs_close(zhp);
2243f3861e1aSahl 
2244fa9e4066Sahrens 	return (ret);
2245fa9e4066Sahrens }
2246fa9e4066Sahrens 
2247fa9e4066Sahrens /*
2248fa9e4066Sahrens  * Iterate over all zvols in the pool and make any necessary minor nodes.
2249fa9e4066Sahrens  */
2250fa9e4066Sahrens int
2251fa9e4066Sahrens zpool_create_zvol_links(zpool_handle_t *zhp)
2252fa9e4066Sahrens {
2253fa9e4066Sahrens 	zfs_handle_t *zfp;
2254fa9e4066Sahrens 	int ret;
2255fa9e4066Sahrens 
2256fa9e4066Sahrens 	/*
2257fa9e4066Sahrens 	 * If the pool is unavailable, just return success.
2258fa9e4066Sahrens 	 */
225999653d4eSeschrock 	if ((zfp = make_dataset_handle(zhp->zpool_hdl,
226099653d4eSeschrock 	    zhp->zpool_name)) == NULL)
2261fa9e4066Sahrens 		return (0);
2262fa9e4066Sahrens 
22633aefe2c7Sahrens 	ret = zfs_iter_filesystems(zfp, do_zvol_create, NULL);
2264fa9e4066Sahrens 
2265fa9e4066Sahrens 	zfs_close(zfp);
2266fa9e4066Sahrens 	return (ret);
2267fa9e4066Sahrens }
2268fa9e4066Sahrens 
2269f3861e1aSahl static int
2270f3861e1aSahl do_zvol_remove(const char *dataset, void *data)
2271f3861e1aSahl {
2272f3861e1aSahl 	zpool_handle_t *zhp = data;
2273f3861e1aSahl 
2274f3861e1aSahl 	return (zvol_remove_link(zhp->zpool_hdl, dataset));
2275f3861e1aSahl }
2276f3861e1aSahl 
2277fa9e4066Sahrens /*
2278f3861e1aSahl  * Iterate over all zvols in the pool and remove any minor nodes.  We iterate
2279f3861e1aSahl  * by examining the /dev links so that a corrupted pool doesn't impede this
2280f3861e1aSahl  * operation.
2281fa9e4066Sahrens  */
2282fa9e4066Sahrens int
2283fa9e4066Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp)
2284fa9e4066Sahrens {
2285f3861e1aSahl 	return (zpool_iter_zvol(zhp, do_zvol_remove, zhp));
2286fa9e4066Sahrens }
2287c67d9675Seschrock 
2288c67d9675Seschrock /*
2289c67d9675Seschrock  * Convert from a devid string to a path.
2290c67d9675Seschrock  */
2291c67d9675Seschrock static char *
2292c67d9675Seschrock devid_to_path(char *devid_str)
2293c67d9675Seschrock {
2294c67d9675Seschrock 	ddi_devid_t devid;
2295c67d9675Seschrock 	char *minor;
2296c67d9675Seschrock 	char *path;
2297c67d9675Seschrock 	devid_nmlist_t *list = NULL;
2298c67d9675Seschrock 	int ret;
2299c67d9675Seschrock 
2300c67d9675Seschrock 	if (devid_str_decode(devid_str, &devid, &minor) != 0)
2301c67d9675Seschrock 		return (NULL);
2302c67d9675Seschrock 
2303c67d9675Seschrock 	ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list);
2304c67d9675Seschrock 
2305c67d9675Seschrock 	devid_str_free(minor);
2306c67d9675Seschrock 	devid_free(devid);
2307c67d9675Seschrock 
2308c67d9675Seschrock 	if (ret != 0)
2309c67d9675Seschrock 		return (NULL);
2310c67d9675Seschrock 
231199653d4eSeschrock 	if ((path = strdup(list[0].devname)) == NULL)
231299653d4eSeschrock 		return (NULL);
231399653d4eSeschrock 
2314c67d9675Seschrock 	devid_free_nmlist(list);
2315c67d9675Seschrock 
2316c67d9675Seschrock 	return (path);
2317c67d9675Seschrock }
2318c67d9675Seschrock 
2319c67d9675Seschrock /*
2320c67d9675Seschrock  * Convert from a path to a devid string.
2321c67d9675Seschrock  */
2322c67d9675Seschrock static char *
2323c67d9675Seschrock path_to_devid(const char *path)
2324c67d9675Seschrock {
2325c67d9675Seschrock 	int fd;
2326c67d9675Seschrock 	ddi_devid_t devid;
2327c67d9675Seschrock 	char *minor, *ret;
2328c67d9675Seschrock 
2329c67d9675Seschrock 	if ((fd = open(path, O_RDONLY)) < 0)
2330c67d9675Seschrock 		return (NULL);
2331c67d9675Seschrock 
2332c67d9675Seschrock 	minor = NULL;
2333c67d9675Seschrock 	ret = NULL;
2334c67d9675Seschrock 	if (devid_get(fd, &devid) == 0) {
2335c67d9675Seschrock 		if (devid_get_minor_name(fd, &minor) == 0)
2336c67d9675Seschrock 			ret = devid_str_encode(devid, minor);
2337c67d9675Seschrock 		if (minor != NULL)
2338c67d9675Seschrock 			devid_str_free(minor);
2339c67d9675Seschrock 		devid_free(devid);
2340c67d9675Seschrock 	}
2341c67d9675Seschrock 	(void) close(fd);
2342c67d9675Seschrock 
2343c67d9675Seschrock 	return (ret);
2344c67d9675Seschrock }
2345c67d9675Seschrock 
2346c67d9675Seschrock /*
2347c67d9675Seschrock  * Issue the necessary ioctl() to update the stored path value for the vdev.  We
2348c67d9675Seschrock  * ignore any failure here, since a common case is for an unprivileged user to
2349c67d9675Seschrock  * type 'zpool status', and we'll display the correct information anyway.
2350c67d9675Seschrock  */
2351c67d9675Seschrock static void
2352c67d9675Seschrock set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path)
2353c67d9675Seschrock {
2354c67d9675Seschrock 	zfs_cmd_t zc = { 0 };
2355c67d9675Seschrock 
2356c67d9675Seschrock 	(void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2357e9dbad6fSeschrock 	(void) strncpy(zc.zc_value, path, sizeof (zc.zc_value));
2358c67d9675Seschrock 	verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
2359ea8dc4b6Seschrock 	    &zc.zc_guid) == 0);
2360c67d9675Seschrock 
236199653d4eSeschrock 	(void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc);
2362c67d9675Seschrock }
2363c67d9675Seschrock 
2364c67d9675Seschrock /*
2365c67d9675Seschrock  * Given a vdev, return the name to display in iostat.  If the vdev has a path,
2366c67d9675Seschrock  * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type.
2367c67d9675Seschrock  * We also check if this is a whole disk, in which case we strip off the
2368c67d9675Seschrock  * trailing 's0' slice name.
2369c67d9675Seschrock  *
2370c67d9675Seschrock  * This routine is also responsible for identifying when disks have been
2371c67d9675Seschrock  * reconfigured in a new location.  The kernel will have opened the device by
2372c67d9675Seschrock  * devid, but the path will still refer to the old location.  To catch this, we
2373c67d9675Seschrock  * first do a path -> devid translation (which is fast for the common case).  If
2374c67d9675Seschrock  * the devid matches, we're done.  If not, we do a reverse devid -> path
2375c67d9675Seschrock  * translation and issue the appropriate ioctl() to update the path of the vdev.
2376c67d9675Seschrock  * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any
2377c67d9675Seschrock  * of these checks.
2378c67d9675Seschrock  */
2379c67d9675Seschrock char *
238099653d4eSeschrock zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv)
2381c67d9675Seschrock {
2382c67d9675Seschrock 	char *path, *devid;
2383ea8dc4b6Seschrock 	uint64_t value;
2384ea8dc4b6Seschrock 	char buf[64];
23853d7072f8Seschrock 	vdev_stat_t *vs;
23863d7072f8Seschrock 	uint_t vsc;
2387c67d9675Seschrock 
2388ea8dc4b6Seschrock 	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
2389ea8dc4b6Seschrock 	    &value) == 0) {
2390ea8dc4b6Seschrock 		verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
2391ea8dc4b6Seschrock 		    &value) == 0);
23925ad82045Snd 		(void) snprintf(buf, sizeof (buf), "%llu",
23935ad82045Snd 		    (u_longlong_t)value);
2394ea8dc4b6Seschrock 		path = buf;
2395ea8dc4b6Seschrock 	} else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
2396c67d9675Seschrock 
23973d7072f8Seschrock 		/*
23983d7072f8Seschrock 		 * If the device is dead (faulted, offline, etc) then don't
23993d7072f8Seschrock 		 * bother opening it.  Otherwise we may be forcing the user to
24003d7072f8Seschrock 		 * open a misbehaving device, which can have undesirable
24013d7072f8Seschrock 		 * effects.
24023d7072f8Seschrock 		 */
24033d7072f8Seschrock 		if ((nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
24043d7072f8Seschrock 		    (uint64_t **)&vs, &vsc) != 0 ||
24053d7072f8Seschrock 		    vs->vs_state >= VDEV_STATE_DEGRADED) &&
24063d7072f8Seschrock 		    zhp != NULL &&
2407c67d9675Seschrock 		    nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) {
2408c67d9675Seschrock 			/*
2409c67d9675Seschrock 			 * Determine if the current path is correct.
2410c67d9675Seschrock 			 */
2411c67d9675Seschrock 			char *newdevid = path_to_devid(path);
2412c67d9675Seschrock 
2413c67d9675Seschrock 			if (newdevid == NULL ||
2414c67d9675Seschrock 			    strcmp(devid, newdevid) != 0) {
2415c67d9675Seschrock 				char *newpath;
2416c67d9675Seschrock 
2417c67d9675Seschrock 				if ((newpath = devid_to_path(devid)) != NULL) {
2418c67d9675Seschrock 					/*
2419c67d9675Seschrock 					 * Update the path appropriately.
2420c67d9675Seschrock 					 */
2421c67d9675Seschrock 					set_path(zhp, nv, newpath);
242299653d4eSeschrock 					if (nvlist_add_string(nv,
242399653d4eSeschrock 					    ZPOOL_CONFIG_PATH, newpath) == 0)
242499653d4eSeschrock 						verify(nvlist_lookup_string(nv,
242599653d4eSeschrock 						    ZPOOL_CONFIG_PATH,
242699653d4eSeschrock 						    &path) == 0);
2427c67d9675Seschrock 					free(newpath);
2428c67d9675Seschrock 				}
2429c67d9675Seschrock 			}
2430c67d9675Seschrock 
243199653d4eSeschrock 			if (newdevid)
243299653d4eSeschrock 				devid_str_free(newdevid);
2433c67d9675Seschrock 		}
2434c67d9675Seschrock 
2435c67d9675Seschrock 		if (strncmp(path, "/dev/dsk/", 9) == 0)
2436c67d9675Seschrock 			path += 9;
2437c67d9675Seschrock 
2438c67d9675Seschrock 		if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
2439ea8dc4b6Seschrock 		    &value) == 0 && value) {
244099653d4eSeschrock 			char *tmp = zfs_strdup(hdl, path);
244199653d4eSeschrock 			if (tmp == NULL)
244299653d4eSeschrock 				return (NULL);
2443c67d9675Seschrock 			tmp[strlen(path) - 2] = '\0';
2444c67d9675Seschrock 			return (tmp);
2445c67d9675Seschrock 		}
2446c67d9675Seschrock 	} else {
2447c67d9675Seschrock 		verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0);
244899653d4eSeschrock 
244999653d4eSeschrock 		/*
245099653d4eSeschrock 		 * If it's a raidz device, we need to stick in the parity level.
245199653d4eSeschrock 		 */
245299653d4eSeschrock 		if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) {
245399653d4eSeschrock 			verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY,
245499653d4eSeschrock 			    &value) == 0);
245599653d4eSeschrock 			(void) snprintf(buf, sizeof (buf), "%s%llu", path,
24565ad82045Snd 			    (u_longlong_t)value);
245799653d4eSeschrock 			path = buf;
245899653d4eSeschrock 		}
2459c67d9675Seschrock 	}
2460c67d9675Seschrock 
246199653d4eSeschrock 	return (zfs_strdup(hdl, path));
2462c67d9675Seschrock }
2463ea8dc4b6Seschrock 
2464ea8dc4b6Seschrock static int
2465ea8dc4b6Seschrock zbookmark_compare(const void *a, const void *b)
2466ea8dc4b6Seschrock {
2467ea8dc4b6Seschrock 	return (memcmp(a, b, sizeof (zbookmark_t)));
2468ea8dc4b6Seschrock }
2469ea8dc4b6Seschrock 
2470ea8dc4b6Seschrock /*
2471ea8dc4b6Seschrock  * Retrieve the persistent error log, uniquify the members, and return to the
2472ea8dc4b6Seschrock  * caller.
2473ea8dc4b6Seschrock  */
2474ea8dc4b6Seschrock int
247555434c77Sek zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
2476ea8dc4b6Seschrock {
2477ea8dc4b6Seschrock 	zfs_cmd_t zc = { 0 };
2478ea8dc4b6Seschrock 	uint64_t count;
2479e9dbad6fSeschrock 	zbookmark_t *zb = NULL;
248055434c77Sek 	int i;
2481ea8dc4b6Seschrock 
2482ea8dc4b6Seschrock 	/*
2483ea8dc4b6Seschrock 	 * Retrieve the raw error list from the kernel.  If the number of errors
2484ea8dc4b6Seschrock 	 * has increased, allocate more space and continue until we get the
2485ea8dc4b6Seschrock 	 * entire list.
2486ea8dc4b6Seschrock 	 */
2487ea8dc4b6Seschrock 	verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT,
2488ea8dc4b6Seschrock 	    &count) == 0);
248975519f38Sek 	if (count == 0)
249075519f38Sek 		return (0);
2491e9dbad6fSeschrock 	if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl,
24925ad82045Snd 	    count * sizeof (zbookmark_t))) == (uintptr_t)NULL)
249399653d4eSeschrock 		return (-1);
2494e9dbad6fSeschrock 	zc.zc_nvlist_dst_size = count;
2495ea8dc4b6Seschrock 	(void) strcpy(zc.zc_name, zhp->zpool_name);
2496ea8dc4b6Seschrock 	for (;;) {
249799653d4eSeschrock 		if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG,
249899653d4eSeschrock 		    &zc) != 0) {
2499e9dbad6fSeschrock 			free((void *)(uintptr_t)zc.zc_nvlist_dst);
2500ea8dc4b6Seschrock 			if (errno == ENOMEM) {
2501bf561db0Svb 				count = zc.zc_nvlist_dst_size;
2502e9dbad6fSeschrock 				if ((zc.zc_nvlist_dst = (uintptr_t)
2503bf561db0Svb 				    zfs_alloc(zhp->zpool_hdl, count *
2504bf561db0Svb 				    sizeof (zbookmark_t))) == (uintptr_t)NULL)
250599653d4eSeschrock 					return (-1);
2506ea8dc4b6Seschrock 			} else {
2507ea8dc4b6Seschrock 				return (-1);
2508ea8dc4b6Seschrock 			}
2509ea8dc4b6Seschrock 		} else {
2510ea8dc4b6Seschrock 			break;
2511ea8dc4b6Seschrock 		}
2512ea8dc4b6Seschrock 	}
2513ea8dc4b6Seschrock 
2514ea8dc4b6Seschrock 	/*
2515ea8dc4b6Seschrock 	 * Sort the resulting bookmarks.  This is a little confusing due to the
2516ea8dc4b6Seschrock 	 * implementation of ZFS_IOC_ERROR_LOG.  The bookmarks are copied last
2517e9dbad6fSeschrock 	 * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks
2518ea8dc4b6Seschrock 	 * _not_ copied as part of the process.  So we point the start of our
2519ea8dc4b6Seschrock 	 * array appropriate and decrement the total number of elements.
2520ea8dc4b6Seschrock 	 */
2521e9dbad6fSeschrock 	zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) +
2522e9dbad6fSeschrock 	    zc.zc_nvlist_dst_size;
2523e9dbad6fSeschrock 	count -= zc.zc_nvlist_dst_size;
2524ea8dc4b6Seschrock 
2525ea8dc4b6Seschrock 	qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare);
2526ea8dc4b6Seschrock 
252755434c77Sek 	verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0);
2528ea8dc4b6Seschrock 
2529ea8dc4b6Seschrock 	/*
253055434c77Sek 	 * Fill in the nverrlistp with nvlist's of dataset and object numbers.
2531ea8dc4b6Seschrock 	 */
2532ea8dc4b6Seschrock 	for (i = 0; i < count; i++) {
2533ea8dc4b6Seschrock 		nvlist_t *nv;
2534ea8dc4b6Seschrock 
2535c0a81264Sek 		/* ignoring zb_blkid and zb_level for now */
2536c0a81264Sek 		if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset &&
2537c0a81264Sek 		    zb[i-1].zb_object == zb[i].zb_object)
2538ea8dc4b6Seschrock 			continue;
2539ea8dc4b6Seschrock 
254055434c77Sek 		if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0)
254155434c77Sek 			goto nomem;
254255434c77Sek 		if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET,
254355434c77Sek 		    zb[i].zb_objset) != 0) {
254455434c77Sek 			nvlist_free(nv);
254599653d4eSeschrock 			goto nomem;
2546ea8dc4b6Seschrock 		}
254755434c77Sek 		if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT,
254855434c77Sek 		    zb[i].zb_object) != 0) {
254955434c77Sek 			nvlist_free(nv);
255055434c77Sek 			goto nomem;
255155434c77Sek 		}
255255434c77Sek 		if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) {
255355434c77Sek 			nvlist_free(nv);
255455434c77Sek 			goto nomem;
255555434c77Sek 		}
255655434c77Sek 		nvlist_free(nv);
2557ea8dc4b6Seschrock 	}
2558ea8dc4b6Seschrock 
25593ccfa83cSahrens 	free((void *)(uintptr_t)zc.zc_nvlist_dst);
2560ea8dc4b6Seschrock 	return (0);
256199653d4eSeschrock 
256299653d4eSeschrock nomem:
2563e9dbad6fSeschrock 	free((void *)(uintptr_t)zc.zc_nvlist_dst);
256499653d4eSeschrock 	return (no_memory(zhp->zpool_hdl));
2565ea8dc4b6Seschrock }
2566eaca9bbdSeschrock 
2567eaca9bbdSeschrock /*
2568eaca9bbdSeschrock  * Upgrade a ZFS pool to the latest on-disk version.
2569eaca9bbdSeschrock  */
2570eaca9bbdSeschrock int
2571990b4856Slling zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version)
2572eaca9bbdSeschrock {
2573eaca9bbdSeschrock 	zfs_cmd_t zc = { 0 };
257499653d4eSeschrock 	libzfs_handle_t *hdl = zhp->zpool_hdl;
2575eaca9bbdSeschrock 
2576eaca9bbdSeschrock 	(void) strcpy(zc.zc_name, zhp->zpool_name);
2577990b4856Slling 	zc.zc_cookie = new_version;
2578990b4856Slling 
2579ecd6cf80Smarks 	if (zfs_ioctl(hdl, ZFS_IOC_POOL_UPGRADE, &zc) != 0)
2580ece3d9b3Slling 		return (zpool_standard_error_fmt(hdl, errno,
258199653d4eSeschrock 		    dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"),
258299653d4eSeschrock 		    zhp->zpool_name));
2583eaca9bbdSeschrock 	return (0);
2584eaca9bbdSeschrock }
258506eeb2adSek 
258606eeb2adSek void
25872a6b87f0Sek zpool_set_history_str(const char *subcommand, int argc, char **argv,
25882a6b87f0Sek     char *history_str)
258906eeb2adSek {
259006eeb2adSek 	int i;
259106eeb2adSek 
25922a6b87f0Sek 	(void) strlcpy(history_str, subcommand, HIS_MAX_RECORD_LEN);
25932a6b87f0Sek 	for (i = 1; i < argc; i++) {
25942a6b87f0Sek 		if (strlen(history_str) + 1 + strlen(argv[i]) >
25952a6b87f0Sek 		    HIS_MAX_RECORD_LEN)
25962a6b87f0Sek 			break;
25972a6b87f0Sek 		(void) strlcat(history_str, " ", HIS_MAX_RECORD_LEN);
25982a6b87f0Sek 		(void) strlcat(history_str, argv[i], HIS_MAX_RECORD_LEN);
25992a6b87f0Sek 	}
26002a6b87f0Sek }
26012a6b87f0Sek 
26022a6b87f0Sek /*
26032a6b87f0Sek  * Stage command history for logging.
26042a6b87f0Sek  */
26052a6b87f0Sek int
26062a6b87f0Sek zpool_stage_history(libzfs_handle_t *hdl, const char *history_str)
26072a6b87f0Sek {
26082a6b87f0Sek 	if (history_str == NULL)
26092a6b87f0Sek 		return (EINVAL);
26102a6b87f0Sek 
26112a6b87f0Sek 	if (strlen(history_str) > HIS_MAX_RECORD_LEN)
26122a6b87f0Sek 		return (EINVAL);
26132a6b87f0Sek 
2614228975ccSek 	if (hdl->libzfs_log_str != NULL)
2615ecd6cf80Smarks 		free(hdl->libzfs_log_str);
261606eeb2adSek 
26172a6b87f0Sek 	if ((hdl->libzfs_log_str = strdup(history_str)) == NULL)
26182a6b87f0Sek 		return (no_memory(hdl));
261906eeb2adSek 
26202a6b87f0Sek 	return (0);
262106eeb2adSek }
262206eeb2adSek 
262306eeb2adSek /*
262406eeb2adSek  * Perform ioctl to get some command history of a pool.
262506eeb2adSek  *
262606eeb2adSek  * 'buf' is the buffer to fill up to 'len' bytes.  'off' is the
262706eeb2adSek  * logical offset of the history buffer to start reading from.
262806eeb2adSek  *
262906eeb2adSek  * Upon return, 'off' is the next logical offset to read from and
263006eeb2adSek  * 'len' is the actual amount of bytes read into 'buf'.
263106eeb2adSek  */
263206eeb2adSek static int
263306eeb2adSek get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len)
263406eeb2adSek {
263506eeb2adSek 	zfs_cmd_t zc = { 0 };
263606eeb2adSek 	libzfs_handle_t *hdl = zhp->zpool_hdl;
263706eeb2adSek 
263806eeb2adSek 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
263906eeb2adSek 
264006eeb2adSek 	zc.zc_history = (uint64_t)(uintptr_t)buf;
264106eeb2adSek 	zc.zc_history_len = *len;
264206eeb2adSek 	zc.zc_history_offset = *off;
264306eeb2adSek 
264406eeb2adSek 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) {
264506eeb2adSek 		switch (errno) {
264606eeb2adSek 		case EPERM:
2647ece3d9b3Slling 			return (zfs_error_fmt(hdl, EZFS_PERM,
2648ece3d9b3Slling 			    dgettext(TEXT_DOMAIN,
264906eeb2adSek 			    "cannot show history for pool '%s'"),
265006eeb2adSek 			    zhp->zpool_name));
265106eeb2adSek 		case ENOENT:
2652ece3d9b3Slling 			return (zfs_error_fmt(hdl, EZFS_NOHISTORY,
265306eeb2adSek 			    dgettext(TEXT_DOMAIN, "cannot get history for pool "
265406eeb2adSek 			    "'%s'"), zhp->zpool_name));
2655d7306b64Sek 		case ENOTSUP:
2656d7306b64Sek 			return (zfs_error_fmt(hdl, EZFS_BADVERSION,
2657d7306b64Sek 			    dgettext(TEXT_DOMAIN, "cannot get history for pool "
2658d7306b64Sek 			    "'%s', pool must be upgraded"), zhp->zpool_name));
265906eeb2adSek 		default:
2660ece3d9b3Slling 			return (zpool_standard_error_fmt(hdl, errno,
266106eeb2adSek 			    dgettext(TEXT_DOMAIN,
266206eeb2adSek 			    "cannot get history for '%s'"), zhp->zpool_name));
266306eeb2adSek 		}
266406eeb2adSek 	}
266506eeb2adSek 
266606eeb2adSek 	*len = zc.zc_history_len;
266706eeb2adSek 	*off = zc.zc_history_offset;
266806eeb2adSek 
266906eeb2adSek 	return (0);
267006eeb2adSek }
267106eeb2adSek 
267206eeb2adSek /*
267306eeb2adSek  * Process the buffer of nvlists, unpacking and storing each nvlist record
267406eeb2adSek  * into 'records'.  'leftover' is set to the number of bytes that weren't
267506eeb2adSek  * processed as there wasn't a complete record.
267606eeb2adSek  */
267706eeb2adSek static int
267806eeb2adSek zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover,
267906eeb2adSek     nvlist_t ***records, uint_t *numrecords)
268006eeb2adSek {
268106eeb2adSek 	uint64_t reclen;
268206eeb2adSek 	nvlist_t *nv;
268306eeb2adSek 	int i;
268406eeb2adSek 
268506eeb2adSek 	while (bytes_read > sizeof (reclen)) {
268606eeb2adSek 
268706eeb2adSek 		/* get length of packed record (stored as little endian) */
268806eeb2adSek 		for (i = 0, reclen = 0; i < sizeof (reclen); i++)
268906eeb2adSek 			reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i);
269006eeb2adSek 
269106eeb2adSek 		if (bytes_read < sizeof (reclen) + reclen)
269206eeb2adSek 			break;
269306eeb2adSek 
269406eeb2adSek 		/* unpack record */
269506eeb2adSek 		if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0)
269606eeb2adSek 			return (ENOMEM);
269706eeb2adSek 		bytes_read -= sizeof (reclen) + reclen;
269806eeb2adSek 		buf += sizeof (reclen) + reclen;
269906eeb2adSek 
270006eeb2adSek 		/* add record to nvlist array */
270106eeb2adSek 		(*numrecords)++;
270206eeb2adSek 		if (ISP2(*numrecords + 1)) {
270306eeb2adSek 			*records = realloc(*records,
270406eeb2adSek 			    *numrecords * 2 * sizeof (nvlist_t *));
270506eeb2adSek 		}
270606eeb2adSek 		(*records)[*numrecords - 1] = nv;
270706eeb2adSek 	}
270806eeb2adSek 
270906eeb2adSek 	*leftover = bytes_read;
271006eeb2adSek 	return (0);
271106eeb2adSek }
271206eeb2adSek 
271306eeb2adSek #define	HIS_BUF_LEN	(128*1024)
271406eeb2adSek 
271506eeb2adSek /*
271606eeb2adSek  * Retrieve the command history of a pool.
271706eeb2adSek  */
271806eeb2adSek int
271906eeb2adSek zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
272006eeb2adSek {
272106eeb2adSek 	char buf[HIS_BUF_LEN];
272206eeb2adSek 	uint64_t off = 0;
272306eeb2adSek 	nvlist_t **records = NULL;
272406eeb2adSek 	uint_t numrecords = 0;
272506eeb2adSek 	int err, i;
272606eeb2adSek 
272706eeb2adSek 	do {
272806eeb2adSek 		uint64_t bytes_read = sizeof (buf);
272906eeb2adSek 		uint64_t leftover;
273006eeb2adSek 
273106eeb2adSek 		if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0)
273206eeb2adSek 			break;
273306eeb2adSek 
273406eeb2adSek 		/* if nothing else was read in, we're at EOF, just return */
273506eeb2adSek 		if (!bytes_read)
273606eeb2adSek 			break;
273706eeb2adSek 
273806eeb2adSek 		if ((err = zpool_history_unpack(buf, bytes_read,
273906eeb2adSek 		    &leftover, &records, &numrecords)) != 0)
274006eeb2adSek 			break;
274106eeb2adSek 		off -= leftover;
274206eeb2adSek 
274306eeb2adSek 		/* CONSTCOND */
274406eeb2adSek 	} while (1);
274506eeb2adSek 
274606eeb2adSek 	if (!err) {
274706eeb2adSek 		verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0);
274806eeb2adSek 		verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD,
274906eeb2adSek 		    records, numrecords) == 0);
275006eeb2adSek 	}
275106eeb2adSek 	for (i = 0; i < numrecords; i++)
275206eeb2adSek 		nvlist_free(records[i]);
275306eeb2adSek 	free(records);
275406eeb2adSek 
275506eeb2adSek 	return (err);
275606eeb2adSek }
275755434c77Sek 
275855434c77Sek void
275955434c77Sek zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
276055434c77Sek     char *pathname, size_t len)
276155434c77Sek {
276255434c77Sek 	zfs_cmd_t zc = { 0 };
276355434c77Sek 	boolean_t mounted = B_FALSE;
276455434c77Sek 	char *mntpnt = NULL;
276555434c77Sek 	char dsname[MAXNAMELEN];
276655434c77Sek 
276755434c77Sek 	if (dsobj == 0) {
276855434c77Sek 		/* special case for the MOS */
276955434c77Sek 		(void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj);
277055434c77Sek 		return;
277155434c77Sek 	}
277255434c77Sek 
277355434c77Sek 	/* get the dataset's name */
277455434c77Sek 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
277555434c77Sek 	zc.zc_obj = dsobj;
277655434c77Sek 	if (ioctl(zhp->zpool_hdl->libzfs_fd,
277755434c77Sek 	    ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) {
277855434c77Sek 		/* just write out a path of two object numbers */
277955434c77Sek 		(void) snprintf(pathname, len, "<0x%llx>:<0x%llx>",
278055434c77Sek 		    dsobj, obj);
278155434c77Sek 		return;
278255434c77Sek 	}
278355434c77Sek 	(void) strlcpy(dsname, zc.zc_value, sizeof (dsname));
278455434c77Sek 
278555434c77Sek 	/* find out if the dataset is mounted */
278655434c77Sek 	mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt);
278755434c77Sek 
278855434c77Sek 	/* get the corrupted object's path */
278955434c77Sek 	(void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name));
279055434c77Sek 	zc.zc_obj = obj;
279155434c77Sek 	if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH,
279255434c77Sek 	    &zc) == 0) {
279355434c77Sek 		if (mounted) {
279455434c77Sek 			(void) snprintf(pathname, len, "%s%s", mntpnt,
279555434c77Sek 			    zc.zc_value);
279655434c77Sek 		} else {
279755434c77Sek 			(void) snprintf(pathname, len, "%s:%s",
279855434c77Sek 			    dsname, zc.zc_value);
279955434c77Sek 		}
280055434c77Sek 	} else {
280155434c77Sek 		(void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj);
280255434c77Sek 	}
280355434c77Sek 	free(mntpnt);
280455434c77Sek }
2805b1b8ab34Slling 
28068488aeb5Staylor #define	RDISK_ROOT	"/dev/rdsk"
28078488aeb5Staylor #define	BACKUP_SLICE	"s2"
28088488aeb5Staylor /*
28098488aeb5Staylor  * Don't start the slice at the default block of 34; many storage
28108488aeb5Staylor  * devices will use a stripe width of 128k, so start there instead.
28118488aeb5Staylor  */
28128488aeb5Staylor #define	NEW_START_BLOCK	256
28138488aeb5Staylor 
281415e6edf1Sgw /*
281515e6edf1Sgw  * Read the EFI label from the config, if a label does not exist then
281615e6edf1Sgw  * pass back the error to the caller. If the caller has passed a non-NULL
281715e6edf1Sgw  * diskaddr argument then we set it to the starting address of the EFI
281815e6edf1Sgw  * partition.
281915e6edf1Sgw  */
282015e6edf1Sgw static int
282115e6edf1Sgw read_efi_label(nvlist_t *config, diskaddr_t *sb)
282215e6edf1Sgw {
282315e6edf1Sgw 	char *path;
282415e6edf1Sgw 	int fd;
282515e6edf1Sgw 	char diskname[MAXPATHLEN];
282615e6edf1Sgw 	int err = -1;
282715e6edf1Sgw 
282815e6edf1Sgw 	if (nvlist_lookup_string(config, ZPOOL_CONFIG_PATH, &path) != 0)
282915e6edf1Sgw 		return (err);
283015e6edf1Sgw 
283115e6edf1Sgw 	(void) snprintf(diskname, sizeof (diskname), "%s%s", RDISK_ROOT,
283215e6edf1Sgw 	    strrchr(path, '/'));
283315e6edf1Sgw 	if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) {
283415e6edf1Sgw 		struct dk_gpt *vtoc;
283515e6edf1Sgw 
283615e6edf1Sgw 		if ((err = efi_alloc_and_read(fd, &vtoc)) >= 0) {
283715e6edf1Sgw 			if (sb != NULL)
283815e6edf1Sgw 				*sb = vtoc->efi_parts[0].p_start;
283915e6edf1Sgw 			efi_free(vtoc);
284015e6edf1Sgw 		}
284115e6edf1Sgw 		(void) close(fd);
284215e6edf1Sgw 	}
284315e6edf1Sgw 	return (err);
284415e6edf1Sgw }
284515e6edf1Sgw 
28468488aeb5Staylor /*
28478488aeb5Staylor  * determine where a partition starts on a disk in the current
28488488aeb5Staylor  * configuration
28498488aeb5Staylor  */
28508488aeb5Staylor static diskaddr_t
28518488aeb5Staylor find_start_block(nvlist_t *config)
28528488aeb5Staylor {
28538488aeb5Staylor 	nvlist_t **child;
28548488aeb5Staylor 	uint_t c, children;
28558488aeb5Staylor 	diskaddr_t sb = MAXOFFSET_T;
28568488aeb5Staylor 	uint64_t wholedisk;
28578488aeb5Staylor 
28588488aeb5Staylor 	if (nvlist_lookup_nvlist_array(config,
28598488aeb5Staylor 	    ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) {
28608488aeb5Staylor 		if (nvlist_lookup_uint64(config,
28618488aeb5Staylor 		    ZPOOL_CONFIG_WHOLE_DISK,
28628488aeb5Staylor 		    &wholedisk) != 0 || !wholedisk) {
28638488aeb5Staylor 			return (MAXOFFSET_T);
28648488aeb5Staylor 		}
286515e6edf1Sgw 		if (read_efi_label(config, &sb) < 0)
286615e6edf1Sgw 			sb = MAXOFFSET_T;
28678488aeb5Staylor 		return (sb);
28688488aeb5Staylor 	}
28698488aeb5Staylor 
28708488aeb5Staylor 	for (c = 0; c < children; c++) {
28718488aeb5Staylor 		sb = find_start_block(child[c]);
28728488aeb5Staylor 		if (sb != MAXOFFSET_T) {
28738488aeb5Staylor 			return (sb);
28748488aeb5Staylor 		}
28758488aeb5Staylor 	}
28768488aeb5Staylor 	return (MAXOFFSET_T);
28778488aeb5Staylor }
28788488aeb5Staylor 
28798488aeb5Staylor /*
28808488aeb5Staylor  * Label an individual disk.  The name provided is the short name,
28818488aeb5Staylor  * stripped of any leading /dev path.
28828488aeb5Staylor  */
28838488aeb5Staylor int
28848488aeb5Staylor zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
28858488aeb5Staylor {
28868488aeb5Staylor 	char path[MAXPATHLEN];
28878488aeb5Staylor 	struct dk_gpt *vtoc;
28888488aeb5Staylor 	int fd;
28898488aeb5Staylor 	size_t resv = EFI_MIN_RESV_SIZE;
28908488aeb5Staylor 	uint64_t slice_size;
28918488aeb5Staylor 	diskaddr_t start_block;
28928488aeb5Staylor 	char errbuf[1024];
28938488aeb5Staylor 
2894c6ef114fSmmusante 	/* prepare an error message just in case */
2895c6ef114fSmmusante 	(void) snprintf(errbuf, sizeof (errbuf),
2896c6ef114fSmmusante 	    dgettext(TEXT_DOMAIN, "cannot label '%s'"), name);
2897c6ef114fSmmusante 
28988488aeb5Staylor 	if (zhp) {
28998488aeb5Staylor 		nvlist_t *nvroot;
29008488aeb5Staylor 
2901b5b76fecSGeorge Wilson 		if (pool_is_bootable(zhp)) {
2902b5b76fecSGeorge Wilson 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2903b5b76fecSGeorge Wilson 			    "EFI labeled devices are not supported on root "
2904b5b76fecSGeorge Wilson 			    "pools."));
2905b5b76fecSGeorge Wilson 			return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf));
2906b5b76fecSGeorge Wilson 		}
2907b5b76fecSGeorge Wilson 
29088488aeb5Staylor 		verify(nvlist_lookup_nvlist(zhp->zpool_config,
29098488aeb5Staylor 		    ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
29108488aeb5Staylor 
29118488aeb5Staylor 		if (zhp->zpool_start_block == 0)
29128488aeb5Staylor 			start_block = find_start_block(nvroot);
29138488aeb5Staylor 		else
29148488aeb5Staylor 			start_block = zhp->zpool_start_block;
29158488aeb5Staylor 		zhp->zpool_start_block = start_block;
29168488aeb5Staylor 	} else {
29178488aeb5Staylor 		/* new pool */
29188488aeb5Staylor 		start_block = NEW_START_BLOCK;
29198488aeb5Staylor 	}
29208488aeb5Staylor 
29218488aeb5Staylor 	(void) snprintf(path, sizeof (path), "%s/%s%s", RDISK_ROOT, name,
29228488aeb5Staylor 	    BACKUP_SLICE);
29238488aeb5Staylor 
29248488aeb5Staylor 	if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) {
29258488aeb5Staylor 		/*
29268488aeb5Staylor 		 * This shouldn't happen.  We've long since verified that this
29278488aeb5Staylor 		 * is a valid device.
29288488aeb5Staylor 		 */
2929c6ef114fSmmusante 		zfs_error_aux(hdl,
2930c6ef114fSmmusante 		    dgettext(TEXT_DOMAIN, "unable to open device"));
29318488aeb5Staylor 		return (zfs_error(hdl, EZFS_OPENFAILED, errbuf));
29328488aeb5Staylor 	}
29338488aeb5Staylor 
29348488aeb5Staylor 	if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) {
29358488aeb5Staylor 		/*
29368488aeb5Staylor 		 * The only way this can fail is if we run out of memory, or we
29378488aeb5Staylor 		 * were unable to read the disk's capacity
29388488aeb5Staylor 		 */
29398488aeb5Staylor 		if (errno == ENOMEM)
29408488aeb5Staylor 			(void) no_memory(hdl);
29418488aeb5Staylor 
29428488aeb5Staylor 		(void) close(fd);
2943c6ef114fSmmusante 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2944c6ef114fSmmusante 		    "unable to read disk capacity"), name);
29458488aeb5Staylor 
29468488aeb5Staylor 		return (zfs_error(hdl, EZFS_NOCAP, errbuf));
29478488aeb5Staylor 	}
29488488aeb5Staylor 
29498488aeb5Staylor 	slice_size = vtoc->efi_last_u_lba + 1;
29508488aeb5Staylor 	slice_size -= EFI_MIN_RESV_SIZE;
29518488aeb5Staylor 	if (start_block == MAXOFFSET_T)
29528488aeb5Staylor 		start_block = NEW_START_BLOCK;
29538488aeb5Staylor 	slice_size -= start_block;
29548488aeb5Staylor 
29558488aeb5Staylor 	vtoc->efi_parts[0].p_start = start_block;
29568488aeb5Staylor 	vtoc->efi_parts[0].p_size = slice_size;
29578488aeb5Staylor 
29588488aeb5Staylor 	/*
29598488aeb5Staylor 	 * Why we use V_USR: V_BACKUP confuses users, and is considered
29608488aeb5Staylor 	 * disposable by some EFI utilities (since EFI doesn't have a backup
29618488aeb5Staylor 	 * slice).  V_UNASSIGNED is supposed to be used only for zero size
29628488aeb5Staylor 	 * partitions, and efi_write() will fail if we use it.  V_ROOT, V_BOOT,
29638488aeb5Staylor 	 * etc. were all pretty specific.  V_USR is as close to reality as we
29648488aeb5Staylor 	 * can get, in the absence of V_OTHER.
29658488aeb5Staylor 	 */
29668488aeb5Staylor 	vtoc->efi_parts[0].p_tag = V_USR;
29678488aeb5Staylor 	(void) strcpy(vtoc->efi_parts[0].p_name, "zfs");
29688488aeb5Staylor 
29698488aeb5Staylor 	vtoc->efi_parts[8].p_start = slice_size + start_block;
29708488aeb5Staylor 	vtoc->efi_parts[8].p_size = resv;
29718488aeb5Staylor 	vtoc->efi_parts[8].p_tag = V_RESERVED;
29728488aeb5Staylor 
29738488aeb5Staylor 	if (efi_write(fd, vtoc) != 0) {
29748488aeb5Staylor 		/*
29758488aeb5Staylor 		 * Some block drivers (like pcata) may not support EFI
29768488aeb5Staylor 		 * GPT labels.  Print out a helpful error message dir-
29778488aeb5Staylor 		 * ecting the user to manually label the disk and give
29788488aeb5Staylor 		 * a specific slice.
29798488aeb5Staylor 		 */
29808488aeb5Staylor 		(void) close(fd);
29818488aeb5Staylor 		efi_free(vtoc);
29828488aeb5Staylor 
29838488aeb5Staylor 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2984c6ef114fSmmusante 		    "try using fdisk(1M) and then provide a specific slice"));
29858488aeb5Staylor 		return (zfs_error(hdl, EZFS_LABELFAILED, errbuf));
29868488aeb5Staylor 	}
29878488aeb5Staylor 
29888488aeb5Staylor 	(void) close(fd);
29898488aeb5Staylor 	efi_free(vtoc);
29908488aeb5Staylor 	return (0);
29918488aeb5Staylor }
2992e7cbe64fSgw 
2993e7cbe64fSgw static boolean_t
2994e7cbe64fSgw supported_dump_vdev_type(libzfs_handle_t *hdl, nvlist_t *config, char *errbuf)
2995e7cbe64fSgw {
2996e7cbe64fSgw 	char *type;
2997e7cbe64fSgw 	nvlist_t **child;
2998e7cbe64fSgw 	uint_t children, c;
2999e7cbe64fSgw 
3000e7cbe64fSgw 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_TYPE, &type) == 0);
3001e7cbe64fSgw 	if (strcmp(type, VDEV_TYPE_RAIDZ) == 0 ||
3002e7cbe64fSgw 	    strcmp(type, VDEV_TYPE_FILE) == 0 ||
3003e7cbe64fSgw 	    strcmp(type, VDEV_TYPE_LOG) == 0 ||
3004e7cbe64fSgw 	    strcmp(type, VDEV_TYPE_MISSING) == 0) {
3005e7cbe64fSgw 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3006e7cbe64fSgw 		    "vdev type '%s' is not supported"), type);
3007e7cbe64fSgw 		(void) zfs_error(hdl, EZFS_VDEVNOTSUP, errbuf);
3008e7cbe64fSgw 		return (B_FALSE);
3009e7cbe64fSgw 	}
3010e7cbe64fSgw 	if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN,
3011e7cbe64fSgw 	    &child, &children) == 0) {
3012e7cbe64fSgw 		for (c = 0; c < children; c++) {
3013e7cbe64fSgw 			if (!supported_dump_vdev_type(hdl, child[c], errbuf))
3014e7cbe64fSgw 				return (B_FALSE);
3015e7cbe64fSgw 		}
3016e7cbe64fSgw 	}
3017e7cbe64fSgw 	return (B_TRUE);
3018e7cbe64fSgw }
3019e7cbe64fSgw 
3020e7cbe64fSgw /*
3021e7cbe64fSgw  * check if this zvol is allowable for use as a dump device; zero if
3022e7cbe64fSgw  * it is, > 0 if it isn't, < 0 if it isn't a zvol
3023e7cbe64fSgw  */
3024e7cbe64fSgw int
3025e7cbe64fSgw zvol_check_dump_config(char *arg)
3026e7cbe64fSgw {
3027e7cbe64fSgw 	zpool_handle_t *zhp = NULL;
3028e7cbe64fSgw 	nvlist_t *config, *nvroot;
3029e7cbe64fSgw 	char *p, *volname;
3030e7cbe64fSgw 	nvlist_t **top;
3031e7cbe64fSgw 	uint_t toplevels;
3032e7cbe64fSgw 	libzfs_handle_t *hdl;
3033e7cbe64fSgw 	char errbuf[1024];
3034e7cbe64fSgw 	char poolname[ZPOOL_MAXNAMELEN];
3035e7cbe64fSgw 	int pathlen = strlen(ZVOL_FULL_DEV_DIR);
3036e7cbe64fSgw 	int ret = 1;
3037e7cbe64fSgw 
3038e7cbe64fSgw 	if (strncmp(arg, ZVOL_FULL_DEV_DIR, pathlen)) {
3039e7cbe64fSgw 		return (-1);
3040e7cbe64fSgw 	}
3041e7cbe64fSgw 
3042e7cbe64fSgw 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3043e7cbe64fSgw 	    "dump is not supported on device '%s'"), arg);
3044e7cbe64fSgw 
3045e7cbe64fSgw 	if ((hdl = libzfs_init()) == NULL)
3046e7cbe64fSgw 		return (1);
3047e7cbe64fSgw 	libzfs_print_on_error(hdl, B_TRUE);
3048e7cbe64fSgw 
3049e7cbe64fSgw 	volname = arg + pathlen;
3050e7cbe64fSgw 
3051e7cbe64fSgw 	/* check the configuration of the pool */
3052e7cbe64fSgw 	if ((p = strchr(volname, '/')) == NULL) {
3053e7cbe64fSgw 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3054e7cbe64fSgw 		    "malformed dataset name"));
3055e7cbe64fSgw 		(void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
3056e7cbe64fSgw 		return (1);
3057e7cbe64fSgw 	} else if (p - volname >= ZFS_MAXNAMELEN) {
3058e7cbe64fSgw 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3059e7cbe64fSgw 		    "dataset name is too long"));
3060e7cbe64fSgw 		(void) zfs_error(hdl, EZFS_NAMETOOLONG, errbuf);
3061e7cbe64fSgw 		return (1);
3062e7cbe64fSgw 	} else {
3063e7cbe64fSgw 		(void) strncpy(poolname, volname, p - volname);
3064e7cbe64fSgw 		poolname[p - volname] = '\0';
3065e7cbe64fSgw 	}
3066e7cbe64fSgw 
3067e7cbe64fSgw 	if ((zhp = zpool_open(hdl, poolname)) == NULL) {
3068e7cbe64fSgw 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3069e7cbe64fSgw 		    "could not open pool '%s'"), poolname);
3070e7cbe64fSgw 		(void) zfs_error(hdl, EZFS_OPENFAILED, errbuf);
3071e7cbe64fSgw 		goto out;
3072e7cbe64fSgw 	}
3073e7cbe64fSgw 	config = zpool_get_config(zhp, NULL);
3074e7cbe64fSgw 	if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3075e7cbe64fSgw 	    &nvroot) != 0) {
3076e7cbe64fSgw 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3077e7cbe64fSgw 		    "could not obtain vdev configuration for  '%s'"), poolname);
3078e7cbe64fSgw 		(void) zfs_error(hdl, EZFS_INVALCONFIG, errbuf);
3079e7cbe64fSgw 		goto out;
3080e7cbe64fSgw 	}
3081e7cbe64fSgw 
3082e7cbe64fSgw 	verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
3083e7cbe64fSgw 	    &top, &toplevels) == 0);
3084e7cbe64fSgw 	if (toplevels != 1) {
3085e7cbe64fSgw 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3086e7cbe64fSgw 		    "'%s' has multiple top level vdevs"), poolname);
3087e7cbe64fSgw 		(void) zfs_error(hdl, EZFS_DEVOVERFLOW, errbuf);
3088e7cbe64fSgw 		goto out;
3089e7cbe64fSgw 	}
3090e7cbe64fSgw 
3091e7cbe64fSgw 	if (!supported_dump_vdev_type(hdl, top[0], errbuf)) {
3092e7cbe64fSgw 		goto out;
3093e7cbe64fSgw 	}
3094e7cbe64fSgw 	ret = 0;
3095e7cbe64fSgw 
3096e7cbe64fSgw out:
3097e7cbe64fSgw 	if (zhp)
3098e7cbe64fSgw 		zpool_close(zhp);
3099e7cbe64fSgw 	libzfs_fini(hdl);
3100e7cbe64fSgw 	return (ret);
3101e7cbe64fSgw }
3102