]> git.proxmox.com Git - mirror_zfs.git/blame - lib/libzfs/libzfs_pool.c
Fix gcc missing case warnings
[mirror_zfs.git] / lib / libzfs / libzfs_pool.c
CommitLineData
34dc7c2f
BB
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
428870ff 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
34dc7c2f
BB
24 */
25
34dc7c2f
BB
26#include <ctype.h>
27#include <errno.h>
28#include <devid.h>
34dc7c2f
BB
29#include <fcntl.h>
30#include <libintl.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <strings.h>
34#include <unistd.h>
35#include <sys/efi_partition.h>
36#include <sys/vtoc.h>
37#include <sys/zfs_ioctl.h>
9babb374 38#include <dlfcn.h>
34dc7c2f
BB
39
40#include "zfs_namecheck.h"
41#include "zfs_prop.h"
42#include "libzfs_impl.h"
428870ff 43#include "zfs_comutil.h"
34dc7c2f 44
b128c09f
BB
45static int read_efi_label(nvlist_t *config, diskaddr_t *sb);
46
9babb374
BB
47#define DISK_ROOT "/dev/dsk"
48#define RDISK_ROOT "/dev/rdsk"
49#define BACKUP_SLICE "s2"
50
572e2857
BB
51typedef struct prop_flags {
52 int create:1; /* Validate property on creation */
53 int import:1; /* Validate property on import */
54} prop_flags_t;
55
34dc7c2f
BB
56/*
57 * ====================================================================
58 * zpool property functions
59 * ====================================================================
60 */
61
62static int
63zpool_get_all_props(zpool_handle_t *zhp)
64{
2598c001 65 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
66 libzfs_handle_t *hdl = zhp->zpool_hdl;
67
68 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
69
70 if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0)
71 return (-1);
72
73 while (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) {
74 if (errno == ENOMEM) {
75 if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
76 zcmd_free_nvlists(&zc);
77 return (-1);
78 }
79 } else {
80 zcmd_free_nvlists(&zc);
81 return (-1);
82 }
83 }
84
85 if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) {
86 zcmd_free_nvlists(&zc);
87 return (-1);
88 }
89
90 zcmd_free_nvlists(&zc);
91
92 return (0);
93}
94
95static int
96zpool_props_refresh(zpool_handle_t *zhp)
97{
98 nvlist_t *old_props;
99
100 old_props = zhp->zpool_props;
101
102 if (zpool_get_all_props(zhp) != 0)
103 return (-1);
104
105 nvlist_free(old_props);
106 return (0);
107}
108
109static char *
110zpool_get_prop_string(zpool_handle_t *zhp, zpool_prop_t prop,
111 zprop_source_t *src)
112{
113 nvlist_t *nv, *nvl;
114 uint64_t ival;
115 char *value;
116 zprop_source_t source;
117
118 nvl = zhp->zpool_props;
119 if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) {
120 verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &ival) == 0);
121 source = ival;
122 verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
123 } else {
124 source = ZPROP_SRC_DEFAULT;
125 if ((value = (char *)zpool_prop_default_string(prop)) == NULL)
126 value = "-";
127 }
128
129 if (src)
130 *src = source;
131
132 return (value);
133}
134
135uint64_t
136zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop, zprop_source_t *src)
137{
138 nvlist_t *nv, *nvl;
139 uint64_t value;
140 zprop_source_t source;
141
b128c09f
BB
142 if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) {
143 /*
144 * zpool_get_all_props() has most likely failed because
145 * the pool is faulted, but if all we need is the top level
146 * vdev's guid then get it from the zhp config nvlist.
147 */
148 if ((prop == ZPOOL_PROP_GUID) &&
149 (nvlist_lookup_nvlist(zhp->zpool_config,
150 ZPOOL_CONFIG_VDEV_TREE, &nv) == 0) &&
151 (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &value)
152 == 0)) {
153 return (value);
154 }
34dc7c2f 155 return (zpool_prop_default_numeric(prop));
b128c09f 156 }
34dc7c2f
BB
157
158 nvl = zhp->zpool_props;
159 if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) {
160 verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &value) == 0);
161 source = value;
162 verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0);
163 } else {
164 source = ZPROP_SRC_DEFAULT;
165 value = zpool_prop_default_numeric(prop);
166 }
167
168 if (src)
169 *src = source;
170
171 return (value);
172}
173
174/*
175 * Map VDEV STATE to printed strings.
176 */
177char *
178zpool_state_to_name(vdev_state_t state, vdev_aux_t aux)
179{
180 switch (state) {
e75c13c3
BB
181 default:
182 break;
34dc7c2f
BB
183 case VDEV_STATE_CLOSED:
184 case VDEV_STATE_OFFLINE:
185 return (gettext("OFFLINE"));
186 case VDEV_STATE_REMOVED:
187 return (gettext("REMOVED"));
188 case VDEV_STATE_CANT_OPEN:
b128c09f 189 if (aux == VDEV_AUX_CORRUPT_DATA || aux == VDEV_AUX_BAD_LOG)
34dc7c2f 190 return (gettext("FAULTED"));
428870ff
BB
191 else if (aux == VDEV_AUX_SPLIT_POOL)
192 return (gettext("SPLIT"));
34dc7c2f
BB
193 else
194 return (gettext("UNAVAIL"));
195 case VDEV_STATE_FAULTED:
196 return (gettext("FAULTED"));
197 case VDEV_STATE_DEGRADED:
198 return (gettext("DEGRADED"));
199 case VDEV_STATE_HEALTHY:
200 return (gettext("ONLINE"));
201 }
202
203 return (gettext("UNKNOWN"));
204}
205
206/*
207 * Get a zpool property value for 'prop' and return the value in
208 * a pre-allocated buffer.
209 */
210int
211zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
212 zprop_source_t *srctype)
213{
214 uint64_t intval;
215 const char *strval;
216 zprop_source_t src = ZPROP_SRC_NONE;
217 nvlist_t *nvroot;
218 vdev_stat_t *vs;
219 uint_t vsc;
220
221 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
d164b209
BB
222 switch (prop) {
223 case ZPOOL_PROP_NAME:
34dc7c2f 224 (void) strlcpy(buf, zpool_get_name(zhp), len);
d164b209
BB
225 break;
226
227 case ZPOOL_PROP_HEALTH:
34dc7c2f 228 (void) strlcpy(buf, "FAULTED", len);
d164b209
BB
229 break;
230
231 case ZPOOL_PROP_GUID:
232 intval = zpool_get_prop_int(zhp, prop, &src);
b8864a23 233 (void) snprintf(buf, len, "%llu", (u_longlong_t)intval);
d164b209
BB
234 break;
235
236 case ZPOOL_PROP_ALTROOT:
237 case ZPOOL_PROP_CACHEFILE:
238 if (zhp->zpool_props != NULL ||
239 zpool_get_all_props(zhp) == 0) {
240 (void) strlcpy(buf,
241 zpool_get_prop_string(zhp, prop, &src),
242 len);
243 if (srctype != NULL)
244 *srctype = src;
245 return (0);
246 }
247 /* FALLTHROUGH */
248 default:
34dc7c2f 249 (void) strlcpy(buf, "-", len);
d164b209
BB
250 break;
251 }
252
253 if (srctype != NULL)
254 *srctype = src;
34dc7c2f
BB
255 return (0);
256 }
257
258 if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) &&
259 prop != ZPOOL_PROP_NAME)
260 return (-1);
261
262 switch (zpool_prop_get_type(prop)) {
263 case PROP_TYPE_STRING:
264 (void) strlcpy(buf, zpool_get_prop_string(zhp, prop, &src),
265 len);
266 break;
267
268 case PROP_TYPE_NUMBER:
269 intval = zpool_get_prop_int(zhp, prop, &src);
270
271 switch (prop) {
272 case ZPOOL_PROP_SIZE:
428870ff
BB
273 case ZPOOL_PROP_ALLOCATED:
274 case ZPOOL_PROP_FREE:
34dc7c2f
BB
275 (void) zfs_nicenum(intval, buf, len);
276 break;
277
278 case ZPOOL_PROP_CAPACITY:
279 (void) snprintf(buf, len, "%llu%%",
280 (u_longlong_t)intval);
281 break;
282
428870ff
BB
283 case ZPOOL_PROP_DEDUPRATIO:
284 (void) snprintf(buf, len, "%llu.%02llux",
285 (u_longlong_t)(intval / 100),
286 (u_longlong_t)(intval % 100));
287 break;
288
34dc7c2f
BB
289 case ZPOOL_PROP_HEALTH:
290 verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
291 ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
292 verify(nvlist_lookup_uint64_array(nvroot,
428870ff
BB
293 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &vsc)
294 == 0);
34dc7c2f
BB
295
296 (void) strlcpy(buf, zpool_state_to_name(intval,
297 vs->vs_aux), len);
298 break;
299 default:
b8864a23 300 (void) snprintf(buf, len, "%llu", (u_longlong_t)intval);
34dc7c2f
BB
301 }
302 break;
303
304 case PROP_TYPE_INDEX:
305 intval = zpool_get_prop_int(zhp, prop, &src);
306 if (zpool_prop_index_to_string(prop, intval, &strval)
307 != 0)
308 return (-1);
309 (void) strlcpy(buf, strval, len);
310 break;
311
312 default:
313 abort();
314 }
315
316 if (srctype)
317 *srctype = src;
318
319 return (0);
320}
321
322/*
323 * Check if the bootfs name has the same pool name as it is set to.
324 * Assuming bootfs is a valid dataset name.
325 */
326static boolean_t
327bootfs_name_valid(const char *pool, char *bootfs)
328{
329 int len = strlen(pool);
330
b128c09f 331 if (!zfs_name_valid(bootfs, ZFS_TYPE_FILESYSTEM|ZFS_TYPE_SNAPSHOT))
34dc7c2f
BB
332 return (B_FALSE);
333
334 if (strncmp(pool, bootfs, len) == 0 &&
335 (bootfs[len] == '/' || bootfs[len] == '\0'))
336 return (B_TRUE);
337
338 return (B_FALSE);
339}
340
b128c09f
BB
341/*
342 * Inspect the configuration to determine if any of the devices contain
343 * an EFI label.
344 */
345static boolean_t
346pool_uses_efi(nvlist_t *config)
347{
348 nvlist_t **child;
349 uint_t c, children;
350
351 if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN,
352 &child, &children) != 0)
353 return (read_efi_label(config, NULL) >= 0);
354
355 for (c = 0; c < children; c++) {
356 if (pool_uses_efi(child[c]))
357 return (B_TRUE);
358 }
359 return (B_FALSE);
360}
361
362static boolean_t
363pool_is_bootable(zpool_handle_t *zhp)
364{
365 char bootfs[ZPOOL_MAXNAMELEN];
366
367 return (zpool_get_prop(zhp, ZPOOL_PROP_BOOTFS, bootfs,
368 sizeof (bootfs), NULL) == 0 && strncmp(bootfs, "-",
369 sizeof (bootfs)) != 0);
370}
371
372
34dc7c2f
BB
373/*
374 * Given an nvlist of zpool properties to be set, validate that they are
375 * correct, and parse any numeric properties (index, boolean, etc) if they are
376 * specified as strings.
377 */
378static nvlist_t *
b128c09f 379zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
572e2857 380 nvlist_t *props, uint64_t version, prop_flags_t flags, char *errbuf)
34dc7c2f
BB
381{
382 nvpair_t *elem;
383 nvlist_t *retprops;
384 zpool_prop_t prop;
385 char *strval;
386 uint64_t intval;
387 char *slash;
388 struct stat64 statbuf;
b128c09f
BB
389 zpool_handle_t *zhp;
390 nvlist_t *nvroot;
34dc7c2f
BB
391
392 if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) {
393 (void) no_memory(hdl);
394 return (NULL);
395 }
396
397 elem = NULL;
398 while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
399 const char *propname = nvpair_name(elem);
400
401 /*
402 * Make sure this property is valid and applies to this type.
403 */
404 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
405 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
406 "invalid property '%s'"), propname);
407 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
408 goto error;
409 }
410
411 if (zpool_prop_readonly(prop)) {
412 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
413 "is readonly"), propname);
414 (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
415 goto error;
416 }
417
418 if (zprop_parse_value(hdl, elem, prop, ZFS_TYPE_POOL, retprops,
419 &strval, &intval, errbuf) != 0)
420 goto error;
421
422 /*
423 * Perform additional checking for specific properties.
424 */
425 switch (prop) {
e75c13c3
BB
426 default:
427 break;
34dc7c2f
BB
428 case ZPOOL_PROP_VERSION:
429 if (intval < version || intval > SPA_VERSION) {
430 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
431 "property '%s' number %d is invalid."),
432 propname, intval);
433 (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
434 goto error;
435 }
436 break;
437
438 case ZPOOL_PROP_BOOTFS:
572e2857 439 if (flags.create || flags.import) {
34dc7c2f
BB
440 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
441 "property '%s' cannot be set at creation "
442 "or import time"), propname);
443 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
444 goto error;
445 }
446
447 if (version < SPA_VERSION_BOOTFS) {
448 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
449 "pool must be upgraded to support "
450 "'%s' property"), propname);
451 (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
452 goto error;
453 }
454
455 /*
456 * bootfs property value has to be a dataset name and
457 * the dataset has to be in the same pool as it sets to.
458 */
459 if (strval[0] != '\0' && !bootfs_name_valid(poolname,
460 strval)) {
461 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
462 "is an invalid name"), strval);
463 (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
464 goto error;
465 }
b128c09f
BB
466
467 if ((zhp = zpool_open_canfail(hdl, poolname)) == NULL) {
468 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
469 "could not open pool '%s'"), poolname);
470 (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf);
471 goto error;
472 }
473 verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
474 ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
475
476 /*
477 * bootfs property cannot be set on a disk which has
478 * been EFI labeled.
479 */
480 if (pool_uses_efi(nvroot)) {
481 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
482 "property '%s' not supported on "
483 "EFI labeled devices"), propname);
484 (void) zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf);
485 zpool_close(zhp);
486 goto error;
487 }
488 zpool_close(zhp);
34dc7c2f
BB
489 break;
490
491 case ZPOOL_PROP_ALTROOT:
572e2857 492 if (!flags.create && !flags.import) {
34dc7c2f
BB
493 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
494 "property '%s' can only be set during pool "
495 "creation or import"), propname);
496 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
497 goto error;
498 }
499
500 if (strval[0] != '/') {
501 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
502 "bad alternate root '%s'"), strval);
503 (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
504 goto error;
505 }
506 break;
507
508 case ZPOOL_PROP_CACHEFILE:
509 if (strval[0] == '\0')
510 break;
511
512 if (strcmp(strval, "none") == 0)
513 break;
514
515 if (strval[0] != '/') {
516 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
517 "property '%s' must be empty, an "
518 "absolute path, or 'none'"), propname);
519 (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
520 goto error;
521 }
522
523 slash = strrchr(strval, '/');
524
525 if (slash[1] == '\0' || strcmp(slash, "/.") == 0 ||
526 strcmp(slash, "/..") == 0) {
527 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
528 "'%s' is not a valid file"), strval);
529 (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
530 goto error;
531 }
532
533 *slash = '\0';
534
535 if (strval[0] != '\0' &&
536 (stat64(strval, &statbuf) != 0 ||
537 !S_ISDIR(statbuf.st_mode))) {
538 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
539 "'%s' is not a valid directory"),
540 strval);
541 (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
542 goto error;
543 }
544
545 *slash = '/';
546 break;
572e2857
BB
547
548 case ZPOOL_PROP_READONLY:
549 if (!flags.import) {
550 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
551 "property '%s' can only be set at "
552 "import time"), propname);
553 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
554 goto error;
555 }
556 break;
34dc7c2f
BB
557 }
558 }
559
560 return (retprops);
561error:
562 nvlist_free(retprops);
563 return (NULL);
564}
565
566/*
567 * Set zpool property : propname=propval.
568 */
569int
570zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval)
571{
2598c001 572 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
573 int ret = -1;
574 char errbuf[1024];
575 nvlist_t *nvl = NULL;
576 nvlist_t *realprops;
577 uint64_t version;
572e2857 578 prop_flags_t flags = { 0 };
34dc7c2f
BB
579
580 (void) snprintf(errbuf, sizeof (errbuf),
581 dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
582 zhp->zpool_name);
583
34dc7c2f
BB
584 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
585 return (no_memory(zhp->zpool_hdl));
586
587 if (nvlist_add_string(nvl, propname, propval) != 0) {
588 nvlist_free(nvl);
589 return (no_memory(zhp->zpool_hdl));
590 }
591
592 version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
b128c09f 593 if ((realprops = zpool_valid_proplist(zhp->zpool_hdl,
572e2857 594 zhp->zpool_name, nvl, version, flags, errbuf)) == NULL) {
34dc7c2f
BB
595 nvlist_free(nvl);
596 return (-1);
597 }
598
599 nvlist_free(nvl);
600 nvl = realprops;
601
602 /*
603 * Execute the corresponding ioctl() to set this property.
604 */
605 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
606
607 if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl) != 0) {
608 nvlist_free(nvl);
609 return (-1);
610 }
611
612 ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SET_PROPS, &zc);
613
614 zcmd_free_nvlists(&zc);
615 nvlist_free(nvl);
616
617 if (ret)
618 (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf);
619 else
620 (void) zpool_props_refresh(zhp);
621
622 return (ret);
623}
624
625int
626zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
627{
628 libzfs_handle_t *hdl = zhp->zpool_hdl;
629 zprop_list_t *entry;
630 char buf[ZFS_MAXPROPLEN];
631
632 if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0)
633 return (-1);
634
635 for (entry = *plp; entry != NULL; entry = entry->pl_next) {
636
637 if (entry->pl_fixed)
638 continue;
639
640 if (entry->pl_prop != ZPROP_INVAL &&
641 zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf),
642 NULL) == 0) {
643 if (strlen(buf) > entry->pl_width)
644 entry->pl_width = strlen(buf);
645 }
646 }
647
648 return (0);
649}
650
651
9babb374
BB
652/*
653 * Don't start the slice at the default block of 34; many storage
654 * devices will use a stripe width of 128k, so start there instead.
655 */
656#define NEW_START_BLOCK 256
657
34dc7c2f
BB
658/*
659 * Validate the given pool name, optionally putting an extended error message in
660 * 'buf'.
661 */
662boolean_t
663zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool)
664{
665 namecheck_err_t why;
666 char what;
667 int ret;
668
669 ret = pool_namecheck(pool, &why, &what);
670
671 /*
672 * The rules for reserved pool names were extended at a later point.
673 * But we need to support users with existing pools that may now be
674 * invalid. So we only check for this expanded set of names during a
675 * create (or import), and only in userland.
676 */
677 if (ret == 0 && !isopen &&
678 (strncmp(pool, "mirror", 6) == 0 ||
679 strncmp(pool, "raidz", 5) == 0 ||
680 strncmp(pool, "spare", 5) == 0 ||
681 strcmp(pool, "log") == 0)) {
682 if (hdl != NULL)
683 zfs_error_aux(hdl,
684 dgettext(TEXT_DOMAIN, "name is reserved"));
685 return (B_FALSE);
686 }
687
688
689 if (ret != 0) {
690 if (hdl != NULL) {
691 switch (why) {
692 case NAME_ERR_TOOLONG:
693 zfs_error_aux(hdl,
694 dgettext(TEXT_DOMAIN, "name is too long"));
695 break;
696
697 case NAME_ERR_INVALCHAR:
698 zfs_error_aux(hdl,
699 dgettext(TEXT_DOMAIN, "invalid character "
700 "'%c' in pool name"), what);
701 break;
702
703 case NAME_ERR_NOLETTER:
704 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
705 "name must begin with a letter"));
706 break;
707
708 case NAME_ERR_RESERVED:
709 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
710 "name is reserved"));
711 break;
712
713 case NAME_ERR_DISKLIKE:
714 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
715 "pool name is reserved"));
716 break;
717
718 case NAME_ERR_LEADING_SLASH:
719 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
720 "leading slash in name"));
721 break;
722
723 case NAME_ERR_EMPTY_COMPONENT:
724 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
725 "empty component in name"));
726 break;
727
728 case NAME_ERR_TRAILING_SLASH:
729 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
730 "trailing slash in name"));
731 break;
732
733 case NAME_ERR_MULTIPLE_AT:
734 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
735 "multiple '@' delimiters in name"));
736 break;
e75c13c3
BB
737 case NAME_ERR_NO_AT:
738 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
739 "permission set is missing '@'"));
740 break;
34dc7c2f
BB
741 }
742 }
743 return (B_FALSE);
744 }
745
746 return (B_TRUE);
747}
748
749/*
750 * Open a handle to the given pool, even if the pool is currently in the FAULTED
751 * state.
752 */
753zpool_handle_t *
754zpool_open_canfail(libzfs_handle_t *hdl, const char *pool)
755{
756 zpool_handle_t *zhp;
757 boolean_t missing;
758
759 /*
760 * Make sure the pool name is valid.
761 */
762 if (!zpool_name_valid(hdl, B_TRUE, pool)) {
763 (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME,
764 dgettext(TEXT_DOMAIN, "cannot open '%s'"),
765 pool);
766 return (NULL);
767 }
768
769 if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
770 return (NULL);
771
772 zhp->zpool_hdl = hdl;
773 (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
774
775 if (zpool_refresh_stats(zhp, &missing) != 0) {
776 zpool_close(zhp);
777 return (NULL);
778 }
779
780 if (missing) {
781 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "no such pool"));
782 (void) zfs_error_fmt(hdl, EZFS_NOENT,
783 dgettext(TEXT_DOMAIN, "cannot open '%s'"), pool);
784 zpool_close(zhp);
785 return (NULL);
786 }
787
788 return (zhp);
789}
790
791/*
792 * Like the above, but silent on error. Used when iterating over pools (because
793 * the configuration cache may be out of date).
794 */
795int
796zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret)
797{
798 zpool_handle_t *zhp;
799 boolean_t missing;
800
801 if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
802 return (-1);
803
804 zhp->zpool_hdl = hdl;
805 (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
806
807 if (zpool_refresh_stats(zhp, &missing) != 0) {
808 zpool_close(zhp);
809 return (-1);
810 }
811
812 if (missing) {
813 zpool_close(zhp);
814 *ret = NULL;
815 return (0);
816 }
817
818 *ret = zhp;
819 return (0);
820}
821
822/*
823 * Similar to zpool_open_canfail(), but refuses to open pools in the faulted
824 * state.
825 */
826zpool_handle_t *
827zpool_open(libzfs_handle_t *hdl, const char *pool)
828{
829 zpool_handle_t *zhp;
830
831 if ((zhp = zpool_open_canfail(hdl, pool)) == NULL)
832 return (NULL);
833
834 if (zhp->zpool_state == POOL_STATE_UNAVAIL) {
835 (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL,
836 dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name);
837 zpool_close(zhp);
838 return (NULL);
839 }
840
841 return (zhp);
842}
843
844/*
845 * Close the handle. Simply frees the memory associated with the handle.
846 */
847void
848zpool_close(zpool_handle_t *zhp)
849{
850 if (zhp->zpool_config)
851 nvlist_free(zhp->zpool_config);
852 if (zhp->zpool_old_config)
853 nvlist_free(zhp->zpool_old_config);
854 if (zhp->zpool_props)
855 nvlist_free(zhp->zpool_props);
856 free(zhp);
857}
858
859/*
860 * Return the name of the pool.
861 */
862const char *
863zpool_get_name(zpool_handle_t *zhp)
864{
865 return (zhp->zpool_name);
866}
867
868
869/*
870 * Return the state of the pool (ACTIVE or UNAVAILABLE)
871 */
872int
873zpool_get_state(zpool_handle_t *zhp)
874{
875 return (zhp->zpool_state);
876}
877
878/*
879 * Create the named pool, using the provided vdev list. It is assumed
880 * that the consumer has already validated the contents of the nvlist, so we
881 * don't have to worry about error semantics.
882 */
883int
884zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
b128c09f 885 nvlist_t *props, nvlist_t *fsprops)
34dc7c2f 886{
2598c001 887 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
b128c09f
BB
888 nvlist_t *zc_fsprops = NULL;
889 nvlist_t *zc_props = NULL;
34dc7c2f
BB
890 char msg[1024];
891 char *altroot;
b128c09f 892 int ret = -1;
34dc7c2f
BB
893
894 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
895 "cannot create '%s'"), pool);
896
897 if (!zpool_name_valid(hdl, B_FALSE, pool))
898 return (zfs_error(hdl, EZFS_INVALIDNAME, msg));
899
900 if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
901 return (-1);
902
b128c09f 903 if (props) {
572e2857
BB
904 prop_flags_t flags = { .create = B_TRUE, .import = B_FALSE };
905
b128c09f 906 if ((zc_props = zpool_valid_proplist(hdl, pool, props,
572e2857 907 SPA_VERSION_1, flags, msg)) == NULL) {
b128c09f
BB
908 goto create_failed;
909 }
910 }
34dc7c2f 911
b128c09f
BB
912 if (fsprops) {
913 uint64_t zoned;
914 char *zonestr;
915
916 zoned = ((nvlist_lookup_string(fsprops,
917 zfs_prop_to_name(ZFS_PROP_ZONED), &zonestr) == 0) &&
918 strcmp(zonestr, "on") == 0);
919
920 if ((zc_fsprops = zfs_valid_proplist(hdl,
921 ZFS_TYPE_FILESYSTEM, fsprops, zoned, NULL, msg)) == NULL) {
922 goto create_failed;
923 }
924 if (!zc_props &&
925 (nvlist_alloc(&zc_props, NV_UNIQUE_NAME, 0) != 0)) {
926 goto create_failed;
927 }
928 if (nvlist_add_nvlist(zc_props,
929 ZPOOL_ROOTFS_PROPS, zc_fsprops) != 0) {
930 goto create_failed;
931 }
34dc7c2f
BB
932 }
933
b128c09f
BB
934 if (zc_props && zcmd_write_src_nvlist(hdl, &zc, zc_props) != 0)
935 goto create_failed;
936
34dc7c2f
BB
937 (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name));
938
b128c09f 939 if ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_CREATE, &zc)) != 0) {
34dc7c2f
BB
940
941 zcmd_free_nvlists(&zc);
b128c09f
BB
942 nvlist_free(zc_props);
943 nvlist_free(zc_fsprops);
34dc7c2f
BB
944
945 switch (errno) {
946 case EBUSY:
947 /*
948 * This can happen if the user has specified the same
949 * device multiple times. We can't reliably detect this
950 * until we try to add it and see we already have a
951 * label.
952 */
953 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
954 "one or more vdevs refer to the same device"));
955 return (zfs_error(hdl, EZFS_BADDEV, msg));
956
957 case EOVERFLOW:
958 /*
959 * This occurs when one of the devices is below
960 * SPA_MINDEVSIZE. Unfortunately, we can't detect which
961 * device was the problem device since there's no
962 * reliable way to determine device size from userland.
963 */
964 {
965 char buf[64];
966
967 zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
968
969 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
970 "one or more devices is less than the "
971 "minimum size (%s)"), buf);
972 }
973 return (zfs_error(hdl, EZFS_BADDEV, msg));
974
975 case ENOSPC:
976 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
977 "one or more devices is out of space"));
978 return (zfs_error(hdl, EZFS_BADDEV, msg));
979
980 case ENOTBLK:
981 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
982 "cache device must be a disk or disk slice"));
983 return (zfs_error(hdl, EZFS_BADDEV, msg));
984
985 default:
986 return (zpool_standard_error(hdl, errno, msg));
987 }
988 }
989
990 /*
991 * If this is an alternate root pool, then we automatically set the
992 * mountpoint of the root dataset to be '/'.
993 */
994 if (nvlist_lookup_string(props, zpool_prop_to_name(ZPOOL_PROP_ALTROOT),
995 &altroot) == 0) {
996 zfs_handle_t *zhp;
997
998 verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_DATASET)) != NULL);
999 verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
1000 "/") == 0);
1001
1002 zfs_close(zhp);
1003 }
1004
b128c09f 1005create_failed:
34dc7c2f 1006 zcmd_free_nvlists(&zc);
b128c09f
BB
1007 nvlist_free(zc_props);
1008 nvlist_free(zc_fsprops);
1009 return (ret);
34dc7c2f
BB
1010}
1011
1012/*
1013 * Destroy the given pool. It is up to the caller to ensure that there are no
1014 * datasets left in the pool.
1015 */
1016int
1017zpool_destroy(zpool_handle_t *zhp)
1018{
2598c001 1019 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
1020 zfs_handle_t *zfp = NULL;
1021 libzfs_handle_t *hdl = zhp->zpool_hdl;
1022 char msg[1024];
1023
1024 if (zhp->zpool_state == POOL_STATE_ACTIVE &&
572e2857 1025 (zfp = zfs_open(hdl, zhp->zpool_name, ZFS_TYPE_FILESYSTEM)) == NULL)
34dc7c2f
BB
1026 return (-1);
1027
34dc7c2f
BB
1028 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1029
572e2857 1030 if (zfs_ioctl(hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
34dc7c2f
BB
1031 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1032 "cannot destroy '%s'"), zhp->zpool_name);
1033
1034 if (errno == EROFS) {
1035 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1036 "one or more devices is read only"));
1037 (void) zfs_error(hdl, EZFS_BADDEV, msg);
1038 } else {
1039 (void) zpool_standard_error(hdl, errno, msg);
1040 }
1041
1042 if (zfp)
1043 zfs_close(zfp);
1044 return (-1);
1045 }
1046
1047 if (zfp) {
1048 remove_mountpoint(zfp);
1049 zfs_close(zfp);
1050 }
1051
1052 return (0);
1053}
1054
1055/*
1056 * Add the given vdevs to the pool. The caller must have already performed the
1057 * necessary verification to ensure that the vdev specification is well-formed.
1058 */
1059int
1060zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
1061{
2598c001 1062 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
1063 int ret;
1064 libzfs_handle_t *hdl = zhp->zpool_hdl;
1065 char msg[1024];
1066 nvlist_t **spares, **l2cache;
1067 uint_t nspares, nl2cache;
1068
1069 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1070 "cannot add to '%s'"), zhp->zpool_name);
1071
1072 if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
1073 SPA_VERSION_SPARES &&
1074 nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
1075 &spares, &nspares) == 0) {
1076 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
1077 "upgraded to add hot spares"));
1078 return (zfs_error(hdl, EZFS_BADVERSION, msg));
1079 }
1080
b128c09f
BB
1081 if (pool_is_bootable(zhp) && nvlist_lookup_nvlist_array(nvroot,
1082 ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0) {
1083 uint64_t s;
1084
1085 for (s = 0; s < nspares; s++) {
1086 char *path;
1087
1088 if (nvlist_lookup_string(spares[s], ZPOOL_CONFIG_PATH,
1089 &path) == 0 && pool_uses_efi(spares[s])) {
1090 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1091 "device '%s' contains an EFI label and "
1092 "cannot be used on root pools."),
428870ff
BB
1093 zpool_vdev_name(hdl, NULL, spares[s],
1094 B_FALSE));
b128c09f
BB
1095 return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg));
1096 }
1097 }
1098 }
1099
34dc7c2f
BB
1100 if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
1101 SPA_VERSION_L2CACHE &&
1102 nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
1103 &l2cache, &nl2cache) == 0) {
1104 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
1105 "upgraded to add cache devices"));
1106 return (zfs_error(hdl, EZFS_BADVERSION, msg));
1107 }
1108
1109 if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
1110 return (-1);
1111 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1112
572e2857 1113 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_ADD, &zc) != 0) {
34dc7c2f
BB
1114 switch (errno) {
1115 case EBUSY:
1116 /*
1117 * This can happen if the user has specified the same
1118 * device multiple times. We can't reliably detect this
1119 * until we try to add it and see we already have a
1120 * label.
1121 */
1122 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1123 "one or more vdevs refer to the same device"));
1124 (void) zfs_error(hdl, EZFS_BADDEV, msg);
1125 break;
1126
1127 case EOVERFLOW:
1128 /*
1129 * This occurrs when one of the devices is below
1130 * SPA_MINDEVSIZE. Unfortunately, we can't detect which
1131 * device was the problem device since there's no
1132 * reliable way to determine device size from userland.
1133 */
1134 {
1135 char buf[64];
1136
1137 zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
1138
1139 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1140 "device is less than the minimum "
1141 "size (%s)"), buf);
1142 }
1143 (void) zfs_error(hdl, EZFS_BADDEV, msg);
1144 break;
1145
1146 case ENOTSUP:
1147 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1148 "pool must be upgraded to add these vdevs"));
1149 (void) zfs_error(hdl, EZFS_BADVERSION, msg);
1150 break;
1151
1152 case EDOM:
1153 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1154 "root pool can not have multiple vdevs"
1155 " or separate logs"));
1156 (void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg);
1157 break;
1158
1159 case ENOTBLK:
1160 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1161 "cache device must be a disk or disk slice"));
1162 (void) zfs_error(hdl, EZFS_BADDEV, msg);
1163 break;
1164
1165 default:
1166 (void) zpool_standard_error(hdl, errno, msg);
1167 }
1168
1169 ret = -1;
1170 } else {
1171 ret = 0;
1172 }
1173
1174 zcmd_free_nvlists(&zc);
1175
1176 return (ret);
1177}
1178
1179/*
1180 * Exports the pool from the system. The caller must ensure that there are no
1181 * mounted datasets in the pool.
1182 */
1183int
fb5f0bc8 1184zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce)
34dc7c2f 1185{
2598c001 1186 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
b128c09f 1187 char msg[1024];
34dc7c2f 1188
b128c09f
BB
1189 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1190 "cannot export '%s'"), zhp->zpool_name);
1191
34dc7c2f 1192 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
b128c09f 1193 zc.zc_cookie = force;
fb5f0bc8 1194 zc.zc_guid = hardforce;
b128c09f
BB
1195
1196 if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) {
1197 switch (errno) {
1198 case EXDEV:
1199 zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
1200 "use '-f' to override the following errors:\n"
1201 "'%s' has an active shared spare which could be"
1202 " used by other pools once '%s' is exported."),
1203 zhp->zpool_name, zhp->zpool_name);
1204 return (zfs_error(zhp->zpool_hdl, EZFS_ACTIVE_SPARE,
1205 msg));
1206 default:
1207 return (zpool_standard_error_fmt(zhp->zpool_hdl, errno,
1208 msg));
1209 }
1210 }
34dc7c2f 1211
34dc7c2f
BB
1212 return (0);
1213}
1214
fb5f0bc8
BB
1215int
1216zpool_export(zpool_handle_t *zhp, boolean_t force)
1217{
1218 return (zpool_export_common(zhp, force, B_FALSE));
1219}
1220
1221int
1222zpool_export_force(zpool_handle_t *zhp)
1223{
1224 return (zpool_export_common(zhp, B_TRUE, B_TRUE));
1225}
1226
428870ff
BB
1227static void
1228zpool_rewind_exclaim(libzfs_handle_t *hdl, const char *name, boolean_t dryrun,
572e2857 1229 nvlist_t *config)
428870ff 1230{
572e2857 1231 nvlist_t *nv = NULL;
428870ff
BB
1232 uint64_t rewindto;
1233 int64_t loss = -1;
1234 struct tm t;
1235 char timestr[128];
1236
572e2857
BB
1237 if (!hdl->libzfs_printerr || config == NULL)
1238 return;
1239
1240 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0)
428870ff
BB
1241 return;
1242
572e2857 1243 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
428870ff 1244 return;
572e2857 1245 (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss);
428870ff
BB
1246
1247 if (localtime_r((time_t *)&rewindto, &t) != NULL &&
b8864a23 1248 strftime(timestr, 128, "%c", &t) != 0) {
428870ff
BB
1249 if (dryrun) {
1250 (void) printf(dgettext(TEXT_DOMAIN,
1251 "Would be able to return %s "
1252 "to its state as of %s.\n"),
1253 name, timestr);
1254 } else {
1255 (void) printf(dgettext(TEXT_DOMAIN,
1256 "Pool %s returned to its state as of %s.\n"),
1257 name, timestr);
1258 }
1259 if (loss > 120) {
1260 (void) printf(dgettext(TEXT_DOMAIN,
1261 "%s approximately %lld "),
1262 dryrun ? "Would discard" : "Discarded",
b8864a23 1263 ((longlong_t)loss + 30) / 60);
428870ff
BB
1264 (void) printf(dgettext(TEXT_DOMAIN,
1265 "minutes of transactions.\n"));
1266 } else if (loss > 0) {
1267 (void) printf(dgettext(TEXT_DOMAIN,
1268 "%s approximately %lld "),
b8864a23
BB
1269 dryrun ? "Would discard" : "Discarded",
1270 (longlong_t)loss);
428870ff
BB
1271 (void) printf(dgettext(TEXT_DOMAIN,
1272 "seconds of transactions.\n"));
1273 }
1274 }
1275}
1276
1277void
1278zpool_explain_recover(libzfs_handle_t *hdl, const char *name, int reason,
1279 nvlist_t *config)
1280{
572e2857 1281 nvlist_t *nv = NULL;
428870ff
BB
1282 int64_t loss = -1;
1283 uint64_t edata = UINT64_MAX;
1284 uint64_t rewindto;
1285 struct tm t;
1286 char timestr[128];
1287
1288 if (!hdl->libzfs_printerr)
1289 return;
1290
1291 if (reason >= 0)
1292 (void) printf(dgettext(TEXT_DOMAIN, "action: "));
1293 else
1294 (void) printf(dgettext(TEXT_DOMAIN, "\t"));
1295
1296 /* All attempted rewinds failed if ZPOOL_CONFIG_LOAD_TIME missing */
572e2857
BB
1297 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||
1298 nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
428870ff
BB
1299 goto no_info;
1300
572e2857
BB
1301 (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss);
1302 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_DATA_ERRORS,
428870ff
BB
1303 &edata);
1304
1305 (void) printf(dgettext(TEXT_DOMAIN,
1306 "Recovery is possible, but will result in some data loss.\n"));
1307
1308 if (localtime_r((time_t *)&rewindto, &t) != NULL &&
b8864a23 1309 strftime(timestr, 128, "%c", &t) != 0) {
428870ff
BB
1310 (void) printf(dgettext(TEXT_DOMAIN,
1311 "\tReturning the pool to its state as of %s\n"
1312 "\tshould correct the problem. "),
1313 timestr);
1314 } else {
1315 (void) printf(dgettext(TEXT_DOMAIN,
1316 "\tReverting the pool to an earlier state "
1317 "should correct the problem.\n\t"));
1318 }
1319
1320 if (loss > 120) {
1321 (void) printf(dgettext(TEXT_DOMAIN,
1322 "Approximately %lld minutes of data\n"
b8864a23
BB
1323 "\tmust be discarded, irreversibly. "),
1324 ((longlong_t)loss + 30) / 60);
428870ff
BB
1325 } else if (loss > 0) {
1326 (void) printf(dgettext(TEXT_DOMAIN,
1327 "Approximately %lld seconds of data\n"
b8864a23
BB
1328 "\tmust be discarded, irreversibly. "),
1329 (longlong_t)loss);
428870ff
BB
1330 }
1331 if (edata != 0 && edata != UINT64_MAX) {
1332 if (edata == 1) {
1333 (void) printf(dgettext(TEXT_DOMAIN,
1334 "After rewind, at least\n"
1335 "\tone persistent user-data error will remain. "));
1336 } else {
1337 (void) printf(dgettext(TEXT_DOMAIN,
1338 "After rewind, several\n"
1339 "\tpersistent user-data errors will remain. "));
1340 }
1341 }
1342 (void) printf(dgettext(TEXT_DOMAIN,
1343 "Recovery can be attempted\n\tby executing 'zpool %s -F %s'. "),
1344 reason >= 0 ? "clear" : "import", name);
1345
1346 (void) printf(dgettext(TEXT_DOMAIN,
1347 "A scrub of the pool\n"
1348 "\tis strongly recommended after recovery.\n"));
1349 return;
1350
1351no_info:
1352 (void) printf(dgettext(TEXT_DOMAIN,
1353 "Destroy and re-create the pool from\n\ta backup source.\n"));
1354}
1355
34dc7c2f
BB
1356/*
1357 * zpool_import() is a contracted interface. Should be kept the same
1358 * if possible.
1359 *
1360 * Applications should use zpool_import_props() to import a pool with
1361 * new properties value to be set.
1362 */
1363int
1364zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
1365 char *altroot)
1366{
1367 nvlist_t *props = NULL;
1368 int ret;
1369
1370 if (altroot != NULL) {
1371 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
1372 return (zfs_error_fmt(hdl, EZFS_NOMEM,
1373 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1374 newname));
1375 }
1376
1377 if (nvlist_add_string(props,
fb5f0bc8
BB
1378 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), altroot) != 0 ||
1379 nvlist_add_string(props,
1380 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), "none") != 0) {
34dc7c2f
BB
1381 nvlist_free(props);
1382 return (zfs_error_fmt(hdl, EZFS_NOMEM,
1383 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1384 newname));
1385 }
1386 }
1387
572e2857
BB
1388 ret = zpool_import_props(hdl, config, newname, props,
1389 ZFS_IMPORT_NORMAL);
34dc7c2f
BB
1390 if (props)
1391 nvlist_free(props);
1392 return (ret);
1393}
1394
572e2857
BB
1395static void
1396print_vdev_tree(libzfs_handle_t *hdl, const char *name, nvlist_t *nv,
1397 int indent)
1398{
1399 nvlist_t **child;
1400 uint_t c, children;
1401 char *vname;
1402 uint64_t is_log = 0;
1403
1404 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG,
1405 &is_log);
1406
1407 if (name != NULL)
1408 (void) printf("\t%*s%s%s\n", indent, "", name,
1409 is_log ? " [log]" : "");
1410
1411 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1412 &child, &children) != 0)
1413 return;
1414
1415 for (c = 0; c < children; c++) {
1416 vname = zpool_vdev_name(hdl, NULL, child[c], B_TRUE);
1417 print_vdev_tree(hdl, vname, child[c], indent + 2);
1418 free(vname);
1419 }
1420}
1421
34dc7c2f
BB
1422/*
1423 * Import the given pool using the known configuration and a list of
1424 * properties to be set. The configuration should have come from
1425 * zpool_find_import(). The 'newname' parameters control whether the pool
1426 * is imported with a different name.
1427 */
1428int
1429zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
572e2857 1430 nvlist_t *props, int flags)
34dc7c2f 1431{
2598c001 1432 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
428870ff 1433 zpool_rewind_policy_t policy;
572e2857
BB
1434 nvlist_t *nv = NULL;
1435 nvlist_t *nvinfo = NULL;
1436 nvlist_t *missing = NULL;
34dc7c2f
BB
1437 char *thename;
1438 char *origname;
1439 int ret;
572e2857 1440 int error = 0;
34dc7c2f
BB
1441 char errbuf[1024];
1442
1443 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1444 &origname) == 0);
1445
1446 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1447 "cannot import pool '%s'"), origname);
1448
1449 if (newname != NULL) {
1450 if (!zpool_name_valid(hdl, B_FALSE, newname))
1451 return (zfs_error_fmt(hdl, EZFS_INVALIDNAME,
1452 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1453 newname));
1454 thename = (char *)newname;
1455 } else {
1456 thename = origname;
1457 }
1458
1459 if (props) {
1460 uint64_t version;
572e2857 1461 prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE };
34dc7c2f
BB
1462
1463 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
1464 &version) == 0);
1465
b128c09f 1466 if ((props = zpool_valid_proplist(hdl, origname,
572e2857 1467 props, version, flags, errbuf)) == NULL) {
34dc7c2f
BB
1468 return (-1);
1469 } else if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
1470 nvlist_free(props);
1471 return (-1);
1472 }
1473 }
1474
1475 (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name));
1476
1477 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1478 &zc.zc_guid) == 0);
1479
1480 if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0) {
1481 nvlist_free(props);
1482 return (-1);
1483 }
572e2857 1484 if (zcmd_alloc_dst_nvlist(hdl, &zc, zc.zc_nvlist_conf_size * 2) != 0) {
428870ff
BB
1485 nvlist_free(props);
1486 return (-1);
1487 }
34dc7c2f 1488
572e2857
BB
1489 zc.zc_cookie = flags;
1490 while ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_IMPORT, &zc)) != 0 &&
1491 errno == ENOMEM) {
1492 if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
1493 zcmd_free_nvlists(&zc);
1494 return (-1);
1495 }
1496 }
1497 if (ret != 0)
1498 error = errno;
1499
1500 (void) zcmd_read_dst_nvlist(hdl, &zc, &nv);
1501 zpool_get_rewind_policy(config, &policy);
1502
1503 if (error) {
34dc7c2f 1504 char desc[1024];
428870ff 1505
428870ff
BB
1506 /*
1507 * Dry-run failed, but we print out what success
1508 * looks like if we found a best txg
1509 */
572e2857 1510 if (policy.zrp_request & ZPOOL_TRY_REWIND) {
428870ff 1511 zpool_rewind_exclaim(hdl, newname ? origname : thename,
572e2857
BB
1512 B_TRUE, nv);
1513 nvlist_free(nv);
428870ff
BB
1514 return (-1);
1515 }
1516
34dc7c2f
BB
1517 if (newname == NULL)
1518 (void) snprintf(desc, sizeof (desc),
1519 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1520 thename);
1521 else
1522 (void) snprintf(desc, sizeof (desc),
1523 dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"),
1524 origname, thename);
1525
572e2857 1526 switch (error) {
34dc7c2f
BB
1527 case ENOTSUP:
1528 /*
1529 * Unsupported version.
1530 */
1531 (void) zfs_error(hdl, EZFS_BADVERSION, desc);
1532 break;
1533
1534 case EINVAL:
1535 (void) zfs_error(hdl, EZFS_INVALCONFIG, desc);
1536 break;
1537
428870ff
BB
1538 case EROFS:
1539 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1540 "one or more devices is read only"));
1541 (void) zfs_error(hdl, EZFS_BADDEV, desc);
1542 break;
1543
572e2857
BB
1544 case ENXIO:
1545 if (nv && nvlist_lookup_nvlist(nv,
1546 ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 &&
1547 nvlist_lookup_nvlist(nvinfo,
1548 ZPOOL_CONFIG_MISSING_DEVICES, &missing) == 0) {
1549 (void) printf(dgettext(TEXT_DOMAIN,
1550 "The devices below are missing, use "
1551 "'-m' to import the pool anyway:\n"));
1552 print_vdev_tree(hdl, NULL, missing, 2);
1553 (void) printf("\n");
1554 }
1555 (void) zpool_standard_error(hdl, error, desc);
1556 break;
1557
1558 case EEXIST:
1559 (void) zpool_standard_error(hdl, error, desc);
1560 break;
1561
34dc7c2f 1562 default:
572e2857 1563 (void) zpool_standard_error(hdl, error, desc);
428870ff 1564 zpool_explain_recover(hdl,
572e2857 1565 newname ? origname : thename, -error, nv);
428870ff 1566 break;
34dc7c2f
BB
1567 }
1568
572e2857 1569 nvlist_free(nv);
34dc7c2f
BB
1570 ret = -1;
1571 } else {
1572 zpool_handle_t *zhp;
1573
1574 /*
1575 * This should never fail, but play it safe anyway.
1576 */
428870ff 1577 if (zpool_open_silent(hdl, thename, &zhp) != 0)
34dc7c2f 1578 ret = -1;
428870ff 1579 else if (zhp != NULL)
34dc7c2f 1580 zpool_close(zhp);
428870ff
BB
1581 if (policy.zrp_request &
1582 (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) {
1583 zpool_rewind_exclaim(hdl, newname ? origname : thename,
572e2857 1584 ((policy.zrp_request & ZPOOL_TRY_REWIND) != 0), nv);
34dc7c2f 1585 }
572e2857 1586 nvlist_free(nv);
428870ff 1587 return (0);
34dc7c2f
BB
1588 }
1589
1590 zcmd_free_nvlists(&zc);
1591 nvlist_free(props);
1592
1593 return (ret);
1594}
1595
1596/*
428870ff 1597 * Scan the pool.
34dc7c2f
BB
1598 */
1599int
428870ff 1600zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func)
34dc7c2f 1601{
2598c001 1602 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
1603 char msg[1024];
1604 libzfs_handle_t *hdl = zhp->zpool_hdl;
1605
1606 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
428870ff 1607 zc.zc_cookie = func;
34dc7c2f 1608
572e2857 1609 if (zfs_ioctl(hdl, ZFS_IOC_POOL_SCAN, &zc) == 0 ||
428870ff 1610 (errno == ENOENT && func != POOL_SCAN_NONE))
34dc7c2f
BB
1611 return (0);
1612
428870ff
BB
1613 if (func == POOL_SCAN_SCRUB) {
1614 (void) snprintf(msg, sizeof (msg),
1615 dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name);
1616 } else if (func == POOL_SCAN_NONE) {
1617 (void) snprintf(msg, sizeof (msg),
1618 dgettext(TEXT_DOMAIN, "cannot cancel scrubbing %s"),
1619 zc.zc_name);
1620 } else {
1621 assert(!"unexpected result");
1622 }
34dc7c2f 1623
428870ff
BB
1624 if (errno == EBUSY) {
1625 nvlist_t *nvroot;
1626 pool_scan_stat_t *ps = NULL;
1627 uint_t psc;
1628
1629 verify(nvlist_lookup_nvlist(zhp->zpool_config,
1630 ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
1631 (void) nvlist_lookup_uint64_array(nvroot,
1632 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &psc);
1633 if (ps && ps->pss_func == POOL_SCAN_SCRUB)
1634 return (zfs_error(hdl, EZFS_SCRUBBING, msg));
1635 else
1636 return (zfs_error(hdl, EZFS_RESILVERING, msg));
1637 } else if (errno == ENOENT) {
1638 return (zfs_error(hdl, EZFS_NO_SCRUB, msg));
1639 } else {
34dc7c2f 1640 return (zpool_standard_error(hdl, errno, msg));
428870ff
BB
1641 }
1642}
1643
1644/*
1645 * This provides a very minimal check whether a given string is likely a
1646 * c#t#d# style string. Users of this are expected to do their own
1647 * verification of the s# part.
1648 */
1649#define CTD_CHECK(str) (str && str[0] == 'c' && isdigit(str[1]))
1650
1651/*
1652 * More elaborate version for ones which may start with "/dev/dsk/"
1653 * and the like.
1654 */
1655static int
1656ctd_check_path(char *str) {
1657 /*
1658 * If it starts with a slash, check the last component.
1659 */
1660 if (str && str[0] == '/') {
1661 char *tmp = strrchr(str, '/');
1662
1663 /*
1664 * If it ends in "/old", check the second-to-last
1665 * component of the string instead.
1666 */
1667 if (tmp != str && strcmp(tmp, "/old") == 0) {
1668 for (tmp--; *tmp != '/'; tmp--)
1669 ;
1670 }
1671 str = tmp + 1;
1672 }
1673 return (CTD_CHECK(str));
34dc7c2f
BB
1674}
1675
1676/*
9babb374
BB
1677 * Find a vdev that matches the search criteria specified. We use the
1678 * the nvpair name to determine how we should look for the device.
34dc7c2f
BB
1679 * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL
1680 * spare; but FALSE if its an INUSE spare.
1681 */
1682static nvlist_t *
9babb374
BB
1683vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
1684 boolean_t *l2cache, boolean_t *log)
34dc7c2f
BB
1685{
1686 uint_t c, children;
1687 nvlist_t **child;
34dc7c2f 1688 nvlist_t *ret;
b128c09f 1689 uint64_t is_log;
9babb374
BB
1690 char *srchkey;
1691 nvpair_t *pair = nvlist_next_nvpair(search, NULL);
1692
1693 /* Nothing to look for */
1694 if (search == NULL || pair == NULL)
1695 return (NULL);
1696
1697 /* Obtain the key we will use to search */
1698 srchkey = nvpair_name(pair);
1699
1700 switch (nvpair_type(pair)) {
572e2857 1701 case DATA_TYPE_UINT64:
9babb374 1702 if (strcmp(srchkey, ZPOOL_CONFIG_GUID) == 0) {
572e2857
BB
1703 uint64_t srchval, theguid;
1704
1705 verify(nvpair_value_uint64(pair, &srchval) == 0);
1706 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1707 &theguid) == 0);
1708 if (theguid == srchval)
1709 return (nv);
9babb374
BB
1710 }
1711 break;
9babb374
BB
1712
1713 case DATA_TYPE_STRING: {
1714 char *srchval, *val;
1715
1716 verify(nvpair_value_string(pair, &srchval) == 0);
1717 if (nvlist_lookup_string(nv, srchkey, &val) != 0)
1718 break;
34dc7c2f 1719
9babb374 1720 /*
428870ff
BB
1721 * Search for the requested value. Special cases:
1722 *
1723 * - ZPOOL_CONFIG_PATH for whole disk entries. These end in
1724 * "s0" or "s0/old". The "s0" part is hidden from the user,
1725 * but included in the string, so this matches around it.
1726 * - looking for a top-level vdev name (i.e. ZPOOL_CONFIG_TYPE).
1727 *
1728 * Otherwise, all other searches are simple string compares.
9babb374 1729 */
428870ff
BB
1730 if (strcmp(srchkey, ZPOOL_CONFIG_PATH) == 0 &&
1731 ctd_check_path(val)) {
9babb374
BB
1732 uint64_t wholedisk = 0;
1733
1734 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
1735 &wholedisk);
1736 if (wholedisk) {
428870ff
BB
1737 int slen = strlen(srchval);
1738 int vlen = strlen(val);
1739
1740 if (slen != vlen - 2)
1741 break;
1742
1743 /*
1744 * make_leaf_vdev() should only set
1745 * wholedisk for ZPOOL_CONFIG_PATHs which
1746 * will include "/dev/dsk/", giving plenty of
1747 * room for the indices used next.
1748 */
1749 ASSERT(vlen >= 6);
1750
9babb374 1751 /*
428870ff 1752 * strings identical except trailing "s0"
9babb374 1753 */
428870ff
BB
1754 if (strcmp(&val[vlen - 2], "s0") == 0 &&
1755 strncmp(srchval, val, slen) == 0)
9babb374 1756 return (nv);
428870ff
BB
1757
1758 /*
1759 * strings identical except trailing "s0/old"
1760 */
1761 if (strcmp(&val[vlen - 6], "s0/old") == 0 &&
1762 strcmp(&srchval[slen - 4], "/old") == 0 &&
1763 strncmp(srchval, val, slen - 4) == 0)
1764 return (nv);
1765
9babb374
BB
1766 break;
1767 }
428870ff
BB
1768 } else if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0 && val) {
1769 char *type, *idx, *end, *p;
1770 uint64_t id, vdev_id;
1771
1772 /*
1773 * Determine our vdev type, keeping in mind
1774 * that the srchval is composed of a type and
1775 * vdev id pair (i.e. mirror-4).
1776 */
1777 if ((type = strdup(srchval)) == NULL)
1778 return (NULL);
1779
1780 if ((p = strrchr(type, '-')) == NULL) {
1781 free(type);
1782 break;
1783 }
1784 idx = p + 1;
1785 *p = '\0';
1786
1787 /*
1788 * If the types don't match then keep looking.
1789 */
1790 if (strncmp(val, type, strlen(val)) != 0) {
1791 free(type);
1792 break;
1793 }
1794
1795 verify(strncmp(type, VDEV_TYPE_RAIDZ,
1796 strlen(VDEV_TYPE_RAIDZ)) == 0 ||
1797 strncmp(type, VDEV_TYPE_MIRROR,
1798 strlen(VDEV_TYPE_MIRROR)) == 0);
1799 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID,
1800 &id) == 0);
1801
1802 errno = 0;
1803 vdev_id = strtoull(idx, &end, 10);
1804
1805 free(type);
1806 if (errno != 0)
1807 return (NULL);
1808
1809 /*
1810 * Now verify that we have the correct vdev id.
1811 */
1812 if (vdev_id == id)
1813 return (nv);
9babb374 1814 }
34dc7c2f 1815
34dc7c2f 1816 /*
9babb374 1817 * Common case
34dc7c2f 1818 */
9babb374 1819 if (strcmp(srchval, val) == 0)
34dc7c2f 1820 return (nv);
9babb374
BB
1821 break;
1822 }
1823
1824 default:
1825 break;
34dc7c2f
BB
1826 }
1827
1828 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1829 &child, &children) != 0)
1830 return (NULL);
1831
b128c09f 1832 for (c = 0; c < children; c++) {
9babb374 1833 if ((ret = vdev_to_nvlist_iter(child[c], search,
b128c09f
BB
1834 avail_spare, l2cache, NULL)) != NULL) {
1835 /*
1836 * The 'is_log' value is only set for the toplevel
1837 * vdev, not the leaf vdevs. So we always lookup the
1838 * log device from the root of the vdev tree (where
1839 * 'log' is non-NULL).
1840 */
1841 if (log != NULL &&
1842 nvlist_lookup_uint64(child[c],
1843 ZPOOL_CONFIG_IS_LOG, &is_log) == 0 &&
1844 is_log) {
1845 *log = B_TRUE;
1846 }
34dc7c2f 1847 return (ret);
b128c09f
BB
1848 }
1849 }
34dc7c2f
BB
1850
1851 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1852 &child, &children) == 0) {
1853 for (c = 0; c < children; c++) {
9babb374 1854 if ((ret = vdev_to_nvlist_iter(child[c], search,
b128c09f 1855 avail_spare, l2cache, NULL)) != NULL) {
34dc7c2f
BB
1856 *avail_spare = B_TRUE;
1857 return (ret);
1858 }
1859 }
1860 }
1861
1862 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1863 &child, &children) == 0) {
1864 for (c = 0; c < children; c++) {
9babb374 1865 if ((ret = vdev_to_nvlist_iter(child[c], search,
b128c09f 1866 avail_spare, l2cache, NULL)) != NULL) {
34dc7c2f
BB
1867 *l2cache = B_TRUE;
1868 return (ret);
1869 }
1870 }
1871 }
1872
1873 return (NULL);
1874}
1875
9babb374
BB
1876/*
1877 * Given a physical path (minus the "/devices" prefix), find the
1878 * associated vdev.
1879 */
1880nvlist_t *
1881zpool_find_vdev_by_physpath(zpool_handle_t *zhp, const char *ppath,
1882 boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log)
1883{
1884 nvlist_t *search, *nvroot, *ret;
1885
1886 verify(nvlist_alloc(&search, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1887 verify(nvlist_add_string(search, ZPOOL_CONFIG_PHYS_PATH, ppath) == 0);
1888
1889 verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
1890 &nvroot) == 0);
1891
1892 *avail_spare = B_FALSE;
572e2857
BB
1893 *l2cache = B_FALSE;
1894 if (log != NULL)
1895 *log = B_FALSE;
9babb374
BB
1896 ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log);
1897 nvlist_free(search);
1898
1899 return (ret);
1900}
1901
428870ff
BB
1902/*
1903 * Determine if we have an "interior" top-level vdev (i.e mirror/raidz).
1904 */
1905boolean_t
1906zpool_vdev_is_interior(const char *name)
1907{
1908 if (strncmp(name, VDEV_TYPE_RAIDZ, strlen(VDEV_TYPE_RAIDZ)) == 0 ||
1909 strncmp(name, VDEV_TYPE_MIRROR, strlen(VDEV_TYPE_MIRROR)) == 0)
1910 return (B_TRUE);
1911 return (B_FALSE);
1912}
1913
34dc7c2f
BB
1914nvlist_t *
1915zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
b128c09f 1916 boolean_t *l2cache, boolean_t *log)
34dc7c2f
BB
1917{
1918 char buf[MAXPATHLEN];
34dc7c2f 1919 char *end;
9babb374 1920 nvlist_t *nvroot, *search, *ret;
34dc7c2f
BB
1921 uint64_t guid;
1922
9babb374
BB
1923 verify(nvlist_alloc(&search, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1924
34dc7c2f
BB
1925 guid = strtoull(path, &end, 10);
1926 if (guid != 0 && *end == '\0') {
9babb374 1927 verify(nvlist_add_uint64(search, ZPOOL_CONFIG_GUID, guid) == 0);
428870ff
BB
1928 } else if (zpool_vdev_is_interior(path)) {
1929 verify(nvlist_add_string(search, ZPOOL_CONFIG_TYPE, path) == 0);
34dc7c2f
BB
1930 } else if (path[0] != '/') {
1931 (void) snprintf(buf, sizeof (buf), "%s%s", "/dev/dsk/", path);
9babb374 1932 verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, buf) == 0);
34dc7c2f 1933 } else {
9babb374 1934 verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, path) == 0);
34dc7c2f
BB
1935 }
1936
1937 verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
1938 &nvroot) == 0);
1939
1940 *avail_spare = B_FALSE;
1941 *l2cache = B_FALSE;
b128c09f
BB
1942 if (log != NULL)
1943 *log = B_FALSE;
9babb374
BB
1944 ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log);
1945 nvlist_free(search);
1946
1947 return (ret);
b128c09f
BB
1948}
1949
1950static int
1951vdev_online(nvlist_t *nv)
1952{
1953 uint64_t ival;
1954
1955 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_OFFLINE, &ival) == 0 ||
1956 nvlist_lookup_uint64(nv, ZPOOL_CONFIG_FAULTED, &ival) == 0 ||
1957 nvlist_lookup_uint64(nv, ZPOOL_CONFIG_REMOVED, &ival) == 0)
1958 return (0);
1959
1960 return (1);
1961}
1962
1963/*
9babb374 1964 * Helper function for zpool_get_physpaths().
b128c09f 1965 */
9babb374
BB
1966static int
1967vdev_get_one_physpath(nvlist_t *config, char *physpath, size_t physpath_size,
1968 size_t *bytes_written)
1969{
1970 size_t bytes_left, pos, rsz;
1971 char *tmppath;
1972 const char *format;
1973
1974 if (nvlist_lookup_string(config, ZPOOL_CONFIG_PHYS_PATH,
1975 &tmppath) != 0)
1976 return (EZFS_NODEVICE);
1977
1978 pos = *bytes_written;
1979 bytes_left = physpath_size - pos;
1980 format = (pos == 0) ? "%s" : " %s";
1981
1982 rsz = snprintf(physpath + pos, bytes_left, format, tmppath);
1983 *bytes_written += rsz;
1984
1985 if (rsz >= bytes_left) {
1986 /* if physpath was not copied properly, clear it */
1987 if (bytes_left != 0) {
1988 physpath[pos] = 0;
1989 }
1990 return (EZFS_NOSPC);
1991 }
1992 return (0);
1993}
1994
1995static int
1996vdev_get_physpaths(nvlist_t *nv, char *physpath, size_t phypath_size,
1997 size_t *rsz, boolean_t is_spare)
1998{
1999 char *type;
2000 int ret;
2001
2002 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
2003 return (EZFS_INVALCONFIG);
2004
2005 if (strcmp(type, VDEV_TYPE_DISK) == 0) {
2006 /*
2007 * An active spare device has ZPOOL_CONFIG_IS_SPARE set.
2008 * For a spare vdev, we only want to boot from the active
2009 * spare device.
2010 */
2011 if (is_spare) {
2012 uint64_t spare = 0;
2013 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_SPARE,
2014 &spare);
2015 if (!spare)
2016 return (EZFS_INVALCONFIG);
2017 }
2018
2019 if (vdev_online(nv)) {
2020 if ((ret = vdev_get_one_physpath(nv, physpath,
2021 phypath_size, rsz)) != 0)
2022 return (ret);
2023 }
2024 } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0 ||
2025 strcmp(type, VDEV_TYPE_REPLACING) == 0 ||
2026 (is_spare = (strcmp(type, VDEV_TYPE_SPARE) == 0))) {
2027 nvlist_t **child;
2028 uint_t count;
2029 int i, ret;
2030
2031 if (nvlist_lookup_nvlist_array(nv,
2032 ZPOOL_CONFIG_CHILDREN, &child, &count) != 0)
2033 return (EZFS_INVALCONFIG);
2034
2035 for (i = 0; i < count; i++) {
2036 ret = vdev_get_physpaths(child[i], physpath,
2037 phypath_size, rsz, is_spare);
2038 if (ret == EZFS_NOSPC)
2039 return (ret);
2040 }
2041 }
2042
2043 return (EZFS_POOL_INVALARG);
2044}
2045
2046/*
2047 * Get phys_path for a root pool config.
2048 * Return 0 on success; non-zero on failure.
2049 */
2050static int
2051zpool_get_config_physpath(nvlist_t *config, char *physpath, size_t phypath_size)
b128c09f 2052{
9babb374 2053 size_t rsz;
b128c09f
BB
2054 nvlist_t *vdev_root;
2055 nvlist_t **child;
2056 uint_t count;
9babb374 2057 char *type;
b128c09f 2058
9babb374 2059 rsz = 0;
b128c09f 2060
9babb374
BB
2061 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2062 &vdev_root) != 0)
2063 return (EZFS_INVALCONFIG);
b128c09f 2064
9babb374
BB
2065 if (nvlist_lookup_string(vdev_root, ZPOOL_CONFIG_TYPE, &type) != 0 ||
2066 nvlist_lookup_nvlist_array(vdev_root, ZPOOL_CONFIG_CHILDREN,
b128c09f 2067 &child, &count) != 0)
9babb374 2068 return (EZFS_INVALCONFIG);
b128c09f 2069
9babb374
BB
2070 /*
2071 * root pool can not have EFI labeled disks and can only have
2072 * a single top-level vdev.
2073 */
2074 if (strcmp(type, VDEV_TYPE_ROOT) != 0 || count != 1 ||
2075 pool_uses_efi(vdev_root))
2076 return (EZFS_POOL_INVALARG);
b128c09f 2077
9babb374
BB
2078 (void) vdev_get_physpaths(child[0], physpath, phypath_size, &rsz,
2079 B_FALSE);
2080
2081 /* No online devices */
2082 if (rsz == 0)
2083 return (EZFS_NODEVICE);
b128c09f
BB
2084
2085 return (0);
34dc7c2f
BB
2086}
2087
9babb374
BB
2088/*
2089 * Get phys_path for a root pool
2090 * Return 0 on success; non-zero on failure.
2091 */
2092int
2093zpool_get_physpath(zpool_handle_t *zhp, char *physpath, size_t phypath_size)
2094{
2095 return (zpool_get_config_physpath(zhp->zpool_config, physpath,
2096 phypath_size));
2097}
2098
9babb374
BB
2099/*
2100 * If the device has being dynamically expanded then we need to relabel
2101 * the disk to use the new unallocated space.
2102 */
2103static int
2104zpool_relabel_disk(libzfs_handle_t *hdl, const char *name)
2105{
2106 char path[MAXPATHLEN];
2107 char errbuf[1024];
2108 int fd, error;
2109 int (*_efi_use_whole_disk)(int);
2110
2111 if ((_efi_use_whole_disk = (int (*)(int))dlsym(RTLD_DEFAULT,
2112 "efi_use_whole_disk")) == NULL)
2113 return (-1);
2114
2115 (void) snprintf(path, sizeof (path), "%s/%s", RDISK_ROOT, name);
2116
2117 if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) {
2118 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
2119 "relabel '%s': unable to open device"), name);
2120 return (zfs_error(hdl, EZFS_OPENFAILED, errbuf));
2121 }
2122
2123 /*
2124 * It's possible that we might encounter an error if the device
2125 * does not have any unallocated space left. If so, we simply
2126 * ignore that error and continue on.
2127 */
2128 error = _efi_use_whole_disk(fd);
2129 (void) close(fd);
2130 if (error && error != VT_ENOSPC) {
2131 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
2132 "relabel '%s': unable to read disk capacity"), name);
2133 return (zfs_error(hdl, EZFS_NOCAP, errbuf));
2134 }
2135 return (0);
2136}
2137
34dc7c2f
BB
2138/*
2139 * Bring the specified vdev online. The 'flags' parameter is a set of the
2140 * ZFS_ONLINE_* flags.
2141 */
2142int
2143zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
2144 vdev_state_t *newstate)
2145{
2598c001 2146 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
2147 char msg[1024];
2148 nvlist_t *tgt;
9babb374 2149 boolean_t avail_spare, l2cache, islog;
34dc7c2f
BB
2150 libzfs_handle_t *hdl = zhp->zpool_hdl;
2151
9babb374
BB
2152 if (flags & ZFS_ONLINE_EXPAND) {
2153 (void) snprintf(msg, sizeof (msg),
2154 dgettext(TEXT_DOMAIN, "cannot expand %s"), path);
2155 } else {
2156 (void) snprintf(msg, sizeof (msg),
2157 dgettext(TEXT_DOMAIN, "cannot online %s"), path);
2158 }
34dc7c2f
BB
2159
2160 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
b128c09f 2161 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
9babb374 2162 &islog)) == NULL)
34dc7c2f
BB
2163 return (zfs_error(hdl, EZFS_NODEVICE, msg));
2164
2165 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
2166
428870ff 2167 if (avail_spare)
34dc7c2f
BB
2168 return (zfs_error(hdl, EZFS_ISSPARE, msg));
2169
9babb374
BB
2170 if (flags & ZFS_ONLINE_EXPAND ||
2171 zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) {
2172 char *pathname = NULL;
2173 uint64_t wholedisk = 0;
2174
2175 (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
2176 &wholedisk);
2177 verify(nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH,
2178 &pathname) == 0);
2179
2180 /*
2181 * XXX - L2ARC 1.0 devices can't support expansion.
2182 */
2183 if (l2cache) {
2184 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2185 "cannot expand cache devices"));
2186 return (zfs_error(hdl, EZFS_VDEVNOTSUP, msg));
2187 }
2188
2189 if (wholedisk) {
2190 pathname += strlen(DISK_ROOT) + 1;
572e2857 2191 (void) zpool_relabel_disk(hdl, pathname);
9babb374
BB
2192 }
2193 }
2194
34dc7c2f
BB
2195 zc.zc_cookie = VDEV_STATE_ONLINE;
2196 zc.zc_obj = flags;
2197
572e2857 2198 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) != 0) {
428870ff
BB
2199 if (errno == EINVAL) {
2200 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "was split "
2201 "from this pool into a new one. Use '%s' "
2202 "instead"), "zpool detach");
2203 return (zfs_error(hdl, EZFS_POSTSPLIT_ONLINE, msg));
2204 }
34dc7c2f 2205 return (zpool_standard_error(hdl, errno, msg));
428870ff 2206 }
34dc7c2f
BB
2207
2208 *newstate = zc.zc_cookie;
2209 return (0);
2210}
2211
2212/*
2213 * Take the specified vdev offline
2214 */
2215int
2216zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
2217{
2598c001 2218 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
2219 char msg[1024];
2220 nvlist_t *tgt;
2221 boolean_t avail_spare, l2cache;
2222 libzfs_handle_t *hdl = zhp->zpool_hdl;
2223
2224 (void) snprintf(msg, sizeof (msg),
2225 dgettext(TEXT_DOMAIN, "cannot offline %s"), path);
2226
2227 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
b128c09f
BB
2228 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
2229 NULL)) == NULL)
34dc7c2f
BB
2230 return (zfs_error(hdl, EZFS_NODEVICE, msg));
2231
2232 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
2233
428870ff 2234 if (avail_spare)
34dc7c2f
BB
2235 return (zfs_error(hdl, EZFS_ISSPARE, msg));
2236
34dc7c2f
BB
2237 zc.zc_cookie = VDEV_STATE_OFFLINE;
2238 zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0;
2239
572e2857 2240 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
34dc7c2f
BB
2241 return (0);
2242
2243 switch (errno) {
2244 case EBUSY:
2245
2246 /*
2247 * There are no other replicas of this device.
2248 */
2249 return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
2250
9babb374
BB
2251 case EEXIST:
2252 /*
2253 * The log device has unplayed logs
2254 */
2255 return (zfs_error(hdl, EZFS_UNPLAYED_LOGS, msg));
2256
34dc7c2f
BB
2257 default:
2258 return (zpool_standard_error(hdl, errno, msg));
2259 }
2260}
2261
2262/*
2263 * Mark the given vdev faulted.
2264 */
2265int
428870ff 2266zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
34dc7c2f 2267{
2598c001 2268 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
2269 char msg[1024];
2270 libzfs_handle_t *hdl = zhp->zpool_hdl;
2271
2272 (void) snprintf(msg, sizeof (msg),
b8864a23 2273 dgettext(TEXT_DOMAIN, "cannot fault %llu"), (u_longlong_t)guid);
34dc7c2f
BB
2274
2275 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2276 zc.zc_guid = guid;
2277 zc.zc_cookie = VDEV_STATE_FAULTED;
428870ff 2278 zc.zc_obj = aux;
34dc7c2f 2279
572e2857 2280 if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
34dc7c2f
BB
2281 return (0);
2282
2283 switch (errno) {
2284 case EBUSY:
2285
2286 /*
2287 * There are no other replicas of this device.
2288 */
2289 return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
2290
2291 default:
2292 return (zpool_standard_error(hdl, errno, msg));
2293 }
2294
2295}
2296
2297/*
2298 * Mark the given vdev degraded.
2299 */
2300int
428870ff 2301zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
34dc7c2f 2302{
2598c001 2303 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
2304 char msg[1024];
2305 libzfs_handle_t *hdl = zhp->zpool_hdl;
2306
2307 (void) snprintf(msg, sizeof (msg),
b8864a23 2308 dgettext(TEXT_DOMAIN, "cannot degrade %llu"), (u_longlong_t)guid);
34dc7c2f
BB
2309
2310 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2311 zc.zc_guid = guid;
2312 zc.zc_cookie = VDEV_STATE_DEGRADED;
428870ff 2313 zc.zc_obj = aux;
34dc7c2f 2314
572e2857 2315 if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
34dc7c2f
BB
2316 return (0);
2317
2318 return (zpool_standard_error(hdl, errno, msg));
2319}
2320
2321/*
2322 * Returns TRUE if the given nvlist is a vdev that was originally swapped in as
2323 * a hot spare.
2324 */
2325static boolean_t
2326is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which)
2327{
2328 nvlist_t **child;
2329 uint_t c, children;
2330 char *type;
2331
2332 if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child,
2333 &children) == 0) {
2334 verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE,
2335 &type) == 0);
2336
2337 if (strcmp(type, VDEV_TYPE_SPARE) == 0 &&
2338 children == 2 && child[which] == tgt)
2339 return (B_TRUE);
2340
2341 for (c = 0; c < children; c++)
2342 if (is_replacing_spare(child[c], tgt, which))
2343 return (B_TRUE);
2344 }
2345
2346 return (B_FALSE);
2347}
2348
2349/*
2350 * Attach new_disk (fully described by nvroot) to old_disk.
2351 * If 'replacing' is specified, the new disk will replace the old one.
2352 */
2353int
2354zpool_vdev_attach(zpool_handle_t *zhp,
2355 const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing)
2356{
2598c001 2357 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
2358 char msg[1024];
2359 int ret;
2360 nvlist_t *tgt;
b128c09f
BB
2361 boolean_t avail_spare, l2cache, islog;
2362 uint64_t val;
572e2857 2363 char *newname;
34dc7c2f
BB
2364 nvlist_t **child;
2365 uint_t children;
2366 nvlist_t *config_root;
2367 libzfs_handle_t *hdl = zhp->zpool_hdl;
b128c09f 2368 boolean_t rootpool = pool_is_bootable(zhp);
34dc7c2f
BB
2369
2370 if (replacing)
2371 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
2372 "cannot replace %s with %s"), old_disk, new_disk);
2373 else
2374 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
2375 "cannot attach %s to %s"), new_disk, old_disk);
2376
b128c09f
BB
2377 /*
2378 * If this is a root pool, make sure that we're not attaching an
2379 * EFI labeled device.
2380 */
2381 if (rootpool && pool_uses_efi(nvroot)) {
2382 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2383 "EFI labeled devices are not supported on root pools."));
2384 return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg));
2385 }
2386
34dc7c2f 2387 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
b128c09f
BB
2388 if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare, &l2cache,
2389 &islog)) == 0)
34dc7c2f
BB
2390 return (zfs_error(hdl, EZFS_NODEVICE, msg));
2391
2392 if (avail_spare)
2393 return (zfs_error(hdl, EZFS_ISSPARE, msg));
2394
2395 if (l2cache)
2396 return (zfs_error(hdl, EZFS_ISL2CACHE, msg));
2397
2398 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
2399 zc.zc_cookie = replacing;
2400
2401 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
2402 &child, &children) != 0 || children != 1) {
2403 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2404 "new device must be a single disk"));
2405 return (zfs_error(hdl, EZFS_INVALCONFIG, msg));
2406 }
2407
2408 verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
2409 ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0);
2410
428870ff 2411 if ((newname = zpool_vdev_name(NULL, NULL, child[0], B_FALSE)) == NULL)
b128c09f
BB
2412 return (-1);
2413
34dc7c2f
BB
2414 /*
2415 * If the target is a hot spare that has been swapped in, we can only
2416 * replace it with another hot spare.
2417 */
2418 if (replacing &&
2419 nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 &&
b128c09f
BB
2420 (zpool_find_vdev(zhp, newname, &avail_spare, &l2cache,
2421 NULL) == NULL || !avail_spare) &&
2422 is_replacing_spare(config_root, tgt, 1)) {
34dc7c2f
BB
2423 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2424 "can only be replaced by another hot spare"));
b128c09f 2425 free(newname);
34dc7c2f
BB
2426 return (zfs_error(hdl, EZFS_BADTARGET, msg));
2427 }
2428
b128c09f
BB
2429 free(newname);
2430
34dc7c2f
BB
2431 if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
2432 return (-1);
2433
572e2857 2434 ret = zfs_ioctl(hdl, ZFS_IOC_VDEV_ATTACH, &zc);
34dc7c2f
BB
2435
2436 zcmd_free_nvlists(&zc);
2437
b128c09f
BB
2438 if (ret == 0) {
2439 if (rootpool) {
9babb374
BB
2440 /*
2441 * XXX need a better way to prevent user from
2442 * booting up a half-baked vdev.
2443 */
2444 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Make "
2445 "sure to wait until resilver is done "
2446 "before rebooting.\n"));
b128c09f 2447 }
34dc7c2f 2448 return (0);
b128c09f 2449 }
34dc7c2f
BB
2450
2451 switch (errno) {
2452 case ENOTSUP:
2453 /*
2454 * Can't attach to or replace this type of vdev.
2455 */
2456 if (replacing) {
572e2857
BB
2457 uint64_t version = zpool_get_prop_int(zhp,
2458 ZPOOL_PROP_VERSION, NULL);
2459
b128c09f 2460 if (islog)
34dc7c2f
BB
2461 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2462 "cannot replace a log with a spare"));
572e2857
BB
2463 else if (version >= SPA_VERSION_MULTI_REPLACE)
2464 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2465 "already in replacing/spare config; wait "
2466 "for completion or use 'zpool detach'"));
34dc7c2f
BB
2467 else
2468 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2469 "cannot replace a replacing device"));
2470 } else {
2471 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2472 "can only attach to mirrors and top-level "
2473 "disks"));
2474 }
2475 (void) zfs_error(hdl, EZFS_BADTARGET, msg);
2476 break;
2477
2478 case EINVAL:
2479 /*
2480 * The new device must be a single disk.
2481 */
2482 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2483 "new device must be a single disk"));
2484 (void) zfs_error(hdl, EZFS_INVALCONFIG, msg);
2485 break;
2486
2487 case EBUSY:
2488 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"),
2489 new_disk);
2490 (void) zfs_error(hdl, EZFS_BADDEV, msg);
2491 break;
2492
2493 case EOVERFLOW:
2494 /*
2495 * The new device is too small.
2496 */
2497 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2498 "device is too small"));
2499 (void) zfs_error(hdl, EZFS_BADDEV, msg);
2500 break;
2501
2502 case EDOM:
2503 /*
2504 * The new device has a different alignment requirement.
2505 */
2506 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2507 "devices have different sector alignment"));
2508 (void) zfs_error(hdl, EZFS_BADDEV, msg);
2509 break;
2510
2511 case ENAMETOOLONG:
2512 /*
2513 * The resulting top-level vdev spec won't fit in the label.
2514 */
2515 (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg);
2516 break;
2517
2518 default:
2519 (void) zpool_standard_error(hdl, errno, msg);
2520 }
2521
2522 return (-1);
2523}
2524
2525/*
2526 * Detach the specified device.
2527 */
2528int
2529zpool_vdev_detach(zpool_handle_t *zhp, const char *path)
2530{
2598c001 2531 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
2532 char msg[1024];
2533 nvlist_t *tgt;
2534 boolean_t avail_spare, l2cache;
2535 libzfs_handle_t *hdl = zhp->zpool_hdl;
2536
2537 (void) snprintf(msg, sizeof (msg),
2538 dgettext(TEXT_DOMAIN, "cannot detach %s"), path);
2539
2540 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
b128c09f
BB
2541 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
2542 NULL)) == 0)
34dc7c2f
BB
2543 return (zfs_error(hdl, EZFS_NODEVICE, msg));
2544
2545 if (avail_spare)
2546 return (zfs_error(hdl, EZFS_ISSPARE, msg));
2547
2548 if (l2cache)
2549 return (zfs_error(hdl, EZFS_ISL2CACHE, msg));
2550
2551 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
2552
2553 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_DETACH, &zc) == 0)
2554 return (0);
2555
2556 switch (errno) {
2557
2558 case ENOTSUP:
2559 /*
2560 * Can't detach from this type of vdev.
2561 */
2562 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only "
2563 "applicable to mirror and replacing vdevs"));
572e2857 2564 (void) zfs_error(hdl, EZFS_BADTARGET, msg);
34dc7c2f
BB
2565 break;
2566
2567 case EBUSY:
2568 /*
2569 * There are no other replicas of this device.
2570 */
2571 (void) zfs_error(hdl, EZFS_NOREPLICAS, msg);
2572 break;
2573
2574 default:
2575 (void) zpool_standard_error(hdl, errno, msg);
2576 }
2577
2578 return (-1);
2579}
2580
428870ff
BB
2581/*
2582 * Find a mirror vdev in the source nvlist.
2583 *
2584 * The mchild array contains a list of disks in one of the top-level mirrors
2585 * of the source pool. The schild array contains a list of disks that the
2586 * user specified on the command line. We loop over the mchild array to
2587 * see if any entry in the schild array matches.
2588 *
2589 * If a disk in the mchild array is found in the schild array, we return
2590 * the index of that entry. Otherwise we return -1.
2591 */
2592static int
2593find_vdev_entry(zpool_handle_t *zhp, nvlist_t **mchild, uint_t mchildren,
2594 nvlist_t **schild, uint_t schildren)
2595{
2596 uint_t mc;
2597
2598 for (mc = 0; mc < mchildren; mc++) {
2599 uint_t sc;
2600 char *mpath = zpool_vdev_name(zhp->zpool_hdl, zhp,
2601 mchild[mc], B_FALSE);
2602
2603 for (sc = 0; sc < schildren; sc++) {
2604 char *spath = zpool_vdev_name(zhp->zpool_hdl, zhp,
2605 schild[sc], B_FALSE);
2606 boolean_t result = (strcmp(mpath, spath) == 0);
2607
2608 free(spath);
2609 if (result) {
2610 free(mpath);
2611 return (mc);
2612 }
2613 }
2614
2615 free(mpath);
2616 }
2617
2618 return (-1);
2619}
2620
2621/*
2622 * Split a mirror pool. If newroot points to null, then a new nvlist
2623 * is generated and it is the responsibility of the caller to free it.
2624 */
2625int
2626zpool_vdev_split(zpool_handle_t *zhp, char *newname, nvlist_t **newroot,
2627 nvlist_t *props, splitflags_t flags)
2628{
2598c001 2629 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
428870ff
BB
2630 char msg[1024];
2631 nvlist_t *tree, *config, **child, **newchild, *newconfig = NULL;
2632 nvlist_t **varray = NULL, *zc_props = NULL;
2633 uint_t c, children, newchildren, lastlog = 0, vcount, found = 0;
2634 libzfs_handle_t *hdl = zhp->zpool_hdl;
2635 uint64_t vers;
2636 boolean_t freelist = B_FALSE, memory_err = B_TRUE;
2637 int retval = 0;
2638
2639 (void) snprintf(msg, sizeof (msg),
2640 dgettext(TEXT_DOMAIN, "Unable to split %s"), zhp->zpool_name);
2641
2642 if (!zpool_name_valid(hdl, B_FALSE, newname))
2643 return (zfs_error(hdl, EZFS_INVALIDNAME, msg));
2644
2645 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
2646 (void) fprintf(stderr, gettext("Internal error: unable to "
2647 "retrieve pool configuration\n"));
2648 return (-1);
2649 }
2650
2651 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &tree)
2652 == 0);
2653 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, &vers) == 0);
2654
2655 if (props) {
572e2857 2656 prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE };
428870ff 2657 if ((zc_props = zpool_valid_proplist(hdl, zhp->zpool_name,
572e2857 2658 props, vers, flags, msg)) == NULL)
428870ff
BB
2659 return (-1);
2660 }
2661
2662 if (nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN, &child,
2663 &children) != 0) {
2664 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2665 "Source pool is missing vdev tree"));
2666 if (zc_props)
2667 nvlist_free(zc_props);
2668 return (-1);
2669 }
2670
2671 varray = zfs_alloc(hdl, children * sizeof (nvlist_t *));
2672 vcount = 0;
2673
2674 if (*newroot == NULL ||
2675 nvlist_lookup_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN,
2676 &newchild, &newchildren) != 0)
2677 newchildren = 0;
2678
2679 for (c = 0; c < children; c++) {
2680 uint64_t is_log = B_FALSE, is_hole = B_FALSE;
2681 char *type;
2682 nvlist_t **mchild, *vdev;
2683 uint_t mchildren;
2684 int entry;
2685
2686 /*
2687 * Unlike cache & spares, slogs are stored in the
2688 * ZPOOL_CONFIG_CHILDREN array. We filter them out here.
2689 */
2690 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2691 &is_log);
2692 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
2693 &is_hole);
2694 if (is_log || is_hole) {
2695 /*
2696 * Create a hole vdev and put it in the config.
2697 */
2698 if (nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) != 0)
2699 goto out;
2700 if (nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE,
2701 VDEV_TYPE_HOLE) != 0)
2702 goto out;
2703 if (nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_HOLE,
2704 1) != 0)
2705 goto out;
2706 if (lastlog == 0)
2707 lastlog = vcount;
2708 varray[vcount++] = vdev;
2709 continue;
2710 }
2711 lastlog = 0;
2712 verify(nvlist_lookup_string(child[c], ZPOOL_CONFIG_TYPE, &type)
2713 == 0);
2714 if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
2715 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2716 "Source pool must be composed only of mirrors\n"));
2717 retval = zfs_error(hdl, EZFS_INVALCONFIG, msg);
2718 goto out;
2719 }
2720
2721 verify(nvlist_lookup_nvlist_array(child[c],
2722 ZPOOL_CONFIG_CHILDREN, &mchild, &mchildren) == 0);
2723
2724 /* find or add an entry for this top-level vdev */
2725 if (newchildren > 0 &&
2726 (entry = find_vdev_entry(zhp, mchild, mchildren,
2727 newchild, newchildren)) >= 0) {
2728 /* We found a disk that the user specified. */
2729 vdev = mchild[entry];
2730 ++found;
2731 } else {
2732 /* User didn't specify a disk for this vdev. */
2733 vdev = mchild[mchildren - 1];
2734 }
2735
2736 if (nvlist_dup(vdev, &varray[vcount++], 0) != 0)
2737 goto out;
2738 }
2739
2740 /* did we find every disk the user specified? */
2741 if (found != newchildren) {
2742 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Device list must "
2743 "include at most one disk from each mirror"));
2744 retval = zfs_error(hdl, EZFS_INVALCONFIG, msg);
2745 goto out;
2746 }
2747
2748 /* Prepare the nvlist for populating. */
2749 if (*newroot == NULL) {
2750 if (nvlist_alloc(newroot, NV_UNIQUE_NAME, 0) != 0)
2751 goto out;
2752 freelist = B_TRUE;
2753 if (nvlist_add_string(*newroot, ZPOOL_CONFIG_TYPE,
2754 VDEV_TYPE_ROOT) != 0)
2755 goto out;
2756 } else {
2757 verify(nvlist_remove_all(*newroot, ZPOOL_CONFIG_CHILDREN) == 0);
2758 }
2759
2760 /* Add all the children we found */
2761 if (nvlist_add_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN, varray,
2762 lastlog == 0 ? vcount : lastlog) != 0)
2763 goto out;
2764
2765 /*
2766 * If we're just doing a dry run, exit now with success.
2767 */
2768 if (flags.dryrun) {
2769 memory_err = B_FALSE;
2770 freelist = B_FALSE;
2771 goto out;
2772 }
2773
2774 /* now build up the config list & call the ioctl */
2775 if (nvlist_alloc(&newconfig, NV_UNIQUE_NAME, 0) != 0)
2776 goto out;
2777
2778 if (nvlist_add_nvlist(newconfig,
2779 ZPOOL_CONFIG_VDEV_TREE, *newroot) != 0 ||
2780 nvlist_add_string(newconfig,
2781 ZPOOL_CONFIG_POOL_NAME, newname) != 0 ||
2782 nvlist_add_uint64(newconfig, ZPOOL_CONFIG_VERSION, vers) != 0)
2783 goto out;
2784
2785 /*
2786 * The new pool is automatically part of the namespace unless we
2787 * explicitly export it.
2788 */
2789 if (!flags.import)
2790 zc.zc_cookie = ZPOOL_EXPORT_AFTER_SPLIT;
2791 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2792 (void) strlcpy(zc.zc_string, newname, sizeof (zc.zc_string));
2793 if (zcmd_write_conf_nvlist(hdl, &zc, newconfig) != 0)
2794 goto out;
2795 if (zc_props != NULL && zcmd_write_src_nvlist(hdl, &zc, zc_props) != 0)
2796 goto out;
2797
2798 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SPLIT, &zc) != 0) {
2799 retval = zpool_standard_error(hdl, errno, msg);
2800 goto out;
2801 }
2802
2803 freelist = B_FALSE;
2804 memory_err = B_FALSE;
2805
2806out:
2807 if (varray != NULL) {
2808 int v;
2809
2810 for (v = 0; v < vcount; v++)
2811 nvlist_free(varray[v]);
2812 free(varray);
2813 }
2814 zcmd_free_nvlists(&zc);
2815 if (zc_props)
2816 nvlist_free(zc_props);
2817 if (newconfig)
2818 nvlist_free(newconfig);
2819 if (freelist) {
2820 nvlist_free(*newroot);
2821 *newroot = NULL;
2822 }
2823
2824 if (retval != 0)
2825 return (retval);
2826
2827 if (memory_err)
2828 return (no_memory(hdl));
2829
2830 return (0);
2831}
2832
34dc7c2f
BB
2833/*
2834 * Remove the given device. Currently, this is supported only for hot spares
2835 * and level 2 cache devices.
2836 */
2837int
2838zpool_vdev_remove(zpool_handle_t *zhp, const char *path)
2839{
2598c001 2840 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
2841 char msg[1024];
2842 nvlist_t *tgt;
428870ff 2843 boolean_t avail_spare, l2cache, islog;
34dc7c2f 2844 libzfs_handle_t *hdl = zhp->zpool_hdl;
428870ff 2845 uint64_t version;
34dc7c2f
BB
2846
2847 (void) snprintf(msg, sizeof (msg),
2848 dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
2849
2850 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
b128c09f 2851 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
428870ff 2852 &islog)) == 0)
34dc7c2f 2853 return (zfs_error(hdl, EZFS_NODEVICE, msg));
428870ff
BB
2854 /*
2855 * XXX - this should just go away.
2856 */
2857 if (!avail_spare && !l2cache && !islog) {
34dc7c2f 2858 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
428870ff
BB
2859 "only inactive hot spares, cache, top-level, "
2860 "or log devices can be removed"));
34dc7c2f
BB
2861 return (zfs_error(hdl, EZFS_NODEVICE, msg));
2862 }
2863
428870ff
BB
2864 version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
2865 if (islog && version < SPA_VERSION_HOLES) {
2866 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2867 "pool must be upgrade to support log removal"));
2868 return (zfs_error(hdl, EZFS_BADVERSION, msg));
2869 }
2870
34dc7c2f
BB
2871 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
2872
2873 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0)
2874 return (0);
2875
2876 return (zpool_standard_error(hdl, errno, msg));
2877}
2878
2879/*
2880 * Clear the errors for the pool, or the particular device if specified.
2881 */
2882int
428870ff 2883zpool_clear(zpool_handle_t *zhp, const char *path, nvlist_t *rewindnvl)
34dc7c2f 2884{
2598c001 2885 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
2886 char msg[1024];
2887 nvlist_t *tgt;
428870ff 2888 zpool_rewind_policy_t policy;
34dc7c2f
BB
2889 boolean_t avail_spare, l2cache;
2890 libzfs_handle_t *hdl = zhp->zpool_hdl;
428870ff 2891 nvlist_t *nvi = NULL;
572e2857 2892 int error;
34dc7c2f
BB
2893
2894 if (path)
2895 (void) snprintf(msg, sizeof (msg),
2896 dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
2897 path);
2898 else
2899 (void) snprintf(msg, sizeof (msg),
2900 dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
2901 zhp->zpool_name);
2902
2903 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2904 if (path) {
2905 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare,
b128c09f 2906 &l2cache, NULL)) == 0)
34dc7c2f
BB
2907 return (zfs_error(hdl, EZFS_NODEVICE, msg));
2908
2909 /*
2910 * Don't allow error clearing for hot spares. Do allow
2911 * error clearing for l2cache devices.
2912 */
2913 if (avail_spare)
2914 return (zfs_error(hdl, EZFS_ISSPARE, msg));
2915
2916 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID,
2917 &zc.zc_guid) == 0);
2918 }
2919
428870ff
BB
2920 zpool_get_rewind_policy(rewindnvl, &policy);
2921 zc.zc_cookie = policy.zrp_request;
2922
572e2857 2923 if (zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size * 2) != 0)
428870ff
BB
2924 return (-1);
2925
572e2857 2926 if (zcmd_write_src_nvlist(hdl, &zc, rewindnvl) != 0)
428870ff
BB
2927 return (-1);
2928
572e2857
BB
2929 while ((error = zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc)) != 0 &&
2930 errno == ENOMEM) {
2931 if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
2932 zcmd_free_nvlists(&zc);
2933 return (-1);
2934 }
2935 }
2936
2937 if (!error || ((policy.zrp_request & ZPOOL_TRY_REWIND) &&
428870ff
BB
2938 errno != EPERM && errno != EACCES)) {
2939 if (policy.zrp_request &
2940 (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) {
2941 (void) zcmd_read_dst_nvlist(hdl, &zc, &nvi);
2942 zpool_rewind_exclaim(hdl, zc.zc_name,
2943 ((policy.zrp_request & ZPOOL_TRY_REWIND) != 0),
2944 nvi);
2945 nvlist_free(nvi);
2946 }
2947 zcmd_free_nvlists(&zc);
34dc7c2f 2948 return (0);
428870ff 2949 }
34dc7c2f 2950
428870ff 2951 zcmd_free_nvlists(&zc);
34dc7c2f
BB
2952 return (zpool_standard_error(hdl, errno, msg));
2953}
2954
2955/*
2956 * Similar to zpool_clear(), but takes a GUID (used by fmd).
2957 */
2958int
2959zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid)
2960{
2598c001 2961 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
2962 char msg[1024];
2963 libzfs_handle_t *hdl = zhp->zpool_hdl;
2964
2965 (void) snprintf(msg, sizeof (msg),
2966 dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"),
b8864a23 2967 (u_longlong_t)guid);
34dc7c2f
BB
2968
2969 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2970 zc.zc_guid = guid;
428870ff 2971 zc.zc_cookie = ZPOOL_NO_REWIND;
34dc7c2f
BB
2972
2973 if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0)
2974 return (0);
2975
2976 return (zpool_standard_error(hdl, errno, msg));
2977}
2978
34dc7c2f
BB
2979/*
2980 * Convert from a devid string to a path.
2981 */
2982static char *
2983devid_to_path(char *devid_str)
2984{
2985 ddi_devid_t devid;
2986 char *minor;
2987 char *path;
2988 devid_nmlist_t *list = NULL;
2989 int ret;
2990
2991 if (devid_str_decode(devid_str, &devid, &minor) != 0)
2992 return (NULL);
2993
2994 ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list);
2995
2996 devid_str_free(minor);
2997 devid_free(devid);
2998
2999 if (ret != 0)
3000 return (NULL);
3001
3002 if ((path = strdup(list[0].devname)) == NULL)
3003 return (NULL);
3004
3005 devid_free_nmlist(list);
3006
3007 return (path);
3008}
3009
3010/*
3011 * Convert from a path to a devid string.
3012 */
3013static char *
3014path_to_devid(const char *path)
3015{
3016 int fd;
3017 ddi_devid_t devid;
3018 char *minor, *ret;
3019
3020 if ((fd = open(path, O_RDONLY)) < 0)
3021 return (NULL);
3022
3023 minor = NULL;
3024 ret = NULL;
3025 if (devid_get(fd, &devid) == 0) {
3026 if (devid_get_minor_name(fd, &minor) == 0)
3027 ret = devid_str_encode(devid, minor);
3028 if (minor != NULL)
3029 devid_str_free(minor);
3030 devid_free(devid);
3031 }
3032 (void) close(fd);
3033
3034 return (ret);
3035}
3036
3037/*
3038 * Issue the necessary ioctl() to update the stored path value for the vdev. We
3039 * ignore any failure here, since a common case is for an unprivileged user to
3040 * type 'zpool status', and we'll display the correct information anyway.
3041 */
3042static void
3043set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path)
3044{
2598c001 3045 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
3046
3047 (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3048 (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value));
3049 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
3050 &zc.zc_guid) == 0);
3051
3052 (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc);
3053}
3054
3055/*
3056 * Given a vdev, return the name to display in iostat. If the vdev has a path,
3057 * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type.
3058 * We also check if this is a whole disk, in which case we strip off the
3059 * trailing 's0' slice name.
3060 *
3061 * This routine is also responsible for identifying when disks have been
3062 * reconfigured in a new location. The kernel will have opened the device by
3063 * devid, but the path will still refer to the old location. To catch this, we
3064 * first do a path -> devid translation (which is fast for the common case). If
3065 * the devid matches, we're done. If not, we do a reverse devid -> path
3066 * translation and issue the appropriate ioctl() to update the path of the vdev.
3067 * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any
3068 * of these checks.
3069 */
3070char *
428870ff
BB
3071zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
3072 boolean_t verbose)
34dc7c2f
BB
3073{
3074 char *path, *devid;
3075 uint64_t value;
3076 char buf[64];
3077 vdev_stat_t *vs;
3078 uint_t vsc;
3079
3080 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
3081 &value) == 0) {
3082 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
3083 &value) == 0);
3084 (void) snprintf(buf, sizeof (buf), "%llu",
3085 (u_longlong_t)value);
3086 path = buf;
3087 } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
3088
3089 /*
3090 * If the device is dead (faulted, offline, etc) then don't
3091 * bother opening it. Otherwise we may be forcing the user to
3092 * open a misbehaving device, which can have undesirable
3093 * effects.
3094 */
428870ff 3095 if ((nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
34dc7c2f
BB
3096 (uint64_t **)&vs, &vsc) != 0 ||
3097 vs->vs_state >= VDEV_STATE_DEGRADED) &&
3098 zhp != NULL &&
3099 nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) {
3100 /*
3101 * Determine if the current path is correct.
3102 */
3103 char *newdevid = path_to_devid(path);
3104
3105 if (newdevid == NULL ||
3106 strcmp(devid, newdevid) != 0) {
3107 char *newpath;
3108
3109 if ((newpath = devid_to_path(devid)) != NULL) {
3110 /*
3111 * Update the path appropriately.
3112 */
3113 set_path(zhp, nv, newpath);
3114 if (nvlist_add_string(nv,
3115 ZPOOL_CONFIG_PATH, newpath) == 0)
3116 verify(nvlist_lookup_string(nv,
3117 ZPOOL_CONFIG_PATH,
3118 &path) == 0);
3119 free(newpath);
3120 }
3121 }
3122
3123 if (newdevid)
3124 devid_str_free(newdevid);
3125 }
3126
3127 if (strncmp(path, "/dev/dsk/", 9) == 0)
3128 path += 9;
3129
3130 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
3131 &value) == 0 && value) {
428870ff 3132 int pathlen = strlen(path);
34dc7c2f 3133 char *tmp = zfs_strdup(hdl, path);
428870ff
BB
3134
3135 /*
3136 * If it starts with c#, and ends with "s0", chop
3137 * the "s0" off, or if it ends with "s0/old", remove
3138 * the "s0" from the middle.
3139 */
3140 if (CTD_CHECK(tmp)) {
3141 if (strcmp(&tmp[pathlen - 2], "s0") == 0) {
3142 tmp[pathlen - 2] = '\0';
3143 } else if (pathlen > 6 &&
3144 strcmp(&tmp[pathlen - 6], "s0/old") == 0) {
3145 (void) strcpy(&tmp[pathlen - 6],
3146 "/old");
3147 }
3148 }
34dc7c2f
BB
3149 return (tmp);
3150 }
3151 } else {
3152 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0);
3153
3154 /*
3155 * If it's a raidz device, we need to stick in the parity level.
3156 */
3157 if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) {
3158 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY,
3159 &value) == 0);
3160 (void) snprintf(buf, sizeof (buf), "%s%llu", path,
3161 (u_longlong_t)value);
3162 path = buf;
3163 }
428870ff
BB
3164
3165 /*
3166 * We identify each top-level vdev by using a <type-id>
3167 * naming convention.
3168 */
3169 if (verbose) {
3170 uint64_t id;
3171
3172 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID,
3173 &id) == 0);
3174 (void) snprintf(buf, sizeof (buf), "%s-%llu", path,
3175 (u_longlong_t)id);
3176 path = buf;
3177 }
34dc7c2f
BB
3178 }
3179
3180 return (zfs_strdup(hdl, path));
3181}
3182
3183static int
3184zbookmark_compare(const void *a, const void *b)
3185{
3186 return (memcmp(a, b, sizeof (zbookmark_t)));
3187}
3188
3189/*
3190 * Retrieve the persistent error log, uniquify the members, and return to the
3191 * caller.
3192 */
3193int
3194zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
3195{
2598c001 3196 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
3197 uint64_t count;
3198 zbookmark_t *zb = NULL;
3199 int i;
3200
3201 /*
3202 * Retrieve the raw error list from the kernel. If the number of errors
3203 * has increased, allocate more space and continue until we get the
3204 * entire list.
3205 */
3206 verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT,
3207 &count) == 0);
3208 if (count == 0)
3209 return (0);
3210 if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl,
3211 count * sizeof (zbookmark_t))) == (uintptr_t)NULL)
3212 return (-1);
3213 zc.zc_nvlist_dst_size = count;
3214 (void) strcpy(zc.zc_name, zhp->zpool_name);
3215 for (;;) {
3216 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG,
3217 &zc) != 0) {
3218 free((void *)(uintptr_t)zc.zc_nvlist_dst);
3219 if (errno == ENOMEM) {
3220 count = zc.zc_nvlist_dst_size;
3221 if ((zc.zc_nvlist_dst = (uintptr_t)
3222 zfs_alloc(zhp->zpool_hdl, count *
3223 sizeof (zbookmark_t))) == (uintptr_t)NULL)
3224 return (-1);
3225 } else {
3226 return (-1);
3227 }
3228 } else {
3229 break;
3230 }
3231 }
3232
3233 /*
3234 * Sort the resulting bookmarks. This is a little confusing due to the
3235 * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last
3236 * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks
3237 * _not_ copied as part of the process. So we point the start of our
3238 * array appropriate and decrement the total number of elements.
3239 */
3240 zb = ((zbookmark_t *)(uintptr_t)zc.zc_nvlist_dst) +
3241 zc.zc_nvlist_dst_size;
3242 count -= zc.zc_nvlist_dst_size;
3243
3244 qsort(zb, count, sizeof (zbookmark_t), zbookmark_compare);
3245
3246 verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0);
3247
3248 /*
3249 * Fill in the nverrlistp with nvlist's of dataset and object numbers.
3250 */
3251 for (i = 0; i < count; i++) {
3252 nvlist_t *nv;
3253
3254 /* ignoring zb_blkid and zb_level for now */
3255 if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset &&
3256 zb[i-1].zb_object == zb[i].zb_object)
3257 continue;
3258
3259 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0)
3260 goto nomem;
3261 if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET,
3262 zb[i].zb_objset) != 0) {
3263 nvlist_free(nv);
3264 goto nomem;
3265 }
3266 if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT,
3267 zb[i].zb_object) != 0) {
3268 nvlist_free(nv);
3269 goto nomem;
3270 }
3271 if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) {
3272 nvlist_free(nv);
3273 goto nomem;
3274 }
3275 nvlist_free(nv);
3276 }
3277
3278 free((void *)(uintptr_t)zc.zc_nvlist_dst);
3279 return (0);
3280
3281nomem:
3282 free((void *)(uintptr_t)zc.zc_nvlist_dst);
3283 return (no_memory(zhp->zpool_hdl));
3284}
3285
3286/*
3287 * Upgrade a ZFS pool to the latest on-disk version.
3288 */
3289int
3290zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version)
3291{
2598c001 3292 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
3293 libzfs_handle_t *hdl = zhp->zpool_hdl;
3294
3295 (void) strcpy(zc.zc_name, zhp->zpool_name);
3296 zc.zc_cookie = new_version;
3297
3298 if (zfs_ioctl(hdl, ZFS_IOC_POOL_UPGRADE, &zc) != 0)
3299 return (zpool_standard_error_fmt(hdl, errno,
3300 dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"),
3301 zhp->zpool_name));
3302 return (0);
3303}
3304
3305void
3306zpool_set_history_str(const char *subcommand, int argc, char **argv,
3307 char *history_str)
3308{
3309 int i;
3310
3311 (void) strlcpy(history_str, subcommand, HIS_MAX_RECORD_LEN);
3312 for (i = 1; i < argc; i++) {
3313 if (strlen(history_str) + 1 + strlen(argv[i]) >
3314 HIS_MAX_RECORD_LEN)
3315 break;
3316 (void) strlcat(history_str, " ", HIS_MAX_RECORD_LEN);
3317 (void) strlcat(history_str, argv[i], HIS_MAX_RECORD_LEN);
3318 }
3319}
3320
3321/*
3322 * Stage command history for logging.
3323 */
3324int
3325zpool_stage_history(libzfs_handle_t *hdl, const char *history_str)
3326{
3327 if (history_str == NULL)
3328 return (EINVAL);
3329
3330 if (strlen(history_str) > HIS_MAX_RECORD_LEN)
3331 return (EINVAL);
3332
3333 if (hdl->libzfs_log_str != NULL)
3334 free(hdl->libzfs_log_str);
3335
3336 if ((hdl->libzfs_log_str = strdup(history_str)) == NULL)
3337 return (no_memory(hdl));
3338
3339 return (0);
3340}
3341
3342/*
3343 * Perform ioctl to get some command history of a pool.
3344 *
3345 * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the
3346 * logical offset of the history buffer to start reading from.
3347 *
3348 * Upon return, 'off' is the next logical offset to read from and
3349 * 'len' is the actual amount of bytes read into 'buf'.
3350 */
3351static int
3352get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len)
3353{
2598c001 3354 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
3355 libzfs_handle_t *hdl = zhp->zpool_hdl;
3356
3357 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3358
3359 zc.zc_history = (uint64_t)(uintptr_t)buf;
3360 zc.zc_history_len = *len;
3361 zc.zc_history_offset = *off;
3362
3363 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) {
3364 switch (errno) {
3365 case EPERM:
3366 return (zfs_error_fmt(hdl, EZFS_PERM,
3367 dgettext(TEXT_DOMAIN,
3368 "cannot show history for pool '%s'"),
3369 zhp->zpool_name));
3370 case ENOENT:
3371 return (zfs_error_fmt(hdl, EZFS_NOHISTORY,
3372 dgettext(TEXT_DOMAIN, "cannot get history for pool "
3373 "'%s'"), zhp->zpool_name));
3374 case ENOTSUP:
3375 return (zfs_error_fmt(hdl, EZFS_BADVERSION,
3376 dgettext(TEXT_DOMAIN, "cannot get history for pool "
3377 "'%s', pool must be upgraded"), zhp->zpool_name));
3378 default:
3379 return (zpool_standard_error_fmt(hdl, errno,
3380 dgettext(TEXT_DOMAIN,
3381 "cannot get history for '%s'"), zhp->zpool_name));
3382 }
3383 }
3384
3385 *len = zc.zc_history_len;
3386 *off = zc.zc_history_offset;
3387
3388 return (0);
3389}
3390
3391/*
3392 * Process the buffer of nvlists, unpacking and storing each nvlist record
3393 * into 'records'. 'leftover' is set to the number of bytes that weren't
3394 * processed as there wasn't a complete record.
3395 */
428870ff 3396int
34dc7c2f
BB
3397zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover,
3398 nvlist_t ***records, uint_t *numrecords)
3399{
3400 uint64_t reclen;
3401 nvlist_t *nv;
3402 int i;
3403
3404 while (bytes_read > sizeof (reclen)) {
3405
3406 /* get length of packed record (stored as little endian) */
3407 for (i = 0, reclen = 0; i < sizeof (reclen); i++)
3408 reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i);
3409
3410 if (bytes_read < sizeof (reclen) + reclen)
3411 break;
3412
3413 /* unpack record */
3414 if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0)
3415 return (ENOMEM);
3416 bytes_read -= sizeof (reclen) + reclen;
3417 buf += sizeof (reclen) + reclen;
3418
3419 /* add record to nvlist array */
3420 (*numrecords)++;
3421 if (ISP2(*numrecords + 1)) {
3422 *records = realloc(*records,
3423 *numrecords * 2 * sizeof (nvlist_t *));
3424 }
3425 (*records)[*numrecords - 1] = nv;
3426 }
3427
3428 *leftover = bytes_read;
3429 return (0);
3430}
3431
3432#define HIS_BUF_LEN (128*1024)
3433
3434/*
3435 * Retrieve the command history of a pool.
3436 */
3437int
3438zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
3439{
3440 char buf[HIS_BUF_LEN];
3441 uint64_t off = 0;
3442 nvlist_t **records = NULL;
3443 uint_t numrecords = 0;
3444 int err, i;
3445
3446 do {
3447 uint64_t bytes_read = sizeof (buf);
3448 uint64_t leftover;
3449
3450 if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0)
3451 break;
3452
3453 /* if nothing else was read in, we're at EOF, just return */
3454 if (!bytes_read)
3455 break;
3456
3457 if ((err = zpool_history_unpack(buf, bytes_read,
3458 &leftover, &records, &numrecords)) != 0)
3459 break;
3460 off -= leftover;
3461
3462 /* CONSTCOND */
3463 } while (1);
3464
3465 if (!err) {
3466 verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0);
3467 verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD,
3468 records, numrecords) == 0);
3469 }
3470 for (i = 0; i < numrecords; i++)
3471 nvlist_free(records[i]);
3472 free(records);
3473
3474 return (err);
3475}
3476
3477void
3478zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
3479 char *pathname, size_t len)
3480{
2598c001 3481 zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
34dc7c2f
BB
3482 boolean_t mounted = B_FALSE;
3483 char *mntpnt = NULL;
3484 char dsname[MAXNAMELEN];
3485
3486 if (dsobj == 0) {
3487 /* special case for the MOS */
b8864a23 3488 (void) snprintf(pathname, len, "<metadata>:<0x%llx>", (longlong_t)obj);
34dc7c2f
BB
3489 return;
3490 }
3491
3492 /* get the dataset's name */
3493 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3494 zc.zc_obj = dsobj;
3495 if (ioctl(zhp->zpool_hdl->libzfs_fd,
3496 ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) {
3497 /* just write out a path of two object numbers */
3498 (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>",
b8864a23 3499 (longlong_t)dsobj, (longlong_t)obj);
34dc7c2f
BB
3500 return;
3501 }
3502 (void) strlcpy(dsname, zc.zc_value, sizeof (dsname));
3503
3504 /* find out if the dataset is mounted */
3505 mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt);
3506
3507 /* get the corrupted object's path */
3508 (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name));
3509 zc.zc_obj = obj;
3510 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH,
3511 &zc) == 0) {
3512 if (mounted) {
3513 (void) snprintf(pathname, len, "%s%s", mntpnt,
3514 zc.zc_value);
3515 } else {
3516 (void) snprintf(pathname, len, "%s:%s",
3517 dsname, zc.zc_value);
3518 }
3519 } else {
b8864a23 3520 (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, (longlong_t)obj);
34dc7c2f
BB
3521 }
3522 free(mntpnt);
3523}
3524
b128c09f
BB
3525/*
3526 * Read the EFI label from the config, if a label does not exist then
3527 * pass back the error to the caller. If the caller has passed a non-NULL
3528 * diskaddr argument then we set it to the starting address of the EFI
3529 * partition.
3530 */
3531static int
3532read_efi_label(nvlist_t *config, diskaddr_t *sb)
3533{
3534 char *path;
3535 int fd;
3536 char diskname[MAXPATHLEN];
3537 int err = -1;
3538
3539 if (nvlist_lookup_string(config, ZPOOL_CONFIG_PATH, &path) != 0)
3540 return (err);
3541
3542 (void) snprintf(diskname, sizeof (diskname), "%s%s", RDISK_ROOT,
3543 strrchr(path, '/'));
3544 if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) {
3545 struct dk_gpt *vtoc;
3546
3547 if ((err = efi_alloc_and_read(fd, &vtoc)) >= 0) {
3548 if (sb != NULL)
3549 *sb = vtoc->efi_parts[0].p_start;
3550 efi_free(vtoc);
3551 }
3552 (void) close(fd);
3553 }
3554 return (err);
3555}
3556
34dc7c2f
BB
3557/*
3558 * determine where a partition starts on a disk in the current
3559 * configuration
3560 */
3561static diskaddr_t
3562find_start_block(nvlist_t *config)
3563{
3564 nvlist_t **child;
3565 uint_t c, children;
34dc7c2f 3566 diskaddr_t sb = MAXOFFSET_T;
34dc7c2f
BB
3567 uint64_t wholedisk;
3568
3569 if (nvlist_lookup_nvlist_array(config,
3570 ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) {
3571 if (nvlist_lookup_uint64(config,
3572 ZPOOL_CONFIG_WHOLE_DISK,
3573 &wholedisk) != 0 || !wholedisk) {
3574 return (MAXOFFSET_T);
3575 }
b128c09f
BB
3576 if (read_efi_label(config, &sb) < 0)
3577 sb = MAXOFFSET_T;
34dc7c2f
BB
3578 return (sb);
3579 }
3580
3581 for (c = 0; c < children; c++) {
3582 sb = find_start_block(child[c]);
3583 if (sb != MAXOFFSET_T) {
3584 return (sb);
3585 }
3586 }
3587 return (MAXOFFSET_T);
3588}
3589
3590/*
3591 * Label an individual disk. The name provided is the short name,
3592 * stripped of any leading /dev path.
3593 */
3594int
3595zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
3596{
3597 char path[MAXPATHLEN];
3598 struct dk_gpt *vtoc;
3599 int fd;
3600 size_t resv = EFI_MIN_RESV_SIZE;
3601 uint64_t slice_size;
3602 diskaddr_t start_block;
3603 char errbuf[1024];
3604
3605 /* prepare an error message just in case */
3606 (void) snprintf(errbuf, sizeof (errbuf),
3607 dgettext(TEXT_DOMAIN, "cannot label '%s'"), name);
3608
3609 if (zhp) {
3610 nvlist_t *nvroot;
3611
b128c09f
BB
3612 if (pool_is_bootable(zhp)) {
3613 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3614 "EFI labeled devices are not supported on root "
3615 "pools."));
3616 return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf));
3617 }
3618
34dc7c2f
BB
3619 verify(nvlist_lookup_nvlist(zhp->zpool_config,
3620 ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
3621
3622 if (zhp->zpool_start_block == 0)
3623 start_block = find_start_block(nvroot);
3624 else
3625 start_block = zhp->zpool_start_block;
3626 zhp->zpool_start_block = start_block;
3627 } else {
3628 /* new pool */
3629 start_block = NEW_START_BLOCK;
3630 }
3631
3632 (void) snprintf(path, sizeof (path), "%s/%s%s", RDISK_ROOT, name,
3633 BACKUP_SLICE);
3634
3635 if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) {
3636 /*
3637 * This shouldn't happen. We've long since verified that this
3638 * is a valid device.
3639 */
3640 zfs_error_aux(hdl,
3641 dgettext(TEXT_DOMAIN, "unable to open device"));
3642 return (zfs_error(hdl, EZFS_OPENFAILED, errbuf));
3643 }
3644
3645 if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) {
3646 /*
3647 * The only way this can fail is if we run out of memory, or we
3648 * were unable to read the disk's capacity
3649 */
3650 if (errno == ENOMEM)
3651 (void) no_memory(hdl);
3652
3653 (void) close(fd);
3654 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3655 "unable to read disk capacity"), name);
3656
3657 return (zfs_error(hdl, EZFS_NOCAP, errbuf));
3658 }
3659
3660 slice_size = vtoc->efi_last_u_lba + 1;
3661 slice_size -= EFI_MIN_RESV_SIZE;
3662 if (start_block == MAXOFFSET_T)
3663 start_block = NEW_START_BLOCK;
3664 slice_size -= start_block;
3665
3666 vtoc->efi_parts[0].p_start = start_block;
3667 vtoc->efi_parts[0].p_size = slice_size;
3668
3669 /*
3670 * Why we use V_USR: V_BACKUP confuses users, and is considered
3671 * disposable by some EFI utilities (since EFI doesn't have a backup
3672 * slice). V_UNASSIGNED is supposed to be used only for zero size
3673 * partitions, and efi_write() will fail if we use it. V_ROOT, V_BOOT,
3674 * etc. were all pretty specific. V_USR is as close to reality as we
3675 * can get, in the absence of V_OTHER.
3676 */
3677 vtoc->efi_parts[0].p_tag = V_USR;
3678 (void) strcpy(vtoc->efi_parts[0].p_name, "zfs");
3679
3680 vtoc->efi_parts[8].p_start = slice_size + start_block;
3681 vtoc->efi_parts[8].p_size = resv;
3682 vtoc->efi_parts[8].p_tag = V_RESERVED;
3683
3684 if (efi_write(fd, vtoc) != 0) {
3685 /*
3686 * Some block drivers (like pcata) may not support EFI
3687 * GPT labels. Print out a helpful error message dir-
3688 * ecting the user to manually label the disk and give
3689 * a specific slice.
3690 */
3691 (void) close(fd);
3692 efi_free(vtoc);
3693
3694 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3695 "try using fdisk(1M) and then provide a specific slice"));
3696 return (zfs_error(hdl, EZFS_LABELFAILED, errbuf));
3697 }
3698
3699 (void) close(fd);
3700 efi_free(vtoc);
3701 return (0);
3702}
3703
3704static boolean_t
3705supported_dump_vdev_type(libzfs_handle_t *hdl, nvlist_t *config, char *errbuf)
3706{
3707 char *type;
3708 nvlist_t **child;
3709 uint_t children, c;
3710
3711 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_TYPE, &type) == 0);
3712 if (strcmp(type, VDEV_TYPE_RAIDZ) == 0 ||
3713 strcmp(type, VDEV_TYPE_FILE) == 0 ||
3714 strcmp(type, VDEV_TYPE_LOG) == 0 ||
428870ff 3715 strcmp(type, VDEV_TYPE_HOLE) == 0 ||
34dc7c2f
BB
3716 strcmp(type, VDEV_TYPE_MISSING) == 0) {
3717 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3718 "vdev type '%s' is not supported"), type);
3719 (void) zfs_error(hdl, EZFS_VDEVNOTSUP, errbuf);
3720 return (B_FALSE);
3721 }
3722 if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN,
3723 &child, &children) == 0) {
3724 for (c = 0; c < children; c++) {
3725 if (!supported_dump_vdev_type(hdl, child[c], errbuf))
3726 return (B_FALSE);
3727 }
3728 }
3729 return (B_TRUE);
3730}
3731
3732/*
3733 * check if this zvol is allowable for use as a dump device; zero if
3734 * it is, > 0 if it isn't, < 0 if it isn't a zvol
3735 */
3736int
3737zvol_check_dump_config(char *arg)
3738{
3739 zpool_handle_t *zhp = NULL;
3740 nvlist_t *config, *nvroot;
3741 char *p, *volname;
3742 nvlist_t **top;
3743 uint_t toplevels;
3744 libzfs_handle_t *hdl;
3745 char errbuf[1024];
3746 char poolname[ZPOOL_MAXNAMELEN];
3747 int pathlen = strlen(ZVOL_FULL_DEV_DIR);
3748 int ret = 1;
3749
3750 if (strncmp(arg, ZVOL_FULL_DEV_DIR, pathlen)) {
3751 return (-1);
3752 }
3753
3754 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3755 "dump is not supported on device '%s'"), arg);
3756
3757 if ((hdl = libzfs_init()) == NULL)
3758 return (1);
3759 libzfs_print_on_error(hdl, B_TRUE);
3760
3761 volname = arg + pathlen;
3762
3763 /* check the configuration of the pool */
3764 if ((p = strchr(volname, '/')) == NULL) {
3765 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3766 "malformed dataset name"));
3767 (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
3768 return (1);
3769 } else if (p - volname >= ZFS_MAXNAMELEN) {
3770 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3771 "dataset name is too long"));
3772 (void) zfs_error(hdl, EZFS_NAMETOOLONG, errbuf);
3773 return (1);
3774 } else {
3775 (void) strncpy(poolname, volname, p - volname);
3776 poolname[p - volname] = '\0';
3777 }
3778
3779 if ((zhp = zpool_open(hdl, poolname)) == NULL) {
3780 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3781 "could not open pool '%s'"), poolname);
3782 (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf);
3783 goto out;
3784 }
3785 config = zpool_get_config(zhp, NULL);
3786 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3787 &nvroot) != 0) {
3788 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3789 "could not obtain vdev configuration for '%s'"), poolname);
3790 (void) zfs_error(hdl, EZFS_INVALCONFIG, errbuf);
3791 goto out;
3792 }
3793
3794 verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
3795 &top, &toplevels) == 0);
3796 if (toplevels != 1) {
3797 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3798 "'%s' has multiple top level vdevs"), poolname);
3799 (void) zfs_error(hdl, EZFS_DEVOVERFLOW, errbuf);
3800 goto out;
3801 }
3802
3803 if (!supported_dump_vdev_type(hdl, top[0], errbuf)) {
3804 goto out;
3805 }
3806 ret = 0;
3807
3808out:
3809 if (zhp)
3810 zpool_close(zhp);
3811 libzfs_fini(hdl);
3812 return (ret);
3813}