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