16666 loader: reading from large dosfs fails
[illumos-gate.git] / usr / src / lib / libzfs / common / libzfs_pool.c
blob980edd6cd8f572e8661adda1fd442fb58d46717c
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
25 * Copyright 2019 Joyent, Inc.
26 * Copyright 2016 Nexenta Systems, Inc.
27 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
28 * Copyright (c) 2017 Datto Inc.
29 * Copyright (c) 2017, Intel Corporation.
30 * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
31 * Copyright 2022 Oxide Computer Company
34 #include <ctype.h>
35 #include <errno.h>
36 #include <devid.h>
37 #include <fcntl.h>
38 #include <libintl.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <strings.h>
42 #include <unistd.h>
43 #include <libgen.h>
44 #include <sys/dkio.h>
45 #include <sys/efi_partition.h>
46 #include <sys/vtoc.h>
47 #include <sys/zfs_ioctl.h>
48 #include <sys/modctl.h>
49 #include <sys/mkdev.h>
50 #include <dlfcn.h>
51 #include <libzutil.h>
53 #include "zfs_namecheck.h"
54 #include "zfs_prop.h"
55 #include "libzfs_impl.h"
56 #include "zfs_comutil.h"
57 #include "zfeature_common.h"
59 static int read_efi_label(nvlist_t *, diskaddr_t *, boolean_t *);
60 static boolean_t zpool_vdev_is_interior(const char *name);
62 #define BACKUP_SLICE "s2"
64 typedef struct prop_flags {
65 int create:1; /* Validate property on creation */
66 int import:1; /* Validate property on import */
67 } prop_flags_t;
70 * ====================================================================
71 * zpool property functions
72 * ====================================================================
75 static int
76 zpool_get_all_props(zpool_handle_t *zhp)
78 zfs_cmd_t zc = { 0 };
79 libzfs_handle_t *hdl = zhp->zpool_hdl;
81 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
83 if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0)
84 return (-1);
86 while (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) {
87 if (errno == ENOMEM) {
88 if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
89 zcmd_free_nvlists(&zc);
90 return (-1);
92 } else {
93 zcmd_free_nvlists(&zc);
94 return (-1);
98 if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) {
99 zcmd_free_nvlists(&zc);
100 return (-1);
103 zcmd_free_nvlists(&zc);
105 return (0);
108 static int
109 zpool_props_refresh(zpool_handle_t *zhp)
111 nvlist_t *old_props;
113 old_props = zhp->zpool_props;
115 if (zpool_get_all_props(zhp) != 0)
116 return (-1);
118 nvlist_free(old_props);
119 return (0);
122 static char *
123 zpool_get_prop_string(zpool_handle_t *zhp, zpool_prop_t prop,
124 zprop_source_t *src)
126 nvlist_t *nv, *nvl;
127 uint64_t ival;
128 char *value;
129 zprop_source_t source;
131 nvl = zhp->zpool_props;
132 if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) {
133 verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &ival) == 0);
134 source = ival;
135 verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
136 } else {
137 source = ZPROP_SRC_DEFAULT;
138 if ((value = (char *)zpool_prop_default_string(prop)) == NULL)
139 value = "-";
142 if (src)
143 *src = source;
145 return (value);
148 uint64_t
149 zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop, zprop_source_t *src)
151 nvlist_t *nv, *nvl;
152 uint64_t value;
153 zprop_source_t source;
155 if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) {
157 * zpool_get_all_props() has most likely failed because
158 * the pool is faulted, but if all we need is the top level
159 * vdev's guid then get it from the zhp config nvlist.
161 if ((prop == ZPOOL_PROP_GUID) &&
162 (nvlist_lookup_nvlist(zhp->zpool_config,
163 ZPOOL_CONFIG_VDEV_TREE, &nv) == 0) &&
164 (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &value)
165 == 0)) {
166 return (value);
168 return (zpool_prop_default_numeric(prop));
171 nvl = zhp->zpool_props;
172 if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) {
173 verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &value) == 0);
174 source = value;
175 verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0);
176 } else {
177 source = ZPROP_SRC_DEFAULT;
178 value = zpool_prop_default_numeric(prop);
181 if (src)
182 *src = source;
184 return (value);
188 * Map VDEV STATE to printed strings.
190 const char *
191 zpool_state_to_name(vdev_state_t state, vdev_aux_t aux)
193 switch (state) {
194 case VDEV_STATE_CLOSED:
195 case VDEV_STATE_OFFLINE:
196 return (gettext("OFFLINE"));
197 case VDEV_STATE_REMOVED:
198 return (gettext("REMOVED"));
199 case VDEV_STATE_CANT_OPEN:
200 if (aux == VDEV_AUX_CORRUPT_DATA || aux == VDEV_AUX_BAD_LOG)
201 return (gettext("FAULTED"));
202 else if (aux == VDEV_AUX_SPLIT_POOL)
203 return (gettext("SPLIT"));
204 else
205 return (gettext("UNAVAIL"));
206 case VDEV_STATE_FAULTED:
207 return (gettext("FAULTED"));
208 case VDEV_STATE_DEGRADED:
209 return (gettext("DEGRADED"));
210 case VDEV_STATE_HEALTHY:
211 return (gettext("ONLINE"));
213 default:
214 break;
217 return (gettext("UNKNOWN"));
221 * Map POOL STATE to printed strings.
223 const char *
224 zpool_pool_state_to_name(pool_state_t state)
226 switch (state) {
227 case POOL_STATE_ACTIVE:
228 return (gettext("ACTIVE"));
229 case POOL_STATE_EXPORTED:
230 return (gettext("EXPORTED"));
231 case POOL_STATE_DESTROYED:
232 return (gettext("DESTROYED"));
233 case POOL_STATE_SPARE:
234 return (gettext("SPARE"));
235 case POOL_STATE_L2CACHE:
236 return (gettext("L2CACHE"));
237 case POOL_STATE_UNINITIALIZED:
238 return (gettext("UNINITIALIZED"));
239 case POOL_STATE_UNAVAIL:
240 return (gettext("UNAVAIL"));
241 case POOL_STATE_POTENTIALLY_ACTIVE:
242 return (gettext("POTENTIALLY_ACTIVE"));
245 return (gettext("UNKNOWN"));
249 * Get a zpool property value for 'prop' and return the value in
250 * a pre-allocated buffer.
253 zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
254 zprop_source_t *srctype, boolean_t literal)
256 uint64_t intval;
257 const char *strval;
258 zprop_source_t src = ZPROP_SRC_NONE;
259 nvlist_t *nvroot;
260 vdev_stat_t *vs;
261 uint_t vsc;
263 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
264 switch (prop) {
265 case ZPOOL_PROP_NAME:
266 (void) strlcpy(buf, zpool_get_name(zhp), len);
267 break;
269 case ZPOOL_PROP_HEALTH:
270 (void) strlcpy(buf, "FAULTED", len);
271 break;
273 case ZPOOL_PROP_GUID:
274 intval = zpool_get_prop_int(zhp, prop, &src);
275 (void) snprintf(buf, len, "%llu", intval);
276 break;
278 case ZPOOL_PROP_ALTROOT:
279 case ZPOOL_PROP_CACHEFILE:
280 case ZPOOL_PROP_COMMENT:
281 if (zhp->zpool_props != NULL ||
282 zpool_get_all_props(zhp) == 0) {
283 (void) strlcpy(buf,
284 zpool_get_prop_string(zhp, prop, &src),
285 len);
286 break;
288 /* FALLTHROUGH */
289 default:
290 (void) strlcpy(buf, "-", len);
291 break;
294 if (srctype != NULL)
295 *srctype = src;
296 return (0);
299 if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) &&
300 prop != ZPOOL_PROP_NAME)
301 return (-1);
303 switch (zpool_prop_get_type(prop)) {
304 case PROP_TYPE_STRING:
305 (void) strlcpy(buf, zpool_get_prop_string(zhp, prop, &src),
306 len);
307 break;
309 case PROP_TYPE_NUMBER:
310 intval = zpool_get_prop_int(zhp, prop, &src);
312 switch (prop) {
313 case ZPOOL_PROP_SIZE:
314 case ZPOOL_PROP_ALLOCATED:
315 case ZPOOL_PROP_FREE:
316 case ZPOOL_PROP_FREEING:
317 case ZPOOL_PROP_LEAKED:
318 case ZPOOL_PROP_ASHIFT:
319 if (literal) {
320 (void) snprintf(buf, len, "%llu",
321 (u_longlong_t)intval);
322 } else {
323 (void) zfs_nicenum(intval, buf, len);
325 break;
326 case ZPOOL_PROP_BOOTSIZE:
327 case ZPOOL_PROP_EXPANDSZ:
328 case ZPOOL_PROP_CHECKPOINT:
329 if (intval == 0) {
330 (void) strlcpy(buf, "-", len);
331 } else if (literal) {
332 (void) snprintf(buf, len, "%llu",
333 (u_longlong_t)intval);
334 } else {
335 (void) zfs_nicebytes(intval, buf, len);
337 break;
338 case ZPOOL_PROP_CAPACITY:
339 if (literal) {
340 (void) snprintf(buf, len, "%llu",
341 (u_longlong_t)intval);
342 } else {
343 (void) snprintf(buf, len, "%llu%%",
344 (u_longlong_t)intval);
346 break;
347 case ZPOOL_PROP_FRAGMENTATION:
348 if (intval == UINT64_MAX) {
349 (void) strlcpy(buf, "-", len);
350 } else if (literal) {
351 (void) snprintf(buf, len, "%llu",
352 (u_longlong_t)intval);
353 } else {
354 (void) snprintf(buf, len, "%llu%%",
355 (u_longlong_t)intval);
357 break;
358 case ZPOOL_PROP_DEDUPRATIO:
359 if (literal)
360 (void) snprintf(buf, len, "%llu.%02llu",
361 (u_longlong_t)(intval / 100),
362 (u_longlong_t)(intval % 100));
363 else
364 (void) snprintf(buf, len, "%llu.%02llux",
365 (u_longlong_t)(intval / 100),
366 (u_longlong_t)(intval % 100));
367 break;
368 case ZPOOL_PROP_HEALTH:
369 verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
370 ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
371 verify(nvlist_lookup_uint64_array(nvroot,
372 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &vsc)
373 == 0);
375 (void) strlcpy(buf, zpool_state_to_name(intval,
376 vs->vs_aux), len);
377 break;
378 case ZPOOL_PROP_VERSION:
379 if (intval >= SPA_VERSION_FEATURES) {
380 (void) snprintf(buf, len, "-");
381 break;
383 /* FALLTHROUGH */
384 default:
385 (void) snprintf(buf, len, "%llu", intval);
387 break;
389 case PROP_TYPE_INDEX:
390 intval = zpool_get_prop_int(zhp, prop, &src);
391 if (zpool_prop_index_to_string(prop, intval, &strval)
392 != 0)
393 return (-1);
394 (void) strlcpy(buf, strval, len);
395 break;
397 default:
398 abort();
401 if (srctype)
402 *srctype = src;
404 return (0);
408 * Check if the bootfs name has the same pool name as it is set to.
409 * Assuming bootfs is a valid dataset name.
411 static boolean_t
412 bootfs_name_valid(const char *pool, const char *bootfs)
414 int len = strlen(pool);
415 if (bootfs[0] == '\0')
416 return (B_TRUE);
418 if (!zfs_name_valid(bootfs, ZFS_TYPE_FILESYSTEM|ZFS_TYPE_SNAPSHOT))
419 return (B_FALSE);
421 if (strncmp(pool, bootfs, len) == 0 &&
422 (bootfs[len] == '/' || bootfs[len] == '\0'))
423 return (B_TRUE);
425 return (B_FALSE);
428 boolean_t
429 zpool_is_bootable(zpool_handle_t *zhp)
431 char bootfs[ZFS_MAX_DATASET_NAME_LEN];
433 return (zpool_get_prop(zhp, ZPOOL_PROP_BOOTFS, bootfs,
434 sizeof (bootfs), NULL, B_FALSE) == 0 && strncmp(bootfs, "-",
435 sizeof (bootfs)) != 0);
440 * Given an nvlist of zpool properties to be set, validate that they are
441 * correct, and parse any numeric properties (index, boolean, etc) if they are
442 * specified as strings.
444 static nvlist_t *
445 zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
446 nvlist_t *props, uint64_t version, prop_flags_t flags, char *errbuf)
448 nvpair_t *elem;
449 nvlist_t *retprops;
450 zpool_prop_t prop;
451 char *strval;
452 uint64_t intval;
453 char *slash, *check;
454 struct stat64 statbuf;
455 zpool_handle_t *zhp;
457 if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) {
458 (void) no_memory(hdl);
459 return (NULL);
462 elem = NULL;
463 while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
464 const char *propname = nvpair_name(elem);
466 prop = zpool_name_to_prop(propname);
467 if (prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname)) {
468 int err;
469 char *fname = strchr(propname, '@') + 1;
471 err = zfeature_lookup_name(fname, NULL);
472 if (err != 0) {
473 ASSERT3U(err, ==, ENOENT);
474 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
475 "invalid feature '%s', '%s'"), fname,
476 propname);
477 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
478 goto error;
481 if (nvpair_type(elem) != DATA_TYPE_STRING) {
482 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
483 "'%s' must be a string"), propname);
484 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
485 goto error;
488 (void) nvpair_value_string(elem, &strval);
489 if (strcmp(strval, ZFS_FEATURE_ENABLED) != 0 &&
490 strcmp(strval, ZFS_FEATURE_DISABLED) != 0) {
491 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
492 "property '%s' can only be set to "
493 "'enabled' or 'disabled'"), propname);
494 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
495 goto error;
498 if (nvlist_add_uint64(retprops, propname, 0) != 0) {
499 (void) no_memory(hdl);
500 goto error;
502 continue;
506 * Make sure this property is valid and applies to this type.
508 if (prop == ZPOOL_PROP_INVAL) {
509 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
510 "invalid property '%s'"), propname);
511 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
512 goto error;
515 if (zpool_prop_readonly(prop)) {
516 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
517 "is readonly"), propname);
518 (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
519 goto error;
522 if (zprop_parse_value(hdl, elem, prop, ZFS_TYPE_POOL, retprops,
523 &strval, &intval, errbuf) != 0)
524 goto error;
527 * Perform additional checking for specific properties.
529 switch (prop) {
530 case ZPOOL_PROP_VERSION:
531 if (intval < version ||
532 !SPA_VERSION_IS_SUPPORTED(intval)) {
533 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
534 "property '%s' number %d is invalid."),
535 propname, intval);
536 (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
537 goto error;
539 break;
541 case ZPOOL_PROP_BOOTSIZE:
542 if (!flags.create) {
543 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
544 "property '%s' can only be set during pool "
545 "creation"), propname);
546 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
547 goto error;
549 break;
551 case ZPOOL_PROP_ASHIFT:
552 if (intval != 0 &&
553 (intval < ASHIFT_MIN || intval > ASHIFT_MAX)) {
554 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
555 "invalid '%s=%d' property: only values "
556 "between %" PRId32 " and %" PRId32 " "
557 "are allowed.\n"),
558 propname, intval, ASHIFT_MIN, ASHIFT_MAX);
559 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
560 goto error;
562 break;
564 case ZPOOL_PROP_BOOTFS:
565 if (flags.create || flags.import) {
566 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
567 "property '%s' cannot be set at creation "
568 "or import time"), propname);
569 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
570 goto error;
573 if (version < SPA_VERSION_BOOTFS) {
574 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
575 "pool must be upgraded to support "
576 "'%s' property"), propname);
577 (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
578 goto error;
582 * bootfs property value has to be a dataset name and
583 * the dataset has to be in the same pool as it sets to.
585 if (!bootfs_name_valid(poolname, strval)) {
586 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
587 "is an invalid name"), strval);
588 (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
589 goto error;
592 if ((zhp = zpool_open_canfail(hdl, poolname)) == NULL) {
593 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
594 "could not open pool '%s'"), poolname);
595 (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf);
596 goto error;
598 zpool_close(zhp);
599 break;
601 case ZPOOL_PROP_ALTROOT:
602 if (!flags.create && !flags.import) {
603 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
604 "property '%s' can only be set during pool "
605 "creation or import"), propname);
606 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
607 goto error;
610 if (strval[0] != '/') {
611 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
612 "bad alternate root '%s'"), strval);
613 (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
614 goto error;
616 break;
618 case ZPOOL_PROP_CACHEFILE:
619 if (strval[0] == '\0')
620 break;
622 if (strcmp(strval, "none") == 0)
623 break;
625 if (strval[0] != '/') {
626 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
627 "property '%s' must be empty, an "
628 "absolute path, or 'none'"), propname);
629 (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
630 goto error;
633 slash = strrchr(strval, '/');
635 if (slash[1] == '\0' || strcmp(slash, "/.") == 0 ||
636 strcmp(slash, "/..") == 0) {
637 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
638 "'%s' is not a valid file"), strval);
639 (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
640 goto error;
643 *slash = '\0';
645 if (strval[0] != '\0' &&
646 (stat64(strval, &statbuf) != 0 ||
647 !S_ISDIR(statbuf.st_mode))) {
648 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
649 "'%s' is not a valid directory"),
650 strval);
651 (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
652 goto error;
655 *slash = '/';
656 break;
658 case ZPOOL_PROP_COMMENT:
659 for (check = strval; *check != '\0'; check++) {
660 if (!isprint(*check)) {
661 zfs_error_aux(hdl,
662 dgettext(TEXT_DOMAIN,
663 "comment may only have printable "
664 "characters"));
665 (void) zfs_error(hdl, EZFS_BADPROP,
666 errbuf);
667 goto error;
670 if (strlen(strval) > ZPROP_MAX_COMMENT) {
671 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
672 "comment must not exceed %d characters"),
673 ZPROP_MAX_COMMENT);
674 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
675 goto error;
677 break;
679 case ZPOOL_PROP_READONLY:
680 if (!flags.import) {
681 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
682 "property '%s' can only be set at "
683 "import time"), propname);
684 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
685 goto error;
687 break;
689 case ZPOOL_PROP_TNAME:
690 if (!flags.create) {
691 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
692 "property '%s' can only be set at "
693 "creation time"), propname);
694 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
695 goto error;
697 break;
699 case ZPOOL_PROP_MULTIHOST:
700 if (get_system_hostid() == 0) {
701 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
702 "requires a non-zero system hostid"));
703 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
704 goto error;
706 break;
708 default:
709 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
710 "property '%s'(%d) not defined"), propname, prop);
711 break;
715 return (retprops);
716 error:
717 nvlist_free(retprops);
718 return (NULL);
722 * Set zpool property : propname=propval.
725 zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval)
727 zfs_cmd_t zc = { 0 };
728 int ret = -1;
729 char errbuf[1024];
730 nvlist_t *nvl = NULL;
731 nvlist_t *realprops;
732 uint64_t version;
733 prop_flags_t flags = { 0 };
735 (void) snprintf(errbuf, sizeof (errbuf),
736 dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
737 zhp->zpool_name);
739 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
740 return (no_memory(zhp->zpool_hdl));
742 if (nvlist_add_string(nvl, propname, propval) != 0) {
743 nvlist_free(nvl);
744 return (no_memory(zhp->zpool_hdl));
747 version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
748 if ((realprops = zpool_valid_proplist(zhp->zpool_hdl,
749 zhp->zpool_name, nvl, version, flags, errbuf)) == NULL) {
750 nvlist_free(nvl);
751 return (-1);
754 nvlist_free(nvl);
755 nvl = realprops;
758 * Execute the corresponding ioctl() to set this property.
760 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
762 if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl) != 0) {
763 nvlist_free(nvl);
764 return (-1);
767 ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SET_PROPS, &zc);
769 zcmd_free_nvlists(&zc);
770 nvlist_free(nvl);
772 if (ret)
773 (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf);
774 else
775 (void) zpool_props_refresh(zhp);
777 return (ret);
781 zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
783 libzfs_handle_t *hdl = zhp->zpool_hdl;
784 zprop_list_t *entry;
785 char buf[ZFS_MAXPROPLEN];
786 nvlist_t *features = NULL;
787 zprop_list_t **last;
788 boolean_t firstexpand = (NULL == *plp);
790 if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0)
791 return (-1);
793 last = plp;
794 while (*last != NULL)
795 last = &(*last)->pl_next;
797 if ((*plp)->pl_all)
798 features = zpool_get_features(zhp);
800 if ((*plp)->pl_all && firstexpand) {
801 for (int i = 0; i < SPA_FEATURES; i++) {
802 zprop_list_t *entry = zfs_alloc(hdl,
803 sizeof (zprop_list_t));
804 entry->pl_prop = ZPROP_INVAL;
805 entry->pl_user_prop = zfs_asprintf(hdl, "feature@%s",
806 spa_feature_table[i].fi_uname);
807 entry->pl_width = strlen(entry->pl_user_prop);
808 entry->pl_all = B_TRUE;
810 *last = entry;
811 last = &entry->pl_next;
815 /* add any unsupported features */
816 for (nvpair_t *nvp = nvlist_next_nvpair(features, NULL);
817 nvp != NULL; nvp = nvlist_next_nvpair(features, nvp)) {
818 char *propname;
819 boolean_t found;
820 zprop_list_t *entry;
822 if (zfeature_is_supported(nvpair_name(nvp)))
823 continue;
825 propname = zfs_asprintf(hdl, "unsupported@%s",
826 nvpair_name(nvp));
829 * Before adding the property to the list make sure that no
830 * other pool already added the same property.
832 found = B_FALSE;
833 entry = *plp;
834 while (entry != NULL) {
835 if (entry->pl_user_prop != NULL &&
836 strcmp(propname, entry->pl_user_prop) == 0) {
837 found = B_TRUE;
838 break;
840 entry = entry->pl_next;
842 if (found) {
843 free(propname);
844 continue;
847 entry = zfs_alloc(hdl, sizeof (zprop_list_t));
848 entry->pl_prop = ZPROP_INVAL;
849 entry->pl_user_prop = propname;
850 entry->pl_width = strlen(entry->pl_user_prop);
851 entry->pl_all = B_TRUE;
853 *last = entry;
854 last = &entry->pl_next;
857 for (entry = *plp; entry != NULL; entry = entry->pl_next) {
859 if (entry->pl_fixed)
860 continue;
862 if (entry->pl_prop != ZPROP_INVAL &&
863 zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf),
864 NULL, B_FALSE) == 0) {
865 if (strlen(buf) > entry->pl_width)
866 entry->pl_width = strlen(buf);
870 return (0);
874 * Get the state for the given feature on the given ZFS pool.
877 zpool_prop_get_feature(zpool_handle_t *zhp, const char *propname, char *buf,
878 size_t len)
880 uint64_t refcount;
881 boolean_t found = B_FALSE;
882 nvlist_t *features = zpool_get_features(zhp);
883 boolean_t supported;
884 const char *feature = strchr(propname, '@') + 1;
886 supported = zpool_prop_feature(propname);
887 ASSERT(supported || zpool_prop_unsupported(propname));
890 * Convert from feature name to feature guid. This conversion is
891 * unecessary for unsupported@... properties because they already
892 * use guids.
894 if (supported) {
895 int ret;
896 spa_feature_t fid;
898 ret = zfeature_lookup_name(feature, &fid);
899 if (ret != 0) {
900 (void) strlcpy(buf, "-", len);
901 return (ENOTSUP);
903 feature = spa_feature_table[fid].fi_guid;
906 if (nvlist_lookup_uint64(features, feature, &refcount) == 0)
907 found = B_TRUE;
909 if (supported) {
910 if (!found) {
911 (void) strlcpy(buf, ZFS_FEATURE_DISABLED, len);
912 } else {
913 if (refcount == 0)
914 (void) strlcpy(buf, ZFS_FEATURE_ENABLED, len);
915 else
916 (void) strlcpy(buf, ZFS_FEATURE_ACTIVE, len);
918 } else {
919 if (found) {
920 if (refcount == 0) {
921 (void) strcpy(buf, ZFS_UNSUPPORTED_INACTIVE);
922 } else {
923 (void) strcpy(buf, ZFS_UNSUPPORTED_READONLY);
925 } else {
926 (void) strlcpy(buf, "-", len);
927 return (ENOTSUP);
931 return (0);
935 * Don't start the slice at the default block of 34; many storage
936 * devices will use a stripe width of 128k, so start there instead.
938 #define NEW_START_BLOCK 256
941 * Validate the given pool name, optionally putting an extended error message in
942 * 'buf'.
944 boolean_t
945 zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool)
947 namecheck_err_t why;
948 char what;
949 int ret;
951 ret = pool_namecheck(pool, &why, &what);
954 * The rules for reserved pool names were extended at a later point.
955 * But we need to support users with existing pools that may now be
956 * invalid. So we only check for this expanded set of names during a
957 * create (or import), and only in userland.
959 if (ret == 0 && !isopen &&
960 (strncmp(pool, "mirror", 6) == 0 ||
961 strncmp(pool, "raidz", 5) == 0 ||
962 strncmp(pool, "spare", 5) == 0 ||
963 strcmp(pool, "log") == 0)) {
964 if (hdl != NULL)
965 zfs_error_aux(hdl,
966 dgettext(TEXT_DOMAIN, "name is reserved"));
967 return (B_FALSE);
971 if (ret != 0) {
972 if (hdl != NULL) {
973 switch (why) {
974 case NAME_ERR_TOOLONG:
975 zfs_error_aux(hdl,
976 dgettext(TEXT_DOMAIN, "name is too long"));
977 break;
979 case NAME_ERR_INVALCHAR:
980 zfs_error_aux(hdl,
981 dgettext(TEXT_DOMAIN, "invalid character "
982 "'%c' in pool name"), what);
983 break;
985 case NAME_ERR_NOLETTER:
986 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
987 "name must begin with a letter"));
988 break;
990 case NAME_ERR_RESERVED:
991 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
992 "name is reserved"));
993 break;
995 case NAME_ERR_DISKLIKE:
996 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
997 "pool name is reserved"));
998 break;
1000 case NAME_ERR_LEADING_SLASH:
1001 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1002 "leading slash in name"));
1003 break;
1005 case NAME_ERR_EMPTY_COMPONENT:
1006 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1007 "empty component in name"));
1008 break;
1010 case NAME_ERR_TRAILING_SLASH:
1011 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1012 "trailing slash in name"));
1013 break;
1015 case NAME_ERR_MULTIPLE_DELIMITERS:
1016 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1017 "multiple '@' and/or '#' delimiters in "
1018 "name"));
1019 break;
1021 default:
1022 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1023 "(%d) not defined"), why);
1024 break;
1027 return (B_FALSE);
1030 return (B_TRUE);
1034 * Open a handle to the given pool, even if the pool is currently in the FAULTED
1035 * state.
1037 zpool_handle_t *
1038 zpool_open_canfail(libzfs_handle_t *hdl, const char *pool)
1040 zpool_handle_t *zhp;
1041 boolean_t missing;
1044 * Make sure the pool name is valid.
1046 if (!zpool_name_valid(hdl, B_TRUE, pool)) {
1047 (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME,
1048 dgettext(TEXT_DOMAIN, "cannot open '%s'"),
1049 pool);
1050 return (NULL);
1053 if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
1054 return (NULL);
1056 zhp->zpool_hdl = hdl;
1057 (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
1059 if (zpool_refresh_stats(zhp, &missing) != 0) {
1060 zpool_close(zhp);
1061 return (NULL);
1064 if (missing) {
1065 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "no such pool"));
1066 (void) zfs_error_fmt(hdl, EZFS_NOENT,
1067 dgettext(TEXT_DOMAIN, "cannot open '%s'"), pool);
1068 zpool_close(zhp);
1069 return (NULL);
1072 return (zhp);
1076 * Like the above, but silent on error. Used when iterating over pools (because
1077 * the configuration cache may be out of date).
1080 zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret)
1082 zpool_handle_t *zhp;
1083 boolean_t missing;
1085 if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
1086 return (-1);
1088 zhp->zpool_hdl = hdl;
1089 (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
1091 if (zpool_refresh_stats(zhp, &missing) != 0) {
1092 zpool_close(zhp);
1093 return (-1);
1096 if (missing) {
1097 zpool_close(zhp);
1098 *ret = NULL;
1099 return (0);
1102 *ret = zhp;
1103 return (0);
1107 * Similar to zpool_open_canfail(), but refuses to open pools in the faulted
1108 * state.
1110 zpool_handle_t *
1111 zpool_open(libzfs_handle_t *hdl, const char *pool)
1113 zpool_handle_t *zhp;
1115 if ((zhp = zpool_open_canfail(hdl, pool)) == NULL)
1116 return (NULL);
1118 if (zhp->zpool_state == POOL_STATE_UNAVAIL) {
1119 (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL,
1120 dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name);
1121 zpool_close(zhp);
1122 return (NULL);
1125 return (zhp);
1129 * Close the handle. Simply frees the memory associated with the handle.
1131 void
1132 zpool_close(zpool_handle_t *zhp)
1134 nvlist_free(zhp->zpool_config);
1135 nvlist_free(zhp->zpool_old_config);
1136 nvlist_free(zhp->zpool_props);
1137 free(zhp);
1141 * Return the name of the pool.
1143 const char *
1144 zpool_get_name(zpool_handle_t *zhp)
1146 return (zhp->zpool_name);
1151 * Return the state of the pool (ACTIVE or UNAVAILABLE)
1154 zpool_get_state(zpool_handle_t *zhp)
1156 return (zhp->zpool_state);
1160 * Check if vdev list contains a special vdev
1162 static boolean_t
1163 zpool_has_special_vdev(nvlist_t *nvroot)
1165 nvlist_t **child;
1166 uint_t children;
1168 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, &child,
1169 &children) == 0) {
1170 for (uint_t c = 0; c < children; c++) {
1171 char *bias;
1173 if (nvlist_lookup_string(child[c],
1174 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias) == 0 &&
1175 strcmp(bias, VDEV_ALLOC_BIAS_SPECIAL) == 0) {
1176 return (B_TRUE);
1180 return (B_FALSE);
1184 * Create the named pool, using the provided vdev list. It is assumed
1185 * that the consumer has already validated the contents of the nvlist, so we
1186 * don't have to worry about error semantics.
1189 zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
1190 nvlist_t *props, nvlist_t *fsprops)
1192 zfs_cmd_t zc = { 0 };
1193 nvlist_t *zc_fsprops = NULL;
1194 nvlist_t *zc_props = NULL;
1195 nvlist_t *hidden_args = NULL;
1196 uint8_t *wkeydata = NULL;
1197 uint_t wkeylen = 0;
1198 char msg[1024];
1199 int ret = -1;
1201 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1202 "cannot create '%s'"), pool);
1204 if (!zpool_name_valid(hdl, B_FALSE, pool))
1205 return (zfs_error(hdl, EZFS_INVALIDNAME, msg));
1207 if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
1208 return (-1);
1210 if (props) {
1211 prop_flags_t flags = { .create = B_TRUE, .import = B_FALSE };
1213 if ((zc_props = zpool_valid_proplist(hdl, pool, props,
1214 SPA_VERSION_1, flags, msg)) == NULL) {
1215 goto create_failed;
1219 if (fsprops) {
1220 uint64_t zoned;
1221 char *zonestr;
1223 zoned = ((nvlist_lookup_string(fsprops,
1224 zfs_prop_to_name(ZFS_PROP_ZONED), &zonestr) == 0) &&
1225 strcmp(zonestr, "on") == 0);
1227 if ((zc_fsprops = zfs_valid_proplist(hdl, ZFS_TYPE_FILESYSTEM,
1228 fsprops, zoned, NULL, NULL, B_TRUE, msg)) == NULL) {
1229 goto create_failed;
1232 if (nvlist_exists(zc_fsprops,
1233 zfs_prop_to_name(ZFS_PROP_SPECIAL_SMALL_BLOCKS)) &&
1234 !zpool_has_special_vdev(nvroot)) {
1235 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1236 "%s property requires a special vdev"),
1237 zfs_prop_to_name(ZFS_PROP_SPECIAL_SMALL_BLOCKS));
1238 (void) zfs_error(hdl, EZFS_BADPROP, msg);
1239 goto create_failed;
1242 if (!zc_props &&
1243 (nvlist_alloc(&zc_props, NV_UNIQUE_NAME, 0) != 0)) {
1244 goto create_failed;
1246 if (zfs_crypto_create(hdl, NULL, zc_fsprops, props, B_TRUE,
1247 &wkeydata, &wkeylen) != 0) {
1248 (void) zfs_error(hdl, EZFS_CRYPTOFAILED, msg);
1249 goto create_failed;
1251 if (nvlist_add_nvlist(zc_props,
1252 ZPOOL_ROOTFS_PROPS, zc_fsprops) != 0) {
1253 goto create_failed;
1255 if (wkeydata != NULL) {
1256 if (nvlist_alloc(&hidden_args, NV_UNIQUE_NAME, 0) != 0)
1257 goto create_failed;
1259 if (nvlist_add_uint8_array(hidden_args, "wkeydata",
1260 wkeydata, wkeylen) != 0)
1261 goto create_failed;
1263 if (nvlist_add_nvlist(zc_props, ZPOOL_HIDDEN_ARGS,
1264 hidden_args) != 0)
1265 goto create_failed;
1269 if (zc_props && zcmd_write_src_nvlist(hdl, &zc, zc_props) != 0)
1270 goto create_failed;
1272 (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name));
1274 if ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_CREATE, &zc)) != 0) {
1276 zcmd_free_nvlists(&zc);
1277 nvlist_free(zc_props);
1278 nvlist_free(zc_fsprops);
1279 nvlist_free(hidden_args);
1280 if (wkeydata != NULL)
1281 free(wkeydata);
1283 switch (errno) {
1284 case EBUSY:
1286 * This can happen if the user has specified the same
1287 * device multiple times. We can't reliably detect this
1288 * until we try to add it and see we already have a
1289 * label.
1291 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1292 "one or more vdevs refer to the same device"));
1293 return (zfs_error(hdl, EZFS_BADDEV, msg));
1295 case ERANGE:
1297 * This happens if the record size is smaller or larger
1298 * than the allowed size range, or not a power of 2.
1300 * NOTE: although zfs_valid_proplist is called earlier,
1301 * this case may have slipped through since the
1302 * pool does not exist yet and it is therefore
1303 * impossible to read properties e.g. max blocksize
1304 * from the pool.
1306 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1307 "record size invalid"));
1308 return (zfs_error(hdl, EZFS_BADPROP, msg));
1310 case EOVERFLOW:
1312 * This occurs when one of the devices is below
1313 * SPA_MINDEVSIZE. Unfortunately, we can't detect which
1314 * device was the problem device since there's no
1315 * reliable way to determine device size from userland.
1318 char buf[64];
1320 zfs_nicebytes(SPA_MINDEVSIZE, buf,
1321 sizeof (buf));
1323 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1324 "one or more devices is less than the "
1325 "minimum size (%s)"), buf);
1327 return (zfs_error(hdl, EZFS_BADDEV, msg));
1329 case ENOSPC:
1330 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1331 "one or more devices is out of space"));
1332 return (zfs_error(hdl, EZFS_BADDEV, msg));
1334 default:
1335 return (zpool_standard_error(hdl, errno, msg));
1339 create_failed:
1340 zcmd_free_nvlists(&zc);
1341 nvlist_free(zc_props);
1342 nvlist_free(zc_fsprops);
1343 nvlist_free(hidden_args);
1344 if (wkeydata != NULL)
1345 free(wkeydata);
1346 return (ret);
1350 * Destroy the given pool. It is up to the caller to ensure that there are no
1351 * datasets left in the pool.
1354 zpool_destroy(zpool_handle_t *zhp, const char *log_str)
1356 zfs_cmd_t zc = { 0 };
1357 zfs_handle_t *zfp = NULL;
1358 libzfs_handle_t *hdl = zhp->zpool_hdl;
1359 char msg[1024];
1361 if (zhp->zpool_state == POOL_STATE_ACTIVE &&
1362 (zfp = zfs_open(hdl, zhp->zpool_name, ZFS_TYPE_FILESYSTEM)) == NULL)
1363 return (-1);
1365 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1366 zc.zc_history = (uint64_t)(uintptr_t)log_str;
1368 if (zfs_ioctl(hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
1369 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1370 "cannot destroy '%s'"), zhp->zpool_name);
1372 if (errno == EROFS) {
1373 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1374 "one or more devices is read only"));
1375 (void) zfs_error(hdl, EZFS_BADDEV, msg);
1376 } else {
1377 (void) zpool_standard_error(hdl, errno, msg);
1380 if (zfp)
1381 zfs_close(zfp);
1382 return (-1);
1385 if (zfp) {
1386 remove_mountpoint(zfp);
1387 zfs_close(zfp);
1390 return (0);
1394 * Create a checkpoint in the given pool.
1397 zpool_checkpoint(zpool_handle_t *zhp)
1399 libzfs_handle_t *hdl = zhp->zpool_hdl;
1400 char msg[1024];
1401 int error;
1403 error = lzc_pool_checkpoint(zhp->zpool_name);
1404 if (error != 0) {
1405 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1406 "cannot checkpoint '%s'"), zhp->zpool_name);
1407 (void) zpool_standard_error(hdl, error, msg);
1408 return (-1);
1411 return (0);
1415 * Discard the checkpoint from the given pool.
1418 zpool_discard_checkpoint(zpool_handle_t *zhp)
1420 libzfs_handle_t *hdl = zhp->zpool_hdl;
1421 char msg[1024];
1422 int error;
1424 error = lzc_pool_checkpoint_discard(zhp->zpool_name);
1425 if (error != 0) {
1426 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1427 "cannot discard checkpoint in '%s'"), zhp->zpool_name);
1428 (void) zpool_standard_error(hdl, error, msg);
1429 return (-1);
1432 return (0);
1436 * Add the given vdevs to the pool. The caller must have already performed the
1437 * necessary verification to ensure that the vdev specification is well-formed.
1440 zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
1442 zfs_cmd_t zc = { 0 };
1443 int ret;
1444 libzfs_handle_t *hdl = zhp->zpool_hdl;
1445 char msg[1024];
1446 nvlist_t **spares, **l2cache;
1447 uint_t nspares, nl2cache;
1449 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1450 "cannot add to '%s'"), zhp->zpool_name);
1452 if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
1453 SPA_VERSION_SPARES &&
1454 nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
1455 &spares, &nspares) == 0) {
1456 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
1457 "upgraded to add hot spares"));
1458 return (zfs_error(hdl, EZFS_BADVERSION, msg));
1461 if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
1462 SPA_VERSION_L2CACHE &&
1463 nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
1464 &l2cache, &nl2cache) == 0) {
1465 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
1466 "upgraded to add cache devices"));
1467 return (zfs_error(hdl, EZFS_BADVERSION, msg));
1470 if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
1471 return (-1);
1472 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1474 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_ADD, &zc) != 0) {
1475 switch (errno) {
1476 case EBUSY:
1478 * This can happen if the user has specified the same
1479 * device multiple times. We can't reliably detect this
1480 * until we try to add it and see we already have a
1481 * label.
1483 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1484 "one or more vdevs refer to the same device"));
1485 (void) zfs_error(hdl, EZFS_BADDEV, msg);
1486 break;
1488 case EINVAL:
1489 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1490 "invalid config; a pool with removing/removed "
1491 "vdevs does not support adding raidz vdevs"));
1492 (void) zfs_error(hdl, EZFS_BADDEV, msg);
1493 break;
1495 case EOVERFLOW:
1497 * This occurrs when one of the devices is below
1498 * SPA_MINDEVSIZE. Unfortunately, we can't detect which
1499 * device was the problem device since there's no
1500 * reliable way to determine device size from userland.
1503 char buf[64];
1505 zfs_nicebytes(SPA_MINDEVSIZE, buf,
1506 sizeof (buf));
1508 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1509 "device is less than the minimum "
1510 "size (%s)"), buf);
1512 (void) zfs_error(hdl, EZFS_BADDEV, msg);
1513 break;
1515 case ENOTSUP:
1516 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1517 "pool must be upgraded to add these vdevs"));
1518 (void) zfs_error(hdl, EZFS_BADVERSION, msg);
1519 break;
1521 default:
1522 (void) zpool_standard_error(hdl, errno, msg);
1525 ret = -1;
1526 } else {
1527 ret = 0;
1530 zcmd_free_nvlists(&zc);
1532 return (ret);
1536 * Exports the pool from the system. The caller must ensure that there are no
1537 * mounted datasets in the pool.
1539 static int
1540 zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce,
1541 const char *log_str)
1543 zfs_cmd_t zc = { 0 };
1544 char msg[1024];
1546 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1547 "cannot export '%s'"), zhp->zpool_name);
1549 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1550 zc.zc_cookie = force;
1551 zc.zc_guid = hardforce;
1552 zc.zc_history = (uint64_t)(uintptr_t)log_str;
1554 if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) {
1555 switch (errno) {
1556 case EXDEV:
1557 zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
1558 "use '-f' to override the following errors:\n"
1559 "'%s' has an active shared spare which could be"
1560 " used by other pools once '%s' is exported."),
1561 zhp->zpool_name, zhp->zpool_name);
1562 return (zfs_error(zhp->zpool_hdl, EZFS_ACTIVE_SPARE,
1563 msg));
1564 default:
1565 return (zpool_standard_error_fmt(zhp->zpool_hdl, errno,
1566 msg));
1570 return (0);
1574 zpool_export(zpool_handle_t *zhp, boolean_t force, const char *log_str)
1576 return (zpool_export_common(zhp, force, B_FALSE, log_str));
1580 zpool_export_force(zpool_handle_t *zhp, const char *log_str)
1582 return (zpool_export_common(zhp, B_TRUE, B_TRUE, log_str));
1585 static void
1586 zpool_rewind_exclaim(libzfs_handle_t *hdl, const char *name, boolean_t dryrun,
1587 nvlist_t *config)
1589 nvlist_t *nv = NULL;
1590 uint64_t rewindto;
1591 int64_t loss = -1;
1592 struct tm t;
1593 char timestr[128];
1595 if (!hdl->libzfs_printerr || config == NULL)
1596 return;
1598 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||
1599 nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0) {
1600 return;
1603 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
1604 return;
1605 (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss);
1607 if (localtime_r((time_t *)&rewindto, &t) != NULL &&
1608 strftime(timestr, 128, 0, &t) != 0) {
1609 if (dryrun) {
1610 (void) printf(dgettext(TEXT_DOMAIN,
1611 "Would be able to return %s "
1612 "to its state as of %s.\n"),
1613 name, timestr);
1614 } else {
1615 (void) printf(dgettext(TEXT_DOMAIN,
1616 "Pool %s returned to its state as of %s.\n"),
1617 name, timestr);
1619 if (loss > 120) {
1620 (void) printf(dgettext(TEXT_DOMAIN,
1621 "%s approximately %lld "),
1622 dryrun ? "Would discard" : "Discarded",
1623 (loss + 30) / 60);
1624 (void) printf(dgettext(TEXT_DOMAIN,
1625 "minutes of transactions.\n"));
1626 } else if (loss > 0) {
1627 (void) printf(dgettext(TEXT_DOMAIN,
1628 "%s approximately %lld "),
1629 dryrun ? "Would discard" : "Discarded", loss);
1630 (void) printf(dgettext(TEXT_DOMAIN,
1631 "seconds of transactions.\n"));
1636 void
1637 zpool_explain_recover(libzfs_handle_t *hdl, const char *name, int reason,
1638 nvlist_t *config)
1640 nvlist_t *nv = NULL;
1641 int64_t loss = -1;
1642 uint64_t edata = UINT64_MAX;
1643 uint64_t rewindto;
1644 struct tm t;
1645 char timestr[128];
1647 if (!hdl->libzfs_printerr)
1648 return;
1650 if (reason >= 0)
1651 (void) printf(dgettext(TEXT_DOMAIN, "action: "));
1652 else
1653 (void) printf(dgettext(TEXT_DOMAIN, "\t"));
1655 /* All attempted rewinds failed if ZPOOL_CONFIG_LOAD_TIME missing */
1656 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||
1657 nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0 ||
1658 nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
1659 goto no_info;
1661 (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss);
1662 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_DATA_ERRORS,
1663 &edata);
1665 (void) printf(dgettext(TEXT_DOMAIN,
1666 "Recovery is possible, but will result in some data loss.\n"));
1668 if (localtime_r((time_t *)&rewindto, &t) != NULL &&
1669 strftime(timestr, 128, 0, &t) != 0) {
1670 (void) printf(dgettext(TEXT_DOMAIN,
1671 "\tReturning the pool to its state as of %s\n"
1672 "\tshould correct the problem. "),
1673 timestr);
1674 } else {
1675 (void) printf(dgettext(TEXT_DOMAIN,
1676 "\tReverting the pool to an earlier state "
1677 "should correct the problem.\n\t"));
1680 if (loss > 120) {
1681 (void) printf(dgettext(TEXT_DOMAIN,
1682 "Approximately %lld minutes of data\n"
1683 "\tmust be discarded, irreversibly. "), (loss + 30) / 60);
1684 } else if (loss > 0) {
1685 (void) printf(dgettext(TEXT_DOMAIN,
1686 "Approximately %lld seconds of data\n"
1687 "\tmust be discarded, irreversibly. "), loss);
1689 if (edata != 0 && edata != UINT64_MAX) {
1690 if (edata == 1) {
1691 (void) printf(dgettext(TEXT_DOMAIN,
1692 "After rewind, at least\n"
1693 "\tone persistent user-data error will remain. "));
1694 } else {
1695 (void) printf(dgettext(TEXT_DOMAIN,
1696 "After rewind, several\n"
1697 "\tpersistent user-data errors will remain. "));
1700 (void) printf(dgettext(TEXT_DOMAIN,
1701 "Recovery can be attempted\n\tby executing 'zpool %s -F %s'. "),
1702 reason >= 0 ? "clear" : "import", name);
1704 (void) printf(dgettext(TEXT_DOMAIN,
1705 "A scrub of the pool\n"
1706 "\tis strongly recommended after recovery.\n"));
1707 return;
1709 no_info:
1710 (void) printf(dgettext(TEXT_DOMAIN,
1711 "Destroy and re-create the pool from\n\ta backup source.\n"));
1715 * zpool_import() is a contracted interface. Should be kept the same
1716 * if possible.
1718 * Applications should use zpool_import_props() to import a pool with
1719 * new properties value to be set.
1722 zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
1723 char *altroot)
1725 nvlist_t *props = NULL;
1726 int ret;
1728 if (altroot != NULL) {
1729 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
1730 return (zfs_error_fmt(hdl, EZFS_NOMEM,
1731 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1732 newname));
1735 if (nvlist_add_string(props,
1736 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), altroot) != 0 ||
1737 nvlist_add_string(props,
1738 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), "none") != 0) {
1739 nvlist_free(props);
1740 return (zfs_error_fmt(hdl, EZFS_NOMEM,
1741 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1742 newname));
1746 ret = zpool_import_props(hdl, config, newname, props,
1747 ZFS_IMPORT_NORMAL);
1748 nvlist_free(props);
1749 return (ret);
1752 static void
1753 print_vdev_tree(libzfs_handle_t *hdl, const char *name, nvlist_t *nv,
1754 int indent)
1756 nvlist_t **child;
1757 uint_t c, children;
1758 char *vname;
1759 uint64_t is_log = 0;
1761 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG,
1762 &is_log);
1764 if (name != NULL)
1765 (void) printf("\t%*s%s%s\n", indent, "", name,
1766 is_log ? " [log]" : "");
1768 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1769 &child, &children) != 0)
1770 return;
1772 for (c = 0; c < children; c++) {
1773 vname = zpool_vdev_name(hdl, NULL, child[c], VDEV_NAME_TYPE_ID);
1774 print_vdev_tree(hdl, vname, child[c], indent + 2);
1775 free(vname);
1779 void
1780 zpool_print_unsup_feat(nvlist_t *config)
1782 nvlist_t *nvinfo, *unsup_feat;
1784 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nvinfo) ==
1786 verify(nvlist_lookup_nvlist(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT,
1787 &unsup_feat) == 0);
1789 for (nvpair_t *nvp = nvlist_next_nvpair(unsup_feat, NULL); nvp != NULL;
1790 nvp = nvlist_next_nvpair(unsup_feat, nvp)) {
1791 char *desc;
1793 verify(nvpair_type(nvp) == DATA_TYPE_STRING);
1794 verify(nvpair_value_string(nvp, &desc) == 0);
1796 if (strlen(desc) > 0)
1797 (void) printf("\t%s (%s)\n", nvpair_name(nvp), desc);
1798 else
1799 (void) printf("\t%s\n", nvpair_name(nvp));
1804 * Import the given pool using the known configuration and a list of
1805 * properties to be set. The configuration should have come from
1806 * zpool_find_import(). The 'newname' parameters control whether the pool
1807 * is imported with a different name.
1810 zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
1811 nvlist_t *props, int flags)
1813 zfs_cmd_t zc = { 0 };
1814 zpool_load_policy_t policy;
1815 nvlist_t *nv = NULL;
1816 nvlist_t *nvinfo = NULL;
1817 nvlist_t *missing = NULL;
1818 char *thename;
1819 char *origname;
1820 int ret;
1821 int error = 0;
1822 char errbuf[1024];
1824 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1825 &origname) == 0);
1827 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1828 "cannot import pool '%s'"), origname);
1830 if (newname != NULL) {
1831 if (!zpool_name_valid(hdl, B_FALSE, newname))
1832 return (zfs_error_fmt(hdl, EZFS_INVALIDNAME,
1833 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1834 newname));
1835 thename = (char *)newname;
1836 } else {
1837 thename = origname;
1840 if (props != NULL) {
1841 uint64_t version;
1842 prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE };
1844 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
1845 &version) == 0);
1847 if ((props = zpool_valid_proplist(hdl, origname,
1848 props, version, flags, errbuf)) == NULL)
1849 return (-1);
1850 if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
1851 nvlist_free(props);
1852 return (-1);
1854 nvlist_free(props);
1857 (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name));
1859 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1860 &zc.zc_guid) == 0);
1862 if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0) {
1863 zcmd_free_nvlists(&zc);
1864 return (-1);
1866 if (zcmd_alloc_dst_nvlist(hdl, &zc, zc.zc_nvlist_conf_size * 2) != 0) {
1867 zcmd_free_nvlists(&zc);
1868 return (-1);
1871 zc.zc_cookie = flags;
1872 while ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_IMPORT, &zc)) != 0 &&
1873 errno == ENOMEM) {
1874 if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
1875 zcmd_free_nvlists(&zc);
1876 return (-1);
1879 if (ret != 0)
1880 error = errno;
1882 (void) zcmd_read_dst_nvlist(hdl, &zc, &nv);
1884 zcmd_free_nvlists(&zc);
1886 zpool_get_load_policy(config, &policy);
1888 if (error) {
1889 char desc[1024];
1890 char aux[256];
1893 * Dry-run failed, but we print out what success
1894 * looks like if we found a best txg
1896 if (policy.zlp_rewind & ZPOOL_TRY_REWIND) {
1897 zpool_rewind_exclaim(hdl, newname ? origname : thename,
1898 B_TRUE, nv);
1899 nvlist_free(nv);
1900 return (-1);
1903 if (newname == NULL)
1904 (void) snprintf(desc, sizeof (desc),
1905 dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1906 thename);
1907 else
1908 (void) snprintf(desc, sizeof (desc),
1909 dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"),
1910 origname, thename);
1912 switch (error) {
1913 case ENOTSUP:
1914 if (nv != NULL && nvlist_lookup_nvlist(nv,
1915 ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 &&
1916 nvlist_exists(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT)) {
1917 (void) printf(dgettext(TEXT_DOMAIN, "This "
1918 "pool uses the following feature(s) not "
1919 "supported by this system:\n"));
1920 zpool_print_unsup_feat(nv);
1921 if (nvlist_exists(nvinfo,
1922 ZPOOL_CONFIG_CAN_RDONLY)) {
1923 (void) printf(dgettext(TEXT_DOMAIN,
1924 "All unsupported features are only "
1925 "required for writing to the pool."
1926 "\nThe pool can be imported using "
1927 "'-o readonly=on'.\n"));
1931 * Unsupported version.
1933 (void) zfs_error(hdl, EZFS_BADVERSION, desc);
1934 break;
1936 case EREMOTEIO:
1937 if (nv != NULL && nvlist_lookup_nvlist(nv,
1938 ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0) {
1939 char *hostname = "<unknown>";
1940 uint64_t hostid = 0;
1941 mmp_state_t mmp_state;
1943 mmp_state = fnvlist_lookup_uint64(nvinfo,
1944 ZPOOL_CONFIG_MMP_STATE);
1946 if (nvlist_exists(nvinfo,
1947 ZPOOL_CONFIG_MMP_HOSTNAME))
1948 hostname = fnvlist_lookup_string(nvinfo,
1949 ZPOOL_CONFIG_MMP_HOSTNAME);
1951 if (nvlist_exists(nvinfo,
1952 ZPOOL_CONFIG_MMP_HOSTID))
1953 hostid = fnvlist_lookup_uint64(nvinfo,
1954 ZPOOL_CONFIG_MMP_HOSTID);
1956 if (mmp_state == MMP_STATE_ACTIVE) {
1957 (void) snprintf(aux, sizeof (aux),
1958 dgettext(TEXT_DOMAIN, "pool is imp"
1959 "orted on host '%s' (hostid=%lx).\n"
1960 "Export the pool on the other "
1961 "system, then run 'zpool import'."),
1962 hostname, (unsigned long) hostid);
1963 } else if (mmp_state == MMP_STATE_NO_HOSTID) {
1964 (void) snprintf(aux, sizeof (aux),
1965 dgettext(TEXT_DOMAIN, "pool has "
1966 "the multihost property on and "
1967 "the\nsystem's hostid is not "
1968 "set.\n"));
1971 (void) zfs_error_aux(hdl, aux);
1973 (void) zfs_error(hdl, EZFS_ACTIVE_POOL, desc);
1974 break;
1976 case EINVAL:
1977 (void) zfs_error(hdl, EZFS_INVALCONFIG, desc);
1978 break;
1980 case EROFS:
1981 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1982 "one or more devices is read only"));
1983 (void) zfs_error(hdl, EZFS_BADDEV, desc);
1984 break;
1986 case ENXIO:
1987 if (nv && nvlist_lookup_nvlist(nv,
1988 ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 &&
1989 nvlist_lookup_nvlist(nvinfo,
1990 ZPOOL_CONFIG_MISSING_DEVICES, &missing) == 0) {
1991 (void) printf(dgettext(TEXT_DOMAIN,
1992 "The devices below are missing or "
1993 "corrupted, use '-m' to import the pool "
1994 "anyway:\n"));
1995 print_vdev_tree(hdl, NULL, missing, 2);
1996 (void) printf("\n");
1998 (void) zpool_standard_error(hdl, error, desc);
1999 break;
2001 case EEXIST:
2002 (void) zpool_standard_error(hdl, error, desc);
2003 break;
2004 case ENAMETOOLONG:
2005 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2006 "new name of at least one dataset is longer than "
2007 "the maximum allowable length"));
2008 (void) zfs_error(hdl, EZFS_NAMETOOLONG, desc);
2009 break;
2010 default:
2011 (void) zpool_standard_error(hdl, error, desc);
2012 zpool_explain_recover(hdl,
2013 newname ? origname : thename, -error, nv);
2014 break;
2017 nvlist_free(nv);
2018 ret = -1;
2019 } else {
2020 zpool_handle_t *zhp;
2023 * This should never fail, but play it safe anyway.
2025 if (zpool_open_silent(hdl, thename, &zhp) != 0)
2026 ret = -1;
2027 else if (zhp != NULL)
2028 zpool_close(zhp);
2029 if (policy.zlp_rewind &
2030 (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) {
2031 zpool_rewind_exclaim(hdl, newname ? origname : thename,
2032 ((policy.zlp_rewind & ZPOOL_TRY_REWIND) != 0), nv);
2034 nvlist_free(nv);
2035 return (0);
2038 return (ret);
2042 * Translate vdev names to guids. If a vdev_path is determined to be
2043 * unsuitable then a vd_errlist is allocated and the vdev path and errno
2044 * are added to it.
2046 static int
2047 zpool_translate_vdev_guids(zpool_handle_t *zhp, nvlist_t *vds,
2048 nvlist_t *vdev_guids, nvlist_t *guids_to_paths, nvlist_t **vd_errlist)
2050 nvlist_t *errlist = NULL;
2051 int error = 0;
2053 for (nvpair_t *elem = nvlist_next_nvpair(vds, NULL); elem != NULL;
2054 elem = nvlist_next_nvpair(vds, elem)) {
2055 boolean_t spare, cache;
2057 char *vd_path = nvpair_name(elem);
2058 nvlist_t *tgt = zpool_find_vdev(zhp, vd_path, &spare, &cache,
2059 NULL);
2061 if ((tgt == NULL) || cache || spare) {
2062 if (errlist == NULL) {
2063 errlist = fnvlist_alloc();
2064 error = EINVAL;
2067 uint64_t err = (tgt == NULL) ? EZFS_NODEVICE :
2068 (spare ? EZFS_ISSPARE : EZFS_ISL2CACHE);
2069 fnvlist_add_int64(errlist, vd_path, err);
2070 continue;
2073 uint64_t guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
2074 fnvlist_add_uint64(vdev_guids, vd_path, guid);
2076 char msg[MAXNAMELEN];
2077 (void) snprintf(msg, sizeof (msg), "%llu", (u_longlong_t)guid);
2078 fnvlist_add_string(guids_to_paths, msg, vd_path);
2081 if (error != 0) {
2082 verify(errlist != NULL);
2083 if (vd_errlist != NULL)
2084 *vd_errlist = errlist;
2085 else
2086 fnvlist_free(errlist);
2089 return (error);
2093 * Scan the pool.
2096 zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd)
2098 zfs_cmd_t zc = { 0 };
2099 char msg[1024];
2100 int err;
2101 libzfs_handle_t *hdl = zhp->zpool_hdl;
2103 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2104 zc.zc_cookie = func;
2105 zc.zc_flags = cmd;
2107 if (zfs_ioctl(hdl, ZFS_IOC_POOL_SCAN, &zc) == 0)
2108 return (0);
2110 err = errno;
2112 /* ECANCELED on a scrub means we resumed a paused scrub */
2113 if (err == ECANCELED && func == POOL_SCAN_SCRUB &&
2114 cmd == POOL_SCRUB_NORMAL)
2115 return (0);
2117 if (err == ENOENT && func != POOL_SCAN_NONE && cmd == POOL_SCRUB_NORMAL)
2118 return (0);
2120 if (func == POOL_SCAN_SCRUB) {
2121 if (cmd == POOL_SCRUB_PAUSE) {
2122 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
2123 "cannot pause scrubbing %s"), zc.zc_name);
2124 } else {
2125 assert(cmd == POOL_SCRUB_NORMAL);
2126 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
2127 "cannot scrub %s"), zc.zc_name);
2129 } else if (func == POOL_SCAN_RESILVER) {
2130 assert(cmd == POOL_SCRUB_NORMAL);
2131 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
2132 "cannot restart resilver on %s"), zc.zc_name);
2133 } else if (func == POOL_SCAN_NONE) {
2134 (void) snprintf(msg, sizeof (msg),
2135 dgettext(TEXT_DOMAIN, "cannot cancel scrubbing %s"),
2136 zc.zc_name);
2137 } else {
2138 assert(!"unexpected result");
2141 if (err == EBUSY) {
2142 nvlist_t *nvroot;
2143 pool_scan_stat_t *ps = NULL;
2144 uint_t psc;
2146 verify(nvlist_lookup_nvlist(zhp->zpool_config,
2147 ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
2148 (void) nvlist_lookup_uint64_array(nvroot,
2149 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &psc);
2150 if (ps && ps->pss_func == POOL_SCAN_SCRUB) {
2151 if (cmd == POOL_SCRUB_PAUSE)
2152 return (zfs_error(hdl, EZFS_SCRUB_PAUSED, msg));
2153 else
2154 return (zfs_error(hdl, EZFS_SCRUBBING, msg));
2155 } else {
2156 return (zfs_error(hdl, EZFS_RESILVERING, msg));
2158 } else if (err == ENOENT) {
2159 return (zfs_error(hdl, EZFS_NO_SCRUB, msg));
2160 } else if (err == ENOTSUP && func == POOL_SCAN_RESILVER) {
2161 return (zfs_error(hdl, EZFS_NO_RESILVER_DEFER, msg));
2162 } else {
2163 return (zpool_standard_error(hdl, err, msg));
2167 static int
2168 xlate_init_err(int err)
2170 switch (err) {
2171 case ENODEV:
2172 return (EZFS_NODEVICE);
2173 case EINVAL:
2174 case EROFS:
2175 return (EZFS_BADDEV);
2176 case EBUSY:
2177 return (EZFS_INITIALIZING);
2178 case ESRCH:
2179 return (EZFS_NO_INITIALIZE);
2181 return (err);
2185 * Begin, suspend, or cancel the initialization (initializing of all free
2186 * blocks) for the given vdevs in the given pool.
2189 zpool_initialize(zpool_handle_t *zhp, pool_initialize_func_t cmd_type,
2190 nvlist_t *vds)
2192 char msg[1024];
2193 int err;
2195 nvlist_t *vdev_guids = fnvlist_alloc();
2196 nvlist_t *guids_to_paths = fnvlist_alloc();
2197 nvlist_t *vd_errlist = NULL;
2198 nvlist_t *errlist;
2199 nvpair_t *elem;
2201 err = zpool_translate_vdev_guids(zhp, vds, vdev_guids,
2202 guids_to_paths, &vd_errlist);
2204 if (err == 0) {
2205 err = lzc_initialize(zhp->zpool_name, cmd_type,
2206 vdev_guids, &errlist);
2207 if (err == 0) {
2208 fnvlist_free(vdev_guids);
2209 fnvlist_free(guids_to_paths);
2210 return (0);
2213 if (errlist != NULL) {
2214 vd_errlist = fnvlist_lookup_nvlist(errlist,
2215 ZPOOL_INITIALIZE_VDEVS);
2218 (void) snprintf(msg, sizeof (msg),
2219 dgettext(TEXT_DOMAIN, "operation failed"));
2220 } else {
2221 verify(vd_errlist != NULL);
2224 for (elem = nvlist_next_nvpair(vd_errlist, NULL); elem != NULL;
2225 elem = nvlist_next_nvpair(vd_errlist, elem)) {
2226 int64_t vd_error = xlate_init_err(fnvpair_value_int64(elem));
2227 char *path;
2229 if (nvlist_lookup_string(guids_to_paths, nvpair_name(elem),
2230 &path) != 0)
2231 path = nvpair_name(elem);
2233 (void) zfs_error_fmt(zhp->zpool_hdl, vd_error,
2234 "cannot initialize '%s'", path);
2237 fnvlist_free(vdev_guids);
2238 fnvlist_free(guids_to_paths);
2240 if (vd_errlist != NULL) {
2241 fnvlist_free(vd_errlist);
2242 return (-1);
2245 return (zpool_standard_error(zhp->zpool_hdl, err, msg));
2248 static int
2249 xlate_trim_err(int err)
2251 switch (err) {
2252 case ENODEV:
2253 return (EZFS_NODEVICE);
2254 case EINVAL:
2255 case EROFS:
2256 return (EZFS_BADDEV);
2257 case EBUSY:
2258 return (EZFS_TRIMMING);
2259 case ESRCH:
2260 return (EZFS_NO_TRIM);
2261 case EOPNOTSUPP:
2262 return (EZFS_TRIM_NOTSUP);
2264 return (err);
2268 * Begin, suspend, or cancel the TRIM (discarding of all free blocks) for
2269 * the given vdevs in the given pool.
2272 zpool_trim(zpool_handle_t *zhp, pool_trim_func_t cmd_type, nvlist_t *vds,
2273 trimflags_t *trim_flags)
2275 char msg[1024];
2276 int err;
2278 nvlist_t *vdev_guids = fnvlist_alloc();
2279 nvlist_t *guids_to_paths = fnvlist_alloc();
2280 nvlist_t *vd_errlist = NULL;
2281 nvlist_t *errlist;
2282 nvpair_t *elem;
2284 err = zpool_translate_vdev_guids(zhp, vds, vdev_guids,
2285 guids_to_paths, &vd_errlist);
2286 if (err == 0) {
2287 err = lzc_trim(zhp->zpool_name, cmd_type, trim_flags->rate,
2288 trim_flags->secure, vdev_guids, &errlist);
2289 if (err == 0) {
2290 fnvlist_free(vdev_guids);
2291 fnvlist_free(guids_to_paths);
2292 return (0);
2295 if (errlist != NULL) {
2296 vd_errlist = fnvlist_lookup_nvlist(errlist,
2297 ZPOOL_TRIM_VDEVS);
2300 (void) snprintf(msg, sizeof (msg),
2301 dgettext(TEXT_DOMAIN, "operation failed"));
2302 } else {
2303 verify(vd_errlist != NULL);
2306 for (elem = nvlist_next_nvpair(vd_errlist, NULL);
2307 elem != NULL; elem = nvlist_next_nvpair(vd_errlist, elem)) {
2308 int64_t vd_error = xlate_trim_err(fnvpair_value_int64(elem));
2309 char *path;
2311 * If only the pool was specified, and it was not a secure
2312 * trim then suppress warnings for individual vdevs which
2313 * do not support trimming.
2315 if (vd_error == EZFS_TRIM_NOTSUP &&
2316 trim_flags->fullpool &&
2317 !trim_flags->secure) {
2318 continue;
2321 if (nvlist_lookup_string(guids_to_paths, nvpair_name(elem),
2322 &path) != 0)
2323 path = nvpair_name(elem);
2325 (void) zfs_error_fmt(zhp->zpool_hdl, vd_error,
2326 "cannot trim '%s'", path);
2329 fnvlist_free(vdev_guids);
2330 fnvlist_free(guids_to_paths);
2332 if (vd_errlist != NULL) {
2333 fnvlist_free(vd_errlist);
2334 return (-1);
2337 return (zpool_standard_error(zhp->zpool_hdl, err, msg));
2341 * This provides a very minimal check whether a given string is likely a
2342 * c#t#d# style string. Users of this are expected to do their own
2343 * verification of the s# part.
2345 #define CTD_CHECK(str) (str && str[0] == 'c' && isdigit(str[1]))
2348 * More elaborate version for ones which may start with "/dev/dsk/"
2349 * and the like.
2351 static int
2352 ctd_check_path(char *str)
2355 * If it starts with a slash, check the last component.
2357 if (str && str[0] == '/') {
2358 char *tmp = strrchr(str, '/');
2361 * If it ends in "/old", check the second-to-last
2362 * component of the string instead.
2364 if (tmp != str && strcmp(tmp, "/old") == 0) {
2365 for (tmp--; *tmp != '/'; tmp--)
2368 str = tmp + 1;
2370 return (CTD_CHECK(str));
2374 * Find a vdev that matches the search criteria specified. We use the
2375 * the nvpair name to determine how we should look for the device.
2376 * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL
2377 * spare; but FALSE if its an INUSE spare.
2379 static nvlist_t *
2380 vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
2381 boolean_t *l2cache, boolean_t *log)
2383 uint_t c, children;
2384 nvlist_t **child;
2385 nvlist_t *ret;
2386 uint64_t is_log;
2387 char *srchkey;
2388 nvpair_t *pair = nvlist_next_nvpair(search, NULL);
2390 /* Nothing to look for */
2391 if (search == NULL || pair == NULL)
2392 return (NULL);
2394 /* Obtain the key we will use to search */
2395 srchkey = nvpair_name(pair);
2397 switch (nvpair_type(pair)) {
2398 case DATA_TYPE_UINT64:
2399 if (strcmp(srchkey, ZPOOL_CONFIG_GUID) == 0) {
2400 uint64_t srchval, theguid;
2402 verify(nvpair_value_uint64(pair, &srchval) == 0);
2403 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
2404 &theguid) == 0);
2405 if (theguid == srchval)
2406 return (nv);
2408 break;
2410 case DATA_TYPE_STRING: {
2411 char *srchval, *val;
2413 verify(nvpair_value_string(pair, &srchval) == 0);
2414 if (nvlist_lookup_string(nv, srchkey, &val) != 0)
2415 break;
2418 * Search for the requested value. Special cases:
2420 * - ZPOOL_CONFIG_PATH for whole disk entries. To support
2421 * UEFI boot, these end in "s0" or "s0/old" or "s1" or
2422 * "s1/old". The "s0" or "s1" part is hidden from the user,
2423 * but included in the string, so this matches around it.
2424 * - looking for a top-level vdev name (i.e. ZPOOL_CONFIG_TYPE).
2426 * Otherwise, all other searches are simple string compares.
2428 if (strcmp(srchkey, ZPOOL_CONFIG_PATH) == 0 &&
2429 ctd_check_path(val)) {
2430 uint64_t wholedisk = 0;
2432 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
2433 &wholedisk);
2434 if (wholedisk) {
2435 int slen = strlen(srchval);
2436 int vlen = strlen(val);
2438 if (slen != vlen - 2)
2439 break;
2442 * make_leaf_vdev() should only set
2443 * wholedisk for ZPOOL_CONFIG_PATHs which
2444 * will include "/dev/dsk/", giving plenty of
2445 * room for the indices used next.
2447 ASSERT(vlen >= 6);
2450 * strings identical except trailing "s0"
2452 if ((strcmp(&val[vlen - 2], "s0") == 0 ||
2453 strcmp(&val[vlen - 2], "s1") == 0) &&
2454 strncmp(srchval, val, slen) == 0)
2455 return (nv);
2458 * strings identical except trailing "s0/old"
2460 if ((strcmp(&val[vlen - 6], "s0/old") == 0 ||
2461 strcmp(&val[vlen - 6], "s1/old") == 0) &&
2462 strcmp(&srchval[slen - 4], "/old") == 0 &&
2463 strncmp(srchval, val, slen - 4) == 0)
2464 return (nv);
2466 break;
2468 } else if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0 && val) {
2469 char *type, *idx, *end, *p;
2470 uint64_t id, vdev_id;
2473 * Determine our vdev type, keeping in mind
2474 * that the srchval is composed of a type and
2475 * vdev id pair (i.e. mirror-4).
2477 if ((type = strdup(srchval)) == NULL)
2478 return (NULL);
2480 if ((p = strrchr(type, '-')) == NULL) {
2481 free(type);
2482 break;
2484 idx = p + 1;
2485 *p = '\0';
2488 * If the types don't match then keep looking.
2490 if (strncmp(val, type, strlen(val)) != 0) {
2491 free(type);
2492 break;
2495 verify(zpool_vdev_is_interior(type));
2496 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID,
2497 &id) == 0);
2499 errno = 0;
2500 vdev_id = strtoull(idx, &end, 10);
2502 free(type);
2503 if (errno != 0)
2504 return (NULL);
2507 * Now verify that we have the correct vdev id.
2509 if (vdev_id == id)
2510 return (nv);
2514 * Common case
2516 if (strcmp(srchval, val) == 0)
2517 return (nv);
2518 break;
2521 default:
2522 break;
2525 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2526 &child, &children) != 0)
2527 return (NULL);
2529 for (c = 0; c < children; c++) {
2530 if ((ret = vdev_to_nvlist_iter(child[c], search,
2531 avail_spare, l2cache, NULL)) != NULL) {
2533 * The 'is_log' value is only set for the toplevel
2534 * vdev, not the leaf vdevs. So we always lookup the
2535 * log device from the root of the vdev tree (where
2536 * 'log' is non-NULL).
2538 if (log != NULL &&
2539 nvlist_lookup_uint64(child[c],
2540 ZPOOL_CONFIG_IS_LOG, &is_log) == 0 &&
2541 is_log) {
2542 *log = B_TRUE;
2544 return (ret);
2548 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
2549 &child, &children) == 0) {
2550 for (c = 0; c < children; c++) {
2551 if ((ret = vdev_to_nvlist_iter(child[c], search,
2552 avail_spare, l2cache, NULL)) != NULL) {
2553 *avail_spare = B_TRUE;
2554 return (ret);
2559 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
2560 &child, &children) == 0) {
2561 for (c = 0; c < children; c++) {
2562 if ((ret = vdev_to_nvlist_iter(child[c], search,
2563 avail_spare, l2cache, NULL)) != NULL) {
2564 *l2cache = B_TRUE;
2565 return (ret);
2570 return (NULL);
2574 * Given a physical path (minus the "/devices" prefix), find the
2575 * associated vdev.
2577 nvlist_t *
2578 zpool_find_vdev_by_physpath(zpool_handle_t *zhp, const char *ppath,
2579 boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log)
2581 nvlist_t *search, *nvroot, *ret;
2583 verify(nvlist_alloc(&search, NV_UNIQUE_NAME, KM_SLEEP) == 0);
2584 verify(nvlist_add_string(search, ZPOOL_CONFIG_PHYS_PATH, ppath) == 0);
2586 verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
2587 &nvroot) == 0);
2589 *avail_spare = B_FALSE;
2590 *l2cache = B_FALSE;
2591 if (log != NULL)
2592 *log = B_FALSE;
2593 ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log);
2594 nvlist_free(search);
2596 return (ret);
2600 * Determine if we have an "interior" top-level vdev (i.e mirror/raidz).
2602 static boolean_t
2603 zpool_vdev_is_interior(const char *name)
2605 if (strncmp(name, VDEV_TYPE_RAIDZ, strlen(VDEV_TYPE_RAIDZ)) == 0 ||
2606 strncmp(name, VDEV_TYPE_SPARE, strlen(VDEV_TYPE_SPARE)) == 0 ||
2607 strncmp(name,
2608 VDEV_TYPE_REPLACING, strlen(VDEV_TYPE_REPLACING)) == 0 ||
2609 strncmp(name, VDEV_TYPE_MIRROR, strlen(VDEV_TYPE_MIRROR)) == 0)
2610 return (B_TRUE);
2611 return (B_FALSE);
2614 nvlist_t *
2615 zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
2616 boolean_t *l2cache, boolean_t *log)
2618 char buf[MAXPATHLEN];
2619 char *end;
2620 nvlist_t *nvroot, *search, *ret;
2621 uint64_t guid;
2623 verify(nvlist_alloc(&search, NV_UNIQUE_NAME, KM_SLEEP) == 0);
2625 guid = strtoull(path, &end, 10);
2626 if (guid != 0 && *end == '\0') {
2627 verify(nvlist_add_uint64(search, ZPOOL_CONFIG_GUID, guid) == 0);
2628 } else if (zpool_vdev_is_interior(path)) {
2629 verify(nvlist_add_string(search, ZPOOL_CONFIG_TYPE, path) == 0);
2630 } else if (path[0] != '/') {
2631 (void) snprintf(buf, sizeof (buf), "%s/%s", ZFS_DISK_ROOT,
2632 path);
2633 verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, buf) == 0);
2634 } else {
2635 verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, path) == 0);
2638 verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
2639 &nvroot) == 0);
2641 *avail_spare = B_FALSE;
2642 *l2cache = B_FALSE;
2643 if (log != NULL)
2644 *log = B_FALSE;
2645 ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log);
2646 nvlist_free(search);
2648 return (ret);
2651 static int
2652 vdev_is_online(nvlist_t *nv)
2654 uint64_t ival;
2656 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_OFFLINE, &ival) == 0 ||
2657 nvlist_lookup_uint64(nv, ZPOOL_CONFIG_FAULTED, &ival) == 0 ||
2658 nvlist_lookup_uint64(nv, ZPOOL_CONFIG_REMOVED, &ival) == 0)
2659 return (0);
2661 return (1);
2665 * Helper function for zpool_get_physpaths().
2667 static int
2668 vdev_get_one_physpath(nvlist_t *config, char *physpath, size_t physpath_size,
2669 size_t *bytes_written)
2671 size_t bytes_left, pos, rsz;
2672 char *tmppath;
2673 const char *format;
2675 if (nvlist_lookup_string(config, ZPOOL_CONFIG_PHYS_PATH,
2676 &tmppath) != 0)
2677 return (EZFS_NODEVICE);
2679 pos = *bytes_written;
2680 bytes_left = physpath_size - pos;
2681 format = (pos == 0) ? "%s" : " %s";
2683 rsz = snprintf(physpath + pos, bytes_left, format, tmppath);
2684 *bytes_written += rsz;
2686 if (rsz >= bytes_left) {
2687 /* if physpath was not copied properly, clear it */
2688 if (bytes_left != 0) {
2689 physpath[pos] = 0;
2691 return (EZFS_NOSPC);
2693 return (0);
2696 static int
2697 vdev_get_physpaths(nvlist_t *nv, char *physpath, size_t phypath_size,
2698 size_t *rsz, boolean_t is_spare)
2700 char *type;
2701 int ret;
2703 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
2704 return (EZFS_INVALCONFIG);
2706 if (strcmp(type, VDEV_TYPE_DISK) == 0) {
2708 * An active spare device has ZPOOL_CONFIG_IS_SPARE set.
2709 * For a spare vdev, we only want to boot from the active
2710 * spare device.
2712 if (is_spare) {
2713 uint64_t spare = 0;
2714 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_SPARE,
2715 &spare);
2716 if (!spare)
2717 return (EZFS_INVALCONFIG);
2720 if (vdev_is_online(nv)) {
2721 if ((ret = vdev_get_one_physpath(nv, physpath,
2722 phypath_size, rsz)) != 0)
2723 return (ret);
2725 } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0 ||
2726 strcmp(type, VDEV_TYPE_RAIDZ) == 0 ||
2727 strcmp(type, VDEV_TYPE_REPLACING) == 0 ||
2728 (is_spare = (strcmp(type, VDEV_TYPE_SPARE) == 0))) {
2729 nvlist_t **child;
2730 uint_t count;
2731 int i, ret;
2733 if (nvlist_lookup_nvlist_array(nv,
2734 ZPOOL_CONFIG_CHILDREN, &child, &count) != 0)
2735 return (EZFS_INVALCONFIG);
2737 for (i = 0; i < count; i++) {
2738 ret = vdev_get_physpaths(child[i], physpath,
2739 phypath_size, rsz, is_spare);
2740 if (ret == EZFS_NOSPC)
2741 return (ret);
2745 return (EZFS_POOL_INVALARG);
2749 * Get phys_path for a root pool config.
2750 * Return 0 on success; non-zero on failure.
2752 static int
2753 zpool_get_config_physpath(nvlist_t *config, char *physpath, size_t phypath_size)
2755 size_t rsz;
2756 nvlist_t *vdev_root;
2757 nvlist_t **child;
2758 uint_t count;
2759 char *type;
2761 rsz = 0;
2763 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2764 &vdev_root) != 0)
2765 return (EZFS_INVALCONFIG);
2767 if (nvlist_lookup_string(vdev_root, ZPOOL_CONFIG_TYPE, &type) != 0 ||
2768 nvlist_lookup_nvlist_array(vdev_root, ZPOOL_CONFIG_CHILDREN,
2769 &child, &count) != 0)
2770 return (EZFS_INVALCONFIG);
2773 * root pool can only have a single top-level vdev.
2775 if (strcmp(type, VDEV_TYPE_ROOT) != 0 || count != 1)
2776 return (EZFS_POOL_INVALARG);
2778 (void) vdev_get_physpaths(child[0], physpath, phypath_size, &rsz,
2779 B_FALSE);
2781 /* No online devices */
2782 if (rsz == 0)
2783 return (EZFS_NODEVICE);
2785 return (0);
2789 * Get phys_path for a root pool
2790 * Return 0 on success; non-zero on failure.
2793 zpool_get_physpath(zpool_handle_t *zhp, char *physpath, size_t phypath_size)
2795 return (zpool_get_config_physpath(zhp->zpool_config, physpath,
2796 phypath_size));
2800 * If the device has being dynamically expanded then we need to relabel
2801 * the disk to use the new unallocated space.
2803 static int
2804 zpool_relabel_disk(libzfs_handle_t *hdl, const char *name, const char *msg)
2806 char path[MAXPATHLEN];
2807 int fd, error;
2808 int (*_efi_use_whole_disk)(int);
2809 char drv[MODMAXNAMELEN];
2810 major_t maj;
2811 struct stat st;
2813 if ((_efi_use_whole_disk = (int (*)(int))dlsym(RTLD_DEFAULT,
2814 "efi_use_whole_disk")) == NULL)
2815 return (-1);
2817 (void) snprintf(path, sizeof (path), "%s/%s", ZFS_RDISK_ROOT, name);
2819 if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) {
2820 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
2821 "relabel '%s': unable to open device"), name);
2822 return (zfs_error(hdl, EZFS_OPENFAILED, msg));
2826 * It's possible that we might encounter an error if the device
2827 * does not have any unallocated space left. If so, we simply
2828 * ignore that error and continue on.
2830 error = _efi_use_whole_disk(fd);
2831 if (error && error != VT_ENOSPC) {
2832 (void) close(fd);
2833 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
2834 "relabel '%s': unable to read disk capacity"), name);
2835 return (zfs_error(hdl, EZFS_NOCAP, msg));
2839 * Writing a new EFI partition table to the disk will have marked
2840 * the geometry as needing re-validation. Before returning, force
2841 * it to be checked by querying the device state, otherwise the
2842 * subsequent vdev_reopen() will very likely fail to read the device
2843 * size, faulting the pool.
2845 * The dkio(4I) ioctls are implemented by the disk driver rather than
2846 * some generic framework, so we limit its use here to drivers with
2847 * which it has been tested.
2849 if (fstat(fd, &st) == 0 &&
2850 (maj = major(st.st_rdev)) != (major_t)NODEV &&
2851 modctl(MODGETNAME, drv, sizeof (drv), &maj) == 0 &&
2852 (strcmp(drv, "blkdev") == 0 || strcmp(drv, "sd") == 0)) {
2853 enum dkio_state dkst = DKIO_NONE;
2854 (void) ioctl(fd, DKIOCSTATE, &dkst);
2857 (void) close(fd);
2859 return (0);
2863 * Bring the specified vdev online. The 'flags' parameter is a set of the
2864 * ZFS_ONLINE_* flags.
2867 zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
2868 vdev_state_t *newstate)
2870 zfs_cmd_t zc = { 0 };
2871 char msg[1024];
2872 char *pathname;
2873 nvlist_t *tgt;
2874 boolean_t avail_spare, l2cache, islog;
2875 libzfs_handle_t *hdl = zhp->zpool_hdl;
2876 int error;
2878 if (flags & ZFS_ONLINE_EXPAND) {
2879 (void) snprintf(msg, sizeof (msg),
2880 dgettext(TEXT_DOMAIN, "cannot expand %s"), path);
2881 } else {
2882 (void) snprintf(msg, sizeof (msg),
2883 dgettext(TEXT_DOMAIN, "cannot online %s"), path);
2886 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2887 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
2888 &islog)) == NULL)
2889 return (zfs_error(hdl, EZFS_NODEVICE, msg));
2891 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
2893 if (avail_spare)
2894 return (zfs_error(hdl, EZFS_ISSPARE, msg));
2896 if ((flags & ZFS_ONLINE_EXPAND ||
2897 zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) &&
2898 nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, &pathname) == 0) {
2899 uint64_t wholedisk = 0;
2901 (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
2902 &wholedisk);
2905 * XXX - L2ARC 1.0 devices can't support expansion.
2907 if (l2cache) {
2908 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2909 "cannot expand cache devices"));
2910 return (zfs_error(hdl, EZFS_VDEVNOTSUP, msg));
2913 if (wholedisk) {
2914 pathname += strlen(ZFS_DISK_ROOT) + 1;
2915 error = zpool_relabel_disk(hdl, pathname, msg);
2916 if (error != 0)
2917 return (error);
2921 zc.zc_cookie = VDEV_STATE_ONLINE;
2922 zc.zc_obj = flags;
2924 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) != 0) {
2925 if (errno == EINVAL) {
2926 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "was split "
2927 "from this pool into a new one. Use '%s' "
2928 "instead"), "zpool detach");
2929 return (zfs_error(hdl, EZFS_POSTSPLIT_ONLINE, msg));
2931 return (zpool_standard_error(hdl, errno, msg));
2934 *newstate = zc.zc_cookie;
2935 return (0);
2939 * Take the specified vdev offline
2942 zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
2944 zfs_cmd_t zc = { 0 };
2945 char msg[1024];
2946 nvlist_t *tgt;
2947 boolean_t avail_spare, l2cache;
2948 libzfs_handle_t *hdl = zhp->zpool_hdl;
2950 (void) snprintf(msg, sizeof (msg),
2951 dgettext(TEXT_DOMAIN, "cannot offline %s"), path);
2953 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2954 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
2955 NULL)) == NULL)
2956 return (zfs_error(hdl, EZFS_NODEVICE, msg));
2958 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
2960 if (avail_spare)
2961 return (zfs_error(hdl, EZFS_ISSPARE, msg));
2963 zc.zc_cookie = VDEV_STATE_OFFLINE;
2964 zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0;
2966 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
2967 return (0);
2969 switch (errno) {
2970 case EBUSY:
2973 * There are no other replicas of this device.
2975 return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
2977 case EEXIST:
2979 * The log device has unplayed logs
2981 return (zfs_error(hdl, EZFS_UNPLAYED_LOGS, msg));
2983 default:
2984 return (zpool_standard_error(hdl, errno, msg));
2989 * Mark the given vdev faulted.
2992 zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
2994 zfs_cmd_t zc = { 0 };
2995 char msg[1024];
2996 libzfs_handle_t *hdl = zhp->zpool_hdl;
2998 (void) snprintf(msg, sizeof (msg),
2999 dgettext(TEXT_DOMAIN, "cannot fault %llu"), guid);
3001 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3002 zc.zc_guid = guid;
3003 zc.zc_cookie = VDEV_STATE_FAULTED;
3004 zc.zc_obj = aux;
3006 if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
3007 return (0);
3009 switch (errno) {
3010 case EBUSY:
3013 * There are no other replicas of this device.
3015 return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
3017 default:
3018 return (zpool_standard_error(hdl, errno, msg));
3024 * Mark the given vdev degraded.
3027 zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
3029 zfs_cmd_t zc = { 0 };
3030 char msg[1024];
3031 libzfs_handle_t *hdl = zhp->zpool_hdl;
3033 (void) snprintf(msg, sizeof (msg),
3034 dgettext(TEXT_DOMAIN, "cannot degrade %llu"), guid);
3036 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3037 zc.zc_guid = guid;
3038 zc.zc_cookie = VDEV_STATE_DEGRADED;
3039 zc.zc_obj = aux;
3041 if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
3042 return (0);
3044 return (zpool_standard_error(hdl, errno, msg));
3048 * Returns TRUE if the given nvlist is a vdev that was originally swapped in as
3049 * a hot spare.
3051 static boolean_t
3052 is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which)
3054 nvlist_t **child;
3055 uint_t c, children;
3056 char *type;
3058 if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child,
3059 &children) == 0) {
3060 verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE,
3061 &type) == 0);
3063 if (strcmp(type, VDEV_TYPE_SPARE) == 0 &&
3064 children == 2 && child[which] == tgt)
3065 return (B_TRUE);
3067 for (c = 0; c < children; c++)
3068 if (is_replacing_spare(child[c], tgt, which))
3069 return (B_TRUE);
3072 return (B_FALSE);
3076 * Attach new_disk (fully described by nvroot) to old_disk.
3077 * If 'replacing' is specified, the new disk will replace the old one.
3080 zpool_vdev_attach(zpool_handle_t *zhp,
3081 const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing)
3083 zfs_cmd_t zc = { 0 };
3084 char msg[1024];
3085 int ret;
3086 nvlist_t *tgt, *newvd;
3087 boolean_t avail_spare, l2cache, islog;
3088 uint64_t val;
3089 char *newname;
3090 nvlist_t **child;
3091 uint_t children;
3092 nvlist_t *config_root;
3093 libzfs_handle_t *hdl = zhp->zpool_hdl;
3094 boolean_t rootpool = zpool_is_bootable(zhp);
3096 if (replacing)
3097 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
3098 "cannot replace %s with %s"), old_disk, new_disk);
3099 else
3100 (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
3101 "cannot attach %s to %s"), new_disk, old_disk);
3103 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3104 if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare, &l2cache,
3105 &islog)) == NULL)
3106 return (zfs_error(hdl, EZFS_NODEVICE, msg));
3108 if (avail_spare)
3109 return (zfs_error(hdl, EZFS_ISSPARE, msg));
3111 if (l2cache)
3112 return (zfs_error(hdl, EZFS_ISL2CACHE, msg));
3114 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
3115 zc.zc_cookie = replacing;
3117 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
3118 &child, &children) != 0 || children != 1) {
3119 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3120 "new device must be a single disk"));
3121 return (zfs_error(hdl, EZFS_INVALCONFIG, msg));
3124 verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
3125 ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0);
3127 if ((newname = zpool_vdev_name(NULL, NULL, child[0], 0)) == NULL)
3128 return (-1);
3130 newvd = zpool_find_vdev(zhp, newname, &avail_spare, &l2cache, NULL);
3132 * If the target is a hot spare that has been swapped in, we can only
3133 * replace it with another hot spare.
3135 if (replacing &&
3136 nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 &&
3137 (newvd == NULL || !avail_spare) &&
3138 is_replacing_spare(config_root, tgt, 1)) {
3139 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3140 "can only be replaced by another hot spare"));
3141 free(newname);
3142 return (zfs_error(hdl, EZFS_BADTARGET, msg));
3145 free(newname);
3147 if (replacing && avail_spare && !vdev_is_online(newvd)) {
3148 (void) zpool_standard_error(hdl, ENXIO, msg);
3149 return (-1);
3152 if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
3153 return (-1);
3155 ret = zfs_ioctl(hdl, ZFS_IOC_VDEV_ATTACH, &zc);
3157 zcmd_free_nvlists(&zc);
3159 if (ret == 0) {
3160 if (rootpool) {
3162 * XXX need a better way to prevent user from
3163 * booting up a half-baked vdev.
3165 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Make "
3166 "sure to wait until resilver is done "
3167 "before rebooting.\n"));
3169 return (0);
3172 switch (errno) {
3173 case ENOTSUP:
3175 * Can't attach to or replace this type of vdev.
3177 if (replacing) {
3178 uint64_t version = zpool_get_prop_int(zhp,
3179 ZPOOL_PROP_VERSION, NULL);
3181 if (islog)
3182 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3183 "cannot replace a log with a spare"));
3184 else if (version >= SPA_VERSION_MULTI_REPLACE)
3185 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3186 "already in replacing/spare config; wait "
3187 "for completion or use 'zpool detach'"));
3188 else
3189 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3190 "cannot replace a replacing device"));
3191 } else {
3192 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3193 "can only attach to mirrors and top-level "
3194 "disks"));
3196 (void) zfs_error(hdl, EZFS_BADTARGET, msg);
3197 break;
3199 case EINVAL:
3201 * The new device must be a single disk.
3203 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3204 "new device must be a single disk"));
3205 (void) zfs_error(hdl, EZFS_INVALCONFIG, msg);
3206 break;
3208 case EBUSY:
3209 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy, "
3210 "or device removal is in progress"),
3211 new_disk);
3212 (void) zfs_error(hdl, EZFS_BADDEV, msg);
3213 break;
3215 case EOVERFLOW:
3217 * The new device is too small.
3219 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3220 "device is too small"));
3221 (void) zfs_error(hdl, EZFS_BADDEV, msg);
3222 break;
3224 case EDOM:
3226 * The new device has a different optimal sector size.
3228 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3229 "new device has a different optimal sector size; use the "
3230 "option '-o ashift=N' to override the optimal size"));
3231 (void) zfs_error(hdl, EZFS_BADDEV, msg);
3232 break;
3234 case ENAMETOOLONG:
3236 * The resulting top-level vdev spec won't fit in the label.
3238 (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg);
3239 break;
3241 default:
3242 (void) zpool_standard_error(hdl, errno, msg);
3245 return (-1);
3249 * Detach the specified device.
3252 zpool_vdev_detach(zpool_handle_t *zhp, const char *path)
3254 zfs_cmd_t zc = { 0 };
3255 char msg[1024];
3256 nvlist_t *tgt;
3257 boolean_t avail_spare, l2cache;
3258 libzfs_handle_t *hdl = zhp->zpool_hdl;
3260 (void) snprintf(msg, sizeof (msg),
3261 dgettext(TEXT_DOMAIN, "cannot detach %s"), path);
3263 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3264 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
3265 NULL)) == NULL)
3266 return (zfs_error(hdl, EZFS_NODEVICE, msg));
3268 if (avail_spare)
3269 return (zfs_error(hdl, EZFS_ISSPARE, msg));
3271 if (l2cache)
3272 return (zfs_error(hdl, EZFS_ISL2CACHE, msg));
3274 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
3276 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_DETACH, &zc) == 0)
3277 return (0);
3279 switch (errno) {
3281 case ENOTSUP:
3283 * Can't detach from this type of vdev.
3285 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only "
3286 "applicable to mirror and replacing vdevs"));
3287 (void) zfs_error(hdl, EZFS_BADTARGET, msg);
3288 break;
3290 case EBUSY:
3292 * There are no other replicas of this device.
3294 (void) zfs_error(hdl, EZFS_NOREPLICAS, msg);
3295 break;
3297 default:
3298 (void) zpool_standard_error(hdl, errno, msg);
3301 return (-1);
3305 * Find a mirror vdev in the source nvlist.
3307 * The mchild array contains a list of disks in one of the top-level mirrors
3308 * of the source pool. The schild array contains a list of disks that the
3309 * user specified on the command line. We loop over the mchild array to
3310 * see if any entry in the schild array matches.
3312 * If a disk in the mchild array is found in the schild array, we return
3313 * the index of that entry. Otherwise we return -1.
3315 static int
3316 find_vdev_entry(zpool_handle_t *zhp, nvlist_t **mchild, uint_t mchildren,
3317 nvlist_t **schild, uint_t schildren)
3319 uint_t mc;
3321 for (mc = 0; mc < mchildren; mc++) {
3322 uint_t sc;
3323 char *mpath = zpool_vdev_name(zhp->zpool_hdl, zhp,
3324 mchild[mc], 0);
3326 for (sc = 0; sc < schildren; sc++) {
3327 char *spath = zpool_vdev_name(zhp->zpool_hdl, zhp,
3328 schild[sc], 0);
3329 boolean_t result = (strcmp(mpath, spath) == 0);
3331 free(spath);
3332 if (result) {
3333 free(mpath);
3334 return (mc);
3338 free(mpath);
3341 return (-1);
3345 * Split a mirror pool. If newroot points to null, then a new nvlist
3346 * is generated and it is the responsibility of the caller to free it.
3349 zpool_vdev_split(zpool_handle_t *zhp, char *newname, nvlist_t **newroot,
3350 nvlist_t *props, splitflags_t flags)
3352 zfs_cmd_t zc = { 0 };
3353 char msg[1024];
3354 nvlist_t *tree, *config, **child, **newchild, *newconfig = NULL;
3355 nvlist_t **varray = NULL, *zc_props = NULL;
3356 uint_t c, children, newchildren, lastlog = 0, vcount, found = 0;
3357 libzfs_handle_t *hdl = zhp->zpool_hdl;
3358 uint64_t vers;
3359 boolean_t freelist = B_FALSE, memory_err = B_TRUE;
3360 int retval = 0;
3362 (void) snprintf(msg, sizeof (msg),
3363 dgettext(TEXT_DOMAIN, "Unable to split %s"), zhp->zpool_name);
3365 if (!zpool_name_valid(hdl, B_FALSE, newname))
3366 return (zfs_error(hdl, EZFS_INVALIDNAME, msg));
3368 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
3369 (void) fprintf(stderr, gettext("Internal error: unable to "
3370 "retrieve pool configuration\n"));
3371 return (-1);
3374 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &tree)
3375 == 0);
3376 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, &vers) == 0);
3378 if (props) {
3379 prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE };
3380 if ((zc_props = zpool_valid_proplist(hdl, zhp->zpool_name,
3381 props, vers, flags, msg)) == NULL)
3382 return (-1);
3385 if (nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN, &child,
3386 &children) != 0) {
3387 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3388 "Source pool is missing vdev tree"));
3389 nvlist_free(zc_props);
3390 return (-1);
3393 varray = zfs_alloc(hdl, children * sizeof (nvlist_t *));
3394 vcount = 0;
3396 if (*newroot == NULL ||
3397 nvlist_lookup_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN,
3398 &newchild, &newchildren) != 0)
3399 newchildren = 0;
3401 for (c = 0; c < children; c++) {
3402 uint64_t is_log = B_FALSE, is_hole = B_FALSE;
3403 char *type;
3404 nvlist_t **mchild, *vdev;
3405 uint_t mchildren;
3406 int entry;
3409 * Unlike cache & spares, slogs are stored in the
3410 * ZPOOL_CONFIG_CHILDREN array. We filter them out here.
3412 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
3413 &is_log);
3414 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
3415 &is_hole);
3416 if (is_log || is_hole) {
3418 * Create a hole vdev and put it in the config.
3420 if (nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) != 0)
3421 goto out;
3422 if (nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE,
3423 VDEV_TYPE_HOLE) != 0)
3424 goto out;
3425 if (nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_HOLE,
3426 1) != 0)
3427 goto out;
3428 if (lastlog == 0)
3429 lastlog = vcount;
3430 varray[vcount++] = vdev;
3431 continue;
3433 lastlog = 0;
3434 verify(nvlist_lookup_string(child[c], ZPOOL_CONFIG_TYPE, &type)
3435 == 0);
3436 if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
3437 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3438 "Source pool must be composed only of mirrors\n"));
3439 retval = zfs_error(hdl, EZFS_INVALCONFIG, msg);
3440 goto out;
3443 verify(nvlist_lookup_nvlist_array(child[c],
3444 ZPOOL_CONFIG_CHILDREN, &mchild, &mchildren) == 0);
3446 /* find or add an entry for this top-level vdev */
3447 if (newchildren > 0 &&
3448 (entry = find_vdev_entry(zhp, mchild, mchildren,
3449 newchild, newchildren)) >= 0) {
3450 /* We found a disk that the user specified. */
3451 vdev = mchild[entry];
3452 ++found;
3453 } else {
3454 /* User didn't specify a disk for this vdev. */
3455 vdev = mchild[mchildren - 1];
3458 if (nvlist_dup(vdev, &varray[vcount++], 0) != 0)
3459 goto out;
3462 /* did we find every disk the user specified? */
3463 if (found != newchildren) {
3464 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Device list must "
3465 "include at most one disk from each mirror"));
3466 retval = zfs_error(hdl, EZFS_INVALCONFIG, msg);
3467 goto out;
3470 /* Prepare the nvlist for populating. */
3471 if (*newroot == NULL) {
3472 if (nvlist_alloc(newroot, NV_UNIQUE_NAME, 0) != 0)
3473 goto out;
3474 freelist = B_TRUE;
3475 if (nvlist_add_string(*newroot, ZPOOL_CONFIG_TYPE,
3476 VDEV_TYPE_ROOT) != 0)
3477 goto out;
3478 } else {
3479 verify(nvlist_remove_all(*newroot, ZPOOL_CONFIG_CHILDREN) == 0);
3482 /* Add all the children we found */
3483 if (nvlist_add_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN, varray,
3484 lastlog == 0 ? vcount : lastlog) != 0)
3485 goto out;
3488 * If we're just doing a dry run, exit now with success.
3490 if (flags.dryrun) {
3491 memory_err = B_FALSE;
3492 freelist = B_FALSE;
3493 goto out;
3496 /* now build up the config list & call the ioctl */
3497 if (nvlist_alloc(&newconfig, NV_UNIQUE_NAME, 0) != 0)
3498 goto out;
3500 if (nvlist_add_nvlist(newconfig,
3501 ZPOOL_CONFIG_VDEV_TREE, *newroot) != 0 ||
3502 nvlist_add_string(newconfig,
3503 ZPOOL_CONFIG_POOL_NAME, newname) != 0 ||
3504 nvlist_add_uint64(newconfig, ZPOOL_CONFIG_VERSION, vers) != 0)
3505 goto out;
3508 * The new pool is automatically part of the namespace unless we
3509 * explicitly export it.
3511 if (!flags.import)
3512 zc.zc_cookie = ZPOOL_EXPORT_AFTER_SPLIT;
3513 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3514 (void) strlcpy(zc.zc_string, newname, sizeof (zc.zc_string));
3515 if (zcmd_write_conf_nvlist(hdl, &zc, newconfig) != 0)
3516 goto out;
3517 if (zc_props != NULL && zcmd_write_src_nvlist(hdl, &zc, zc_props) != 0)
3518 goto out;
3520 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SPLIT, &zc) != 0) {
3521 retval = zpool_standard_error(hdl, errno, msg);
3522 goto out;
3525 freelist = B_FALSE;
3526 memory_err = B_FALSE;
3528 out:
3529 if (varray != NULL) {
3530 int v;
3532 for (v = 0; v < vcount; v++)
3533 nvlist_free(varray[v]);
3534 free(varray);
3536 zcmd_free_nvlists(&zc);
3537 nvlist_free(zc_props);
3538 nvlist_free(newconfig);
3539 if (freelist) {
3540 nvlist_free(*newroot);
3541 *newroot = NULL;
3544 if (retval != 0)
3545 return (retval);
3547 if (memory_err)
3548 return (no_memory(hdl));
3550 return (0);
3554 * Remove the given device.
3557 zpool_vdev_remove(zpool_handle_t *zhp, const char *path)
3559 zfs_cmd_t zc = { 0 };
3560 char msg[1024];
3561 nvlist_t *tgt;
3562 boolean_t avail_spare, l2cache, islog;
3563 libzfs_handle_t *hdl = zhp->zpool_hdl;
3564 uint64_t version;
3566 (void) snprintf(msg, sizeof (msg),
3567 dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
3569 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3570 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
3571 &islog)) == NULL)
3572 return (zfs_error(hdl, EZFS_NODEVICE, msg));
3574 version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
3575 if (islog && version < SPA_VERSION_HOLES) {
3576 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3577 "pool must be upgraded to support log removal"));
3578 return (zfs_error(hdl, EZFS_BADVERSION, msg));
3581 zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
3583 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0)
3584 return (0);
3586 switch (errno) {
3588 case EINVAL:
3589 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3590 "invalid config; all top-level vdevs must "
3591 "have the same sector size and not be raidz."));
3592 (void) zfs_error(hdl, EZFS_INVALCONFIG, msg);
3593 break;
3595 case EBUSY:
3596 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3597 "Pool busy; removal may already be in progress"));
3598 (void) zfs_error(hdl, EZFS_BUSY, msg);
3599 break;
3601 default:
3602 (void) zpool_standard_error(hdl, errno, msg);
3604 return (-1);
3608 zpool_vdev_remove_cancel(zpool_handle_t *zhp)
3610 zfs_cmd_t zc = { 0 };
3611 char msg[1024];
3612 libzfs_handle_t *hdl = zhp->zpool_hdl;
3614 (void) snprintf(msg, sizeof (msg),
3615 dgettext(TEXT_DOMAIN, "cannot cancel removal"));
3617 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3618 zc.zc_cookie = 1;
3620 if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0)
3621 return (0);
3623 return (zpool_standard_error(hdl, errno, msg));
3627 zpool_vdev_indirect_size(zpool_handle_t *zhp, const char *path,
3628 uint64_t *sizep)
3630 char msg[1024];
3631 nvlist_t *tgt;
3632 boolean_t avail_spare, l2cache, islog;
3633 libzfs_handle_t *hdl = zhp->zpool_hdl;
3635 (void) snprintf(msg, sizeof (msg),
3636 dgettext(TEXT_DOMAIN, "cannot determine indirect size of %s"),
3637 path);
3639 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
3640 &islog)) == NULL)
3641 return (zfs_error(hdl, EZFS_NODEVICE, msg));
3643 if (avail_spare || l2cache || islog) {
3644 *sizep = 0;
3645 return (0);
3648 if (nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_INDIRECT_SIZE, sizep) != 0) {
3649 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3650 "indirect size not available"));
3651 return (zfs_error(hdl, EINVAL, msg));
3653 return (0);
3657 * Clear the errors for the pool, or the particular device if specified.
3660 zpool_clear(zpool_handle_t *zhp, const char *path, nvlist_t *rewindnvl)
3662 zfs_cmd_t zc = { 0 };
3663 char msg[1024];
3664 nvlist_t *tgt;
3665 zpool_load_policy_t policy;
3666 boolean_t avail_spare, l2cache;
3667 libzfs_handle_t *hdl = zhp->zpool_hdl;
3668 nvlist_t *nvi = NULL;
3669 int error;
3671 if (path)
3672 (void) snprintf(msg, sizeof (msg),
3673 dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
3674 path);
3675 else
3676 (void) snprintf(msg, sizeof (msg),
3677 dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
3678 zhp->zpool_name);
3680 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3681 if (path) {
3682 if ((tgt = zpool_find_vdev(zhp, path, &avail_spare,
3683 &l2cache, NULL)) == NULL)
3684 return (zfs_error(hdl, EZFS_NODEVICE, msg));
3687 * Don't allow error clearing for hot spares. Do allow
3688 * error clearing for l2cache devices.
3690 if (avail_spare)
3691 return (zfs_error(hdl, EZFS_ISSPARE, msg));
3693 verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID,
3694 &zc.zc_guid) == 0);
3697 zpool_get_load_policy(rewindnvl, &policy);
3698 zc.zc_cookie = policy.zlp_rewind;
3700 if (zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size * 2) != 0)
3701 return (-1);
3703 if (zcmd_write_src_nvlist(hdl, &zc, rewindnvl) != 0)
3704 return (-1);
3706 while ((error = zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc)) != 0 &&
3707 errno == ENOMEM) {
3708 if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
3709 zcmd_free_nvlists(&zc);
3710 return (-1);
3714 if (!error || ((policy.zlp_rewind & ZPOOL_TRY_REWIND) &&
3715 errno != EPERM && errno != EACCES)) {
3716 if (policy.zlp_rewind &
3717 (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) {
3718 (void) zcmd_read_dst_nvlist(hdl, &zc, &nvi);
3719 zpool_rewind_exclaim(hdl, zc.zc_name,
3720 ((policy.zlp_rewind & ZPOOL_TRY_REWIND) != 0),
3721 nvi);
3722 nvlist_free(nvi);
3724 zcmd_free_nvlists(&zc);
3725 return (0);
3728 zcmd_free_nvlists(&zc);
3729 return (zpool_standard_error(hdl, errno, msg));
3733 * Similar to zpool_clear(), but takes a GUID (used by fmd).
3736 zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid)
3738 zfs_cmd_t zc = { 0 };
3739 char msg[1024];
3740 libzfs_handle_t *hdl = zhp->zpool_hdl;
3742 (void) snprintf(msg, sizeof (msg),
3743 dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"),
3744 guid);
3746 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3747 zc.zc_guid = guid;
3748 zc.zc_cookie = ZPOOL_NO_REWIND;
3750 if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0)
3751 return (0);
3753 return (zpool_standard_error(hdl, errno, msg));
3757 * Change the GUID for a pool.
3760 zpool_reguid(zpool_handle_t *zhp)
3762 char msg[1024];
3763 libzfs_handle_t *hdl = zhp->zpool_hdl;
3764 zfs_cmd_t zc = { 0 };
3766 (void) snprintf(msg, sizeof (msg),
3767 dgettext(TEXT_DOMAIN, "cannot reguid '%s'"), zhp->zpool_name);
3769 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3770 if (zfs_ioctl(hdl, ZFS_IOC_POOL_REGUID, &zc) == 0)
3771 return (0);
3773 return (zpool_standard_error(hdl, errno, msg));
3777 * Reopen the pool.
3780 zpool_reopen(zpool_handle_t *zhp)
3782 zfs_cmd_t zc = { 0 };
3783 char msg[1024];
3784 libzfs_handle_t *hdl = zhp->zpool_hdl;
3786 (void) snprintf(msg, sizeof (msg),
3787 dgettext(TEXT_DOMAIN, "cannot reopen '%s'"),
3788 zhp->zpool_name);
3790 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3791 if (zfs_ioctl(hdl, ZFS_IOC_POOL_REOPEN, &zc) == 0)
3792 return (0);
3793 return (zpool_standard_error(hdl, errno, msg));
3796 /* call into libzfs_core to execute the sync IOCTL per pool */
3798 zpool_sync_one(zpool_handle_t *zhp, void *data)
3800 int ret;
3801 libzfs_handle_t *hdl = zpool_get_handle(zhp);
3802 const char *pool_name = zpool_get_name(zhp);
3803 boolean_t *force = data;
3804 nvlist_t *innvl = fnvlist_alloc();
3806 fnvlist_add_boolean_value(innvl, "force", *force);
3807 if ((ret = lzc_sync(pool_name, innvl, NULL)) != 0) {
3808 nvlist_free(innvl);
3809 return (zpool_standard_error_fmt(hdl, ret,
3810 dgettext(TEXT_DOMAIN, "sync '%s' failed"), pool_name));
3812 nvlist_free(innvl);
3814 return (0);
3818 * Convert from a devid string to a path.
3820 static char *
3821 devid_to_path(char *devid_str)
3823 ddi_devid_t devid;
3824 char *minor;
3825 char *path;
3826 devid_nmlist_t *list = NULL;
3827 int ret;
3829 if (devid_str_decode(devid_str, &devid, &minor) != 0)
3830 return (NULL);
3832 ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list);
3834 devid_str_free(minor);
3835 devid_free(devid);
3837 if (ret != 0)
3838 return (NULL);
3841 * In a case the strdup() fails, we will just return NULL below.
3843 path = strdup(list[0].devname);
3845 devid_free_nmlist(list);
3847 return (path);
3851 * Convert from a path to a devid string.
3853 static char *
3854 path_to_devid(const char *path)
3856 int fd;
3857 ddi_devid_t devid;
3858 char *minor, *ret;
3860 if ((fd = open(path, O_RDONLY)) < 0)
3861 return (NULL);
3863 minor = NULL;
3864 ret = NULL;
3865 if (devid_get(fd, &devid) == 0) {
3866 if (devid_get_minor_name(fd, &minor) == 0)
3867 ret = devid_str_encode(devid, minor);
3868 if (minor != NULL)
3869 devid_str_free(minor);
3870 devid_free(devid);
3872 (void) close(fd);
3874 return (ret);
3877 struct path_from_physpath_walker_args {
3878 char *pfpwa_path;
3882 * Walker for use with di_devlink_walk(). Stores the "/dev" path of the first
3883 * primary devlink (i.e., the first devlink which refers to our "/devices"
3884 * node) and stops walking.
3886 static int
3887 path_from_physpath_walker(di_devlink_t devlink, void *arg)
3889 struct path_from_physpath_walker_args *pfpwa = arg;
3891 if (di_devlink_type(devlink) != DI_PRIMARY_LINK) {
3892 return (DI_WALK_CONTINUE);
3895 verify(pfpwa->pfpwa_path == NULL);
3896 if ((pfpwa->pfpwa_path = strdup(di_devlink_path(devlink))) != NULL) {
3897 return (DI_WALK_TERMINATE);
3900 return (DI_WALK_CONTINUE);
3904 * Search for a "/dev" path that refers to our physical path. Returns the new
3905 * path if one is found and it does not match the existing "path" value. If
3906 * the value is unchanged, or one could not be found, returns NULL.
3908 static char *
3909 path_from_physpath(libzfs_handle_t *hdl, const char *path,
3910 const char *physpath)
3912 struct path_from_physpath_walker_args pfpwa;
3914 if (physpath == NULL) {
3915 return (NULL);
3918 if (hdl->libzfs_devlink == NULL) {
3919 if ((hdl->libzfs_devlink = di_devlink_init(NULL, 0)) ==
3920 DI_LINK_NIL) {
3922 * We may not be able to open a handle if this process
3923 * is insufficiently privileged, or we are too early in
3924 * boot for devfsadm to be ready. Ignore this error
3925 * and defer the path check to a subsequent run.
3927 return (NULL);
3931 pfpwa.pfpwa_path = NULL;
3932 (void) di_devlink_walk(hdl->libzfs_devlink, NULL, physpath,
3933 DI_PRIMARY_LINK, &pfpwa, path_from_physpath_walker);
3935 if (path != NULL && pfpwa.pfpwa_path != NULL &&
3936 strcmp(path, pfpwa.pfpwa_path) == 0) {
3938 * If the path is already correct, no change is required.
3940 free(pfpwa.pfpwa_path);
3941 return (NULL);
3944 return (pfpwa.pfpwa_path);
3948 * Issue the necessary ioctl() to update the stored path value for the vdev. We
3949 * ignore any failure here, since a common case is for an unprivileged user to
3950 * type 'zpool status', and we'll display the correct information anyway.
3952 static void
3953 set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path)
3955 zfs_cmd_t zc = { 0 };
3957 (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3958 (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value));
3959 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
3960 &zc.zc_guid) == 0);
3962 (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc);
3966 * This routine is responsible for identifying when disks have been
3967 * reconfigured in a new location. The kernel will have opened the device by
3968 * devid, but the path will still refer to the old location. To catch this, we
3969 * first do a path -> devid translation (which is fast for the common case).
3970 * If the devid matches, we're done. If not, we do a reverse devid -> path
3971 * translation and issue the appropriate ioctl() to update the path of the
3972 * vdev.
3974 void
3975 zpool_vdev_refresh_path(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv)
3977 char *path = NULL;
3978 char *newpath = NULL;
3979 char *physpath = NULL;
3980 char *devid = NULL;
3982 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) != 0) {
3983 return;
3986 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) {
3988 * This vdev has a devid. We can use it to check the current
3989 * path.
3991 char *newdevid = path_to_devid(path);
3993 if (newdevid == NULL || strcmp(devid, newdevid) != 0) {
3994 newpath = devid_to_path(devid);
3997 if (newdevid != NULL) {
3998 devid_str_free(newdevid);
4001 } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PHYS_PATH,
4002 &physpath) == 0) {
4004 * This vdev does not have a devid, but it does have a physical
4005 * path. Attempt to translate this to a /dev path.
4007 newpath = path_from_physpath(hdl, path, physpath);
4010 if (newpath == NULL) {
4012 * No path update is required.
4014 return;
4017 set_path(zhp, nv, newpath);
4018 fnvlist_add_string(nv, ZPOOL_CONFIG_PATH, newpath);
4020 free(newpath);
4024 * Given a vdev, return the name to display in iostat. If the vdev has a path,
4025 * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type.
4026 * We will confirm that the path and name of the vdev are current, and update
4027 * them if not. We also check if this is a whole disk, in which case we strip
4028 * off the trailing 's0' slice name.
4030 * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any
4031 * of these checks.
4033 char *
4034 zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
4035 int name_flags)
4037 char *path, *type, *env;
4038 uint64_t value;
4041 * vdev_name will be "root"/"root-0" for the root vdev, but it is the
4042 * zpool name that will be displayed to the user.
4044 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
4045 if (zhp != NULL && strcmp(type, "root") == 0)
4046 return (zfs_strdup(hdl, zpool_get_name(zhp)));
4048 env = getenv("ZPOOL_VDEV_NAME_PATH");
4049 if (env && (strtoul(env, NULL, 0) > 0 ||
4050 !strncasecmp(env, "YES", 3) || !strncasecmp(env, "ON", 2)))
4051 name_flags |= VDEV_NAME_PATH;
4053 env = getenv("ZPOOL_VDEV_NAME_GUID");
4054 if (env && (strtoul(env, NULL, 0) > 0 ||
4055 !strncasecmp(env, "YES", 3) || !strncasecmp(env, "ON", 2)))
4056 name_flags |= VDEV_NAME_GUID;
4058 env = getenv("ZPOOL_VDEV_NAME_FOLLOW_LINKS");
4059 if (env && (strtoul(env, NULL, 0) > 0 ||
4060 !strncasecmp(env, "YES", 3) || !strncasecmp(env, "ON", 2)))
4061 name_flags |= VDEV_NAME_FOLLOW_LINKS;
4063 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &value) == 0 ||
4064 name_flags & VDEV_NAME_GUID) {
4065 nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &value);
4066 path = zfs_asprintf(hdl, "%llu", (u_longlong_t)value);
4067 } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
4068 vdev_stat_t *vs;
4069 uint_t vsc;
4072 * If the device is dead (faulted, offline, etc) then don't
4073 * bother opening it. Otherwise we may be forcing the user to
4074 * open a misbehaving device, which can have undesirable
4075 * effects.
4077 if (nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
4078 (uint64_t **)&vs, &vsc) != 0 ||
4079 vs->vs_state < VDEV_STATE_DEGRADED ||
4080 zhp == NULL) {
4081 path = zfs_strdup(hdl, path);
4082 goto after_open;
4086 * Refresh the /dev path for this vdev if required, then ensure
4087 * we're using the latest path value:
4089 zpool_vdev_refresh_path(hdl, zhp, nv);
4090 path = fnvlist_lookup_string(nv, ZPOOL_CONFIG_PATH);
4092 if (name_flags & VDEV_NAME_FOLLOW_LINKS) {
4093 char *rp = realpath(path, NULL);
4094 if (rp == NULL)
4095 no_memory(hdl);
4096 path = rp;
4097 } else {
4098 path = zfs_strdup(hdl, path);
4101 after_open:
4102 if (strncmp(path, ZFS_DISK_ROOTD,
4103 sizeof (ZFS_DISK_ROOTD) - 1) == 0) {
4104 const char *p2 = path + sizeof (ZFS_DISK_ROOTD) - 1;
4106 memmove(path, p2, strlen(p2) + 1);
4110 * Remove the partition from the path it this is a whole disk.
4112 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, &value)
4113 == 0 && value && !(name_flags & VDEV_NAME_PATH)) {
4114 int pathlen = strlen(path);
4117 * If it starts with c#, and ends with "s0" or "s1",
4118 * chop the slice off, or if it ends with "s0/old" or
4119 * "s1/old", remove the slice from the middle.
4121 if (CTD_CHECK(path)) {
4122 if (strcmp(&path[pathlen - 2], "s0") == 0 ||
4123 strcmp(&path[pathlen - 2], "s1") == 0) {
4124 path[pathlen - 2] = '\0';
4125 } else if (pathlen > 6 &&
4126 (strcmp(&path[pathlen - 6],
4127 "s0/old") == 0 ||
4128 strcmp(&path[pathlen - 6],
4129 "s1/old") == 0)) {
4130 (void) strcpy(&path[pathlen - 6],
4131 "/old");
4134 return (path);
4136 } else {
4138 * If it's a raidz device, we need to stick in the parity level.
4140 if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
4141 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY,
4142 &value) == 0);
4143 path = zfs_asprintf(hdl, "%s%llu", type,
4144 (u_longlong_t)value);
4145 } else {
4146 path = zfs_strdup(hdl, type);
4150 * We identify each top-level vdev by using a <type-id>
4151 * naming convention.
4153 if (name_flags & VDEV_NAME_TYPE_ID) {
4154 uint64_t id;
4155 char *tmp;
4157 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID,
4158 &id) == 0);
4159 tmp = zfs_asprintf(hdl, "%s-%llu", path,
4160 (u_longlong_t)id);
4161 free(path);
4162 path = tmp;
4166 return (path);
4169 static int
4170 zbookmark_mem_compare(const void *a, const void *b)
4172 return (memcmp(a, b, sizeof (zbookmark_phys_t)));
4176 * Retrieve the persistent error log, uniquify the members, and return to the
4177 * caller.
4180 zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
4182 zfs_cmd_t zc = { 0 };
4183 uint64_t count;
4184 zbookmark_phys_t *zb = NULL;
4185 int i;
4188 * Retrieve the raw error list from the kernel. If the number of errors
4189 * has increased, allocate more space and continue until we get the
4190 * entire list.
4192 verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT,
4193 &count) == 0);
4194 if (count == 0)
4195 return (0);
4196 if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl,
4197 count * sizeof (zbookmark_phys_t))) == (uintptr_t)NULL)
4198 return (-1);
4199 zc.zc_nvlist_dst_size = count;
4200 (void) strcpy(zc.zc_name, zhp->zpool_name);
4201 for (;;) {
4202 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG,
4203 &zc) != 0) {
4204 free((void *)(uintptr_t)zc.zc_nvlist_dst);
4205 if (errno == ENOMEM) {
4206 void *dst;
4208 count = zc.zc_nvlist_dst_size;
4209 dst = zfs_alloc(zhp->zpool_hdl, count *
4210 sizeof (zbookmark_phys_t));
4211 if (dst == NULL)
4212 return (-1);
4213 zc.zc_nvlist_dst = (uintptr_t)dst;
4214 } else {
4215 return (-1);
4217 } else {
4218 break;
4223 * Sort the resulting bookmarks. This is a little confusing due to the
4224 * implementation of ZFS_IOC_ERROR_LOG. The bookmarks are copied last
4225 * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks
4226 * _not_ copied as part of the process. So we point the start of our
4227 * array appropriate and decrement the total number of elements.
4229 zb = ((zbookmark_phys_t *)(uintptr_t)zc.zc_nvlist_dst) +
4230 zc.zc_nvlist_dst_size;
4231 count -= zc.zc_nvlist_dst_size;
4233 qsort(zb, count, sizeof (zbookmark_phys_t), zbookmark_mem_compare);
4235 verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0);
4238 * Fill in the nverrlistp with nvlist's of dataset and object numbers.
4240 for (i = 0; i < count; i++) {
4241 nvlist_t *nv;
4243 /* ignoring zb_blkid and zb_level for now */
4244 if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset &&
4245 zb[i-1].zb_object == zb[i].zb_object)
4246 continue;
4248 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0)
4249 goto nomem;
4250 if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET,
4251 zb[i].zb_objset) != 0) {
4252 nvlist_free(nv);
4253 goto nomem;
4255 if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT,
4256 zb[i].zb_object) != 0) {
4257 nvlist_free(nv);
4258 goto nomem;
4260 if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) {
4261 nvlist_free(nv);
4262 goto nomem;
4264 nvlist_free(nv);
4267 free((void *)(uintptr_t)zc.zc_nvlist_dst);
4268 return (0);
4270 nomem:
4271 free((void *)(uintptr_t)zc.zc_nvlist_dst);
4272 return (no_memory(zhp->zpool_hdl));
4276 * Upgrade a ZFS pool to the latest on-disk version.
4279 zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version)
4281 zfs_cmd_t zc = { 0 };
4282 libzfs_handle_t *hdl = zhp->zpool_hdl;
4284 (void) strcpy(zc.zc_name, zhp->zpool_name);
4285 zc.zc_cookie = new_version;
4287 if (zfs_ioctl(hdl, ZFS_IOC_POOL_UPGRADE, &zc) != 0)
4288 return (zpool_standard_error_fmt(hdl, errno,
4289 dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"),
4290 zhp->zpool_name));
4291 return (0);
4294 void
4295 zfs_save_arguments(int argc, char **argv, char *string, int len)
4297 (void) strlcpy(string, basename(argv[0]), len);
4298 for (int i = 1; i < argc; i++) {
4299 (void) strlcat(string, " ", len);
4300 (void) strlcat(string, argv[i], len);
4305 zpool_log_history(libzfs_handle_t *hdl, const char *message)
4307 zfs_cmd_t zc = { 0 };
4308 nvlist_t *args;
4309 int err;
4311 args = fnvlist_alloc();
4312 fnvlist_add_string(args, "message", message);
4313 err = zcmd_write_src_nvlist(hdl, &zc, args);
4314 if (err == 0)
4315 err = ioctl(hdl->libzfs_fd, ZFS_IOC_LOG_HISTORY, &zc);
4316 nvlist_free(args);
4317 zcmd_free_nvlists(&zc);
4318 return (err);
4322 * Perform ioctl to get some command history of a pool.
4324 * 'buf' is the buffer to fill up to 'len' bytes. 'off' is the
4325 * logical offset of the history buffer to start reading from.
4327 * Upon return, 'off' is the next logical offset to read from and
4328 * 'len' is the actual amount of bytes read into 'buf'.
4330 static int
4331 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len)
4333 zfs_cmd_t zc = { 0 };
4334 libzfs_handle_t *hdl = zhp->zpool_hdl;
4336 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4338 zc.zc_history = (uint64_t)(uintptr_t)buf;
4339 zc.zc_history_len = *len;
4340 zc.zc_history_offset = *off;
4342 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) {
4343 switch (errno) {
4344 case EPERM:
4345 return (zfs_error_fmt(hdl, EZFS_PERM,
4346 dgettext(TEXT_DOMAIN,
4347 "cannot show history for pool '%s'"),
4348 zhp->zpool_name));
4349 case ENOENT:
4350 return (zfs_error_fmt(hdl, EZFS_NOHISTORY,
4351 dgettext(TEXT_DOMAIN, "cannot get history for pool "
4352 "'%s'"), zhp->zpool_name));
4353 case ENOTSUP:
4354 return (zfs_error_fmt(hdl, EZFS_BADVERSION,
4355 dgettext(TEXT_DOMAIN, "cannot get history for pool "
4356 "'%s', pool must be upgraded"), zhp->zpool_name));
4357 default:
4358 return (zpool_standard_error_fmt(hdl, errno,
4359 dgettext(TEXT_DOMAIN,
4360 "cannot get history for '%s'"), zhp->zpool_name));
4364 *len = zc.zc_history_len;
4365 *off = zc.zc_history_offset;
4367 return (0);
4371 * Retrieve the command history of a pool.
4374 zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp, uint64_t *off,
4375 boolean_t *eof)
4377 char *buf;
4378 int buflen = 128 * 1024;
4379 nvlist_t **records = NULL;
4380 uint_t numrecords = 0;
4381 int err = 0, i;
4382 uint64_t start = *off;
4384 buf = malloc(buflen);
4385 if (buf == NULL)
4386 return (ENOMEM);
4387 /* process about 1MB a time */
4388 while (*off - start < 1024 * 1024) {
4389 uint64_t bytes_read = buflen;
4390 uint64_t leftover;
4392 if ((err = get_history(zhp, buf, off, &bytes_read)) != 0)
4393 break;
4395 /* if nothing else was read in, we're at EOF, just return */
4396 if (!bytes_read) {
4397 *eof = B_TRUE;
4398 break;
4401 if ((err = zpool_history_unpack(buf, bytes_read,
4402 &leftover, &records, &numrecords)) != 0)
4403 break;
4404 *off -= leftover;
4405 if (leftover == bytes_read) {
4407 * no progress made, because buffer is not big enough
4408 * to hold this record; resize and retry.
4410 buflen *= 2;
4411 free(buf);
4412 buf = malloc(buflen);
4413 if (buf == NULL)
4414 return (ENOMEM);
4418 free(buf);
4420 if (!err) {
4421 verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0);
4422 verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD,
4423 records, numrecords) == 0);
4425 for (i = 0; i < numrecords; i++)
4426 nvlist_free(records[i]);
4427 free(records);
4429 return (err);
4432 void
4433 zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
4434 char *pathname, size_t len)
4436 zfs_cmd_t zc = { 0 };
4437 boolean_t mounted = B_FALSE;
4438 char *mntpnt = NULL;
4439 char dsname[ZFS_MAX_DATASET_NAME_LEN];
4441 if (dsobj == 0) {
4442 /* special case for the MOS */
4443 (void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj);
4444 return;
4447 /* get the dataset's name */
4448 (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4449 zc.zc_obj = dsobj;
4450 if (ioctl(zhp->zpool_hdl->libzfs_fd,
4451 ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) {
4452 /* just write out a path of two object numbers */
4453 (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>",
4454 dsobj, obj);
4455 return;
4457 (void) strlcpy(dsname, zc.zc_value, sizeof (dsname));
4459 /* find out if the dataset is mounted */
4460 mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt);
4462 /* get the corrupted object's path */
4463 (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name));
4464 zc.zc_obj = obj;
4465 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH,
4466 &zc) == 0) {
4467 if (mounted) {
4468 (void) snprintf(pathname, len, "%s%s", mntpnt,
4469 zc.zc_value);
4470 } else {
4471 (void) snprintf(pathname, len, "%s:%s",
4472 dsname, zc.zc_value);
4474 } else {
4475 (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj);
4477 free(mntpnt);
4481 zpool_set_bootenv(zpool_handle_t *zhp, const nvlist_t *envmap)
4483 int error = lzc_set_bootenv(zhp->zpool_name, envmap);
4484 if (error != 0) {
4485 (void) zpool_standard_error_fmt(zhp->zpool_hdl, error,
4486 dgettext(TEXT_DOMAIN,
4487 "error setting bootenv in pool '%s'"), zhp->zpool_name);
4490 return (error);
4494 zpool_get_bootenv(zpool_handle_t *zhp, nvlist_t **nvlp)
4496 nvlist_t *nvl;
4497 int error;
4499 nvl = NULL;
4500 error = lzc_get_bootenv(zhp->zpool_name, &nvl);
4501 if (error != 0) {
4502 (void) zpool_standard_error_fmt(zhp->zpool_hdl, error,
4503 dgettext(TEXT_DOMAIN,
4504 "error getting bootenv in pool '%s'"), zhp->zpool_name);
4505 } else {
4506 *nvlp = nvl;
4509 return (error);
4513 * Read the EFI label from the config, if a label does not exist then
4514 * pass back the error to the caller. If the caller has passed a non-NULL
4515 * diskaddr argument then we set it to the starting address of the EFI
4516 * partition. If the caller has passed a non-NULL boolean argument, then
4517 * we set it to indicate if the disk does have efi system partition.
4519 static int
4520 read_efi_label(nvlist_t *config, diskaddr_t *sb, boolean_t *system)
4522 char *path;
4523 int fd;
4524 char diskname[MAXPATHLEN];
4525 boolean_t boot = B_FALSE;
4526 int err = -1;
4527 int slice;
4529 if (nvlist_lookup_string(config, ZPOOL_CONFIG_PATH, &path) != 0)
4530 return (err);
4532 (void) snprintf(diskname, sizeof (diskname), "%s%s", ZFS_RDISK_ROOT,
4533 strrchr(path, '/'));
4534 if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) {
4535 struct dk_gpt *vtoc;
4537 if ((err = efi_alloc_and_read(fd, &vtoc)) >= 0) {
4538 for (slice = 0; slice < vtoc->efi_nparts; slice++) {
4539 if (vtoc->efi_parts[slice].p_tag == V_SYSTEM)
4540 boot = B_TRUE;
4541 if (vtoc->efi_parts[slice].p_tag == V_USR)
4542 break;
4544 if (sb != NULL && vtoc->efi_parts[slice].p_tag == V_USR)
4545 *sb = vtoc->efi_parts[slice].p_start;
4546 if (system != NULL)
4547 *system = boot;
4548 efi_free(vtoc);
4550 (void) close(fd);
4552 return (err);
4556 * determine where a partition starts on a disk in the current
4557 * configuration
4559 static diskaddr_t
4560 find_start_block(nvlist_t *config)
4562 nvlist_t **child;
4563 uint_t c, children;
4564 diskaddr_t sb = MAXOFFSET_T;
4565 uint64_t wholedisk;
4567 if (nvlist_lookup_nvlist_array(config,
4568 ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) {
4569 if (nvlist_lookup_uint64(config,
4570 ZPOOL_CONFIG_WHOLE_DISK,
4571 &wholedisk) != 0 || !wholedisk) {
4572 return (MAXOFFSET_T);
4574 if (read_efi_label(config, &sb, NULL) < 0)
4575 sb = MAXOFFSET_T;
4576 return (sb);
4579 for (c = 0; c < children; c++) {
4580 sb = find_start_block(child[c]);
4581 if (sb != MAXOFFSET_T) {
4582 return (sb);
4585 return (MAXOFFSET_T);
4589 * Label an individual disk. The name provided is the short name,
4590 * stripped of any leading /dev path.
4593 zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name,
4594 zpool_boot_label_t boot_type, uint64_t boot_size, int *slice)
4596 char path[MAXPATHLEN];
4597 struct dk_gpt *vtoc;
4598 int fd;
4599 size_t resv;
4600 uint64_t slice_size;
4601 diskaddr_t start_block;
4602 char errbuf[1024];
4604 /* prepare an error message just in case */
4605 (void) snprintf(errbuf, sizeof (errbuf),
4606 dgettext(TEXT_DOMAIN, "cannot label '%s'"), name);
4608 if (zhp) {
4609 nvlist_t *nvroot;
4611 verify(nvlist_lookup_nvlist(zhp->zpool_config,
4612 ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
4614 if (zhp->zpool_start_block == 0)
4615 start_block = find_start_block(nvroot);
4616 else
4617 start_block = zhp->zpool_start_block;
4618 zhp->zpool_start_block = start_block;
4619 } else {
4620 /* new pool */
4621 start_block = NEW_START_BLOCK;
4624 (void) snprintf(path, sizeof (path), "%s/%s%s", ZFS_RDISK_ROOT, name,
4625 BACKUP_SLICE);
4627 if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) {
4629 * This shouldn't happen. We've long since verified that this
4630 * is a valid device.
4632 zfs_error_aux(hdl,
4633 dgettext(TEXT_DOMAIN, "unable to open device"));
4634 return (zfs_error(hdl, EZFS_OPENFAILED, errbuf));
4637 if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) {
4639 * The only way this can fail is if we run out of memory, or we
4640 * were unable to read the disk's capacity
4642 if (errno == ENOMEM)
4643 (void) no_memory(hdl);
4645 (void) close(fd);
4646 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4647 "unable to read disk capacity"), name);
4649 return (zfs_error(hdl, EZFS_NOCAP, errbuf));
4651 resv = efi_reserved_sectors(vtoc);
4654 * Why we use V_USR: V_BACKUP confuses users, and is considered
4655 * disposable by some EFI utilities (since EFI doesn't have a backup
4656 * slice). V_UNASSIGNED is supposed to be used only for zero size
4657 * partitions, and efi_write() will fail if we use it. V_ROOT, V_BOOT,
4658 * etc. were all pretty specific. V_USR is as close to reality as we
4659 * can get, in the absence of V_OTHER.
4661 /* first fix the partition start block */
4662 if (start_block == MAXOFFSET_T)
4663 start_block = NEW_START_BLOCK;
4666 * EFI System partition is using slice 0.
4667 * ZFS is on slice 1 and slice 8 is reserved.
4668 * We assume the GPT partition table without system
4669 * partition has zfs p_start == NEW_START_BLOCK.
4670 * If start_block != NEW_START_BLOCK, it means we have
4671 * system partition. Correct solution would be to query/cache vtoc
4672 * from existing vdev member.
4674 if (boot_type == ZPOOL_CREATE_BOOT_LABEL) {
4675 if (boot_size % vtoc->efi_lbasize != 0) {
4676 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4677 "boot partition size must be a multiple of %d"),
4678 vtoc->efi_lbasize);
4679 (void) close(fd);
4680 efi_free(vtoc);
4681 return (zfs_error(hdl, EZFS_LABELFAILED, errbuf));
4684 * System partition size checks.
4685 * Note the 1MB is quite arbitrary value, since we
4686 * are creating dedicated pool, it should be enough
4687 * to hold fat + efi bootloader. May need to be
4688 * adjusted if the bootloader size will grow.
4690 if (boot_size < 1024 * 1024) {
4691 char buf[64];
4692 zfs_nicenum(boot_size, buf, sizeof (buf));
4693 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4694 "Specified size %s for EFI System partition is too "
4695 "small, the minimum size is 1MB."), buf);
4696 (void) close(fd);
4697 efi_free(vtoc);
4698 return (zfs_error(hdl, EZFS_LABELFAILED, errbuf));
4700 /* 33MB is tested with mkfs -F pcfs */
4701 if (hdl->libzfs_printerr &&
4702 ((vtoc->efi_lbasize == 512 &&
4703 boot_size < 33 * 1024 * 1024) ||
4704 (vtoc->efi_lbasize == 4096 &&
4705 boot_size < 256 * 1024 * 1024))) {
4706 char buf[64];
4707 zfs_nicenum(boot_size, buf, sizeof (buf));
4708 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
4709 "Warning: EFI System partition size %s is "
4710 "not allowing to create FAT32 file\nsystem, which "
4711 "may result in unbootable system.\n"), buf);
4713 /* Adjust zfs partition start by size of system partition. */
4714 start_block += boot_size / vtoc->efi_lbasize;
4717 if (start_block == NEW_START_BLOCK) {
4719 * Use default layout.
4720 * ZFS is on slice 0 and slice 8 is reserved.
4722 slice_size = vtoc->efi_last_u_lba + 1;
4723 slice_size -= resv;
4724 slice_size -= start_block;
4725 if (slice != NULL)
4726 *slice = 0;
4728 vtoc->efi_parts[0].p_start = start_block;
4729 vtoc->efi_parts[0].p_size = slice_size;
4731 vtoc->efi_parts[0].p_tag = V_USR;
4732 (void) strcpy(vtoc->efi_parts[0].p_name, "zfs");
4734 vtoc->efi_parts[8].p_start = slice_size + start_block;
4735 vtoc->efi_parts[8].p_size = resv;
4736 vtoc->efi_parts[8].p_tag = V_RESERVED;
4737 } else {
4738 slice_size = start_block - NEW_START_BLOCK;
4739 vtoc->efi_parts[0].p_start = NEW_START_BLOCK;
4740 vtoc->efi_parts[0].p_size = slice_size;
4741 vtoc->efi_parts[0].p_tag = V_SYSTEM;
4742 (void) strcpy(vtoc->efi_parts[0].p_name, "loader");
4743 if (slice != NULL)
4744 *slice = 1;
4745 /* prepare slice 1 */
4746 slice_size = vtoc->efi_last_u_lba + 1 - slice_size;
4747 slice_size -= resv;
4748 slice_size -= NEW_START_BLOCK;
4749 vtoc->efi_parts[1].p_start = start_block;
4750 vtoc->efi_parts[1].p_size = slice_size;
4751 vtoc->efi_parts[1].p_tag = V_USR;
4752 (void) strcpy(vtoc->efi_parts[1].p_name, "zfs");
4754 vtoc->efi_parts[8].p_start = slice_size + start_block;
4755 vtoc->efi_parts[8].p_size = resv;
4756 vtoc->efi_parts[8].p_tag = V_RESERVED;
4759 if (efi_write(fd, vtoc) != 0) {
4761 * Some block drivers (like pcata) may not support EFI
4762 * GPT labels. Print out a helpful error message dir-
4763 * ecting the user to manually label the disk and give
4764 * a specific slice.
4766 (void) close(fd);
4767 efi_free(vtoc);
4769 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4770 "try using fdisk(8) and then provide a specific slice"));
4771 return (zfs_error(hdl, EZFS_LABELFAILED, errbuf));
4774 (void) close(fd);
4775 efi_free(vtoc);
4776 return (0);
4779 static boolean_t
4780 supported_dump_vdev_type(libzfs_handle_t *hdl, nvlist_t *config, char *errbuf)
4782 char *type;
4783 nvlist_t **child;
4784 uint_t children, c;
4786 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_TYPE, &type) == 0);
4787 if (strcmp(type, VDEV_TYPE_FILE) == 0 ||
4788 strcmp(type, VDEV_TYPE_HOLE) == 0 ||
4789 strcmp(type, VDEV_TYPE_MISSING) == 0) {
4790 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4791 "vdev type '%s' is not supported"), type);
4792 (void) zfs_error(hdl, EZFS_VDEVNOTSUP, errbuf);
4793 return (B_FALSE);
4795 if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN,
4796 &child, &children) == 0) {
4797 for (c = 0; c < children; c++) {
4798 if (!supported_dump_vdev_type(hdl, child[c], errbuf))
4799 return (B_FALSE);
4802 return (B_TRUE);
4806 * Check if this zvol is allowable for use as a dump device; zero if
4807 * it is, > 0 if it isn't, < 0 if it isn't a zvol.
4809 * Allowable storage configurations include mirrors, all raidz variants, and
4810 * pools with log, cache, and spare devices. Pools which are backed by files or
4811 * have missing/hole vdevs are not suitable.
4814 zvol_check_dump_config(char *arg)
4816 zpool_handle_t *zhp = NULL;
4817 nvlist_t *config, *nvroot;
4818 char *p, *volname;
4819 nvlist_t **top;
4820 uint_t toplevels;
4821 libzfs_handle_t *hdl;
4822 char errbuf[1024];
4823 char poolname[ZFS_MAX_DATASET_NAME_LEN];
4824 int pathlen = strlen(ZVOL_FULL_DEV_DIR);
4825 int ret = 1;
4827 if (strncmp(arg, ZVOL_FULL_DEV_DIR, pathlen)) {
4828 return (-1);
4831 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4832 "dump is not supported on device '%s'"), arg);
4834 if ((hdl = libzfs_init()) == NULL)
4835 return (1);
4836 libzfs_print_on_error(hdl, B_TRUE);
4838 volname = arg + pathlen;
4840 /* check the configuration of the pool */
4841 if ((p = strchr(volname, '/')) == NULL) {
4842 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4843 "malformed dataset name"));
4844 (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
4845 return (1);
4846 } else if (p - volname >= ZFS_MAX_DATASET_NAME_LEN) {
4847 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4848 "dataset name is too long"));
4849 (void) zfs_error(hdl, EZFS_NAMETOOLONG, errbuf);
4850 return (1);
4851 } else {
4852 (void) strncpy(poolname, volname, p - volname);
4853 poolname[p - volname] = '\0';
4856 if ((zhp = zpool_open(hdl, poolname)) == NULL) {
4857 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4858 "could not open pool '%s'"), poolname);
4859 (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf);
4860 goto out;
4862 config = zpool_get_config(zhp, NULL);
4863 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
4864 &nvroot) != 0) {
4865 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4866 "could not obtain vdev configuration for '%s'"), poolname);
4867 (void) zfs_error(hdl, EZFS_INVALCONFIG, errbuf);
4868 goto out;
4871 verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4872 &top, &toplevels) == 0);
4874 if (!supported_dump_vdev_type(hdl, top[0], errbuf)) {
4875 goto out;
4877 ret = 0;
4879 out:
4880 if (zhp)
4881 zpool_close(zhp);
4882 libzfs_fini(hdl);
4883 return (ret);