1789Sahrens /*
2789Sahrens  * CDDL HEADER START
3789Sahrens  *
4789Sahrens  * The contents of this file are subject to the terms of the
5789Sahrens  * Common Development and Distribution License, Version 1.0 only
6789Sahrens  * (the "License").  You may not use this file except in compliance
7789Sahrens  * with the License.
8789Sahrens  *
9789Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10789Sahrens  * or http://www.opensolaris.org/os/licensing.
11789Sahrens  * See the License for the specific language governing permissions
12789Sahrens  * and limitations under the License.
13789Sahrens  *
14789Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
15789Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16789Sahrens  * If applicable, add the following below this CDDL HEADER, with the
17789Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
18789Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
19789Sahrens  *
20789Sahrens  * CDDL HEADER END
21789Sahrens  */
22789Sahrens /*
23789Sahrens  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24789Sahrens  * Use is subject to license terms.
25789Sahrens  */
26789Sahrens 
27789Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
28789Sahrens 
29789Sahrens #include <assert.h>
30789Sahrens #include <ctype.h>
31789Sahrens #include <errno.h>
32789Sahrens #include <devid.h>
33789Sahrens #include <fcntl.h>
34789Sahrens #include <libintl.h>
35789Sahrens #include <stdio.h>
36789Sahrens #include <stdlib.h>
37789Sahrens #include <string.h>
38789Sahrens #include <unistd.h>
39789Sahrens #include <sys/zfs_ioctl.h>
40789Sahrens 
41789Sahrens #include "zfs_namecheck.h"
42789Sahrens #include "libzfs_impl.h"
43789Sahrens 
44789Sahrens /*
45789Sahrens  * Validate the given pool name, optionally putting an extended error message in
46789Sahrens  * 'buf'.
47789Sahrens  */
48789Sahrens static int
49789Sahrens zpool_name_valid(const char *pool, char *buf, size_t buflen)
50789Sahrens {
51789Sahrens 	namecheck_err_t why;
52789Sahrens 	char what;
53789Sahrens 
54789Sahrens 	if (strlen(pool) >= ZPOOL_MAXNAMELEN) {
55789Sahrens 		if (buf)
56789Sahrens 			(void) snprintf(buf, buflen,
57789Sahrens 			    dgettext(TEXT_DOMAIN, "name is too long"));
58789Sahrens 		return (FALSE);
59789Sahrens 	}
60789Sahrens 
61789Sahrens 	if (pool_namecheck(pool, &why, &what) != 0) {
62789Sahrens 		if (buf != NULL) {
63789Sahrens 			switch (why) {
64789Sahrens 			case NAME_ERR_INVALCHAR:
65789Sahrens 				(void) snprintf(buf, buflen,
66789Sahrens 				    dgettext(TEXT_DOMAIN, "invalid character "
67789Sahrens 				    "'%c' in pool name"), what);
68789Sahrens 				break;
69789Sahrens 
70789Sahrens 			case NAME_ERR_NOLETTER:
71789Sahrens 				(void) strlcpy(buf, dgettext(TEXT_DOMAIN,
72789Sahrens 				    "name must begin with a letter"), buflen);
73789Sahrens 				break;
74789Sahrens 
75789Sahrens 			case NAME_ERR_RESERVED:
76789Sahrens 				(void) strlcpy(buf, dgettext(TEXT_DOMAIN,
77789Sahrens 				    "name is reserved\n"
78789Sahrens 				    "pool name may have been omitted"), buflen);
79789Sahrens 				break;
80789Sahrens 
81789Sahrens 			case NAME_ERR_DISKLIKE:
82789Sahrens 				(void) strlcpy(buf, dgettext(TEXT_DOMAIN,
83789Sahrens 				    "pool name is reserved\n"
84789Sahrens 				    "pool name may have been omitted"), buflen);
85789Sahrens 				break;
86789Sahrens 			}
87789Sahrens 		}
88789Sahrens 		return (FALSE);
89789Sahrens 	}
90789Sahrens 
91789Sahrens 	return (TRUE);
92789Sahrens }
93789Sahrens 
94789Sahrens /*
95789Sahrens  * Set the pool-wide health based on the vdev state of the root vdev.
96789Sahrens  */
97789Sahrens void
98789Sahrens set_pool_health(nvlist_t *config)
99789Sahrens {
100789Sahrens 	nvlist_t *nvroot;
101789Sahrens 	vdev_stat_t *vs;
102789Sahrens 	uint_t vsc;
103789Sahrens 	char *health;
104789Sahrens 
105789Sahrens 	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
106789Sahrens 	    &nvroot) == 0);
107789Sahrens 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
108789Sahrens 	    (uint64_t **)&vs, &vsc) == 0);
109789Sahrens 
110789Sahrens 	switch (vs->vs_state) {
111789Sahrens 
112789Sahrens 	case VDEV_STATE_CLOSED:
113789Sahrens 	case VDEV_STATE_CANT_OPEN:
114789Sahrens 	case VDEV_STATE_OFFLINE:
115789Sahrens 		health = dgettext(TEXT_DOMAIN, "FAULTED");
116789Sahrens 		break;
117789Sahrens 
118789Sahrens 	case VDEV_STATE_DEGRADED:
119789Sahrens 		health = dgettext(TEXT_DOMAIN, "DEGRADED");
120789Sahrens 		break;
121789Sahrens 
122789Sahrens 	case VDEV_STATE_HEALTHY:
123789Sahrens 		health = dgettext(TEXT_DOMAIN, "ONLINE");
124789Sahrens 		break;
125789Sahrens 
126789Sahrens 	default:
127789Sahrens 		zfs_baderror(vs->vs_state);
128789Sahrens 	}
129789Sahrens 
130789Sahrens 	verify(nvlist_add_string(config, ZPOOL_CONFIG_POOL_HEALTH,
131789Sahrens 	    health) == 0);
132789Sahrens }
133789Sahrens 
134789Sahrens /*
135789Sahrens  * Open a handle to the given pool, even if the pool is currently in the FAULTED
136789Sahrens  * state.
137789Sahrens  */
138789Sahrens zpool_handle_t *
139789Sahrens zpool_open_canfail(const char *pool)
140789Sahrens {
141789Sahrens 	zpool_handle_t *zhp;
142789Sahrens 	int error;
143789Sahrens 
144789Sahrens 	/*
145789Sahrens 	 * Make sure the pool name is valid.
146789Sahrens 	 */
147789Sahrens 	if (!zpool_name_valid(pool, NULL, 0)) {
148789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': invalid "
149789Sahrens 		    "pool name"), pool);
150789Sahrens 		return (NULL);
151789Sahrens 	}
152789Sahrens 
153789Sahrens 	zhp = zfs_malloc(sizeof (zpool_handle_t));
154789Sahrens 
155789Sahrens 	(void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
156789Sahrens 
157*952Seschrock 	if ((error = zpool_refresh_stats(zhp)) != 0) {
158789Sahrens 		if (error == ENOENT || error == EINVAL) {
159789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': no "
160789Sahrens 			    "such pool"), pool);
161789Sahrens 			free(zhp);
162789Sahrens 			return (NULL);
163789Sahrens 		} else {
164789Sahrens 			zhp->zpool_state = POOL_STATE_UNAVAIL;
165789Sahrens 		}
166789Sahrens 	} else {
167789Sahrens 		zhp->zpool_state = POOL_STATE_ACTIVE;
168789Sahrens 	}
169789Sahrens 
170789Sahrens 	return (zhp);
171789Sahrens }
172789Sahrens 
173789Sahrens /*
174789Sahrens  * Like the above, but silent on error.  Used when iterating over pools (because
175789Sahrens  * the configuration cache may be out of date).
176789Sahrens  */
177789Sahrens zpool_handle_t *
178789Sahrens zpool_open_silent(const char *pool)
179789Sahrens {
180789Sahrens 	zpool_handle_t *zhp;
181789Sahrens 	int error;
182789Sahrens 
183789Sahrens 	zhp = zfs_malloc(sizeof (zpool_handle_t));
184789Sahrens 
185789Sahrens 	(void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
186789Sahrens 
187*952Seschrock 	if ((error = zpool_refresh_stats(zhp)) != 0) {
188789Sahrens 		if (error == ENOENT || error == EINVAL) {
189789Sahrens 			free(zhp);
190789Sahrens 			return (NULL);
191789Sahrens 		} else {
192789Sahrens 			zhp->zpool_state = POOL_STATE_UNAVAIL;
193789Sahrens 		}
194789Sahrens 	} else {
195789Sahrens 		zhp->zpool_state = POOL_STATE_ACTIVE;
196789Sahrens 	}
197789Sahrens 
198789Sahrens 	return (zhp);
199789Sahrens }
200789Sahrens 
201789Sahrens /*
202789Sahrens  * Similar to zpool_open_canfail(), but refuses to open pools in the faulted
203789Sahrens  * state.
204789Sahrens  */
205789Sahrens zpool_handle_t *
206789Sahrens zpool_open(const char *pool)
207789Sahrens {
208789Sahrens 	zpool_handle_t *zhp;
209789Sahrens 
210789Sahrens 	if ((zhp = zpool_open_canfail(pool)) == NULL)
211789Sahrens 		return (NULL);
212789Sahrens 
213789Sahrens 	if (zhp->zpool_state == POOL_STATE_UNAVAIL) {
214789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "cannot open ' %s': pool is "
215789Sahrens 		    "currently unavailable\n"), zhp->zpool_name);
216789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "run 'zpool status -v %s' for "
217789Sahrens 		    "detailed information\n"), zhp->zpool_name);
218789Sahrens 		zpool_close(zhp);
219789Sahrens 		return (NULL);
220789Sahrens 	}
221789Sahrens 
222789Sahrens 	return (zhp);
223789Sahrens }
224789Sahrens 
225789Sahrens /*
226789Sahrens  * Close the handle.  Simply frees the memory associated with the handle.
227789Sahrens  */
228789Sahrens void
229789Sahrens zpool_close(zpool_handle_t *zhp)
230789Sahrens {
231789Sahrens 	if (zhp->zpool_config)
232789Sahrens 		nvlist_free(zhp->zpool_config);
233*952Seschrock 	if (zhp->zpool_old_config)
234*952Seschrock 		nvlist_free(zhp->zpool_old_config);
235789Sahrens 	free(zhp);
236789Sahrens }
237789Sahrens 
238789Sahrens /*
239789Sahrens  * Return the name of the pool.
240789Sahrens  */
241789Sahrens const char *
242789Sahrens zpool_get_name(zpool_handle_t *zhp)
243789Sahrens {
244789Sahrens 	return (zhp->zpool_name);
245789Sahrens }
246789Sahrens 
247789Sahrens /*
248789Sahrens  * Return the GUID of the pool.
249789Sahrens  */
250789Sahrens uint64_t
251789Sahrens zpool_get_guid(zpool_handle_t *zhp)
252789Sahrens {
253789Sahrens 	uint64_t guid;
254789Sahrens 
255789Sahrens 	verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID,
256789Sahrens 	    &guid) == 0);
257789Sahrens 	return (guid);
258789Sahrens }
259789Sahrens 
260789Sahrens /*
261789Sahrens  * Return the amount of space currently consumed by the pool.
262789Sahrens  */
263789Sahrens uint64_t
264789Sahrens zpool_get_space_used(zpool_handle_t *zhp)
265789Sahrens {
266789Sahrens 	nvlist_t *nvroot;
267789Sahrens 	vdev_stat_t *vs;
268789Sahrens 	uint_t vsc;
269789Sahrens 
270789Sahrens 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
271789Sahrens 	    &nvroot) == 0);
272789Sahrens 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
273789Sahrens 	    (uint64_t **)&vs, &vsc) == 0);
274789Sahrens 
275789Sahrens 	return (vs->vs_alloc);
276789Sahrens }
277789Sahrens 
278789Sahrens /*
279789Sahrens  * Return the total space in the pool.
280789Sahrens  */
281789Sahrens uint64_t
282789Sahrens zpool_get_space_total(zpool_handle_t *zhp)
283789Sahrens {
284789Sahrens 	nvlist_t *nvroot;
285789Sahrens 	vdev_stat_t *vs;
286789Sahrens 	uint_t vsc;
287789Sahrens 
288789Sahrens 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
289789Sahrens 	    &nvroot) == 0);
290789Sahrens 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
291789Sahrens 	    (uint64_t **)&vs, &vsc) == 0);
292789Sahrens 
293789Sahrens 	return (vs->vs_space);
294789Sahrens }
295789Sahrens 
296789Sahrens /*
297789Sahrens  * Return the alternate root for this pool, if any.
298789Sahrens  */
299789Sahrens int
300789Sahrens zpool_get_root(zpool_handle_t *zhp, char *buf, size_t buflen)
301789Sahrens {
302789Sahrens 	zfs_cmd_t zc = { 0 };
303789Sahrens 
304789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
305789Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 ||
306789Sahrens 	    zc.zc_objset_stats.dds_altroot[0] == '\0')
307789Sahrens 		return (-1);
308789Sahrens 
309789Sahrens 	(void) strlcpy(buf, zc.zc_objset_stats.dds_altroot, buflen);
310789Sahrens 
311789Sahrens 	return (0);
312789Sahrens }
313789Sahrens 
314789Sahrens /*
315789Sahrens  * Return the state of the pool (ACTIVE or UNAVAILABLE)
316789Sahrens  */
317789Sahrens int
318789Sahrens zpool_get_state(zpool_handle_t *zhp)
319789Sahrens {
320789Sahrens 	return (zhp->zpool_state);
321789Sahrens }
322789Sahrens 
323789Sahrens /*
324789Sahrens  * Create the named pool, using the provided vdev list.  It is assumed
325789Sahrens  * that the consumer has already validated the contents of the nvlist, so we
326789Sahrens  * don't have to worry about error semantics.
327789Sahrens  */
328789Sahrens int
329789Sahrens zpool_create(const char *pool, nvlist_t *nvroot, const char *altroot)
330789Sahrens {
331789Sahrens 	zfs_cmd_t zc = { 0 };
332789Sahrens 	char *packed;
333789Sahrens 	size_t len;
334789Sahrens 	int err;
335789Sahrens 	char reason[64];
336789Sahrens 
337789Sahrens 	if (!zpool_name_valid(pool, reason, sizeof (reason))) {
338789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': %s"),
339789Sahrens 		    pool, reason);
340789Sahrens 		return (-1);
341789Sahrens 	}
342789Sahrens 
343789Sahrens 	if (altroot != NULL && altroot[0] != '/') {
344789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': alternate "
345789Sahrens 		    "root '%s' must be a complete path"), pool, altroot);
346789Sahrens 		return (-1);
347789Sahrens 	}
348789Sahrens 
349789Sahrens 	if ((err = nvlist_size(nvroot, &len, NV_ENCODE_NATIVE)) != 0)
350789Sahrens 		zfs_baderror(err);
351789Sahrens 
352789Sahrens 	packed = zfs_malloc(len);
353789Sahrens 
354789Sahrens 	if ((err = nvlist_pack(nvroot, &packed, &len,
355789Sahrens 	    NV_ENCODE_NATIVE, 0)) != 0)
356789Sahrens 		zfs_baderror(err);
357789Sahrens 
358789Sahrens 	(void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name));
359789Sahrens 	zc.zc_config_src = (uint64_t)(uintptr_t)packed;
360789Sahrens 	zc.zc_config_src_size = len;
361789Sahrens 
362789Sahrens 	if (altroot != NULL)
363789Sahrens 		(void) strlcpy(zc.zc_root, altroot, sizeof (zc.zc_root));
364789Sahrens 
365789Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) {
366789Sahrens 		switch (errno) {
367789Sahrens 		case EEXIST:
368789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': "
369789Sahrens 			    "pool exists"), pool);
370789Sahrens 			break;
371789Sahrens 
372789Sahrens 		case EPERM:
373789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': "
374789Sahrens 			    "permission denied"), pool);
375789Sahrens 			break;
376789Sahrens 
377789Sahrens 		case EBUSY:
378789Sahrens 			/*
379789Sahrens 			 * This can happen if the user has specified the same
380789Sahrens 			 * device multiple times.  We can't reliably detect this
381789Sahrens 			 * until we try to add it and see we already have a
382789Sahrens 			 * label.
383789Sahrens 			 */
384789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': "
385789Sahrens 			    "one or more vdevs refer to the same device"),
386789Sahrens 			    pool);
387789Sahrens 			break;
388789Sahrens 
389789Sahrens 		case EOVERFLOW:
390789Sahrens 			/*
391789Sahrens 			 * This occurrs when one of the devices is below
392789Sahrens 			 * SPA_MINDEVSIZE.  Unfortunately, we can't detect which
393789Sahrens 			 * device was the problem device since there's no
394789Sahrens 			 * reliable way to determine device size from userland.
395789Sahrens 			 */
396789Sahrens 			{
397789Sahrens 				char buf[64];
398789Sahrens 
399789Sahrens 				zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
400789Sahrens 
401789Sahrens 				zfs_error(dgettext(TEXT_DOMAIN, "cannot "
402789Sahrens 				    "create '%s': one or more devices is less "
403789Sahrens 				    "than the minimum size (%s)"), pool,
404789Sahrens 				    buf);
405789Sahrens 			}
406789Sahrens 			break;
407789Sahrens 
408789Sahrens 		case ENAMETOOLONG:
409789Sahrens 			/*
410789Sahrens 			 * One of the vdevs has exceeded VDEV_SPEC_MAX length in
411789Sahrens 			 * its plaintext representation.
412789Sahrens 			 */
413789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': "
414789Sahrens 			    "too many devices in a single vdev"), pool);
415789Sahrens 			break;
416789Sahrens 
417789Sahrens 		case EIO:
418789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': "
419789Sahrens 			    "I/O error on one or more devices"), pool);
420789Sahrens 			break;
421789Sahrens 
422789Sahrens 		case ENXIO:
423789Sahrens 			/*
424789Sahrens 			 * This is unlikely to happen since we've verified that
425789Sahrens 			 * all the devices can be opened from userland, but it's
426789Sahrens 			 * still possible in some circumstances.
427789Sahrens 			 */
428789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': "
429789Sahrens 			    "one or more devices is unavailable"), pool);
430789Sahrens 			break;
431789Sahrens 
432789Sahrens 		case ENOSPC:
433789Sahrens 			/*
434789Sahrens 			 * This can occur if we were incapable of writing to a
435789Sahrens 			 * file vdev because the underlying filesystem is out of
436789Sahrens 			 * space.  This is very similar to EOVERFLOW, but we'll
437789Sahrens 			 * produce a slightly different message.
438789Sahrens 			 */
439789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': "
440789Sahrens 			    "one or more devices is out of space"), pool);
441789Sahrens 			break;
442789Sahrens 
443789Sahrens 		default:
444789Sahrens 			zfs_baderror(errno);
445789Sahrens 		}
446789Sahrens 
447789Sahrens 		return (-1);
448789Sahrens 	}
449789Sahrens 
450789Sahrens 	free(packed);
451789Sahrens 
452789Sahrens 	/*
453789Sahrens 	 * If this is an alternate root pool, then we automatically set the
454789Sahrens 	 * moutnpoint of the root dataset to be '/'.
455789Sahrens 	 */
456789Sahrens 	if (altroot != NULL) {
457789Sahrens 		zfs_handle_t *zhp;
458789Sahrens 
459789Sahrens 		verify((zhp = zfs_open(pool, ZFS_TYPE_ANY)) != NULL);
460789Sahrens 		verify(zfs_prop_set(zhp, ZFS_PROP_MOUNTPOINT, "/") == 0);
461789Sahrens 
462789Sahrens 		zfs_close(zhp);
463789Sahrens 	}
464789Sahrens 
465789Sahrens 	return (0);
466789Sahrens }
467789Sahrens 
468789Sahrens /*
469789Sahrens  * Destroy the given pool.  It is up to the caller to ensure that there are no
470789Sahrens  * datasets left in the pool.
471789Sahrens  */
472789Sahrens int
473789Sahrens zpool_destroy(zpool_handle_t *zhp)
474789Sahrens {
475789Sahrens 	zfs_cmd_t zc = { 0 };
476789Sahrens 	zfs_handle_t *zfp = NULL;
477789Sahrens 
478789Sahrens 	if (zhp->zpool_state == POOL_STATE_ACTIVE &&
479789Sahrens 	    (zfp = zfs_open(zhp->zpool_name, ZFS_TYPE_FILESYSTEM)) == NULL)
480789Sahrens 		return (-1);
481789Sahrens 
482789Sahrens 	if (zpool_remove_zvol_links(zhp) != NULL)
483789Sahrens 		return (-1);
484789Sahrens 
485789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
486789Sahrens 
487789Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
488789Sahrens 		switch (errno) {
489789Sahrens 		case EPERM:
490789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
491789Sahrens 			    "cannot destroy '%s': permission denied"),
492789Sahrens 			    zhp->zpool_name);
493789Sahrens 			break;
494789Sahrens 
495789Sahrens 		case EBUSY:
496789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
497789Sahrens 			    "cannot destroy '%s': pool busy"),
498789Sahrens 			    zhp->zpool_name);
499789Sahrens 			break;
500789Sahrens 
501789Sahrens 		case ENOENT:
502789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
503789Sahrens 			    "cannot destroy '%s': no such pool"),
504789Sahrens 			    zhp->zpool_name);
505789Sahrens 			break;
506789Sahrens 
507789Sahrens 		case EROFS:
508789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
509789Sahrens 			    "cannot destroy '%s': one or more devices is "
510789Sahrens 			    "read only, or '/' is mounted read only"),
511789Sahrens 			    zhp->zpool_name);
512789Sahrens 			break;
513789Sahrens 
514789Sahrens 		default:
515789Sahrens 			zfs_baderror(errno);
516789Sahrens 		}
517789Sahrens 
518789Sahrens 		if (zfp)
519789Sahrens 			zfs_close(zfp);
520789Sahrens 		return (-1);
521789Sahrens 	}
522789Sahrens 
523789Sahrens 	if (zfp) {
524789Sahrens 		remove_mountpoint(zfp);
525789Sahrens 		zfs_close(zfp);
526789Sahrens 	}
527789Sahrens 
528789Sahrens 	return (0);
529789Sahrens }
530789Sahrens 
531789Sahrens /*
532789Sahrens  * Add the given vdevs to the pool.  The caller must have already performed the
533789Sahrens  * necessary verification to ensure that the vdev specification is well-formed.
534789Sahrens  */
535789Sahrens int
536789Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
537789Sahrens {
538789Sahrens 	char *packed;
539789Sahrens 	size_t len;
540789Sahrens 	zfs_cmd_t zc;
541789Sahrens 
542789Sahrens 	verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0);
543789Sahrens 
544789Sahrens 	packed = zfs_malloc(len);
545789Sahrens 
546789Sahrens 	verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
547789Sahrens 
548789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
549789Sahrens 	zc.zc_config_src = (uint64_t)(uintptr_t)packed;
550789Sahrens 	zc.zc_config_src_size = len;
551789Sahrens 
552789Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) {
553789Sahrens 		switch (errno) {
554789Sahrens 		case EPERM:
555789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': "
556789Sahrens 			    "permission denied"), zhp->zpool_name);
557789Sahrens 			break;
558789Sahrens 
559789Sahrens 		case EBUSY:
560789Sahrens 			/*
561789Sahrens 			 * This can happen if the user has specified the same
562789Sahrens 			 * device multiple times.  We can't reliably detect this
563789Sahrens 			 * until we try to add it and see we already have a
564789Sahrens 			 * label.
565789Sahrens 			 */
566789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': "
567789Sahrens 			    "one or more vdevs refer to the same device"),
568789Sahrens 			    zhp->zpool_name);
569789Sahrens 			break;
570789Sahrens 
571789Sahrens 		case ENAMETOOLONG:
572789Sahrens 			/*
573789Sahrens 			 * One of the vdevs has exceeded VDEV_SPEC_MAX length in
574789Sahrens 			 * its plaintext representation.
575789Sahrens 			 */
576789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': "
577789Sahrens 			    "too many devices in a single vdev"),
578789Sahrens 			    zhp->zpool_name);
579789Sahrens 			break;
580789Sahrens 
581789Sahrens 		case ENXIO:
582789Sahrens 			/*
583789Sahrens 			 * This is unlikely to happen since we've verified that
584789Sahrens 			 * all the devices can be opened from userland, but it's
585789Sahrens 			 * still possible in some circumstances.
586789Sahrens 			 */
587789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': "
588789Sahrens 			    "one or more devices is unavailable"),
589789Sahrens 			    zhp->zpool_name);
590789Sahrens 			break;
591789Sahrens 
592789Sahrens 		case EOVERFLOW:
593789Sahrens 			/*
594789Sahrens 			 * This occurrs when one of the devices is below
595789Sahrens 			 * SPA_MINDEVSIZE.  Unfortunately, we can't detect which
596789Sahrens 			 * device was the problem device since there's no
597789Sahrens 			 * reliable way to determine device size from userland.
598789Sahrens 			 */
599789Sahrens 			{
600789Sahrens 				char buf[64];
601789Sahrens 
602789Sahrens 				zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
603789Sahrens 
604789Sahrens 				zfs_error(dgettext(TEXT_DOMAIN, "cannot "
605789Sahrens 				    "add to '%s': one or more devices is less "
606789Sahrens 				    "than the minimum size (%s)"),
607789Sahrens 				    zhp->zpool_name, buf);
608789Sahrens 			}
609789Sahrens 			break;
610789Sahrens 
611789Sahrens 		default:
612789Sahrens 			zfs_baderror(errno);
613789Sahrens 		}
614789Sahrens 
615789Sahrens 		return (-1);
616789Sahrens 	}
617789Sahrens 
618789Sahrens 	free(packed);
619789Sahrens 
620789Sahrens 	return (0);
621789Sahrens }
622789Sahrens 
623789Sahrens /*
624789Sahrens  * Exports the pool from the system.  The caller must ensure that there are no
625789Sahrens  * mounted datasets in the pool.
626789Sahrens  */
627789Sahrens int
628789Sahrens zpool_export(zpool_handle_t *zhp)
629789Sahrens {
630789Sahrens 	zfs_cmd_t zc = { 0 };
631789Sahrens 
632789Sahrens 	if (zpool_remove_zvol_links(zhp) != 0)
633789Sahrens 		return (-1);
634789Sahrens 
635789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
636789Sahrens 
637789Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_POOL_EXPORT, &zc) != 0) {
638789Sahrens 		switch (errno) {
639789Sahrens 		case EPERM:
640789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
641789Sahrens 			    "cannot export '%s': permission denied"),
642789Sahrens 			    zhp->zpool_name);
643789Sahrens 			break;
644789Sahrens 
645789Sahrens 		case EBUSY:
646789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
647789Sahrens 			    "cannot export '%s': pool is in use"),
648789Sahrens 			    zhp->zpool_name);
649789Sahrens 			break;
650789Sahrens 
651789Sahrens 		case ENOENT:
652789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
653789Sahrens 			    "cannot export '%s': no such pool"),
654789Sahrens 			    zhp->zpool_name);
655789Sahrens 			break;
656789Sahrens 
657789Sahrens 		default:
658789Sahrens 			zfs_baderror(errno);
659789Sahrens 		}
660789Sahrens 
661789Sahrens 		return (-1);
662789Sahrens 	}
663789Sahrens 
664789Sahrens 	return (0);
665789Sahrens }
666789Sahrens 
667789Sahrens /*
668789Sahrens  * Import the given pool using the known configuration.  The configuration
669789Sahrens  * should have come from zpool_find_import().  The 'newname' and 'altroot'
670789Sahrens  * parameters control whether the pool is imported with a different name or with
671789Sahrens  * an alternate root, respectively.
672789Sahrens  */
673789Sahrens int
674789Sahrens zpool_import(nvlist_t *config, const char *newname, const char *altroot)
675789Sahrens {
676789Sahrens 	zfs_cmd_t zc;
677789Sahrens 	char *packed;
678789Sahrens 	size_t len;
679789Sahrens 	char *thename;
680789Sahrens 	char *origname;
681789Sahrens 	int ret;
682789Sahrens 
683789Sahrens 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
684789Sahrens 	    &origname) == 0);
685789Sahrens 
686789Sahrens 	if (newname != NULL) {
687789Sahrens 		if (!zpool_name_valid(newname, NULL, 0)) {
688789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot import '%s': "
689789Sahrens 			    "invalid pool name"), newname);
690789Sahrens 			return (-1);
691789Sahrens 		}
692789Sahrens 		thename = (char *)newname;
693789Sahrens 	} else {
694789Sahrens 		thename = origname;
695789Sahrens 	}
696789Sahrens 
697789Sahrens 	if (altroot != NULL && altroot[0] != '/') {
698789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "cannot import '%s': alternate "
699789Sahrens 		    "root '%s' must be a complete path"), thename,
700789Sahrens 		    altroot);
701789Sahrens 		return (-1);
702789Sahrens 	}
703789Sahrens 
704789Sahrens 	(void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name));
705789Sahrens 
706789Sahrens 	if (altroot != NULL)
707789Sahrens 		(void) strlcpy(zc.zc_root, altroot, sizeof (zc.zc_root));
708789Sahrens 	else
709789Sahrens 		zc.zc_root[0] = '\0';
710789Sahrens 
711789Sahrens 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
712789Sahrens 	    &zc.zc_pool_guid) == 0);
713789Sahrens 
714789Sahrens 	verify(nvlist_size(config, &len, NV_ENCODE_NATIVE) == 0);
715789Sahrens 
716789Sahrens 	packed = zfs_malloc(len);
717789Sahrens 
718789Sahrens 	verify(nvlist_pack(config, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
719789Sahrens 
720789Sahrens 	zc.zc_config_src = (uint64_t)(uintptr_t)packed;
721789Sahrens 	zc.zc_config_src_size = len;
722789Sahrens 
723789Sahrens 	ret = 0;
724789Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) {
725789Sahrens 		char desc[1024];
726789Sahrens 		if (newname == NULL)
727789Sahrens 			(void) snprintf(desc, sizeof (desc),
728789Sahrens 			    dgettext(TEXT_DOMAIN, "cannot import '%s'"),
729789Sahrens 			    thename);
730789Sahrens 		else
731789Sahrens 			(void) snprintf(desc, sizeof (desc),
732789Sahrens 			    dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"),
733789Sahrens 			    origname, thename);
734789Sahrens 
735789Sahrens 		switch (errno) {
736789Sahrens 		case EEXIST:
737789Sahrens 			/*
738789Sahrens 			 * A pool with that name already exists.
739789Sahrens 			 */
740789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "%s: pool exists"),
741789Sahrens 			    desc);
742789Sahrens 			break;
743789Sahrens 
744789Sahrens 		case EPERM:
745789Sahrens 			/*
746789Sahrens 			 * The user doesn't have permission to create pools.
747789Sahrens 			 */
748789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "%s: permission "
749789Sahrens 			    "denied"), desc);
750789Sahrens 			break;
751789Sahrens 
752789Sahrens 		case ENXIO:
753789Sahrens 		case EDOM:
754789Sahrens 			/*
755789Sahrens 			 * Device is unavailable, or vdev sum didn't match.
756789Sahrens 			 */
757789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "%s: one or more "
758789Sahrens 			    "devices is unavailable"),
759789Sahrens 			    desc);
760789Sahrens 			break;
761789Sahrens 
762789Sahrens 		default:
763789Sahrens 			zfs_baderror(errno);
764789Sahrens 		}
765789Sahrens 
766789Sahrens 		ret = -1;
767789Sahrens 	} else {
768789Sahrens 		zpool_handle_t *zhp;
769789Sahrens 		/*
770789Sahrens 		 * This should never fail, but play it safe anyway.
771789Sahrens 		 */
772789Sahrens 		if ((zhp = zpool_open_silent(thename)) != NULL) {
773789Sahrens 			ret = zpool_create_zvol_links(zhp);
774789Sahrens 			zpool_close(zhp);
775789Sahrens 		}
776789Sahrens 	}
777789Sahrens 
778789Sahrens 	free(packed);
779789Sahrens 	return (ret);
780789Sahrens }
781789Sahrens 
782789Sahrens /*
783789Sahrens  * Scrub the pool.
784789Sahrens  */
785789Sahrens int
786789Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type)
787789Sahrens {
788789Sahrens 	zfs_cmd_t zc = { 0 };
789789Sahrens 	char msg[1024];
790789Sahrens 
791789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
792789Sahrens 	zc.zc_cookie = type;
793789Sahrens 
794789Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_POOL_SCRUB, &zc) == 0)
795789Sahrens 		return (0);
796789Sahrens 
797789Sahrens 	(void) snprintf(msg, sizeof (msg),
798789Sahrens 	    dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name);
799789Sahrens 
800789Sahrens 	switch (errno) {
801789Sahrens 	    case EPERM:
802789Sahrens 		/*
803789Sahrens 		 * No permission to scrub this pool.
804789Sahrens 		 */
805789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg);
806789Sahrens 		break;
807789Sahrens 
808789Sahrens 	    case EBUSY:
809789Sahrens 		/*
810789Sahrens 		 * Resilver in progress.
811789Sahrens 		 */
812789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: currently resilvering"),
813789Sahrens 		    msg);
814789Sahrens 		break;
815789Sahrens 
816789Sahrens 	    default:
817789Sahrens 		zfs_baderror(errno);
818789Sahrens 	}
819789Sahrens 	return (-1);
820789Sahrens }
821789Sahrens 
822789Sahrens /*
823789Sahrens  * Bring the specified vdev online
824789Sahrens  */
825789Sahrens int
826789Sahrens zpool_vdev_online(zpool_handle_t *zhp, const char *path)
827789Sahrens {
828789Sahrens 	zfs_cmd_t zc = { 0 };
829789Sahrens 	char msg[1024];
830789Sahrens 
831789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
832789Sahrens 	(void) snprintf(zc.zc_prop_value, sizeof (zc.zc_prop_value),
833789Sahrens 	    "%s%s", path[0] == '/' ? "" : "/dev/dsk/", path);
834789Sahrens 
835789Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_VDEV_ONLINE, &zc) == 0)
836789Sahrens 		return (0);
837789Sahrens 
838789Sahrens 	(void) snprintf(msg, sizeof (msg),
839789Sahrens 	    dgettext(TEXT_DOMAIN, "cannot online %s"), zc.zc_prop_value);
840789Sahrens 
841789Sahrens 	switch (errno) {
842789Sahrens 	    case ENODEV:
843789Sahrens 		/*
844789Sahrens 		 * Device doesn't exist
845789Sahrens 		 */
846789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: device not in pool"), msg);
847789Sahrens 		break;
848789Sahrens 
849789Sahrens 	    case EPERM:
850789Sahrens 		/*
851789Sahrens 		 * No permission to bring this vdev online.
852789Sahrens 		 */
853789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg);
854789Sahrens 		break;
855789Sahrens 
856789Sahrens 	    default:
857789Sahrens 		zfs_baderror(errno);
858789Sahrens 	}
859789Sahrens 	return (-1);
860789Sahrens }
861789Sahrens 
862789Sahrens /*
863789Sahrens  * Take the specified vdev offline
864789Sahrens  */
865789Sahrens int
866789Sahrens zpool_vdev_offline(zpool_handle_t *zhp, const char *path)
867789Sahrens {
868789Sahrens 	zfs_cmd_t zc = { 0 };
869789Sahrens 	char msg[1024];
870789Sahrens 
871789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
872789Sahrens 	(void) snprintf(zc.zc_prop_value, sizeof (zc.zc_prop_value),
873789Sahrens 	    "%s%s", path[0] == '/' ? "" : "/dev/dsk/", path);
874789Sahrens 
875789Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_VDEV_OFFLINE, &zc) == 0)
876789Sahrens 		return (0);
877789Sahrens 
878789Sahrens 	(void) snprintf(msg, sizeof (msg),
879789Sahrens 	    dgettext(TEXT_DOMAIN, "cannot offline %s"), zc.zc_prop_value);
880789Sahrens 
881789Sahrens 	switch (errno) {
882789Sahrens 	    case ENODEV:
883789Sahrens 		/*
884789Sahrens 		 * Device doesn't exist
885789Sahrens 		 */
886789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: device not in pool"), msg);
887789Sahrens 		break;
888789Sahrens 
889789Sahrens 	    case EPERM:
890789Sahrens 		/*
891789Sahrens 		 * No permission to take this vdev offline.
892789Sahrens 		 */
893789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg);
894789Sahrens 		break;
895789Sahrens 
896789Sahrens 	    case EBUSY:
897789Sahrens 		/*
898789Sahrens 		 * There are no other replicas of this device.
899789Sahrens 		 */
900789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: no valid replicas"), msg);
901789Sahrens 		break;
902789Sahrens 
903789Sahrens 	    default:
904789Sahrens 		zfs_baderror(errno);
905789Sahrens 	}
906789Sahrens 	return (-1);
907789Sahrens }
908789Sahrens 
909789Sahrens /*
910789Sahrens  * Attach new_disk (fully described by nvroot) to old_disk.
911789Sahrens  * If 'replacing' is specified, tne new disk will replace the old one.
912789Sahrens  */
913789Sahrens int
914789Sahrens zpool_vdev_attach(zpool_handle_t *zhp,
915789Sahrens     const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing)
916789Sahrens {
917789Sahrens 	zfs_cmd_t zc = { 0 };
918789Sahrens 	char msg[1024];
919789Sahrens 	char *packed;
920789Sahrens 	int ret;
921789Sahrens 	size_t len;
922789Sahrens 
923789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
924789Sahrens 	(void) snprintf(zc.zc_prop_value, sizeof (zc.zc_prop_value),
925789Sahrens 	    "%s%s", old_disk[0] == '/' ? "" : "/dev/dsk/", old_disk);
926789Sahrens 	zc.zc_cookie = replacing;
927789Sahrens 
928789Sahrens 	verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0);
929789Sahrens 
930789Sahrens 	packed = zfs_malloc(len);
931789Sahrens 
932789Sahrens 	verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
933789Sahrens 
934789Sahrens 	zc.zc_config_src = (uint64_t)(uintptr_t)packed;
935789Sahrens 	zc.zc_config_src_size = len;
936789Sahrens 
937789Sahrens 	ret = ioctl(zfs_fd, ZFS_IOC_VDEV_ATTACH, &zc);
938789Sahrens 
939789Sahrens 	free(packed);
940789Sahrens 
941789Sahrens 	if (ret == 0)
942789Sahrens 		return (0);
943789Sahrens 
944789Sahrens 	if (replacing)
945789Sahrens 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
946789Sahrens 		    "cannot replace %s with %s"), old_disk, new_disk);
947789Sahrens 	else
948789Sahrens 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
949789Sahrens 		    "cannot attach %s to %s"), new_disk, old_disk);
950789Sahrens 
951789Sahrens 	switch (errno) {
952789Sahrens 	    case EPERM:
953789Sahrens 		/*
954789Sahrens 		 * No permission to mess with the config.
955789Sahrens 		 */
956789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg);
957789Sahrens 		break;
958789Sahrens 
959789Sahrens 	    case ENODEV:
960789Sahrens 		/*
961789Sahrens 		 * Device doesn't exist.
962789Sahrens 		 */
963789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: %s not in pool"),
964789Sahrens 		    msg, old_disk);
965789Sahrens 		break;
966789Sahrens 
967789Sahrens 	    case ENOTSUP:
968789Sahrens 		/*
969789Sahrens 		 * Can't attach to or replace this type of vdev.
970789Sahrens 		 */
971789Sahrens 		if (replacing)
972789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
973789Sahrens 			    "%s: cannot replace a replacing device"), msg);
974789Sahrens 		else
975789Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
976789Sahrens 			    "%s: attach is only applicable to mirrors"), msg);
977789Sahrens 		break;
978789Sahrens 
979789Sahrens 	    case EINVAL:
980789Sahrens 		/*
981789Sahrens 		 * The new device must be a single disk.
982789Sahrens 		 */
983789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN,
984789Sahrens 		    "%s: <new_device> must be a single disk"), msg);
985789Sahrens 		break;
986789Sahrens 
987789Sahrens 	    case ENXIO:
988789Sahrens 		/*
989789Sahrens 		 * This is unlikely to happen since we've verified that
990789Sahrens 		 * all the devices can be opened from userland, but it's
991789Sahrens 		 * still possible in some circumstances.
992789Sahrens 		 */
993789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: %s is unavailable"),
994789Sahrens 		    msg, new_disk);
995789Sahrens 		break;
996789Sahrens 
997789Sahrens 	    case EBUSY:
998789Sahrens 		/*
999789Sahrens 		 * The new device is is use.
1000789Sahrens 		 */
1001789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: %s busy"), msg, new_disk);
1002789Sahrens 		break;
1003789Sahrens 
1004789Sahrens 	    case EOVERFLOW:
1005789Sahrens 		/*
1006789Sahrens 		 * The new device is too small.
1007789Sahrens 		 */
1008789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: %s is too small"),
1009789Sahrens 		    msg, new_disk);
1010789Sahrens 		break;
1011789Sahrens 
1012789Sahrens 	    case EDOM:
1013789Sahrens 		/*
1014789Sahrens 		 * The new device has a different alignment requirement.
1015789Sahrens 		 */
1016789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN,
1017789Sahrens 		    "%s: devices have different sector alignment"), msg);
1018789Sahrens 		break;
1019789Sahrens 
1020789Sahrens 	    case ENAMETOOLONG:
1021789Sahrens 		/*
1022789Sahrens 		 * The resulting top-level vdev spec won't fit in the label.
1023789Sahrens 		 */
1024789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN,
1025789Sahrens 		    "%s: too many devices in a single vdev"), msg);
1026789Sahrens 		break;
1027789Sahrens 
1028789Sahrens 	    default:
1029789Sahrens 		zfs_baderror(errno);
1030789Sahrens 	}
1031789Sahrens 
1032789Sahrens 	return (1);
1033789Sahrens }
1034789Sahrens 
1035789Sahrens /*
1036789Sahrens  * Detach the specified device.
1037789Sahrens  */
1038789Sahrens int
1039789Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path)
1040789Sahrens {
1041789Sahrens 	zfs_cmd_t zc = { 0 };
1042789Sahrens 	char msg[1024];
1043789Sahrens 
1044789Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1045789Sahrens 	(void) snprintf(zc.zc_prop_value, sizeof (zc.zc_prop_value),
1046789Sahrens 	    "%s%s", path[0] == '/' ? "" : "/dev/dsk/", path);
1047789Sahrens 
1048789Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_VDEV_DETACH, &zc) == 0)
1049789Sahrens 		return (0);
1050789Sahrens 
1051789Sahrens 	(void) snprintf(msg, sizeof (msg),
1052789Sahrens 	    dgettext(TEXT_DOMAIN, "cannot detach %s"), zc.zc_prop_value);
1053789Sahrens 
1054789Sahrens 	switch (errno) {
1055789Sahrens 	    case EPERM:
1056789Sahrens 		/*
1057789Sahrens 		 * No permission to mess with the config.
1058789Sahrens 		 */
1059789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg);
1060789Sahrens 		break;
1061789Sahrens 
1062789Sahrens 	    case ENODEV:
1063789Sahrens 		/*
1064789Sahrens 		 * Device doesn't exist.
1065789Sahrens 		 */
1066789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: device not in pool"), msg);
1067789Sahrens 		break;
1068789Sahrens 
1069789Sahrens 	    case ENOTSUP:
1070789Sahrens 		/*
1071789Sahrens 		 * Can't detach from this type of vdev.
1072789Sahrens 		 */
1073789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN,
1074789Sahrens 		    "%s: only applicable to mirror and replacing vdevs"), msg);
1075789Sahrens 		break;
1076789Sahrens 
1077789Sahrens 	    case EBUSY:
1078789Sahrens 		/*
1079789Sahrens 		 * There are no other replicas of this device.
1080789Sahrens 		 */
1081789Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: no valid replicas"), msg);
1082789Sahrens 		break;
1083789Sahrens 
1084789Sahrens 	    default:
1085789Sahrens 		zfs_baderror(errno);
1086789Sahrens 	}
1087789Sahrens 
1088789Sahrens 	return (1);
1089789Sahrens }
1090789Sahrens 
1091789Sahrens static int
1092789Sahrens do_zvol(zfs_handle_t *zhp, void *data)
1093789Sahrens {
1094789Sahrens 	int linktype = (int)(uintptr_t)data;
1095789Sahrens 	int ret;
1096789Sahrens 
1097789Sahrens 	/*
1098789Sahrens 	 * We check for volblocksize intead of ZFS_TYPE_VOLUME so that we
1099789Sahrens 	 * correctly handle snapshots of volumes.
1100789Sahrens 	 */
1101789Sahrens 	if (zhp->zfs_volblocksize != 0) {
1102789Sahrens 		if (linktype)
1103789Sahrens 			ret = zvol_create_link(zhp->zfs_name);
1104789Sahrens 		else
1105789Sahrens 			ret = zvol_remove_link(zhp->zfs_name);
1106789Sahrens 	}
1107789Sahrens 
1108789Sahrens 	ret = zfs_iter_children(zhp, do_zvol, data);
1109789Sahrens 
1110789Sahrens 	zfs_close(zhp);
1111789Sahrens 	return (ret);
1112789Sahrens }
1113789Sahrens 
1114789Sahrens /*
1115789Sahrens  * Iterate over all zvols in the pool and make any necessary minor nodes.
1116789Sahrens  */
1117789Sahrens int
1118789Sahrens zpool_create_zvol_links(zpool_handle_t *zhp)
1119789Sahrens {
1120789Sahrens 	zfs_handle_t *zfp;
1121789Sahrens 	int ret;
1122789Sahrens 
1123789Sahrens 	/*
1124789Sahrens 	 * If the pool is unavailable, just return success.
1125789Sahrens 	 */
1126789Sahrens 	if ((zfp = make_dataset_handle(zhp->zpool_name)) == NULL)
1127789Sahrens 		return (0);
1128789Sahrens 
1129789Sahrens 	ret = zfs_iter_children(zfp, do_zvol, (void *)TRUE);
1130789Sahrens 
1131789Sahrens 	zfs_close(zfp);
1132789Sahrens 	return (ret);
1133789Sahrens }
1134789Sahrens 
1135789Sahrens /*
1136789Sahrens  * Iterate over all zvols in the poool and remove any minor nodes.
1137789Sahrens  */
1138789Sahrens int
1139789Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp)
1140789Sahrens {
1141789Sahrens 	zfs_handle_t *zfp;
1142789Sahrens 	int ret;
1143789Sahrens 
1144789Sahrens 	/*
1145789Sahrens 	 * If the pool is unavailable, just return success.
1146789Sahrens 	 */
1147789Sahrens 	if ((zfp = make_dataset_handle(zhp->zpool_name)) == NULL)
1148789Sahrens 		return (0);
1149789Sahrens 
1150789Sahrens 	ret = zfs_iter_children(zfp, do_zvol, (void *)FALSE);
1151789Sahrens 
1152789Sahrens 	zfs_close(zfp);
1153789Sahrens 	return (ret);
1154789Sahrens }
1155