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