xref: /illumos-gate/usr/src/lib/libzfs/common/libzfs_pool.c (revision fa9e4066f08beec538e775443c5be79dd423fcab)
1*fa9e4066Sahrens /*
2*fa9e4066Sahrens  * CDDL HEADER START
3*fa9e4066Sahrens  *
4*fa9e4066Sahrens  * The contents of this file are subject to the terms of the
5*fa9e4066Sahrens  * Common Development and Distribution License, Version 1.0 only
6*fa9e4066Sahrens  * (the "License").  You may not use this file except in compliance
7*fa9e4066Sahrens  * with the License.
8*fa9e4066Sahrens  *
9*fa9e4066Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*fa9e4066Sahrens  * or http://www.opensolaris.org/os/licensing.
11*fa9e4066Sahrens  * See the License for the specific language governing permissions
12*fa9e4066Sahrens  * and limitations under the License.
13*fa9e4066Sahrens  *
14*fa9e4066Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
15*fa9e4066Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*fa9e4066Sahrens  * If applicable, add the following below this CDDL HEADER, with the
17*fa9e4066Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
18*fa9e4066Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
19*fa9e4066Sahrens  *
20*fa9e4066Sahrens  * CDDL HEADER END
21*fa9e4066Sahrens  */
22*fa9e4066Sahrens /*
23*fa9e4066Sahrens  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*fa9e4066Sahrens  * Use is subject to license terms.
25*fa9e4066Sahrens  */
26*fa9e4066Sahrens 
27*fa9e4066Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*fa9e4066Sahrens 
29*fa9e4066Sahrens #include <assert.h>
30*fa9e4066Sahrens #include <ctype.h>
31*fa9e4066Sahrens #include <errno.h>
32*fa9e4066Sahrens #include <devid.h>
33*fa9e4066Sahrens #include <fcntl.h>
34*fa9e4066Sahrens #include <libintl.h>
35*fa9e4066Sahrens #include <stdio.h>
36*fa9e4066Sahrens #include <stdlib.h>
37*fa9e4066Sahrens #include <string.h>
38*fa9e4066Sahrens #include <unistd.h>
39*fa9e4066Sahrens #include <sys/zfs_ioctl.h>
40*fa9e4066Sahrens 
41*fa9e4066Sahrens #include "zfs_namecheck.h"
42*fa9e4066Sahrens #include "libzfs_impl.h"
43*fa9e4066Sahrens 
44*fa9e4066Sahrens /*
45*fa9e4066Sahrens  * Validate the given pool name, optionally putting an extended error message in
46*fa9e4066Sahrens  * 'buf'.
47*fa9e4066Sahrens  */
48*fa9e4066Sahrens static int
49*fa9e4066Sahrens zpool_name_valid(const char *pool, char *buf, size_t buflen)
50*fa9e4066Sahrens {
51*fa9e4066Sahrens 	namecheck_err_t why;
52*fa9e4066Sahrens 	char what;
53*fa9e4066Sahrens 
54*fa9e4066Sahrens 	if (strlen(pool) >= ZPOOL_MAXNAMELEN) {
55*fa9e4066Sahrens 		if (buf)
56*fa9e4066Sahrens 			(void) snprintf(buf, buflen,
57*fa9e4066Sahrens 			    dgettext(TEXT_DOMAIN, "name is too long"));
58*fa9e4066Sahrens 		return (FALSE);
59*fa9e4066Sahrens 	}
60*fa9e4066Sahrens 
61*fa9e4066Sahrens 	if (pool_namecheck(pool, &why, &what) != 0) {
62*fa9e4066Sahrens 		if (buf != NULL) {
63*fa9e4066Sahrens 			switch (why) {
64*fa9e4066Sahrens 			case NAME_ERR_INVALCHAR:
65*fa9e4066Sahrens 				(void) snprintf(buf, buflen,
66*fa9e4066Sahrens 				    dgettext(TEXT_DOMAIN, "invalid character "
67*fa9e4066Sahrens 				    "'%c' in pool name"), what);
68*fa9e4066Sahrens 				break;
69*fa9e4066Sahrens 
70*fa9e4066Sahrens 			case NAME_ERR_NOLETTER:
71*fa9e4066Sahrens 				(void) strlcpy(buf, dgettext(TEXT_DOMAIN,
72*fa9e4066Sahrens 				    "name must begin with a letter"), buflen);
73*fa9e4066Sahrens 				break;
74*fa9e4066Sahrens 
75*fa9e4066Sahrens 			case NAME_ERR_RESERVED:
76*fa9e4066Sahrens 				(void) strlcpy(buf, dgettext(TEXT_DOMAIN,
77*fa9e4066Sahrens 				    "name is reserved\n"
78*fa9e4066Sahrens 				    "pool name may have been omitted"), buflen);
79*fa9e4066Sahrens 				break;
80*fa9e4066Sahrens 
81*fa9e4066Sahrens 			case NAME_ERR_DISKLIKE:
82*fa9e4066Sahrens 				(void) strlcpy(buf, dgettext(TEXT_DOMAIN,
83*fa9e4066Sahrens 				    "pool name is reserved\n"
84*fa9e4066Sahrens 				    "pool name may have been omitted"), buflen);
85*fa9e4066Sahrens 				break;
86*fa9e4066Sahrens 			}
87*fa9e4066Sahrens 		}
88*fa9e4066Sahrens 		return (FALSE);
89*fa9e4066Sahrens 	}
90*fa9e4066Sahrens 
91*fa9e4066Sahrens 	return (TRUE);
92*fa9e4066Sahrens }
93*fa9e4066Sahrens 
94*fa9e4066Sahrens /*
95*fa9e4066Sahrens  * Set the pool-wide health based on the vdev state of the root vdev.
96*fa9e4066Sahrens  */
97*fa9e4066Sahrens void
98*fa9e4066Sahrens set_pool_health(nvlist_t *config)
99*fa9e4066Sahrens {
100*fa9e4066Sahrens 	nvlist_t *nvroot;
101*fa9e4066Sahrens 	vdev_stat_t *vs;
102*fa9e4066Sahrens 	uint_t vsc;
103*fa9e4066Sahrens 	char *health;
104*fa9e4066Sahrens 
105*fa9e4066Sahrens 	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
106*fa9e4066Sahrens 	    &nvroot) == 0);
107*fa9e4066Sahrens 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
108*fa9e4066Sahrens 	    (uint64_t **)&vs, &vsc) == 0);
109*fa9e4066Sahrens 
110*fa9e4066Sahrens 	switch (vs->vs_state) {
111*fa9e4066Sahrens 
112*fa9e4066Sahrens 	case VDEV_STATE_CLOSED:
113*fa9e4066Sahrens 	case VDEV_STATE_CANT_OPEN:
114*fa9e4066Sahrens 	case VDEV_STATE_OFFLINE:
115*fa9e4066Sahrens 		health = dgettext(TEXT_DOMAIN, "FAULTED");
116*fa9e4066Sahrens 		break;
117*fa9e4066Sahrens 
118*fa9e4066Sahrens 	case VDEV_STATE_DEGRADED:
119*fa9e4066Sahrens 		health = dgettext(TEXT_DOMAIN, "DEGRADED");
120*fa9e4066Sahrens 		break;
121*fa9e4066Sahrens 
122*fa9e4066Sahrens 	case VDEV_STATE_HEALTHY:
123*fa9e4066Sahrens 		health = dgettext(TEXT_DOMAIN, "ONLINE");
124*fa9e4066Sahrens 		break;
125*fa9e4066Sahrens 
126*fa9e4066Sahrens 	default:
127*fa9e4066Sahrens 		zfs_baderror(vs->vs_state);
128*fa9e4066Sahrens 	}
129*fa9e4066Sahrens 
130*fa9e4066Sahrens 	verify(nvlist_add_string(config, ZPOOL_CONFIG_POOL_HEALTH,
131*fa9e4066Sahrens 	    health) == 0);
132*fa9e4066Sahrens }
133*fa9e4066Sahrens 
134*fa9e4066Sahrens /*
135*fa9e4066Sahrens  * Open a handle to the given pool, even if the pool is currently in the FAULTED
136*fa9e4066Sahrens  * state.
137*fa9e4066Sahrens  */
138*fa9e4066Sahrens zpool_handle_t *
139*fa9e4066Sahrens zpool_open_canfail(const char *pool)
140*fa9e4066Sahrens {
141*fa9e4066Sahrens 	zpool_handle_t *zhp;
142*fa9e4066Sahrens 	nvlist_t *newconfig;
143*fa9e4066Sahrens 	int error;
144*fa9e4066Sahrens 
145*fa9e4066Sahrens 	/*
146*fa9e4066Sahrens 	 * Make sure the pool name is valid.
147*fa9e4066Sahrens 	 */
148*fa9e4066Sahrens 	if (!zpool_name_valid(pool, NULL, 0)) {
149*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': invalid "
150*fa9e4066Sahrens 		    "pool name"), pool);
151*fa9e4066Sahrens 		return (NULL);
152*fa9e4066Sahrens 	}
153*fa9e4066Sahrens 
154*fa9e4066Sahrens 	zhp = zfs_malloc(sizeof (zpool_handle_t));
155*fa9e4066Sahrens 
156*fa9e4066Sahrens 	(void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
157*fa9e4066Sahrens 
158*fa9e4066Sahrens 	if ((error = zpool_refresh_stats(zhp, NULL, &newconfig)) != 0) {
159*fa9e4066Sahrens 		if (error == ENOENT || error == EINVAL) {
160*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': no "
161*fa9e4066Sahrens 			    "such pool"), pool);
162*fa9e4066Sahrens 			free(zhp);
163*fa9e4066Sahrens 			return (NULL);
164*fa9e4066Sahrens 		} else {
165*fa9e4066Sahrens 			zhp->zpool_state = POOL_STATE_UNAVAIL;
166*fa9e4066Sahrens 		}
167*fa9e4066Sahrens 	} else {
168*fa9e4066Sahrens 		zhp->zpool_state = POOL_STATE_ACTIVE;
169*fa9e4066Sahrens 	}
170*fa9e4066Sahrens 
171*fa9e4066Sahrens 	return (zhp);
172*fa9e4066Sahrens }
173*fa9e4066Sahrens 
174*fa9e4066Sahrens /*
175*fa9e4066Sahrens  * Like the above, but silent on error.  Used when iterating over pools (because
176*fa9e4066Sahrens  * the configuration cache may be out of date).
177*fa9e4066Sahrens  */
178*fa9e4066Sahrens zpool_handle_t *
179*fa9e4066Sahrens zpool_open_silent(const char *pool)
180*fa9e4066Sahrens {
181*fa9e4066Sahrens 	zpool_handle_t *zhp;
182*fa9e4066Sahrens 	nvlist_t *newconfig;
183*fa9e4066Sahrens 	int error;
184*fa9e4066Sahrens 
185*fa9e4066Sahrens 	zhp = zfs_malloc(sizeof (zpool_handle_t));
186*fa9e4066Sahrens 
187*fa9e4066Sahrens 	(void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
188*fa9e4066Sahrens 
189*fa9e4066Sahrens 	if ((error = zpool_refresh_stats(zhp, NULL, &newconfig)) != 0) {
190*fa9e4066Sahrens 		if (error == ENOENT || error == EINVAL) {
191*fa9e4066Sahrens 			free(zhp);
192*fa9e4066Sahrens 			return (NULL);
193*fa9e4066Sahrens 		} else {
194*fa9e4066Sahrens 			zhp->zpool_state = POOL_STATE_UNAVAIL;
195*fa9e4066Sahrens 		}
196*fa9e4066Sahrens 	} else {
197*fa9e4066Sahrens 		zhp->zpool_state = POOL_STATE_ACTIVE;
198*fa9e4066Sahrens 	}
199*fa9e4066Sahrens 
200*fa9e4066Sahrens 	return (zhp);
201*fa9e4066Sahrens }
202*fa9e4066Sahrens 
203*fa9e4066Sahrens /*
204*fa9e4066Sahrens  * Similar to zpool_open_canfail(), but refuses to open pools in the faulted
205*fa9e4066Sahrens  * state.
206*fa9e4066Sahrens  */
207*fa9e4066Sahrens zpool_handle_t *
208*fa9e4066Sahrens zpool_open(const char *pool)
209*fa9e4066Sahrens {
210*fa9e4066Sahrens 	zpool_handle_t *zhp;
211*fa9e4066Sahrens 
212*fa9e4066Sahrens 	if ((zhp = zpool_open_canfail(pool)) == NULL)
213*fa9e4066Sahrens 		return (NULL);
214*fa9e4066Sahrens 
215*fa9e4066Sahrens 	if (zhp->zpool_state == POOL_STATE_UNAVAIL) {
216*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "cannot open ' %s': pool is "
217*fa9e4066Sahrens 		    "currently unavailable\n"), zhp->zpool_name);
218*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "run 'zpool status -v %s' for "
219*fa9e4066Sahrens 		    "detailed information\n"), zhp->zpool_name);
220*fa9e4066Sahrens 		zpool_close(zhp);
221*fa9e4066Sahrens 		return (NULL);
222*fa9e4066Sahrens 	}
223*fa9e4066Sahrens 
224*fa9e4066Sahrens 	return (zhp);
225*fa9e4066Sahrens }
226*fa9e4066Sahrens 
227*fa9e4066Sahrens /*
228*fa9e4066Sahrens  * Close the handle.  Simply frees the memory associated with the handle.
229*fa9e4066Sahrens  */
230*fa9e4066Sahrens void
231*fa9e4066Sahrens zpool_close(zpool_handle_t *zhp)
232*fa9e4066Sahrens {
233*fa9e4066Sahrens 	if (zhp->zpool_config)
234*fa9e4066Sahrens 		nvlist_free(zhp->zpool_config);
235*fa9e4066Sahrens 	free(zhp);
236*fa9e4066Sahrens }
237*fa9e4066Sahrens 
238*fa9e4066Sahrens /*
239*fa9e4066Sahrens  * Return the name of the pool.
240*fa9e4066Sahrens  */
241*fa9e4066Sahrens const char *
242*fa9e4066Sahrens zpool_get_name(zpool_handle_t *zhp)
243*fa9e4066Sahrens {
244*fa9e4066Sahrens 	return (zhp->zpool_name);
245*fa9e4066Sahrens }
246*fa9e4066Sahrens 
247*fa9e4066Sahrens /*
248*fa9e4066Sahrens  * Return the GUID of the pool.
249*fa9e4066Sahrens  */
250*fa9e4066Sahrens uint64_t
251*fa9e4066Sahrens zpool_get_guid(zpool_handle_t *zhp)
252*fa9e4066Sahrens {
253*fa9e4066Sahrens 	uint64_t guid;
254*fa9e4066Sahrens 
255*fa9e4066Sahrens 	verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID,
256*fa9e4066Sahrens 	    &guid) == 0);
257*fa9e4066Sahrens 	return (guid);
258*fa9e4066Sahrens }
259*fa9e4066Sahrens 
260*fa9e4066Sahrens /*
261*fa9e4066Sahrens  * Return the amount of space currently consumed by the pool.
262*fa9e4066Sahrens  */
263*fa9e4066Sahrens uint64_t
264*fa9e4066Sahrens zpool_get_space_used(zpool_handle_t *zhp)
265*fa9e4066Sahrens {
266*fa9e4066Sahrens 	nvlist_t *nvroot;
267*fa9e4066Sahrens 	vdev_stat_t *vs;
268*fa9e4066Sahrens 	uint_t vsc;
269*fa9e4066Sahrens 
270*fa9e4066Sahrens 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
271*fa9e4066Sahrens 	    &nvroot) == 0);
272*fa9e4066Sahrens 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
273*fa9e4066Sahrens 	    (uint64_t **)&vs, &vsc) == 0);
274*fa9e4066Sahrens 
275*fa9e4066Sahrens 	return (vs->vs_alloc);
276*fa9e4066Sahrens }
277*fa9e4066Sahrens 
278*fa9e4066Sahrens /*
279*fa9e4066Sahrens  * Return the total space in the pool.
280*fa9e4066Sahrens  */
281*fa9e4066Sahrens uint64_t
282*fa9e4066Sahrens zpool_get_space_total(zpool_handle_t *zhp)
283*fa9e4066Sahrens {
284*fa9e4066Sahrens 	nvlist_t *nvroot;
285*fa9e4066Sahrens 	vdev_stat_t *vs;
286*fa9e4066Sahrens 	uint_t vsc;
287*fa9e4066Sahrens 
288*fa9e4066Sahrens 	verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
289*fa9e4066Sahrens 	    &nvroot) == 0);
290*fa9e4066Sahrens 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
291*fa9e4066Sahrens 	    (uint64_t **)&vs, &vsc) == 0);
292*fa9e4066Sahrens 
293*fa9e4066Sahrens 	return (vs->vs_space);
294*fa9e4066Sahrens }
295*fa9e4066Sahrens 
296*fa9e4066Sahrens /*
297*fa9e4066Sahrens  * Return the alternate root for this pool, if any.
298*fa9e4066Sahrens  */
299*fa9e4066Sahrens int
300*fa9e4066Sahrens zpool_get_root(zpool_handle_t *zhp, char *buf, size_t buflen)
301*fa9e4066Sahrens {
302*fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
303*fa9e4066Sahrens 
304*fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
305*fa9e4066Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 ||
306*fa9e4066Sahrens 	    zc.zc_objset_stats.dds_altroot[0] == '\0')
307*fa9e4066Sahrens 		return (-1);
308*fa9e4066Sahrens 
309*fa9e4066Sahrens 	(void) strlcpy(buf, zc.zc_objset_stats.dds_altroot, buflen);
310*fa9e4066Sahrens 
311*fa9e4066Sahrens 	return (0);
312*fa9e4066Sahrens }
313*fa9e4066Sahrens 
314*fa9e4066Sahrens /*
315*fa9e4066Sahrens  * Return the state of the pool (ACTIVE or UNAVAILABLE)
316*fa9e4066Sahrens  */
317*fa9e4066Sahrens int
318*fa9e4066Sahrens zpool_get_state(zpool_handle_t *zhp)
319*fa9e4066Sahrens {
320*fa9e4066Sahrens 	return (zhp->zpool_state);
321*fa9e4066Sahrens }
322*fa9e4066Sahrens 
323*fa9e4066Sahrens /*
324*fa9e4066Sahrens  * Create the named pool, using the provided vdev list.  It is assumed
325*fa9e4066Sahrens  * that the consumer has already validated the contents of the nvlist, so we
326*fa9e4066Sahrens  * don't have to worry about error semantics.
327*fa9e4066Sahrens  */
328*fa9e4066Sahrens int
329*fa9e4066Sahrens zpool_create(const char *pool, nvlist_t *nvroot, const char *altroot)
330*fa9e4066Sahrens {
331*fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
332*fa9e4066Sahrens 	char *packed;
333*fa9e4066Sahrens 	size_t len;
334*fa9e4066Sahrens 	int err;
335*fa9e4066Sahrens 	char reason[64];
336*fa9e4066Sahrens 
337*fa9e4066Sahrens 	if (!zpool_name_valid(pool, reason, sizeof (reason))) {
338*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': %s"),
339*fa9e4066Sahrens 		    pool, reason);
340*fa9e4066Sahrens 		return (-1);
341*fa9e4066Sahrens 	}
342*fa9e4066Sahrens 
343*fa9e4066Sahrens 	if (altroot != NULL && altroot[0] != '/') {
344*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': alternate "
345*fa9e4066Sahrens 		    "root '%s' must be a complete path"), pool, altroot);
346*fa9e4066Sahrens 		return (-1);
347*fa9e4066Sahrens 	}
348*fa9e4066Sahrens 
349*fa9e4066Sahrens 	if ((err = nvlist_size(nvroot, &len, NV_ENCODE_NATIVE)) != 0)
350*fa9e4066Sahrens 		zfs_baderror(err);
351*fa9e4066Sahrens 
352*fa9e4066Sahrens 	packed = zfs_malloc(len);
353*fa9e4066Sahrens 
354*fa9e4066Sahrens 	if ((err = nvlist_pack(nvroot, &packed, &len,
355*fa9e4066Sahrens 	    NV_ENCODE_NATIVE, 0)) != 0)
356*fa9e4066Sahrens 		zfs_baderror(err);
357*fa9e4066Sahrens 
358*fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name));
359*fa9e4066Sahrens 	zc.zc_config_src = (uint64_t)(uintptr_t)packed;
360*fa9e4066Sahrens 	zc.zc_config_src_size = len;
361*fa9e4066Sahrens 
362*fa9e4066Sahrens 	if (altroot != NULL)
363*fa9e4066Sahrens 		(void) strlcpy(zc.zc_root, altroot, sizeof (zc.zc_root));
364*fa9e4066Sahrens 
365*fa9e4066Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_POOL_CREATE, &zc) != 0) {
366*fa9e4066Sahrens 		switch (errno) {
367*fa9e4066Sahrens 		case EEXIST:
368*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': "
369*fa9e4066Sahrens 			    "pool exists"), pool);
370*fa9e4066Sahrens 			break;
371*fa9e4066Sahrens 
372*fa9e4066Sahrens 		case EPERM:
373*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': "
374*fa9e4066Sahrens 			    "permission denied"), pool);
375*fa9e4066Sahrens 			break;
376*fa9e4066Sahrens 
377*fa9e4066Sahrens 		case EBUSY:
378*fa9e4066Sahrens 			/*
379*fa9e4066Sahrens 			 * This can happen if the user has specified the same
380*fa9e4066Sahrens 			 * device multiple times.  We can't reliably detect this
381*fa9e4066Sahrens 			 * until we try to add it and see we already have a
382*fa9e4066Sahrens 			 * label.
383*fa9e4066Sahrens 			 */
384*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': "
385*fa9e4066Sahrens 			    "one or more vdevs refer to the same device"),
386*fa9e4066Sahrens 			    pool);
387*fa9e4066Sahrens 			break;
388*fa9e4066Sahrens 
389*fa9e4066Sahrens 		case EOVERFLOW:
390*fa9e4066Sahrens 			/*
391*fa9e4066Sahrens 			 * This occurrs when one of the devices is below
392*fa9e4066Sahrens 			 * SPA_MINDEVSIZE.  Unfortunately, we can't detect which
393*fa9e4066Sahrens 			 * device was the problem device since there's no
394*fa9e4066Sahrens 			 * reliable way to determine device size from userland.
395*fa9e4066Sahrens 			 */
396*fa9e4066Sahrens 			{
397*fa9e4066Sahrens 				char buf[64];
398*fa9e4066Sahrens 
399*fa9e4066Sahrens 				zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
400*fa9e4066Sahrens 
401*fa9e4066Sahrens 				zfs_error(dgettext(TEXT_DOMAIN, "cannot "
402*fa9e4066Sahrens 				    "create '%s': one or more devices is less "
403*fa9e4066Sahrens 				    "than the minimum size (%s)"), pool,
404*fa9e4066Sahrens 				    buf);
405*fa9e4066Sahrens 			}
406*fa9e4066Sahrens 			break;
407*fa9e4066Sahrens 
408*fa9e4066Sahrens 		case ENAMETOOLONG:
409*fa9e4066Sahrens 			/*
410*fa9e4066Sahrens 			 * One of the vdevs has exceeded VDEV_SPEC_MAX length in
411*fa9e4066Sahrens 			 * its plaintext representation.
412*fa9e4066Sahrens 			 */
413*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': "
414*fa9e4066Sahrens 			    "too many devices in a single vdev"), pool);
415*fa9e4066Sahrens 			break;
416*fa9e4066Sahrens 
417*fa9e4066Sahrens 		case EIO:
418*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': "
419*fa9e4066Sahrens 			    "I/O error on one or more devices"), pool);
420*fa9e4066Sahrens 			break;
421*fa9e4066Sahrens 
422*fa9e4066Sahrens 		case ENXIO:
423*fa9e4066Sahrens 			/*
424*fa9e4066Sahrens 			 * This is unlikely to happen since we've verified that
425*fa9e4066Sahrens 			 * all the devices can be opened from userland, but it's
426*fa9e4066Sahrens 			 * still possible in some circumstances.
427*fa9e4066Sahrens 			 */
428*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': "
429*fa9e4066Sahrens 			    "one or more devices is unavailable"), pool);
430*fa9e4066Sahrens 			break;
431*fa9e4066Sahrens 
432*fa9e4066Sahrens 		case ENOSPC:
433*fa9e4066Sahrens 			/*
434*fa9e4066Sahrens 			 * This can occur if we were incapable of writing to a
435*fa9e4066Sahrens 			 * file vdev because the underlying filesystem is out of
436*fa9e4066Sahrens 			 * space.  This is very similar to EOVERFLOW, but we'll
437*fa9e4066Sahrens 			 * produce a slightly different message.
438*fa9e4066Sahrens 			 */
439*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': "
440*fa9e4066Sahrens 			    "one or more devices is out of space"), pool);
441*fa9e4066Sahrens 			break;
442*fa9e4066Sahrens 
443*fa9e4066Sahrens 		default:
444*fa9e4066Sahrens 			zfs_baderror(errno);
445*fa9e4066Sahrens 		}
446*fa9e4066Sahrens 
447*fa9e4066Sahrens 		return (-1);
448*fa9e4066Sahrens 	}
449*fa9e4066Sahrens 
450*fa9e4066Sahrens 	free(packed);
451*fa9e4066Sahrens 
452*fa9e4066Sahrens 	/*
453*fa9e4066Sahrens 	 * If this is an alternate root pool, then we automatically set the
454*fa9e4066Sahrens 	 * moutnpoint of the root dataset to be '/'.
455*fa9e4066Sahrens 	 */
456*fa9e4066Sahrens 	if (altroot != NULL) {
457*fa9e4066Sahrens 		zfs_handle_t *zhp;
458*fa9e4066Sahrens 
459*fa9e4066Sahrens 		verify((zhp = zfs_open(pool, ZFS_TYPE_ANY)) != NULL);
460*fa9e4066Sahrens 		verify(zfs_prop_set(zhp, ZFS_PROP_MOUNTPOINT, "/") == 0);
461*fa9e4066Sahrens 
462*fa9e4066Sahrens 		zfs_close(zhp);
463*fa9e4066Sahrens 	}
464*fa9e4066Sahrens 
465*fa9e4066Sahrens 	return (0);
466*fa9e4066Sahrens }
467*fa9e4066Sahrens 
468*fa9e4066Sahrens /*
469*fa9e4066Sahrens  * Destroy the given pool.  It is up to the caller to ensure that there are no
470*fa9e4066Sahrens  * datasets left in the pool.
471*fa9e4066Sahrens  */
472*fa9e4066Sahrens int
473*fa9e4066Sahrens zpool_destroy(zpool_handle_t *zhp)
474*fa9e4066Sahrens {
475*fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
476*fa9e4066Sahrens 	zfs_handle_t *zfp = NULL;
477*fa9e4066Sahrens 
478*fa9e4066Sahrens 	if (zhp->zpool_state == POOL_STATE_ACTIVE &&
479*fa9e4066Sahrens 	    (zfp = zfs_open(zhp->zpool_name, ZFS_TYPE_FILESYSTEM)) == NULL)
480*fa9e4066Sahrens 		return (-1);
481*fa9e4066Sahrens 
482*fa9e4066Sahrens 	if (zpool_remove_zvol_links(zhp) != NULL)
483*fa9e4066Sahrens 		return (-1);
484*fa9e4066Sahrens 
485*fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
486*fa9e4066Sahrens 
487*fa9e4066Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
488*fa9e4066Sahrens 		switch (errno) {
489*fa9e4066Sahrens 		case EPERM:
490*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
491*fa9e4066Sahrens 			    "cannot destroy '%s': permission denied"),
492*fa9e4066Sahrens 			    zhp->zpool_name);
493*fa9e4066Sahrens 			break;
494*fa9e4066Sahrens 
495*fa9e4066Sahrens 		case EBUSY:
496*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
497*fa9e4066Sahrens 			    "cannot destroy '%s': pool busy"),
498*fa9e4066Sahrens 			    zhp->zpool_name);
499*fa9e4066Sahrens 			break;
500*fa9e4066Sahrens 
501*fa9e4066Sahrens 		case ENOENT:
502*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
503*fa9e4066Sahrens 			    "cannot destroy '%s': no such pool"),
504*fa9e4066Sahrens 			    zhp->zpool_name);
505*fa9e4066Sahrens 			break;
506*fa9e4066Sahrens 
507*fa9e4066Sahrens 		case EROFS:
508*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
509*fa9e4066Sahrens 			    "cannot destroy '%s': one or more devices is "
510*fa9e4066Sahrens 			    "read only, or '/' is mounted read only"),
511*fa9e4066Sahrens 			    zhp->zpool_name);
512*fa9e4066Sahrens 			break;
513*fa9e4066Sahrens 
514*fa9e4066Sahrens 		default:
515*fa9e4066Sahrens 			zfs_baderror(errno);
516*fa9e4066Sahrens 		}
517*fa9e4066Sahrens 
518*fa9e4066Sahrens 		if (zfp)
519*fa9e4066Sahrens 			zfs_close(zfp);
520*fa9e4066Sahrens 		return (-1);
521*fa9e4066Sahrens 	}
522*fa9e4066Sahrens 
523*fa9e4066Sahrens 	if (zfp) {
524*fa9e4066Sahrens 		remove_mountpoint(zfp);
525*fa9e4066Sahrens 		zfs_close(zfp);
526*fa9e4066Sahrens 	}
527*fa9e4066Sahrens 
528*fa9e4066Sahrens 	return (0);
529*fa9e4066Sahrens }
530*fa9e4066Sahrens 
531*fa9e4066Sahrens /*
532*fa9e4066Sahrens  * Add the given vdevs to the pool.  The caller must have already performed the
533*fa9e4066Sahrens  * necessary verification to ensure that the vdev specification is well-formed.
534*fa9e4066Sahrens  */
535*fa9e4066Sahrens int
536*fa9e4066Sahrens zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
537*fa9e4066Sahrens {
538*fa9e4066Sahrens 	char *packed;
539*fa9e4066Sahrens 	size_t len;
540*fa9e4066Sahrens 	zfs_cmd_t zc;
541*fa9e4066Sahrens 
542*fa9e4066Sahrens 	verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0);
543*fa9e4066Sahrens 
544*fa9e4066Sahrens 	packed = zfs_malloc(len);
545*fa9e4066Sahrens 
546*fa9e4066Sahrens 	verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
547*fa9e4066Sahrens 
548*fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
549*fa9e4066Sahrens 	zc.zc_config_src = (uint64_t)(uintptr_t)packed;
550*fa9e4066Sahrens 	zc.zc_config_src_size = len;
551*fa9e4066Sahrens 
552*fa9e4066Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) {
553*fa9e4066Sahrens 		switch (errno) {
554*fa9e4066Sahrens 		case EPERM:
555*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': "
556*fa9e4066Sahrens 			    "permission denied"), zhp->zpool_name);
557*fa9e4066Sahrens 			break;
558*fa9e4066Sahrens 
559*fa9e4066Sahrens 		case EBUSY:
560*fa9e4066Sahrens 			/*
561*fa9e4066Sahrens 			 * This can happen if the user has specified the same
562*fa9e4066Sahrens 			 * device multiple times.  We can't reliably detect this
563*fa9e4066Sahrens 			 * until we try to add it and see we already have a
564*fa9e4066Sahrens 			 * label.
565*fa9e4066Sahrens 			 */
566*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': "
567*fa9e4066Sahrens 			    "one or more vdevs refer to the same device"),
568*fa9e4066Sahrens 			    zhp->zpool_name);
569*fa9e4066Sahrens 			break;
570*fa9e4066Sahrens 
571*fa9e4066Sahrens 		case ENAMETOOLONG:
572*fa9e4066Sahrens 			/*
573*fa9e4066Sahrens 			 * One of the vdevs has exceeded VDEV_SPEC_MAX length in
574*fa9e4066Sahrens 			 * its plaintext representation.
575*fa9e4066Sahrens 			 */
576*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': "
577*fa9e4066Sahrens 			    "too many devices in a single vdev"),
578*fa9e4066Sahrens 			    zhp->zpool_name);
579*fa9e4066Sahrens 			break;
580*fa9e4066Sahrens 
581*fa9e4066Sahrens 		case ENXIO:
582*fa9e4066Sahrens 			/*
583*fa9e4066Sahrens 			 * This is unlikely to happen since we've verified that
584*fa9e4066Sahrens 			 * all the devices can be opened from userland, but it's
585*fa9e4066Sahrens 			 * still possible in some circumstances.
586*fa9e4066Sahrens 			 */
587*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot add to '%s': "
588*fa9e4066Sahrens 			    "one or more devices is unavailable"),
589*fa9e4066Sahrens 			    zhp->zpool_name);
590*fa9e4066Sahrens 			break;
591*fa9e4066Sahrens 
592*fa9e4066Sahrens 		case EOVERFLOW:
593*fa9e4066Sahrens 			/*
594*fa9e4066Sahrens 			 * This occurrs when one of the devices is below
595*fa9e4066Sahrens 			 * SPA_MINDEVSIZE.  Unfortunately, we can't detect which
596*fa9e4066Sahrens 			 * device was the problem device since there's no
597*fa9e4066Sahrens 			 * reliable way to determine device size from userland.
598*fa9e4066Sahrens 			 */
599*fa9e4066Sahrens 			{
600*fa9e4066Sahrens 				char buf[64];
601*fa9e4066Sahrens 
602*fa9e4066Sahrens 				zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
603*fa9e4066Sahrens 
604*fa9e4066Sahrens 				zfs_error(dgettext(TEXT_DOMAIN, "cannot "
605*fa9e4066Sahrens 				    "add to '%s': one or more devices is less "
606*fa9e4066Sahrens 				    "than the minimum size (%s)"),
607*fa9e4066Sahrens 				    zhp->zpool_name, buf);
608*fa9e4066Sahrens 			}
609*fa9e4066Sahrens 			break;
610*fa9e4066Sahrens 
611*fa9e4066Sahrens 		default:
612*fa9e4066Sahrens 			zfs_baderror(errno);
613*fa9e4066Sahrens 		}
614*fa9e4066Sahrens 
615*fa9e4066Sahrens 		return (-1);
616*fa9e4066Sahrens 	}
617*fa9e4066Sahrens 
618*fa9e4066Sahrens 	free(packed);
619*fa9e4066Sahrens 
620*fa9e4066Sahrens 	return (0);
621*fa9e4066Sahrens }
622*fa9e4066Sahrens 
623*fa9e4066Sahrens /*
624*fa9e4066Sahrens  * Exports the pool from the system.  The caller must ensure that there are no
625*fa9e4066Sahrens  * mounted datasets in the pool.
626*fa9e4066Sahrens  */
627*fa9e4066Sahrens int
628*fa9e4066Sahrens zpool_export(zpool_handle_t *zhp)
629*fa9e4066Sahrens {
630*fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
631*fa9e4066Sahrens 
632*fa9e4066Sahrens 	if (zpool_remove_zvol_links(zhp) != 0)
633*fa9e4066Sahrens 		return (-1);
634*fa9e4066Sahrens 
635*fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
636*fa9e4066Sahrens 
637*fa9e4066Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_POOL_EXPORT, &zc) != 0) {
638*fa9e4066Sahrens 		switch (errno) {
639*fa9e4066Sahrens 		case EPERM:
640*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
641*fa9e4066Sahrens 			    "cannot export '%s': permission denied"),
642*fa9e4066Sahrens 			    zhp->zpool_name);
643*fa9e4066Sahrens 			break;
644*fa9e4066Sahrens 
645*fa9e4066Sahrens 		case EBUSY:
646*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
647*fa9e4066Sahrens 			    "cannot export '%s': pool is in use"),
648*fa9e4066Sahrens 			    zhp->zpool_name);
649*fa9e4066Sahrens 			break;
650*fa9e4066Sahrens 
651*fa9e4066Sahrens 		case ENOENT:
652*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
653*fa9e4066Sahrens 			    "cannot export '%s': no such pool"),
654*fa9e4066Sahrens 			    zhp->zpool_name);
655*fa9e4066Sahrens 			break;
656*fa9e4066Sahrens 
657*fa9e4066Sahrens 		default:
658*fa9e4066Sahrens 			zfs_baderror(errno);
659*fa9e4066Sahrens 		}
660*fa9e4066Sahrens 
661*fa9e4066Sahrens 		return (-1);
662*fa9e4066Sahrens 	}
663*fa9e4066Sahrens 
664*fa9e4066Sahrens 	return (0);
665*fa9e4066Sahrens }
666*fa9e4066Sahrens 
667*fa9e4066Sahrens /*
668*fa9e4066Sahrens  * Import the given pool using the known configuration.  The configuration
669*fa9e4066Sahrens  * should have come from zpool_find_import().  The 'newname' and 'altroot'
670*fa9e4066Sahrens  * parameters control whether the pool is imported with a different name or with
671*fa9e4066Sahrens  * an alternate root, respectively.
672*fa9e4066Sahrens  */
673*fa9e4066Sahrens int
674*fa9e4066Sahrens zpool_import(nvlist_t *config, const char *newname, const char *altroot)
675*fa9e4066Sahrens {
676*fa9e4066Sahrens 	zfs_cmd_t zc;
677*fa9e4066Sahrens 	char *packed;
678*fa9e4066Sahrens 	size_t len;
679*fa9e4066Sahrens 	char *thename;
680*fa9e4066Sahrens 	char *origname;
681*fa9e4066Sahrens 	int ret;
682*fa9e4066Sahrens 
683*fa9e4066Sahrens 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
684*fa9e4066Sahrens 	    &origname) == 0);
685*fa9e4066Sahrens 
686*fa9e4066Sahrens 	if (newname != NULL) {
687*fa9e4066Sahrens 		if (!zpool_name_valid(newname, NULL, 0)) {
688*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "cannot import '%s': "
689*fa9e4066Sahrens 			    "invalid pool name"), newname);
690*fa9e4066Sahrens 			return (-1);
691*fa9e4066Sahrens 		}
692*fa9e4066Sahrens 		thename = (char *)newname;
693*fa9e4066Sahrens 	} else {
694*fa9e4066Sahrens 		thename = origname;
695*fa9e4066Sahrens 	}
696*fa9e4066Sahrens 
697*fa9e4066Sahrens 	if (altroot != NULL && altroot[0] != '/') {
698*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "cannot import '%s': alternate "
699*fa9e4066Sahrens 		    "root '%s' must be a complete path"), thename,
700*fa9e4066Sahrens 		    altroot);
701*fa9e4066Sahrens 		return (-1);
702*fa9e4066Sahrens 	}
703*fa9e4066Sahrens 
704*fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name));
705*fa9e4066Sahrens 
706*fa9e4066Sahrens 	if (altroot != NULL)
707*fa9e4066Sahrens 		(void) strlcpy(zc.zc_root, altroot, sizeof (zc.zc_root));
708*fa9e4066Sahrens 	else
709*fa9e4066Sahrens 		zc.zc_root[0] = '\0';
710*fa9e4066Sahrens 
711*fa9e4066Sahrens 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
712*fa9e4066Sahrens 	    &zc.zc_pool_guid) == 0);
713*fa9e4066Sahrens 
714*fa9e4066Sahrens 	verify(nvlist_size(config, &len, NV_ENCODE_NATIVE) == 0);
715*fa9e4066Sahrens 
716*fa9e4066Sahrens 	packed = zfs_malloc(len);
717*fa9e4066Sahrens 
718*fa9e4066Sahrens 	verify(nvlist_pack(config, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
719*fa9e4066Sahrens 
720*fa9e4066Sahrens 	zc.zc_config_src = (uint64_t)(uintptr_t)packed;
721*fa9e4066Sahrens 	zc.zc_config_src_size = len;
722*fa9e4066Sahrens 
723*fa9e4066Sahrens 	ret = 0;
724*fa9e4066Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_POOL_IMPORT, &zc) != 0) {
725*fa9e4066Sahrens 		char desc[1024];
726*fa9e4066Sahrens 		if (newname == NULL)
727*fa9e4066Sahrens 			(void) snprintf(desc, sizeof (desc),
728*fa9e4066Sahrens 			    dgettext(TEXT_DOMAIN, "cannot import '%s'"),
729*fa9e4066Sahrens 			    thename);
730*fa9e4066Sahrens 		else
731*fa9e4066Sahrens 			(void) snprintf(desc, sizeof (desc),
732*fa9e4066Sahrens 			    dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"),
733*fa9e4066Sahrens 			    origname, thename);
734*fa9e4066Sahrens 
735*fa9e4066Sahrens 		switch (errno) {
736*fa9e4066Sahrens 		case EEXIST:
737*fa9e4066Sahrens 			/*
738*fa9e4066Sahrens 			 * A pool with that name already exists.
739*fa9e4066Sahrens 			 */
740*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "%s: pool exists"),
741*fa9e4066Sahrens 			    desc);
742*fa9e4066Sahrens 			break;
743*fa9e4066Sahrens 
744*fa9e4066Sahrens 		case EPERM:
745*fa9e4066Sahrens 			/*
746*fa9e4066Sahrens 			 * The user doesn't have permission to create pools.
747*fa9e4066Sahrens 			 */
748*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "%s: permission "
749*fa9e4066Sahrens 			    "denied"), desc);
750*fa9e4066Sahrens 			break;
751*fa9e4066Sahrens 
752*fa9e4066Sahrens 		case ENXIO:
753*fa9e4066Sahrens 		case EDOM:
754*fa9e4066Sahrens 			/*
755*fa9e4066Sahrens 			 * Device is unavailable, or vdev sum didn't match.
756*fa9e4066Sahrens 			 */
757*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN, "%s: one or more "
758*fa9e4066Sahrens 			    "devices is unavailable"),
759*fa9e4066Sahrens 			    desc);
760*fa9e4066Sahrens 			break;
761*fa9e4066Sahrens 
762*fa9e4066Sahrens 		default:
763*fa9e4066Sahrens 			zfs_baderror(errno);
764*fa9e4066Sahrens 		}
765*fa9e4066Sahrens 
766*fa9e4066Sahrens 		ret = -1;
767*fa9e4066Sahrens 	} else {
768*fa9e4066Sahrens 		zpool_handle_t *zhp;
769*fa9e4066Sahrens 		/*
770*fa9e4066Sahrens 		 * This should never fail, but play it safe anyway.
771*fa9e4066Sahrens 		 */
772*fa9e4066Sahrens 		if ((zhp = zpool_open_silent(thename)) != NULL) {
773*fa9e4066Sahrens 			ret = zpool_create_zvol_links(zhp);
774*fa9e4066Sahrens 			zpool_close(zhp);
775*fa9e4066Sahrens 		}
776*fa9e4066Sahrens 	}
777*fa9e4066Sahrens 
778*fa9e4066Sahrens 	free(packed);
779*fa9e4066Sahrens 	return (ret);
780*fa9e4066Sahrens }
781*fa9e4066Sahrens 
782*fa9e4066Sahrens /*
783*fa9e4066Sahrens  * Scrub the pool.
784*fa9e4066Sahrens  */
785*fa9e4066Sahrens int
786*fa9e4066Sahrens zpool_scrub(zpool_handle_t *zhp, pool_scrub_type_t type)
787*fa9e4066Sahrens {
788*fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
789*fa9e4066Sahrens 	char msg[1024];
790*fa9e4066Sahrens 
791*fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
792*fa9e4066Sahrens 	zc.zc_cookie = type;
793*fa9e4066Sahrens 
794*fa9e4066Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_POOL_SCRUB, &zc) == 0)
795*fa9e4066Sahrens 		return (0);
796*fa9e4066Sahrens 
797*fa9e4066Sahrens 	(void) snprintf(msg, sizeof (msg),
798*fa9e4066Sahrens 	    dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name);
799*fa9e4066Sahrens 
800*fa9e4066Sahrens 	switch (errno) {
801*fa9e4066Sahrens 	    case EPERM:
802*fa9e4066Sahrens 		/*
803*fa9e4066Sahrens 		 * No permission to scrub this pool.
804*fa9e4066Sahrens 		 */
805*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg);
806*fa9e4066Sahrens 		break;
807*fa9e4066Sahrens 
808*fa9e4066Sahrens 	    case EBUSY:
809*fa9e4066Sahrens 		/*
810*fa9e4066Sahrens 		 * Resilver in progress.
811*fa9e4066Sahrens 		 */
812*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: currently resilvering"),
813*fa9e4066Sahrens 		    msg);
814*fa9e4066Sahrens 		break;
815*fa9e4066Sahrens 
816*fa9e4066Sahrens 	    default:
817*fa9e4066Sahrens 		zfs_baderror(errno);
818*fa9e4066Sahrens 	}
819*fa9e4066Sahrens 	return (-1);
820*fa9e4066Sahrens }
821*fa9e4066Sahrens 
822*fa9e4066Sahrens /*
823*fa9e4066Sahrens  * Bring the specified vdev online
824*fa9e4066Sahrens  */
825*fa9e4066Sahrens int
826*fa9e4066Sahrens zpool_vdev_online(zpool_handle_t *zhp, const char *path)
827*fa9e4066Sahrens {
828*fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
829*fa9e4066Sahrens 	char msg[1024];
830*fa9e4066Sahrens 
831*fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
832*fa9e4066Sahrens 	(void) snprintf(zc.zc_prop_value, sizeof (zc.zc_prop_value),
833*fa9e4066Sahrens 	    "%s%s", path[0] == '/' ? "" : "/dev/dsk/", path);
834*fa9e4066Sahrens 
835*fa9e4066Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_VDEV_ONLINE, &zc) == 0)
836*fa9e4066Sahrens 		return (0);
837*fa9e4066Sahrens 
838*fa9e4066Sahrens 	(void) snprintf(msg, sizeof (msg),
839*fa9e4066Sahrens 	    dgettext(TEXT_DOMAIN, "cannot online %s"), zc.zc_prop_value);
840*fa9e4066Sahrens 
841*fa9e4066Sahrens 	switch (errno) {
842*fa9e4066Sahrens 	    case ENODEV:
843*fa9e4066Sahrens 		/*
844*fa9e4066Sahrens 		 * Device doesn't exist
845*fa9e4066Sahrens 		 */
846*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: device not in pool"), msg);
847*fa9e4066Sahrens 		break;
848*fa9e4066Sahrens 
849*fa9e4066Sahrens 	    case EPERM:
850*fa9e4066Sahrens 		/*
851*fa9e4066Sahrens 		 * No permission to bring this vdev online.
852*fa9e4066Sahrens 		 */
853*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg);
854*fa9e4066Sahrens 		break;
855*fa9e4066Sahrens 
856*fa9e4066Sahrens 	    default:
857*fa9e4066Sahrens 		zfs_baderror(errno);
858*fa9e4066Sahrens 	}
859*fa9e4066Sahrens 	return (-1);
860*fa9e4066Sahrens }
861*fa9e4066Sahrens 
862*fa9e4066Sahrens /*
863*fa9e4066Sahrens  * Take the specified vdev offline
864*fa9e4066Sahrens  */
865*fa9e4066Sahrens int
866*fa9e4066Sahrens zpool_vdev_offline(zpool_handle_t *zhp, const char *path)
867*fa9e4066Sahrens {
868*fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
869*fa9e4066Sahrens 	char msg[1024];
870*fa9e4066Sahrens 
871*fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
872*fa9e4066Sahrens 	(void) snprintf(zc.zc_prop_value, sizeof (zc.zc_prop_value),
873*fa9e4066Sahrens 	    "%s%s", path[0] == '/' ? "" : "/dev/dsk/", path);
874*fa9e4066Sahrens 
875*fa9e4066Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_VDEV_OFFLINE, &zc) == 0)
876*fa9e4066Sahrens 		return (0);
877*fa9e4066Sahrens 
878*fa9e4066Sahrens 	(void) snprintf(msg, sizeof (msg),
879*fa9e4066Sahrens 	    dgettext(TEXT_DOMAIN, "cannot offline %s"), zc.zc_prop_value);
880*fa9e4066Sahrens 
881*fa9e4066Sahrens 	switch (errno) {
882*fa9e4066Sahrens 	    case ENODEV:
883*fa9e4066Sahrens 		/*
884*fa9e4066Sahrens 		 * Device doesn't exist
885*fa9e4066Sahrens 		 */
886*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: device not in pool"), msg);
887*fa9e4066Sahrens 		break;
888*fa9e4066Sahrens 
889*fa9e4066Sahrens 	    case EPERM:
890*fa9e4066Sahrens 		/*
891*fa9e4066Sahrens 		 * No permission to take this vdev offline.
892*fa9e4066Sahrens 		 */
893*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg);
894*fa9e4066Sahrens 		break;
895*fa9e4066Sahrens 
896*fa9e4066Sahrens 	    case EBUSY:
897*fa9e4066Sahrens 		/*
898*fa9e4066Sahrens 		 * There are no other replicas of this device.
899*fa9e4066Sahrens 		 */
900*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: no valid replicas"), msg);
901*fa9e4066Sahrens 		break;
902*fa9e4066Sahrens 
903*fa9e4066Sahrens 	    default:
904*fa9e4066Sahrens 		zfs_baderror(errno);
905*fa9e4066Sahrens 	}
906*fa9e4066Sahrens 	return (-1);
907*fa9e4066Sahrens }
908*fa9e4066Sahrens 
909*fa9e4066Sahrens /*
910*fa9e4066Sahrens  * Attach new_disk (fully described by nvroot) to old_disk.
911*fa9e4066Sahrens  * If 'replacing' is specified, tne new disk will replace the old one.
912*fa9e4066Sahrens  */
913*fa9e4066Sahrens int
914*fa9e4066Sahrens zpool_vdev_attach(zpool_handle_t *zhp,
915*fa9e4066Sahrens     const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing)
916*fa9e4066Sahrens {
917*fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
918*fa9e4066Sahrens 	char msg[1024];
919*fa9e4066Sahrens 	char *packed;
920*fa9e4066Sahrens 	int ret;
921*fa9e4066Sahrens 	size_t len;
922*fa9e4066Sahrens 
923*fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
924*fa9e4066Sahrens 	(void) snprintf(zc.zc_prop_value, sizeof (zc.zc_prop_value),
925*fa9e4066Sahrens 	    "%s%s", old_disk[0] == '/' ? "" : "/dev/dsk/", old_disk);
926*fa9e4066Sahrens 	zc.zc_cookie = replacing;
927*fa9e4066Sahrens 
928*fa9e4066Sahrens 	verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0);
929*fa9e4066Sahrens 
930*fa9e4066Sahrens 	packed = zfs_malloc(len);
931*fa9e4066Sahrens 
932*fa9e4066Sahrens 	verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
933*fa9e4066Sahrens 
934*fa9e4066Sahrens 	zc.zc_config_src = (uint64_t)(uintptr_t)packed;
935*fa9e4066Sahrens 	zc.zc_config_src_size = len;
936*fa9e4066Sahrens 
937*fa9e4066Sahrens 	ret = ioctl(zfs_fd, ZFS_IOC_VDEV_ATTACH, &zc);
938*fa9e4066Sahrens 
939*fa9e4066Sahrens 	free(packed);
940*fa9e4066Sahrens 
941*fa9e4066Sahrens 	if (ret == 0)
942*fa9e4066Sahrens 		return (0);
943*fa9e4066Sahrens 
944*fa9e4066Sahrens 	if (replacing)
945*fa9e4066Sahrens 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
946*fa9e4066Sahrens 		    "cannot replace %s with %s"), old_disk, new_disk);
947*fa9e4066Sahrens 	else
948*fa9e4066Sahrens 		(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
949*fa9e4066Sahrens 		    "cannot attach %s to %s"), new_disk, old_disk);
950*fa9e4066Sahrens 
951*fa9e4066Sahrens 	switch (errno) {
952*fa9e4066Sahrens 	    case EPERM:
953*fa9e4066Sahrens 		/*
954*fa9e4066Sahrens 		 * No permission to mess with the config.
955*fa9e4066Sahrens 		 */
956*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg);
957*fa9e4066Sahrens 		break;
958*fa9e4066Sahrens 
959*fa9e4066Sahrens 	    case ENODEV:
960*fa9e4066Sahrens 		/*
961*fa9e4066Sahrens 		 * Device doesn't exist.
962*fa9e4066Sahrens 		 */
963*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: %s not in pool"),
964*fa9e4066Sahrens 		    msg, old_disk);
965*fa9e4066Sahrens 		break;
966*fa9e4066Sahrens 
967*fa9e4066Sahrens 	    case ENOTSUP:
968*fa9e4066Sahrens 		/*
969*fa9e4066Sahrens 		 * Can't attach to or replace this type of vdev.
970*fa9e4066Sahrens 		 */
971*fa9e4066Sahrens 		if (replacing)
972*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
973*fa9e4066Sahrens 			    "%s: cannot replace a replacing device"), msg);
974*fa9e4066Sahrens 		else
975*fa9e4066Sahrens 			zfs_error(dgettext(TEXT_DOMAIN,
976*fa9e4066Sahrens 			    "%s: attach is only applicable to mirrors"), msg);
977*fa9e4066Sahrens 		break;
978*fa9e4066Sahrens 
979*fa9e4066Sahrens 	    case EINVAL:
980*fa9e4066Sahrens 		/*
981*fa9e4066Sahrens 		 * The new device must be a single disk.
982*fa9e4066Sahrens 		 */
983*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN,
984*fa9e4066Sahrens 		    "%s: <new_device> must be a single disk"), msg);
985*fa9e4066Sahrens 		break;
986*fa9e4066Sahrens 
987*fa9e4066Sahrens 	    case ENXIO:
988*fa9e4066Sahrens 		/*
989*fa9e4066Sahrens 		 * This is unlikely to happen since we've verified that
990*fa9e4066Sahrens 		 * all the devices can be opened from userland, but it's
991*fa9e4066Sahrens 		 * still possible in some circumstances.
992*fa9e4066Sahrens 		 */
993*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: %s is unavailable"),
994*fa9e4066Sahrens 		    msg, new_disk);
995*fa9e4066Sahrens 		break;
996*fa9e4066Sahrens 
997*fa9e4066Sahrens 	    case EBUSY:
998*fa9e4066Sahrens 		/*
999*fa9e4066Sahrens 		 * The new device is is use.
1000*fa9e4066Sahrens 		 */
1001*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: %s busy"), msg, new_disk);
1002*fa9e4066Sahrens 		break;
1003*fa9e4066Sahrens 
1004*fa9e4066Sahrens 	    case EOVERFLOW:
1005*fa9e4066Sahrens 		/*
1006*fa9e4066Sahrens 		 * The new device is too small.
1007*fa9e4066Sahrens 		 */
1008*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: %s is too small"),
1009*fa9e4066Sahrens 		    msg, new_disk);
1010*fa9e4066Sahrens 		break;
1011*fa9e4066Sahrens 
1012*fa9e4066Sahrens 	    case EDOM:
1013*fa9e4066Sahrens 		/*
1014*fa9e4066Sahrens 		 * The new device has a different alignment requirement.
1015*fa9e4066Sahrens 		 */
1016*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN,
1017*fa9e4066Sahrens 		    "%s: devices have different sector alignment"), msg);
1018*fa9e4066Sahrens 		break;
1019*fa9e4066Sahrens 
1020*fa9e4066Sahrens 	    case ENAMETOOLONG:
1021*fa9e4066Sahrens 		/*
1022*fa9e4066Sahrens 		 * The resulting top-level vdev spec won't fit in the label.
1023*fa9e4066Sahrens 		 */
1024*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN,
1025*fa9e4066Sahrens 		    "%s: too many devices in a single vdev"), msg);
1026*fa9e4066Sahrens 		break;
1027*fa9e4066Sahrens 
1028*fa9e4066Sahrens 	    default:
1029*fa9e4066Sahrens 		zfs_baderror(errno);
1030*fa9e4066Sahrens 	}
1031*fa9e4066Sahrens 
1032*fa9e4066Sahrens 	return (1);
1033*fa9e4066Sahrens }
1034*fa9e4066Sahrens 
1035*fa9e4066Sahrens /*
1036*fa9e4066Sahrens  * Detach the specified device.
1037*fa9e4066Sahrens  */
1038*fa9e4066Sahrens int
1039*fa9e4066Sahrens zpool_vdev_detach(zpool_handle_t *zhp, const char *path)
1040*fa9e4066Sahrens {
1041*fa9e4066Sahrens 	zfs_cmd_t zc = { 0 };
1042*fa9e4066Sahrens 	char msg[1024];
1043*fa9e4066Sahrens 
1044*fa9e4066Sahrens 	(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1045*fa9e4066Sahrens 	(void) snprintf(zc.zc_prop_value, sizeof (zc.zc_prop_value),
1046*fa9e4066Sahrens 	    "%s%s", path[0] == '/' ? "" : "/dev/dsk/", path);
1047*fa9e4066Sahrens 
1048*fa9e4066Sahrens 	if (ioctl(zfs_fd, ZFS_IOC_VDEV_DETACH, &zc) == 0)
1049*fa9e4066Sahrens 		return (0);
1050*fa9e4066Sahrens 
1051*fa9e4066Sahrens 	(void) snprintf(msg, sizeof (msg),
1052*fa9e4066Sahrens 	    dgettext(TEXT_DOMAIN, "cannot detach %s"), zc.zc_prop_value);
1053*fa9e4066Sahrens 
1054*fa9e4066Sahrens 	switch (errno) {
1055*fa9e4066Sahrens 	    case EPERM:
1056*fa9e4066Sahrens 		/*
1057*fa9e4066Sahrens 		 * No permission to mess with the config.
1058*fa9e4066Sahrens 		 */
1059*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: permission denied"), msg);
1060*fa9e4066Sahrens 		break;
1061*fa9e4066Sahrens 
1062*fa9e4066Sahrens 	    case ENODEV:
1063*fa9e4066Sahrens 		/*
1064*fa9e4066Sahrens 		 * Device doesn't exist.
1065*fa9e4066Sahrens 		 */
1066*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: device not in pool"), msg);
1067*fa9e4066Sahrens 		break;
1068*fa9e4066Sahrens 
1069*fa9e4066Sahrens 	    case ENOTSUP:
1070*fa9e4066Sahrens 		/*
1071*fa9e4066Sahrens 		 * Can't detach from this type of vdev.
1072*fa9e4066Sahrens 		 */
1073*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN,
1074*fa9e4066Sahrens 		    "%s: only applicable to mirror and replacing vdevs"), msg);
1075*fa9e4066Sahrens 		break;
1076*fa9e4066Sahrens 
1077*fa9e4066Sahrens 	    case EBUSY:
1078*fa9e4066Sahrens 		/*
1079*fa9e4066Sahrens 		 * There are no other replicas of this device.
1080*fa9e4066Sahrens 		 */
1081*fa9e4066Sahrens 		zfs_error(dgettext(TEXT_DOMAIN, "%s: no valid replicas"), msg);
1082*fa9e4066Sahrens 		break;
1083*fa9e4066Sahrens 
1084*fa9e4066Sahrens 	    default:
1085*fa9e4066Sahrens 		zfs_baderror(errno);
1086*fa9e4066Sahrens 	}
1087*fa9e4066Sahrens 
1088*fa9e4066Sahrens 	return (1);
1089*fa9e4066Sahrens }
1090*fa9e4066Sahrens 
1091*fa9e4066Sahrens static int
1092*fa9e4066Sahrens do_zvol(zfs_handle_t *zhp, void *data)
1093*fa9e4066Sahrens {
1094*fa9e4066Sahrens 	int linktype = (int)(uintptr_t)data;
1095*fa9e4066Sahrens 	int ret;
1096*fa9e4066Sahrens 
1097*fa9e4066Sahrens 	/*
1098*fa9e4066Sahrens 	 * We check for volblocksize intead of ZFS_TYPE_VOLUME so that we
1099*fa9e4066Sahrens 	 * correctly handle snapshots of volumes.
1100*fa9e4066Sahrens 	 */
1101*fa9e4066Sahrens 	if (zhp->zfs_volblocksize != 0) {
1102*fa9e4066Sahrens 		if (linktype)
1103*fa9e4066Sahrens 			ret = zvol_create_link(zhp->zfs_name);
1104*fa9e4066Sahrens 		else
1105*fa9e4066Sahrens 			ret = zvol_remove_link(zhp->zfs_name);
1106*fa9e4066Sahrens 	}
1107*fa9e4066Sahrens 
1108*fa9e4066Sahrens 	ret = zfs_iter_children(zhp, do_zvol, data);
1109*fa9e4066Sahrens 
1110*fa9e4066Sahrens 	zfs_close(zhp);
1111*fa9e4066Sahrens 	return (ret);
1112*fa9e4066Sahrens }
1113*fa9e4066Sahrens 
1114*fa9e4066Sahrens /*
1115*fa9e4066Sahrens  * Iterate over all zvols in the pool and make any necessary minor nodes.
1116*fa9e4066Sahrens  */
1117*fa9e4066Sahrens int
1118*fa9e4066Sahrens zpool_create_zvol_links(zpool_handle_t *zhp)
1119*fa9e4066Sahrens {
1120*fa9e4066Sahrens 	zfs_handle_t *zfp;
1121*fa9e4066Sahrens 	int ret;
1122*fa9e4066Sahrens 
1123*fa9e4066Sahrens 	/*
1124*fa9e4066Sahrens 	 * If the pool is unavailable, just return success.
1125*fa9e4066Sahrens 	 */
1126*fa9e4066Sahrens 	if ((zfp = make_dataset_handle(zhp->zpool_name)) == NULL)
1127*fa9e4066Sahrens 		return (0);
1128*fa9e4066Sahrens 
1129*fa9e4066Sahrens 	ret = zfs_iter_children(zfp, do_zvol, (void *)TRUE);
1130*fa9e4066Sahrens 
1131*fa9e4066Sahrens 	zfs_close(zfp);
1132*fa9e4066Sahrens 	return (ret);
1133*fa9e4066Sahrens }
1134*fa9e4066Sahrens 
1135*fa9e4066Sahrens /*
1136*fa9e4066Sahrens  * Iterate over all zvols in the poool and remove any minor nodes.
1137*fa9e4066Sahrens  */
1138*fa9e4066Sahrens int
1139*fa9e4066Sahrens zpool_remove_zvol_links(zpool_handle_t *zhp)
1140*fa9e4066Sahrens {
1141*fa9e4066Sahrens 	zfs_handle_t *zfp;
1142*fa9e4066Sahrens 	int ret;
1143*fa9e4066Sahrens 
1144*fa9e4066Sahrens 	/*
1145*fa9e4066Sahrens 	 * If the pool is unavailable, just return success.
1146*fa9e4066Sahrens 	 */
1147*fa9e4066Sahrens 	if ((zfp = make_dataset_handle(zhp->zpool_name)) == NULL)
1148*fa9e4066Sahrens 		return (0);
1149*fa9e4066Sahrens 
1150*fa9e4066Sahrens 	ret = zfs_iter_children(zfp, do_zvol, (void *)FALSE);
1151*fa9e4066Sahrens 
1152*fa9e4066Sahrens 	zfs_close(zfp);
1153*fa9e4066Sahrens 	return (ret);
1154*fa9e4066Sahrens }
1155