9166 zfs storage pool checkpoint
[unleashed.git] / usr / src / cmd / zpool / zpool_main.c
blob7786530756d10eb8d6e84e01ea74a2280d398535
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, 2018 by Delphix. All rights reserved.
25 * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
26 * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
27 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
28 * Copyright 2016 Nexenta Systems, Inc.
29 * Copyright (c) 2017 Datto Inc.
32 #include <assert.h>
33 #include <ctype.h>
34 #include <dirent.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <getopt.h>
38 #include <libgen.h>
39 #include <libintl.h>
40 #include <libuutil.h>
41 #include <locale.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <strings.h>
46 #include <unistd.h>
47 #include <priv.h>
48 #include <pwd.h>
49 #include <zone.h>
50 #include <zfs_prop.h>
51 #include <sys/fs/zfs.h>
52 #include <sys/stat.h>
54 #include <libzfs.h>
56 #include "zpool_util.h"
57 #include "zfs_comutil.h"
58 #include "zfeature_common.h"
60 #include "statcommon.h"
62 static int zpool_do_create(int, char **);
63 static int zpool_do_destroy(int, char **);
65 static int zpool_do_add(int, char **);
66 static int zpool_do_remove(int, char **);
67 static int zpool_do_labelclear(int, char **);
69 static int zpool_do_checkpoint(int, char **);
71 static int zpool_do_list(int, char **);
72 static int zpool_do_iostat(int, char **);
73 static int zpool_do_status(int, char **);
75 static int zpool_do_online(int, char **);
76 static int zpool_do_offline(int, char **);
77 static int zpool_do_clear(int, char **);
78 static int zpool_do_reopen(int, char **);
80 static int zpool_do_reguid(int, char **);
82 static int zpool_do_attach(int, char **);
83 static int zpool_do_detach(int, char **);
84 static int zpool_do_replace(int, char **);
85 static int zpool_do_split(int, char **);
87 static int zpool_do_scrub(int, char **);
89 static int zpool_do_import(int, char **);
90 static int zpool_do_export(int, char **);
92 static int zpool_do_upgrade(int, char **);
94 static int zpool_do_history(int, char **);
96 static int zpool_do_get(int, char **);
97 static int zpool_do_set(int, char **);
100 * These libumem hooks provide a reasonable set of defaults for the allocator's
101 * debugging facilities.
104 #ifdef DEBUG
105 const char *
106 _umem_debug_init(void)
108 return ("default,verbose"); /* $UMEM_DEBUG setting */
111 const char *
112 _umem_logging_init(void)
114 return ("fail,contents"); /* $UMEM_LOGGING setting */
116 #endif
118 typedef enum {
119 HELP_ADD,
120 HELP_ATTACH,
121 HELP_CLEAR,
122 HELP_CREATE,
123 HELP_CHECKPOINT,
124 HELP_DESTROY,
125 HELP_DETACH,
126 HELP_EXPORT,
127 HELP_HISTORY,
128 HELP_IMPORT,
129 HELP_IOSTAT,
130 HELP_LABELCLEAR,
131 HELP_LIST,
132 HELP_OFFLINE,
133 HELP_ONLINE,
134 HELP_REPLACE,
135 HELP_REMOVE,
136 HELP_SCRUB,
137 HELP_STATUS,
138 HELP_UPGRADE,
139 HELP_GET,
140 HELP_SET,
141 HELP_SPLIT,
142 HELP_REGUID,
143 HELP_REOPEN
144 } zpool_help_t;
147 typedef struct zpool_command {
148 const char *name;
149 int (*func)(int, char **);
150 zpool_help_t usage;
151 } zpool_command_t;
154 * Master command table. Each ZFS command has a name, associated function, and
155 * usage message. The usage messages need to be internationalized, so we have
156 * to have a function to return the usage message based on a command index.
158 * These commands are organized according to how they are displayed in the usage
159 * message. An empty command (one with a NULL name) indicates an empty line in
160 * the generic usage message.
162 static zpool_command_t command_table[] = {
163 { "create", zpool_do_create, HELP_CREATE },
164 { "destroy", zpool_do_destroy, HELP_DESTROY },
165 { NULL },
166 { "add", zpool_do_add, HELP_ADD },
167 { "remove", zpool_do_remove, HELP_REMOVE },
168 { NULL },
169 { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR },
170 { NULL },
171 { "checkpoint", zpool_do_checkpoint, HELP_CHECKPOINT },
172 { NULL },
173 { "list", zpool_do_list, HELP_LIST },
174 { "iostat", zpool_do_iostat, HELP_IOSTAT },
175 { "status", zpool_do_status, HELP_STATUS },
176 { NULL },
177 { "online", zpool_do_online, HELP_ONLINE },
178 { "offline", zpool_do_offline, HELP_OFFLINE },
179 { "clear", zpool_do_clear, HELP_CLEAR },
180 { "reopen", zpool_do_reopen, HELP_REOPEN },
181 { NULL },
182 { "attach", zpool_do_attach, HELP_ATTACH },
183 { "detach", zpool_do_detach, HELP_DETACH },
184 { "replace", zpool_do_replace, HELP_REPLACE },
185 { "split", zpool_do_split, HELP_SPLIT },
186 { NULL },
187 { "scrub", zpool_do_scrub, HELP_SCRUB },
188 { NULL },
189 { "import", zpool_do_import, HELP_IMPORT },
190 { "export", zpool_do_export, HELP_EXPORT },
191 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
192 { "reguid", zpool_do_reguid, HELP_REGUID },
193 { NULL },
194 { "history", zpool_do_history, HELP_HISTORY },
195 { "get", zpool_do_get, HELP_GET },
196 { "set", zpool_do_set, HELP_SET },
199 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
201 static zpool_command_t *current_command;
202 static char history_str[HIS_MAX_RECORD_LEN];
203 static boolean_t log_history = B_TRUE;
204 static uint_t timestamp_fmt = NODATE;
206 static const char *
207 get_usage(zpool_help_t idx)
209 switch (idx) {
210 case HELP_ADD:
211 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
212 case HELP_ATTACH:
213 return (gettext("\tattach [-f] <pool> <device> "
214 "<new-device>\n"));
215 case HELP_CLEAR:
216 return (gettext("\tclear [-nF] <pool> [device]\n"));
217 case HELP_CREATE:
218 return (gettext("\tcreate [-fnd] [-B] "
219 "[-o property=value] ... \n"
220 "\t [-O file-system-property=value] ... \n"
221 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
222 case HELP_CHECKPOINT:
223 return (gettext("\tcheckpoint [--discard] <pool> ...\n"));
224 case HELP_DESTROY:
225 return (gettext("\tdestroy [-f] <pool>\n"));
226 case HELP_DETACH:
227 return (gettext("\tdetach <pool> <device>\n"));
228 case HELP_EXPORT:
229 return (gettext("\texport [-f] <pool> ...\n"));
230 case HELP_HISTORY:
231 return (gettext("\thistory [-il] [<pool>] ...\n"));
232 case HELP_IMPORT:
233 return (gettext("\timport [-d dir] [-D]\n"
234 "\timport [-o mntopts] [-o property=value] ... \n"
235 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
236 "[-R root] [-F [-n]] -a\n"
237 "\timport [-o mntopts] [-o property=value] ... \n"
238 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
239 "[-R root] [-F [-n]]\n"
240 "\t [--rewind-to-checkpoint] <pool | id> [newpool]\n"));
241 case HELP_IOSTAT:
242 return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
243 "[count]]\n"));
244 case HELP_LABELCLEAR:
245 return (gettext("\tlabelclear [-f] <vdev>\n"));
246 case HELP_LIST:
247 return (gettext("\tlist [-Hp] [-o property[,...]] "
248 "[-T d|u] [pool] ... [interval [count]]\n"));
249 case HELP_OFFLINE:
250 return (gettext("\toffline [-t] <pool> <device> ...\n"));
251 case HELP_ONLINE:
252 return (gettext("\tonline <pool> <device> ...\n"));
253 case HELP_REPLACE:
254 return (gettext("\treplace [-f] <pool> <device> "
255 "[new-device]\n"));
256 case HELP_REMOVE:
257 return (gettext("\tremove [-nps] <pool> <device> ...\n"));
258 case HELP_REOPEN:
259 return (gettext("\treopen <pool>\n"));
260 case HELP_SCRUB:
261 return (gettext("\tscrub [-s | -p] <pool> ...\n"));
262 case HELP_STATUS:
263 return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
264 "[count]]\n"));
265 case HELP_UPGRADE:
266 return (gettext("\tupgrade\n"
267 "\tupgrade -v\n"
268 "\tupgrade [-V version] <-a | pool ...>\n"));
269 case HELP_GET:
270 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
271 "<\"all\" | property[,...]> <pool> ...\n"));
272 case HELP_SET:
273 return (gettext("\tset <property=value> <pool> \n"));
274 case HELP_SPLIT:
275 return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
276 "\t [-o property=value] <pool> <newpool> "
277 "[<device> ...]\n"));
278 case HELP_REGUID:
279 return (gettext("\treguid <pool>\n"));
282 abort();
283 /* NOTREACHED */
288 * Callback routine that will print out a pool property value.
290 static int
291 print_prop_cb(int prop, void *cb)
293 FILE *fp = cb;
295 (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop));
297 if (zpool_prop_readonly(prop))
298 (void) fprintf(fp, " NO ");
299 else
300 (void) fprintf(fp, " YES ");
302 if (zpool_prop_values(prop) == NULL)
303 (void) fprintf(fp, "-\n");
304 else
305 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
307 return (ZPROP_CONT);
311 * Display usage message. If we're inside a command, display only the usage for
312 * that command. Otherwise, iterate over the entire command table and display
313 * a complete usage message.
315 void
316 usage(boolean_t requested)
318 FILE *fp = requested ? stdout : stderr;
320 if (current_command == NULL) {
321 int i;
323 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
324 (void) fprintf(fp,
325 gettext("where 'command' is one of the following:\n\n"));
327 for (i = 0; i < NCOMMAND; i++) {
328 if (command_table[i].name == NULL)
329 (void) fprintf(fp, "\n");
330 else
331 (void) fprintf(fp, "%s",
332 get_usage(command_table[i].usage));
334 } else {
335 (void) fprintf(fp, gettext("usage:\n"));
336 (void) fprintf(fp, "%s", get_usage(current_command->usage));
339 if (current_command != NULL &&
340 ((strcmp(current_command->name, "set") == 0) ||
341 (strcmp(current_command->name, "get") == 0) ||
342 (strcmp(current_command->name, "list") == 0))) {
344 (void) fprintf(fp,
345 gettext("\nthe following properties are supported:\n"));
347 (void) fprintf(fp, "\n\t%-15s %s %s\n\n",
348 "PROPERTY", "EDIT", "VALUES");
350 /* Iterate over all properties */
351 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
352 ZFS_TYPE_POOL);
354 (void) fprintf(fp, "\t%-15s ", "feature@...");
355 (void) fprintf(fp, "YES disabled | enabled | active\n");
357 (void) fprintf(fp, gettext("\nThe feature@ properties must be "
358 "appended with a feature name.\nSee zpool-features(5).\n"));
362 * See comments at end of main().
364 if (getenv("ZFS_ABORT") != NULL) {
365 (void) printf("dumping core by request\n");
366 abort();
369 exit(requested ? 0 : 2);
372 void
373 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
374 boolean_t print_logs)
376 nvlist_t **child;
377 uint_t c, children;
378 char *vname;
380 if (name != NULL)
381 (void) printf("\t%*s%s\n", indent, "", name);
383 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
384 &child, &children) != 0)
385 return;
387 for (c = 0; c < children; c++) {
388 uint64_t is_log = B_FALSE;
390 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
391 &is_log);
392 if ((is_log && !print_logs) || (!is_log && print_logs))
393 continue;
395 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
396 print_vdev_tree(zhp, vname, child[c], indent + 2,
397 B_FALSE);
398 free(vname);
402 static boolean_t
403 prop_list_contains_feature(nvlist_t *proplist)
405 nvpair_t *nvp;
406 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
407 nvp = nvlist_next_nvpair(proplist, nvp)) {
408 if (zpool_prop_feature(nvpair_name(nvp)))
409 return (B_TRUE);
411 return (B_FALSE);
415 * Add a property pair (name, string-value) into a property nvlist.
417 static int
418 add_prop_list(const char *propname, char *propval, nvlist_t **props,
419 boolean_t poolprop)
421 zpool_prop_t prop = ZPOOL_PROP_INVAL;
422 zfs_prop_t fprop;
423 nvlist_t *proplist;
424 const char *normnm;
425 char *strval;
427 if (*props == NULL &&
428 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
429 (void) fprintf(stderr,
430 gettext("internal error: out of memory\n"));
431 return (1);
434 proplist = *props;
436 if (poolprop) {
437 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
439 if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL &&
440 !zpool_prop_feature(propname)) {
441 (void) fprintf(stderr, gettext("property '%s' is "
442 "not a valid pool property\n"), propname);
443 return (2);
447 * feature@ properties and version should not be specified
448 * at the same time.
450 if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
451 nvlist_exists(proplist, vname)) ||
452 (prop == ZPOOL_PROP_VERSION &&
453 prop_list_contains_feature(proplist))) {
454 (void) fprintf(stderr, gettext("'feature@' and "
455 "'version' properties cannot be specified "
456 "together\n"));
457 return (2);
461 if (zpool_prop_feature(propname))
462 normnm = propname;
463 else
464 normnm = zpool_prop_to_name(prop);
465 } else {
466 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
467 normnm = zfs_prop_to_name(fprop);
468 } else {
469 normnm = propname;
473 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
474 prop != ZPOOL_PROP_CACHEFILE) {
475 (void) fprintf(stderr, gettext("property '%s' "
476 "specified multiple times\n"), propname);
477 return (2);
480 if (nvlist_add_string(proplist, normnm, propval) != 0) {
481 (void) fprintf(stderr, gettext("internal "
482 "error: out of memory\n"));
483 return (1);
486 return (0);
490 * zpool add [-fn] <pool> <vdev> ...
492 * -f Force addition of devices, even if they appear in use
493 * -n Do not add the devices, but display the resulting layout if
494 * they were to be added.
496 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
497 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
498 * libzfs.
501 zpool_do_add(int argc, char **argv)
503 boolean_t force = B_FALSE;
504 boolean_t dryrun = B_FALSE;
505 int c;
506 nvlist_t *nvroot;
507 char *poolname;
508 zpool_boot_label_t boot_type;
509 uint64_t boot_size;
510 int ret;
511 zpool_handle_t *zhp;
512 nvlist_t *config;
514 /* check options */
515 while ((c = getopt(argc, argv, "fn")) != -1) {
516 switch (c) {
517 case 'f':
518 force = B_TRUE;
519 break;
520 case 'n':
521 dryrun = B_TRUE;
522 break;
523 case '?':
524 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
525 optopt);
526 usage(B_FALSE);
530 argc -= optind;
531 argv += optind;
533 /* get pool name and check number of arguments */
534 if (argc < 1) {
535 (void) fprintf(stderr, gettext("missing pool name argument\n"));
536 usage(B_FALSE);
538 if (argc < 2) {
539 (void) fprintf(stderr, gettext("missing vdev specification\n"));
540 usage(B_FALSE);
543 poolname = argv[0];
545 argc--;
546 argv++;
548 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
549 return (1);
551 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
552 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
553 poolname);
554 zpool_close(zhp);
555 return (1);
558 if (zpool_is_bootable(zhp))
559 boot_type = ZPOOL_COPY_BOOT_LABEL;
560 else
561 boot_type = ZPOOL_NO_BOOT_LABEL;
563 /* pass off to get_vdev_spec for processing */
564 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
565 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
566 boot_type, boot_size, argc, argv);
567 if (nvroot == NULL) {
568 zpool_close(zhp);
569 return (1);
572 if (dryrun) {
573 nvlist_t *poolnvroot;
575 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
576 &poolnvroot) == 0);
578 (void) printf(gettext("would update '%s' to the following "
579 "configuration:\n"), zpool_get_name(zhp));
581 /* print original main pool and new tree */
582 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
583 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
585 /* Do the same for the logs */
586 if (num_logs(poolnvroot) > 0) {
587 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
588 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
589 } else if (num_logs(nvroot) > 0) {
590 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
593 ret = 0;
594 } else {
595 ret = (zpool_add(zhp, nvroot) != 0);
598 nvlist_free(nvroot);
599 zpool_close(zhp);
601 return (ret);
605 * zpool remove <pool> <vdev> ...
607 * Removes the given vdev from the pool.
610 zpool_do_remove(int argc, char **argv)
612 char *poolname;
613 int i, ret = 0;
614 zpool_handle_t *zhp;
615 boolean_t stop = B_FALSE;
616 boolean_t noop = B_FALSE;
617 boolean_t parsable = B_FALSE;
618 char c;
620 /* check options */
621 while ((c = getopt(argc, argv, "nps")) != -1) {
622 switch (c) {
623 case 'n':
624 noop = B_TRUE;
625 break;
626 case 'p':
627 parsable = B_TRUE;
628 break;
629 case 's':
630 stop = B_TRUE;
631 break;
632 case '?':
633 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
634 optopt);
635 usage(B_FALSE);
639 argc -= optind;
640 argv += optind;
642 /* get pool name and check number of arguments */
643 if (argc < 1) {
644 (void) fprintf(stderr, gettext("missing pool name argument\n"));
645 usage(B_FALSE);
648 poolname = argv[0];
650 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
651 return (1);
653 if (stop && noop) {
654 (void) fprintf(stderr, gettext("stop request ignored\n"));
655 return (0);
658 if (stop) {
659 if (argc > 1) {
660 (void) fprintf(stderr, gettext("too many arguments\n"));
661 usage(B_FALSE);
663 if (zpool_vdev_remove_cancel(zhp) != 0)
664 ret = 1;
665 } else {
666 if (argc < 2) {
667 (void) fprintf(stderr, gettext("missing device\n"));
668 usage(B_FALSE);
671 for (i = 1; i < argc; i++) {
672 if (noop) {
673 uint64_t size;
675 if (zpool_vdev_indirect_size(zhp, argv[i],
676 &size) != 0) {
677 ret = 1;
678 break;
680 if (parsable) {
681 (void) printf("%s %llu\n",
682 argv[i], size);
683 } else {
684 char valstr[32];
685 zfs_nicenum(size, valstr,
686 sizeof (valstr));
687 (void) printf("Memory that will be "
688 "used after removing %s: %s\n",
689 argv[i], valstr);
691 } else {
692 if (zpool_vdev_remove(zhp, argv[i]) != 0)
693 ret = 1;
698 return (ret);
702 * zpool labelclear [-f] <vdev>
704 * -f Force clearing the label for the vdevs which are members of
705 * the exported or foreign pools.
707 * Verifies that the vdev is not active and zeros out the label information
708 * on the device.
711 zpool_do_labelclear(int argc, char **argv)
713 char vdev[MAXPATHLEN];
714 char *name = NULL;
715 struct stat st;
716 int c, fd, ret = 0;
717 nvlist_t *config;
718 pool_state_t state;
719 boolean_t inuse = B_FALSE;
720 boolean_t force = B_FALSE;
722 /* check options */
723 while ((c = getopt(argc, argv, "f")) != -1) {
724 switch (c) {
725 case 'f':
726 force = B_TRUE;
727 break;
728 default:
729 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
730 optopt);
731 usage(B_FALSE);
735 argc -= optind;
736 argv += optind;
738 /* get vdev name */
739 if (argc < 1) {
740 (void) fprintf(stderr, gettext("missing vdev name\n"));
741 usage(B_FALSE);
743 if (argc > 1) {
744 (void) fprintf(stderr, gettext("too many arguments\n"));
745 usage(B_FALSE);
749 * Check if we were given absolute path and use it as is.
750 * Otherwise if the provided vdev name doesn't point to a file,
751 * try prepending dsk path and appending s0.
753 (void) strlcpy(vdev, argv[0], sizeof (vdev));
754 if (vdev[0] != '/' && stat(vdev, &st) != 0) {
755 char *s;
757 (void) snprintf(vdev, sizeof (vdev), "%s/%s",
758 ZFS_DISK_ROOT, argv[0]);
759 if ((s = strrchr(argv[0], 's')) == NULL ||
760 !isdigit(*(s + 1)))
761 (void) strlcat(vdev, "s0", sizeof (vdev));
762 if (stat(vdev, &st) != 0) {
763 (void) fprintf(stderr, gettext(
764 "failed to find device %s, try specifying absolute "
765 "path instead\n"), argv[0]);
766 return (1);
770 if ((fd = open(vdev, O_RDWR)) < 0) {
771 (void) fprintf(stderr, gettext("failed to open %s: %s\n"),
772 vdev, strerror(errno));
773 return (1);
776 if (zpool_read_label(fd, &config) != 0) {
777 (void) fprintf(stderr,
778 gettext("failed to read label from %s\n"), vdev);
779 return (1);
781 nvlist_free(config);
783 ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse);
784 if (ret != 0) {
785 (void) fprintf(stderr,
786 gettext("failed to check state for %s\n"), vdev);
787 return (1);
790 if (!inuse)
791 goto wipe_label;
793 switch (state) {
794 default:
795 case POOL_STATE_ACTIVE:
796 case POOL_STATE_SPARE:
797 case POOL_STATE_L2CACHE:
798 (void) fprintf(stderr, gettext(
799 "%s is a member (%s) of pool \"%s\"\n"),
800 vdev, zpool_pool_state_to_name(state), name);
801 ret = 1;
802 goto errout;
804 case POOL_STATE_EXPORTED:
805 if (force)
806 break;
807 (void) fprintf(stderr, gettext(
808 "use '-f' to override the following error:\n"
809 "%s is a member of exported pool \"%s\"\n"),
810 vdev, name);
811 ret = 1;
812 goto errout;
814 case POOL_STATE_POTENTIALLY_ACTIVE:
815 if (force)
816 break;
817 (void) fprintf(stderr, gettext(
818 "use '-f' to override the following error:\n"
819 "%s is a member of potentially active pool \"%s\"\n"),
820 vdev, name);
821 ret = 1;
822 goto errout;
824 case POOL_STATE_DESTROYED:
825 /* inuse should never be set for a destroyed pool */
826 assert(0);
827 break;
830 wipe_label:
831 ret = zpool_clear_label(fd);
832 if (ret != 0) {
833 (void) fprintf(stderr,
834 gettext("failed to clear label for %s\n"), vdev);
837 errout:
838 free(name);
839 (void) close(fd);
841 return (ret);
845 * zpool create [-fnd] [-B] [-o property=value] ...
846 * [-O file-system-property=value] ...
847 * [-R root] [-m mountpoint] <pool> <dev> ...
849 * -B Create boot partition.
850 * -f Force creation, even if devices appear in use
851 * -n Do not create the pool, but display the resulting layout if it
852 * were to be created.
853 * -R Create a pool under an alternate root
854 * -m Set default mountpoint for the root dataset. By default it's
855 * '/<pool>'
856 * -o Set property=value.
857 * -d Don't automatically enable all supported pool features
858 * (individual features can be enabled with -o).
859 * -O Set fsproperty=value in the pool's root file system
861 * Creates the named pool according to the given vdev specification. The
862 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once
863 * we get the nvlist back from get_vdev_spec(), we either print out the contents
864 * (if '-n' was specified), or pass it to libzfs to do the creation.
867 #define SYSTEM256 (256 * 1024 * 1024)
869 zpool_do_create(int argc, char **argv)
871 boolean_t force = B_FALSE;
872 boolean_t dryrun = B_FALSE;
873 boolean_t enable_all_pool_feat = B_TRUE;
874 zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL;
875 uint64_t boot_size = 0;
876 int c;
877 nvlist_t *nvroot = NULL;
878 char *poolname;
879 int ret = 1;
880 char *altroot = NULL;
881 char *mountpoint = NULL;
882 nvlist_t *fsprops = NULL;
883 nvlist_t *props = NULL;
884 char *propval;
886 /* check options */
887 while ((c = getopt(argc, argv, ":fndBR:m:o:O:")) != -1) {
888 switch (c) {
889 case 'f':
890 force = B_TRUE;
891 break;
892 case 'n':
893 dryrun = B_TRUE;
894 break;
895 case 'd':
896 enable_all_pool_feat = B_FALSE;
897 break;
898 case 'B':
900 * We should create the system partition.
901 * Also make sure the size is set.
903 boot_type = ZPOOL_CREATE_BOOT_LABEL;
904 if (boot_size == 0)
905 boot_size = SYSTEM256;
906 break;
907 case 'R':
908 altroot = optarg;
909 if (add_prop_list(zpool_prop_to_name(
910 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
911 goto errout;
912 if (nvlist_lookup_string(props,
913 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
914 &propval) == 0)
915 break;
916 if (add_prop_list(zpool_prop_to_name(
917 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
918 goto errout;
919 break;
920 case 'm':
921 /* Equivalent to -O mountpoint=optarg */
922 mountpoint = optarg;
923 break;
924 case 'o':
925 if ((propval = strchr(optarg, '=')) == NULL) {
926 (void) fprintf(stderr, gettext("missing "
927 "'=' for -o option\n"));
928 goto errout;
930 *propval = '\0';
931 propval++;
933 if (add_prop_list(optarg, propval, &props, B_TRUE))
934 goto errout;
937 * Get bootsize value for make_root_vdev().
939 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) {
940 if (zfs_nicestrtonum(g_zfs, propval,
941 &boot_size) < 0 || boot_size == 0) {
942 (void) fprintf(stderr,
943 gettext("bad boot partition size "
944 "'%s': %s\n"), propval,
945 libzfs_error_description(g_zfs));
946 goto errout;
951 * If the user is creating a pool that doesn't support
952 * feature flags, don't enable any features.
954 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
955 char *end;
956 u_longlong_t ver;
958 ver = strtoull(propval, &end, 10);
959 if (*end == '\0' &&
960 ver < SPA_VERSION_FEATURES) {
961 enable_all_pool_feat = B_FALSE;
964 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
965 altroot = propval;
966 break;
967 case 'O':
968 if ((propval = strchr(optarg, '=')) == NULL) {
969 (void) fprintf(stderr, gettext("missing "
970 "'=' for -O option\n"));
971 goto errout;
973 *propval = '\0';
974 propval++;
977 * Mountpoints are checked and then added later.
978 * Uniquely among properties, they can be specified
979 * more than once, to avoid conflict with -m.
981 if (0 == strcmp(optarg,
982 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
983 mountpoint = propval;
984 } else if (add_prop_list(optarg, propval, &fsprops,
985 B_FALSE)) {
986 goto errout;
988 break;
989 case ':':
990 (void) fprintf(stderr, gettext("missing argument for "
991 "'%c' option\n"), optopt);
992 goto badusage;
993 case '?':
994 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
995 optopt);
996 goto badusage;
1000 argc -= optind;
1001 argv += optind;
1003 /* get pool name and check number of arguments */
1004 if (argc < 1) {
1005 (void) fprintf(stderr, gettext("missing pool name argument\n"));
1006 goto badusage;
1008 if (argc < 2) {
1009 (void) fprintf(stderr, gettext("missing vdev specification\n"));
1010 goto badusage;
1013 poolname = argv[0];
1016 * As a special case, check for use of '/' in the name, and direct the
1017 * user to use 'zfs create' instead.
1019 if (strchr(poolname, '/') != NULL) {
1020 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
1021 "character '/' in pool name\n"), poolname);
1022 (void) fprintf(stderr, gettext("use 'zfs create' to "
1023 "create a dataset\n"));
1024 goto errout;
1028 * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used,
1029 * and not set otherwise.
1031 if (boot_type == ZPOOL_CREATE_BOOT_LABEL) {
1032 const char *propname;
1033 char *strptr, *buf = NULL;
1034 int rv;
1036 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1037 if (nvlist_lookup_string(props, propname, &strptr) != 0) {
1038 (void) asprintf(&buf, "%" PRIu64, boot_size);
1039 if (buf == NULL) {
1040 (void) fprintf(stderr,
1041 gettext("internal error: out of memory\n"));
1042 goto errout;
1044 rv = add_prop_list(propname, buf, &props, B_TRUE);
1045 free(buf);
1046 if (rv != 0)
1047 goto errout;
1049 } else {
1050 const char *propname;
1051 char *strptr;
1053 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1054 if (nvlist_lookup_string(props, propname, &strptr) == 0) {
1055 (void) fprintf(stderr, gettext("error: setting boot "
1056 "partition size requires option '-B'\n"));
1057 goto errout;
1061 /* pass off to get_vdev_spec for bulk processing */
1062 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
1063 boot_type, boot_size, argc - 1, argv + 1);
1064 if (nvroot == NULL)
1065 goto errout;
1067 /* make_root_vdev() allows 0 toplevel children if there are spares */
1068 if (!zfs_allocatable_devs(nvroot)) {
1069 (void) fprintf(stderr, gettext("invalid vdev "
1070 "specification: at least one toplevel vdev must be "
1071 "specified\n"));
1072 goto errout;
1075 if (altroot != NULL && altroot[0] != '/') {
1076 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
1077 "must be an absolute path\n"), altroot);
1078 goto errout;
1082 * Check the validity of the mountpoint and direct the user to use the
1083 * '-m' mountpoint option if it looks like its in use.
1085 if (mountpoint == NULL ||
1086 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
1087 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
1088 char buf[MAXPATHLEN];
1089 DIR *dirp;
1091 if (mountpoint && mountpoint[0] != '/') {
1092 (void) fprintf(stderr, gettext("invalid mountpoint "
1093 "'%s': must be an absolute path, 'legacy', or "
1094 "'none'\n"), mountpoint);
1095 goto errout;
1098 if (mountpoint == NULL) {
1099 if (altroot != NULL)
1100 (void) snprintf(buf, sizeof (buf), "%s/%s",
1101 altroot, poolname);
1102 else
1103 (void) snprintf(buf, sizeof (buf), "/%s",
1104 poolname);
1105 } else {
1106 if (altroot != NULL)
1107 (void) snprintf(buf, sizeof (buf), "%s%s",
1108 altroot, mountpoint);
1109 else
1110 (void) snprintf(buf, sizeof (buf), "%s",
1111 mountpoint);
1114 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
1115 (void) fprintf(stderr, gettext("mountpoint '%s' : "
1116 "%s\n"), buf, strerror(errno));
1117 (void) fprintf(stderr, gettext("use '-m' "
1118 "option to provide a different default\n"));
1119 goto errout;
1120 } else if (dirp) {
1121 int count = 0;
1123 while (count < 3 && readdir(dirp) != NULL)
1124 count++;
1125 (void) closedir(dirp);
1127 if (count > 2) {
1128 (void) fprintf(stderr, gettext("mountpoint "
1129 "'%s' exists and is not empty\n"), buf);
1130 (void) fprintf(stderr, gettext("use '-m' "
1131 "option to provide a "
1132 "different default\n"));
1133 goto errout;
1139 * Now that the mountpoint's validity has been checked, ensure that
1140 * the property is set appropriately prior to creating the pool.
1142 if (mountpoint != NULL) {
1143 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
1144 mountpoint, &fsprops, B_FALSE);
1145 if (ret != 0)
1146 goto errout;
1149 ret = 1;
1150 if (dryrun) {
1152 * For a dry run invocation, print out a basic message and run
1153 * through all the vdevs in the list and print out in an
1154 * appropriate hierarchy.
1156 (void) printf(gettext("would create '%s' with the "
1157 "following layout:\n\n"), poolname);
1159 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
1160 if (num_logs(nvroot) > 0)
1161 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
1163 ret = 0;
1164 } else {
1166 * Hand off to libzfs.
1168 if (enable_all_pool_feat) {
1169 spa_feature_t i;
1170 for (i = 0; i < SPA_FEATURES; i++) {
1171 char propname[MAXPATHLEN];
1172 zfeature_info_t *feat = &spa_feature_table[i];
1174 (void) snprintf(propname, sizeof (propname),
1175 "feature@%s", feat->fi_uname);
1178 * Skip feature if user specified it manually
1179 * on the command line.
1181 if (nvlist_exists(props, propname))
1182 continue;
1184 ret = add_prop_list(propname,
1185 ZFS_FEATURE_ENABLED, &props, B_TRUE);
1186 if (ret != 0)
1187 goto errout;
1191 ret = 1;
1192 if (zpool_create(g_zfs, poolname,
1193 nvroot, props, fsprops) == 0) {
1194 zfs_handle_t *pool = zfs_open(g_zfs, poolname,
1195 ZFS_TYPE_FILESYSTEM);
1196 if (pool != NULL) {
1197 if (zfs_mount(pool, NULL, 0) == 0)
1198 ret = zfs_shareall(pool);
1199 zfs_close(pool);
1201 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
1202 (void) fprintf(stderr, gettext("pool name may have "
1203 "been omitted\n"));
1207 errout:
1208 nvlist_free(nvroot);
1209 nvlist_free(fsprops);
1210 nvlist_free(props);
1211 return (ret);
1212 badusage:
1213 nvlist_free(fsprops);
1214 nvlist_free(props);
1215 usage(B_FALSE);
1216 return (2);
1220 * zpool destroy <pool>
1222 * -f Forcefully unmount any datasets
1224 * Destroy the given pool. Automatically unmounts any datasets in the pool.
1227 zpool_do_destroy(int argc, char **argv)
1229 boolean_t force = B_FALSE;
1230 int c;
1231 char *pool;
1232 zpool_handle_t *zhp;
1233 int ret;
1235 /* check options */
1236 while ((c = getopt(argc, argv, "f")) != -1) {
1237 switch (c) {
1238 case 'f':
1239 force = B_TRUE;
1240 break;
1241 case '?':
1242 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1243 optopt);
1244 usage(B_FALSE);
1248 argc -= optind;
1249 argv += optind;
1251 /* check arguments */
1252 if (argc < 1) {
1253 (void) fprintf(stderr, gettext("missing pool argument\n"));
1254 usage(B_FALSE);
1256 if (argc > 1) {
1257 (void) fprintf(stderr, gettext("too many arguments\n"));
1258 usage(B_FALSE);
1261 pool = argv[0];
1263 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1265 * As a special case, check for use of '/' in the name, and
1266 * direct the user to use 'zfs destroy' instead.
1268 if (strchr(pool, '/') != NULL)
1269 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1270 "destroy a dataset\n"));
1271 return (1);
1274 if (zpool_disable_datasets(zhp, force) != 0) {
1275 (void) fprintf(stderr, gettext("could not destroy '%s': "
1276 "could not unmount datasets\n"), zpool_get_name(zhp));
1277 return (1);
1280 /* The history must be logged as part of the export */
1281 log_history = B_FALSE;
1283 ret = (zpool_destroy(zhp, history_str) != 0);
1285 zpool_close(zhp);
1287 return (ret);
1291 * zpool export [-f] <pool> ...
1293 * -f Forcefully unmount datasets
1295 * Export the given pools. By default, the command will attempt to cleanly
1296 * unmount any active datasets within the pool. If the '-f' flag is specified,
1297 * then the datasets will be forcefully unmounted.
1300 zpool_do_export(int argc, char **argv)
1302 boolean_t force = B_FALSE;
1303 boolean_t hardforce = B_FALSE;
1304 int c;
1305 zpool_handle_t *zhp;
1306 int ret;
1307 int i;
1309 /* check options */
1310 while ((c = getopt(argc, argv, "fF")) != -1) {
1311 switch (c) {
1312 case 'f':
1313 force = B_TRUE;
1314 break;
1315 case 'F':
1316 hardforce = B_TRUE;
1317 break;
1318 case '?':
1319 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1320 optopt);
1321 usage(B_FALSE);
1325 argc -= optind;
1326 argv += optind;
1328 /* check arguments */
1329 if (argc < 1) {
1330 (void) fprintf(stderr, gettext("missing pool argument\n"));
1331 usage(B_FALSE);
1334 ret = 0;
1335 for (i = 0; i < argc; i++) {
1336 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1337 ret = 1;
1338 continue;
1341 if (zpool_disable_datasets(zhp, force) != 0) {
1342 ret = 1;
1343 zpool_close(zhp);
1344 continue;
1347 /* The history must be logged as part of the export */
1348 log_history = B_FALSE;
1350 if (hardforce) {
1351 if (zpool_export_force(zhp, history_str) != 0)
1352 ret = 1;
1353 } else if (zpool_export(zhp, force, history_str) != 0) {
1354 ret = 1;
1357 zpool_close(zhp);
1360 return (ret);
1364 * Given a vdev configuration, determine the maximum width needed for the device
1365 * name column.
1367 static int
1368 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
1370 char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
1371 nvlist_t **child;
1372 uint_t c, children;
1373 int ret;
1375 if (strlen(name) + depth > max)
1376 max = strlen(name) + depth;
1378 free(name);
1380 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1381 &child, &children) == 0) {
1382 for (c = 0; c < children; c++)
1383 if ((ret = max_width(zhp, child[c], depth + 2,
1384 max)) > max)
1385 max = ret;
1388 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1389 &child, &children) == 0) {
1390 for (c = 0; c < children; c++)
1391 if ((ret = max_width(zhp, child[c], depth + 2,
1392 max)) > max)
1393 max = ret;
1396 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1397 &child, &children) == 0) {
1398 for (c = 0; c < children; c++)
1399 if ((ret = max_width(zhp, child[c], depth + 2,
1400 max)) > max)
1401 max = ret;
1405 return (max);
1408 typedef struct spare_cbdata {
1409 uint64_t cb_guid;
1410 zpool_handle_t *cb_zhp;
1411 } spare_cbdata_t;
1413 static boolean_t
1414 find_vdev(nvlist_t *nv, uint64_t search)
1416 uint64_t guid;
1417 nvlist_t **child;
1418 uint_t c, children;
1420 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
1421 search == guid)
1422 return (B_TRUE);
1424 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1425 &child, &children) == 0) {
1426 for (c = 0; c < children; c++)
1427 if (find_vdev(child[c], search))
1428 return (B_TRUE);
1431 return (B_FALSE);
1434 static int
1435 find_spare(zpool_handle_t *zhp, void *data)
1437 spare_cbdata_t *cbp = data;
1438 nvlist_t *config, *nvroot;
1440 config = zpool_get_config(zhp, NULL);
1441 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1442 &nvroot) == 0);
1444 if (find_vdev(nvroot, cbp->cb_guid)) {
1445 cbp->cb_zhp = zhp;
1446 return (1);
1449 zpool_close(zhp);
1450 return (0);
1454 * Print out configuration state as requested by status_callback.
1456 void
1457 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
1458 int namewidth, int depth, boolean_t isspare)
1460 nvlist_t **child;
1461 uint_t c, children;
1462 pool_scan_stat_t *ps = NULL;
1463 vdev_stat_t *vs;
1464 char rbuf[6], wbuf[6], cbuf[6];
1465 char *vname;
1466 uint64_t notpresent;
1467 spare_cbdata_t cb;
1468 const char *state;
1469 char *type;
1471 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1472 &child, &children) != 0)
1473 children = 0;
1475 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1476 (uint64_t **)&vs, &c) == 0);
1478 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1480 if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
1481 return;
1483 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1484 if (isspare) {
1486 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1487 * online drives.
1489 if (vs->vs_aux == VDEV_AUX_SPARED)
1490 state = "INUSE";
1491 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1492 state = "AVAIL";
1495 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth,
1496 name, state);
1498 if (!isspare) {
1499 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1500 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1501 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1502 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1505 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
1506 &notpresent) == 0) {
1507 char *path;
1508 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
1509 (void) printf(" was %s", path);
1510 } else if (vs->vs_aux != 0) {
1511 (void) printf(" ");
1513 switch (vs->vs_aux) {
1514 case VDEV_AUX_OPEN_FAILED:
1515 (void) printf(gettext("cannot open"));
1516 break;
1518 case VDEV_AUX_BAD_GUID_SUM:
1519 (void) printf(gettext("missing device"));
1520 break;
1522 case VDEV_AUX_NO_REPLICAS:
1523 (void) printf(gettext("insufficient replicas"));
1524 break;
1526 case VDEV_AUX_VERSION_NEWER:
1527 (void) printf(gettext("newer version"));
1528 break;
1530 case VDEV_AUX_UNSUP_FEAT:
1531 (void) printf(gettext("unsupported feature(s)"));
1532 break;
1534 case VDEV_AUX_SPARED:
1535 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1536 &cb.cb_guid) == 0);
1537 if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
1538 if (strcmp(zpool_get_name(cb.cb_zhp),
1539 zpool_get_name(zhp)) == 0)
1540 (void) printf(gettext("currently in "
1541 "use"));
1542 else
1543 (void) printf(gettext("in use by "
1544 "pool '%s'"),
1545 zpool_get_name(cb.cb_zhp));
1546 zpool_close(cb.cb_zhp);
1547 } else {
1548 (void) printf(gettext("currently in use"));
1550 break;
1552 case VDEV_AUX_ERR_EXCEEDED:
1553 (void) printf(gettext("too many errors"));
1554 break;
1556 case VDEV_AUX_IO_FAILURE:
1557 (void) printf(gettext("experienced I/O failures"));
1558 break;
1560 case VDEV_AUX_BAD_LOG:
1561 (void) printf(gettext("bad intent log"));
1562 break;
1564 case VDEV_AUX_EXTERNAL:
1565 (void) printf(gettext("external device fault"));
1566 break;
1568 case VDEV_AUX_SPLIT_POOL:
1569 (void) printf(gettext("split into new pool"));
1570 break;
1572 case VDEV_AUX_CHILDREN_OFFLINE:
1573 (void) printf(gettext("all children offline"));
1574 break;
1576 default:
1577 (void) printf(gettext("corrupted data"));
1578 break;
1582 (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1583 (uint64_t **)&ps, &c);
1585 if (ps && ps->pss_state == DSS_SCANNING &&
1586 vs->vs_scan_processed != 0 && children == 0) {
1587 (void) printf(gettext(" (%s)"),
1588 (ps->pss_func == POOL_SCAN_RESILVER) ?
1589 "resilvering" : "repairing");
1592 (void) printf("\n");
1594 for (c = 0; c < children; c++) {
1595 uint64_t islog = B_FALSE, ishole = B_FALSE;
1597 /* Don't print logs or holes here */
1598 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1599 &islog);
1600 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1601 &ishole);
1602 if (islog || ishole)
1603 continue;
1604 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1605 print_status_config(zhp, vname, child[c],
1606 namewidth, depth + 2, isspare);
1607 free(vname);
1613 * Print the configuration of an exported pool. Iterate over all vdevs in the
1614 * pool, printing out the name and status for each one.
1616 void
1617 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1619 nvlist_t **child;
1620 uint_t c, children;
1621 vdev_stat_t *vs;
1622 char *type, *vname;
1624 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1625 if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
1626 strcmp(type, VDEV_TYPE_HOLE) == 0)
1627 return;
1629 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1630 (uint64_t **)&vs, &c) == 0);
1632 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1633 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1635 if (vs->vs_aux != 0) {
1636 (void) printf(" ");
1638 switch (vs->vs_aux) {
1639 case VDEV_AUX_OPEN_FAILED:
1640 (void) printf(gettext("cannot open"));
1641 break;
1643 case VDEV_AUX_BAD_GUID_SUM:
1644 (void) printf(gettext("missing device"));
1645 break;
1647 case VDEV_AUX_NO_REPLICAS:
1648 (void) printf(gettext("insufficient replicas"));
1649 break;
1651 case VDEV_AUX_VERSION_NEWER:
1652 (void) printf(gettext("newer version"));
1653 break;
1655 case VDEV_AUX_UNSUP_FEAT:
1656 (void) printf(gettext("unsupported feature(s)"));
1657 break;
1659 case VDEV_AUX_ERR_EXCEEDED:
1660 (void) printf(gettext("too many errors"));
1661 break;
1663 case VDEV_AUX_CHILDREN_OFFLINE:
1664 (void) printf(gettext("all children offline"));
1665 break;
1667 default:
1668 (void) printf(gettext("corrupted data"));
1669 break;
1672 (void) printf("\n");
1674 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1675 &child, &children) != 0)
1676 return;
1678 for (c = 0; c < children; c++) {
1679 uint64_t is_log = B_FALSE;
1681 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1682 &is_log);
1683 if (is_log)
1684 continue;
1686 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1687 print_import_config(vname, child[c], namewidth, depth + 2);
1688 free(vname);
1691 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1692 &child, &children) == 0) {
1693 (void) printf(gettext("\tcache\n"));
1694 for (c = 0; c < children; c++) {
1695 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1696 (void) printf("\t %s\n", vname);
1697 free(vname);
1701 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1702 &child, &children) == 0) {
1703 (void) printf(gettext("\tspares\n"));
1704 for (c = 0; c < children; c++) {
1705 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1706 (void) printf("\t %s\n", vname);
1707 free(vname);
1713 * Print log vdevs.
1714 * Logs are recorded as top level vdevs in the main pool child array
1715 * but with "is_log" set to 1. We use either print_status_config() or
1716 * print_import_config() to print the top level logs then any log
1717 * children (eg mirrored slogs) are printed recursively - which
1718 * works because only the top level vdev is marked "is_log"
1720 static void
1721 print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose)
1723 uint_t c, children;
1724 nvlist_t **child;
1726 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1727 &children) != 0)
1728 return;
1730 (void) printf(gettext("\tlogs\n"));
1732 for (c = 0; c < children; c++) {
1733 uint64_t is_log = B_FALSE;
1734 char *name;
1736 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1737 &is_log);
1738 if (!is_log)
1739 continue;
1740 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1741 if (verbose)
1742 print_status_config(zhp, name, child[c], namewidth,
1743 2, B_FALSE);
1744 else
1745 print_import_config(name, child[c], namewidth, 2);
1746 free(name);
1751 * Display the status for the given pool.
1753 static void
1754 show_import(nvlist_t *config)
1756 uint64_t pool_state;
1757 vdev_stat_t *vs;
1758 char *name;
1759 uint64_t guid;
1760 char *msgid;
1761 nvlist_t *nvroot;
1762 int reason;
1763 const char *health;
1764 uint_t vsc;
1765 int namewidth;
1766 char *comment;
1768 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1769 &name) == 0);
1770 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1771 &guid) == 0);
1772 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1773 &pool_state) == 0);
1774 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1775 &nvroot) == 0);
1777 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
1778 (uint64_t **)&vs, &vsc) == 0);
1779 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1781 reason = zpool_import_status(config, &msgid);
1783 (void) printf(gettext(" pool: %s\n"), name);
1784 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
1785 (void) printf(gettext(" state: %s"), health);
1786 if (pool_state == POOL_STATE_DESTROYED)
1787 (void) printf(gettext(" (DESTROYED)"));
1788 (void) printf("\n");
1790 switch (reason) {
1791 case ZPOOL_STATUS_MISSING_DEV_R:
1792 case ZPOOL_STATUS_MISSING_DEV_NR:
1793 case ZPOOL_STATUS_BAD_GUID_SUM:
1794 (void) printf(gettext(" status: One or more devices are "
1795 "missing from the system.\n"));
1796 break;
1798 case ZPOOL_STATUS_CORRUPT_LABEL_R:
1799 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1800 (void) printf(gettext(" status: One or more devices contains "
1801 "corrupted data.\n"));
1802 break;
1804 case ZPOOL_STATUS_CORRUPT_DATA:
1805 (void) printf(
1806 gettext(" status: The pool data is corrupted.\n"));
1807 break;
1809 case ZPOOL_STATUS_OFFLINE_DEV:
1810 (void) printf(gettext(" status: One or more devices "
1811 "are offlined.\n"));
1812 break;
1814 case ZPOOL_STATUS_CORRUPT_POOL:
1815 (void) printf(gettext(" status: The pool metadata is "
1816 "corrupted.\n"));
1817 break;
1819 case ZPOOL_STATUS_VERSION_OLDER:
1820 (void) printf(gettext(" status: The pool is formatted using a "
1821 "legacy on-disk version.\n"));
1822 break;
1824 case ZPOOL_STATUS_VERSION_NEWER:
1825 (void) printf(gettext(" status: The pool is formatted using an "
1826 "incompatible version.\n"));
1827 break;
1829 case ZPOOL_STATUS_FEAT_DISABLED:
1830 (void) printf(gettext(" status: Some supported features are "
1831 "not enabled on the pool.\n"));
1832 break;
1834 case ZPOOL_STATUS_UNSUP_FEAT_READ:
1835 (void) printf(gettext("status: The pool uses the following "
1836 "feature(s) not supported on this system:\n"));
1837 zpool_print_unsup_feat(config);
1838 break;
1840 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1841 (void) printf(gettext("status: The pool can only be accessed "
1842 "in read-only mode on this system. It\n\tcannot be "
1843 "accessed in read-write mode because it uses the "
1844 "following\n\tfeature(s) not supported on this system:\n"));
1845 zpool_print_unsup_feat(config);
1846 break;
1848 case ZPOOL_STATUS_HOSTID_MISMATCH:
1849 (void) printf(gettext(" status: The pool was last accessed by "
1850 "another system.\n"));
1851 break;
1853 case ZPOOL_STATUS_FAULTED_DEV_R:
1854 case ZPOOL_STATUS_FAULTED_DEV_NR:
1855 (void) printf(gettext(" status: One or more devices are "
1856 "faulted.\n"));
1857 break;
1859 case ZPOOL_STATUS_BAD_LOG:
1860 (void) printf(gettext(" status: An intent log record cannot be "
1861 "read.\n"));
1862 break;
1864 case ZPOOL_STATUS_RESILVERING:
1865 (void) printf(gettext(" status: One or more devices were being "
1866 "resilvered.\n"));
1867 break;
1869 default:
1871 * No other status can be seen when importing pools.
1873 assert(reason == ZPOOL_STATUS_OK);
1877 * Print out an action according to the overall state of the pool.
1879 if (vs->vs_state == VDEV_STATE_HEALTHY) {
1880 if (reason == ZPOOL_STATUS_VERSION_OLDER ||
1881 reason == ZPOOL_STATUS_FEAT_DISABLED) {
1882 (void) printf(gettext(" action: The pool can be "
1883 "imported using its name or numeric identifier, "
1884 "though\n\tsome features will not be available "
1885 "without an explicit 'zpool upgrade'.\n"));
1886 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
1887 (void) printf(gettext(" action: The pool can be "
1888 "imported using its name or numeric "
1889 "identifier and\n\tthe '-f' flag.\n"));
1890 } else {
1891 (void) printf(gettext(" action: The pool can be "
1892 "imported using its name or numeric "
1893 "identifier.\n"));
1895 } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1896 (void) printf(gettext(" action: The pool can be imported "
1897 "despite missing or damaged devices. The\n\tfault "
1898 "tolerance of the pool may be compromised if imported.\n"));
1899 } else {
1900 switch (reason) {
1901 case ZPOOL_STATUS_VERSION_NEWER:
1902 (void) printf(gettext(" action: The pool cannot be "
1903 "imported. Access the pool on a system running "
1904 "newer\n\tsoftware, or recreate the pool from "
1905 "backup.\n"));
1906 break;
1907 case ZPOOL_STATUS_UNSUP_FEAT_READ:
1908 (void) printf(gettext("action: The pool cannot be "
1909 "imported. Access the pool on a system that "
1910 "supports\n\tthe required feature(s), or recreate "
1911 "the pool from backup.\n"));
1912 break;
1913 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1914 (void) printf(gettext("action: The pool cannot be "
1915 "imported in read-write mode. Import the pool "
1916 "with\n"
1917 "\t\"-o readonly=on\", access the pool on a system "
1918 "that supports the\n\trequired feature(s), or "
1919 "recreate the pool from backup.\n"));
1920 break;
1921 case ZPOOL_STATUS_MISSING_DEV_R:
1922 case ZPOOL_STATUS_MISSING_DEV_NR:
1923 case ZPOOL_STATUS_BAD_GUID_SUM:
1924 (void) printf(gettext(" action: The pool cannot be "
1925 "imported. Attach the missing\n\tdevices and try "
1926 "again.\n"));
1927 break;
1928 default:
1929 (void) printf(gettext(" action: The pool cannot be "
1930 "imported due to damaged devices or data.\n"));
1934 /* Print the comment attached to the pool. */
1935 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
1936 (void) printf(gettext("comment: %s\n"), comment);
1939 * If the state is "closed" or "can't open", and the aux state
1940 * is "corrupt data":
1942 if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1943 (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1944 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1945 if (pool_state == POOL_STATE_DESTROYED)
1946 (void) printf(gettext("\tThe pool was destroyed, "
1947 "but can be imported using the '-Df' flags.\n"));
1948 else if (pool_state != POOL_STATE_EXPORTED)
1949 (void) printf(gettext("\tThe pool may be active on "
1950 "another system, but can be imported using\n\t"
1951 "the '-f' flag.\n"));
1954 if (msgid != NULL)
1955 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
1956 msgid);
1958 (void) printf(gettext(" config:\n\n"));
1960 namewidth = max_width(NULL, nvroot, 0, 0);
1961 if (namewidth < 10)
1962 namewidth = 10;
1964 print_import_config(name, nvroot, namewidth, 0);
1965 if (num_logs(nvroot) > 0)
1966 print_logs(NULL, nvroot, namewidth, B_FALSE);
1968 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1969 (void) printf(gettext("\n\tAdditional devices are known to "
1970 "be part of this pool, though their\n\texact "
1971 "configuration cannot be determined.\n"));
1976 * Perform the import for the given configuration. This passes the heavy
1977 * lifting off to zpool_import_props(), and then mounts the datasets contained
1978 * within the pool.
1980 static int
1981 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1982 nvlist_t *props, int flags)
1984 zpool_handle_t *zhp;
1985 char *name;
1986 uint64_t state;
1987 uint64_t version;
1989 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1990 &name) == 0);
1992 verify(nvlist_lookup_uint64(config,
1993 ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1994 verify(nvlist_lookup_uint64(config,
1995 ZPOOL_CONFIG_VERSION, &version) == 0);
1996 if (!SPA_VERSION_IS_SUPPORTED(version)) {
1997 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1998 "is formatted using an unsupported ZFS version\n"), name);
1999 return (1);
2000 } else if (state != POOL_STATE_EXPORTED &&
2001 !(flags & ZFS_IMPORT_ANY_HOST)) {
2002 uint64_t hostid;
2004 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
2005 &hostid) == 0) {
2006 if ((unsigned long)hostid != gethostid()) {
2007 char *hostname;
2008 uint64_t timestamp;
2009 time_t t;
2011 verify(nvlist_lookup_string(config,
2012 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
2013 verify(nvlist_lookup_uint64(config,
2014 ZPOOL_CONFIG_TIMESTAMP, &timestamp) == 0);
2015 t = timestamp;
2016 (void) fprintf(stderr, gettext("cannot import "
2017 "'%s': pool may be in use from other "
2018 "system, it was last accessed by %s "
2019 "(hostid: 0x%lx) on %s"), name, hostname,
2020 (unsigned long)hostid,
2021 asctime(localtime(&t)));
2022 (void) fprintf(stderr, gettext("use '-f' to "
2023 "import anyway\n"));
2024 return (1);
2026 } else {
2027 (void) fprintf(stderr, gettext("cannot import '%s': "
2028 "pool may be in use from other system\n"), name);
2029 (void) fprintf(stderr, gettext("use '-f' to import "
2030 "anyway\n"));
2031 return (1);
2035 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2036 return (1);
2038 if (newname != NULL)
2039 name = (char *)newname;
2041 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2042 return (1);
2044 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2045 !(flags & ZFS_IMPORT_ONLY) &&
2046 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
2047 zpool_close(zhp);
2048 return (1);
2051 zpool_close(zhp);
2052 return (0);
2056 * zpool checkpoint <pool>
2057 * checkpoint --discard <pool>
2059 * -d Discard the checkpoint from a checkpointed
2060 * --discard pool.
2062 * Checkpoints the specified pool, by taking a "snapshot" of its
2063 * current state. A pool can only have one checkpoint at a time.
2066 zpool_do_checkpoint(int argc, char **argv)
2068 boolean_t discard;
2069 char *pool;
2070 zpool_handle_t *zhp;
2071 int c, err;
2073 struct option long_options[] = {
2074 {"discard", no_argument, NULL, 'd'},
2075 {0, 0, 0, 0}
2078 discard = B_FALSE;
2079 while ((c = getopt_long(argc, argv, ":d", long_options, NULL)) != -1) {
2080 switch (c) {
2081 case 'd':
2082 discard = B_TRUE;
2083 break;
2084 case '?':
2085 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2086 optopt);
2087 usage(B_FALSE);
2091 argc -= optind;
2092 argv += optind;
2094 if (argc < 1) {
2095 (void) fprintf(stderr, gettext("missing pool argument\n"));
2096 usage(B_FALSE);
2099 if (argc > 1) {
2100 (void) fprintf(stderr, gettext("too many arguments\n"));
2101 usage(B_FALSE);
2104 pool = argv[0];
2106 if ((zhp = zpool_open(g_zfs, pool)) == NULL) {
2107 /* As a special case, check for use of '/' in the name */
2108 if (strchr(pool, '/') != NULL)
2109 (void) fprintf(stderr, gettext("'zpool checkpoint' "
2110 "doesn't work on datasets. To save the state "
2111 "of a dataset from a specific point in time "
2112 "please use 'zfs snapshot'\n"));
2113 return (1);
2116 if (discard)
2117 err = (zpool_discard_checkpoint(zhp) != 0);
2118 else
2119 err = (zpool_checkpoint(zhp) != 0);
2121 zpool_close(zhp);
2123 return (err);
2126 #define CHECKPOINT_OPT 1024
2129 * zpool import [-d dir] [-D]
2130 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2131 * [-d dir | -c cachefile] [-f] -a
2132 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2133 * [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
2135 * -c Read pool information from a cachefile instead of searching
2136 * devices.
2138 * -d Scan in a specific directory, other than /dev/dsk. More than
2139 * one directory can be specified using multiple '-d' options.
2141 * -D Scan for previously destroyed pools or import all or only
2142 * specified destroyed pools.
2144 * -R Temporarily import the pool, with all mountpoints relative to
2145 * the given root. The pool will remain exported when the machine
2146 * is rebooted.
2148 * -V Import even in the presence of faulted vdevs. This is an
2149 * intentionally undocumented option for testing purposes, and
2150 * treats the pool configuration as complete, leaving any bad
2151 * vdevs in the FAULTED state. In other words, it does verbatim
2152 * import.
2154 * -f Force import, even if it appears that the pool is active.
2156 * -F Attempt rewind if necessary.
2158 * -n See if rewind would work, but don't actually rewind.
2160 * -N Import the pool but don't mount datasets.
2162 * -T Specify a starting txg to use for import. This option is
2163 * intentionally undocumented option for testing purposes.
2165 * -a Import all pools found.
2167 * -o Set property=value and/or temporary mount options (without '=').
2169 * --rewind-to-checkpoint
2170 * Import the pool and revert back to the checkpoint.
2172 * The import command scans for pools to import, and import pools based on pool
2173 * name and GUID. The pool can also be renamed as part of the import process.
2176 zpool_do_import(int argc, char **argv)
2178 char **searchdirs = NULL;
2179 int nsearch = 0;
2180 int c;
2181 int err = 0;
2182 nvlist_t *pools = NULL;
2183 boolean_t do_all = B_FALSE;
2184 boolean_t do_destroyed = B_FALSE;
2185 char *mntopts = NULL;
2186 nvpair_t *elem;
2187 nvlist_t *config;
2188 uint64_t searchguid = 0;
2189 char *searchname = NULL;
2190 char *propval;
2191 nvlist_t *found_config;
2192 nvlist_t *policy = NULL;
2193 nvlist_t *props = NULL;
2194 boolean_t first;
2195 int flags = ZFS_IMPORT_NORMAL;
2196 uint32_t rewind_policy = ZPOOL_NO_REWIND;
2197 boolean_t dryrun = B_FALSE;
2198 boolean_t do_rewind = B_FALSE;
2199 boolean_t xtreme_rewind = B_FALSE;
2200 uint64_t pool_state, txg = -1ULL;
2201 char *cachefile = NULL;
2202 importargs_t idata = { 0 };
2203 char *endptr;
2206 struct option long_options[] = {
2207 {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT},
2208 {0, 0, 0, 0}
2211 /* check options */
2212 while ((c = getopt_long(argc, argv, ":aCc:d:DEfFmnNo:rR:T:VX",
2213 long_options, NULL)) != -1) {
2214 switch (c) {
2215 case 'a':
2216 do_all = B_TRUE;
2217 break;
2218 case 'c':
2219 cachefile = optarg;
2220 break;
2221 case 'd':
2222 if (searchdirs == NULL) {
2223 searchdirs = safe_malloc(sizeof (char *));
2224 } else {
2225 char **tmp = safe_malloc((nsearch + 1) *
2226 sizeof (char *));
2227 bcopy(searchdirs, tmp, nsearch *
2228 sizeof (char *));
2229 free(searchdirs);
2230 searchdirs = tmp;
2232 searchdirs[nsearch++] = optarg;
2233 break;
2234 case 'D':
2235 do_destroyed = B_TRUE;
2236 break;
2237 case 'f':
2238 flags |= ZFS_IMPORT_ANY_HOST;
2239 break;
2240 case 'F':
2241 do_rewind = B_TRUE;
2242 break;
2243 case 'm':
2244 flags |= ZFS_IMPORT_MISSING_LOG;
2245 break;
2246 case 'n':
2247 dryrun = B_TRUE;
2248 break;
2249 case 'N':
2250 flags |= ZFS_IMPORT_ONLY;
2251 break;
2252 case 'o':
2253 if ((propval = strchr(optarg, '=')) != NULL) {
2254 *propval = '\0';
2255 propval++;
2256 if (add_prop_list(optarg, propval,
2257 &props, B_TRUE))
2258 goto error;
2259 } else {
2260 mntopts = optarg;
2262 break;
2263 case 'R':
2264 if (add_prop_list(zpool_prop_to_name(
2265 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2266 goto error;
2267 if (nvlist_lookup_string(props,
2268 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
2269 &propval) == 0)
2270 break;
2271 if (add_prop_list(zpool_prop_to_name(
2272 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2273 goto error;
2274 break;
2275 case 'T':
2276 errno = 0;
2277 txg = strtoull(optarg, &endptr, 0);
2278 if (errno != 0 || *endptr != '\0') {
2279 (void) fprintf(stderr,
2280 gettext("invalid txg value\n"));
2281 usage(B_FALSE);
2283 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2284 break;
2285 case 'V':
2286 flags |= ZFS_IMPORT_VERBATIM;
2287 break;
2288 case 'X':
2289 xtreme_rewind = B_TRUE;
2290 break;
2291 case CHECKPOINT_OPT:
2292 flags |= ZFS_IMPORT_CHECKPOINT;
2293 break;
2294 case ':':
2295 (void) fprintf(stderr, gettext("missing argument for "
2296 "'%c' option\n"), optopt);
2297 usage(B_FALSE);
2298 break;
2299 case '?':
2300 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2301 optopt);
2302 usage(B_FALSE);
2306 argc -= optind;
2307 argv += optind;
2309 if (cachefile && nsearch != 0) {
2310 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
2311 usage(B_FALSE);
2314 if ((dryrun || xtreme_rewind) && !do_rewind) {
2315 (void) fprintf(stderr,
2316 gettext("-n or -X only meaningful with -F\n"));
2317 usage(B_FALSE);
2319 if (dryrun)
2320 rewind_policy = ZPOOL_TRY_REWIND;
2321 else if (do_rewind)
2322 rewind_policy = ZPOOL_DO_REWIND;
2323 if (xtreme_rewind)
2324 rewind_policy |= ZPOOL_EXTREME_REWIND;
2326 /* In the future, we can capture further policy and include it here */
2327 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
2328 nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, txg) != 0 ||
2329 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
2330 goto error;
2332 if (searchdirs == NULL) {
2333 searchdirs = safe_malloc(sizeof (char *));
2334 searchdirs[0] = ZFS_DISK_ROOT;
2335 nsearch = 1;
2338 /* check argument count */
2339 if (do_all) {
2340 if (argc != 0) {
2341 (void) fprintf(stderr, gettext("too many arguments\n"));
2342 usage(B_FALSE);
2344 } else {
2345 if (argc > 2) {
2346 (void) fprintf(stderr, gettext("too many arguments\n"));
2347 usage(B_FALSE);
2351 * Check for the SYS_CONFIG privilege. We do this explicitly
2352 * here because otherwise any attempt to discover pools will
2353 * silently fail.
2355 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
2356 (void) fprintf(stderr, gettext("cannot "
2357 "discover pools: permission denied\n"));
2358 free(searchdirs);
2359 nvlist_free(policy);
2360 return (1);
2365 * Depending on the arguments given, we do one of the following:
2367 * <none> Iterate through all pools and display information about
2368 * each one.
2370 * -a Iterate through all pools and try to import each one.
2372 * <id> Find the pool that corresponds to the given GUID/pool
2373 * name and import that one.
2375 * -D Above options applies only to destroyed pools.
2377 if (argc != 0) {
2378 char *endptr;
2380 errno = 0;
2381 searchguid = strtoull(argv[0], &endptr, 10);
2382 if (errno != 0 || *endptr != '\0') {
2383 searchname = argv[0];
2384 searchguid = 0;
2386 found_config = NULL;
2389 * User specified a name or guid. Ensure it's unique.
2391 idata.unique = B_TRUE;
2395 idata.path = searchdirs;
2396 idata.paths = nsearch;
2397 idata.poolname = searchname;
2398 idata.guid = searchguid;
2399 idata.cachefile = cachefile;
2400 idata.policy = policy;
2402 pools = zpool_search_import(g_zfs, &idata);
2404 if (pools != NULL && idata.exists &&
2405 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2406 (void) fprintf(stderr, gettext("cannot import '%s': "
2407 "a pool with that name already exists\n"),
2408 argv[0]);
2409 (void) fprintf(stderr, gettext("use the form '%s "
2410 "<pool | id> <newpool>' to give it a new name\n"),
2411 "zpool import");
2412 err = 1;
2413 } else if (pools == NULL && idata.exists) {
2414 (void) fprintf(stderr, gettext("cannot import '%s': "
2415 "a pool with that name is already created/imported,\n"),
2416 argv[0]);
2417 (void) fprintf(stderr, gettext("and no additional pools "
2418 "with that name were found\n"));
2419 err = 1;
2420 } else if (pools == NULL) {
2421 if (argc != 0) {
2422 (void) fprintf(stderr, gettext("cannot import '%s': "
2423 "no such pool available\n"), argv[0]);
2425 err = 1;
2428 if (err == 1) {
2429 free(searchdirs);
2430 nvlist_free(policy);
2431 return (1);
2435 * At this point we have a list of import candidate configs. Even if
2436 * we were searching by pool name or guid, we still need to
2437 * post-process the list to deal with pool state and possible
2438 * duplicate names.
2440 err = 0;
2441 elem = NULL;
2442 first = B_TRUE;
2443 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2445 verify(nvpair_value_nvlist(elem, &config) == 0);
2447 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2448 &pool_state) == 0);
2449 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2450 continue;
2451 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2452 continue;
2454 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
2455 policy) == 0);
2457 if (argc == 0) {
2458 if (first)
2459 first = B_FALSE;
2460 else if (!do_all)
2461 (void) printf("\n");
2463 if (do_all) {
2464 err |= do_import(config, NULL, mntopts,
2465 props, flags);
2466 } else {
2467 show_import(config);
2469 } else if (searchname != NULL) {
2470 char *name;
2473 * We are searching for a pool based on name.
2475 verify(nvlist_lookup_string(config,
2476 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2478 if (strcmp(name, searchname) == 0) {
2479 if (found_config != NULL) {
2480 (void) fprintf(stderr, gettext(
2481 "cannot import '%s': more than "
2482 "one matching pool\n"), searchname);
2483 (void) fprintf(stderr, gettext(
2484 "import by numeric ID instead\n"));
2485 err = B_TRUE;
2487 found_config = config;
2489 } else {
2490 uint64_t guid;
2493 * Search for a pool by guid.
2495 verify(nvlist_lookup_uint64(config,
2496 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2498 if (guid == searchguid)
2499 found_config = config;
2504 * If we were searching for a specific pool, verify that we found a
2505 * pool, and then do the import.
2507 if (argc != 0 && err == 0) {
2508 if (found_config == NULL) {
2509 (void) fprintf(stderr, gettext("cannot import '%s': "
2510 "no such pool available\n"), argv[0]);
2511 err = B_TRUE;
2512 } else {
2513 err |= do_import(found_config, argc == 1 ? NULL :
2514 argv[1], mntopts, props, flags);
2519 * If we were just looking for pools, report an error if none were
2520 * found.
2522 if (argc == 0 && first)
2523 (void) fprintf(stderr,
2524 gettext("no pools available to import\n"));
2526 error:
2527 nvlist_free(props);
2528 nvlist_free(pools);
2529 nvlist_free(policy);
2530 free(searchdirs);
2532 return (err ? 1 : 0);
2535 typedef struct iostat_cbdata {
2536 boolean_t cb_verbose;
2537 int cb_namewidth;
2538 int cb_iteration;
2539 zpool_list_t *cb_list;
2540 } iostat_cbdata_t;
2542 static void
2543 print_iostat_separator(iostat_cbdata_t *cb)
2545 int i = 0;
2547 for (i = 0; i < cb->cb_namewidth; i++)
2548 (void) printf("-");
2549 (void) printf(" ----- ----- ----- ----- ----- -----\n");
2552 static void
2553 print_iostat_header(iostat_cbdata_t *cb)
2555 (void) printf("%*s capacity operations bandwidth\n",
2556 cb->cb_namewidth, "");
2557 (void) printf("%-*s alloc free read write read write\n",
2558 cb->cb_namewidth, "pool");
2559 print_iostat_separator(cb);
2563 * Display a single statistic.
2565 static void
2566 print_one_stat(uint64_t value)
2568 char buf[64];
2570 zfs_nicenum(value, buf, sizeof (buf));
2571 (void) printf(" %5s", buf);
2575 * Print out all the statistics for the given vdev. This can either be the
2576 * toplevel configuration, or called recursively. If 'name' is NULL, then this
2577 * is a verbose output, and we don't want to display the toplevel pool stats.
2579 void
2580 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2581 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2583 nvlist_t **oldchild, **newchild;
2584 uint_t c, children;
2585 vdev_stat_t *oldvs, *newvs;
2586 vdev_stat_t zerovs = { 0 };
2587 uint64_t tdelta;
2588 double scale;
2589 char *vname;
2591 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
2592 return;
2594 if (oldnv != NULL) {
2595 verify(nvlist_lookup_uint64_array(oldnv,
2596 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2597 } else {
2598 oldvs = &zerovs;
2601 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2602 (uint64_t **)&newvs, &c) == 0);
2604 if (strlen(name) + depth > cb->cb_namewidth)
2605 (void) printf("%*s%s", depth, "", name);
2606 else
2607 (void) printf("%*s%s%*s", depth, "", name,
2608 (int)(cb->cb_namewidth - strlen(name) - depth), "");
2610 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2612 if (tdelta == 0)
2613 scale = 1.0;
2614 else
2615 scale = (double)NANOSEC / tdelta;
2617 /* only toplevel vdevs have capacity stats */
2618 if (newvs->vs_space == 0) {
2619 (void) printf(" - -");
2620 } else {
2621 print_one_stat(newvs->vs_alloc);
2622 print_one_stat(newvs->vs_space - newvs->vs_alloc);
2625 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2626 oldvs->vs_ops[ZIO_TYPE_READ])));
2628 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2629 oldvs->vs_ops[ZIO_TYPE_WRITE])));
2631 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2632 oldvs->vs_bytes[ZIO_TYPE_READ])));
2634 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2635 oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2637 (void) printf("\n");
2639 if (!cb->cb_verbose)
2640 return;
2642 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2643 &newchild, &children) != 0)
2644 return;
2646 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2647 &oldchild, &c) != 0)
2648 return;
2650 for (c = 0; c < children; c++) {
2651 uint64_t ishole = B_FALSE, islog = B_FALSE;
2653 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2654 &ishole);
2656 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2657 &islog);
2659 if (ishole || islog)
2660 continue;
2662 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2663 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2664 newchild[c], cb, depth + 2);
2665 free(vname);
2669 * Log device section
2672 if (num_logs(newnv) > 0) {
2673 (void) printf("%-*s - - - - - "
2674 "-\n", cb->cb_namewidth, "logs");
2676 for (c = 0; c < children; c++) {
2677 uint64_t islog = B_FALSE;
2678 (void) nvlist_lookup_uint64(newchild[c],
2679 ZPOOL_CONFIG_IS_LOG, &islog);
2681 if (islog) {
2682 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2683 B_FALSE);
2684 print_vdev_stats(zhp, vname, oldnv ?
2685 oldchild[c] : NULL, newchild[c],
2686 cb, depth + 2);
2687 free(vname);
2694 * Include level 2 ARC devices in iostat output
2696 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2697 &newchild, &children) != 0)
2698 return;
2700 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2701 &oldchild, &c) != 0)
2702 return;
2704 if (children > 0) {
2705 (void) printf("%-*s - - - - - "
2706 "-\n", cb->cb_namewidth, "cache");
2707 for (c = 0; c < children; c++) {
2708 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2709 B_FALSE);
2710 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2711 newchild[c], cb, depth + 2);
2712 free(vname);
2717 static int
2718 refresh_iostat(zpool_handle_t *zhp, void *data)
2720 iostat_cbdata_t *cb = data;
2721 boolean_t missing;
2724 * If the pool has disappeared, remove it from the list and continue.
2726 if (zpool_refresh_stats(zhp, &missing) != 0)
2727 return (-1);
2729 if (missing)
2730 pool_list_remove(cb->cb_list, zhp);
2732 return (0);
2736 * Callback to print out the iostats for the given pool.
2739 print_iostat(zpool_handle_t *zhp, void *data)
2741 iostat_cbdata_t *cb = data;
2742 nvlist_t *oldconfig, *newconfig;
2743 nvlist_t *oldnvroot, *newnvroot;
2745 newconfig = zpool_get_config(zhp, &oldconfig);
2747 if (cb->cb_iteration == 1)
2748 oldconfig = NULL;
2750 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
2751 &newnvroot) == 0);
2753 if (oldconfig == NULL)
2754 oldnvroot = NULL;
2755 else
2756 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
2757 &oldnvroot) == 0);
2760 * Print out the statistics for the pool.
2762 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
2764 if (cb->cb_verbose)
2765 print_iostat_separator(cb);
2767 return (0);
2771 get_namewidth(zpool_handle_t *zhp, void *data)
2773 iostat_cbdata_t *cb = data;
2774 nvlist_t *config, *nvroot;
2776 if ((config = zpool_get_config(zhp, NULL)) != NULL) {
2777 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2778 &nvroot) == 0);
2779 if (!cb->cb_verbose)
2780 cb->cb_namewidth = strlen(zpool_get_name(zhp));
2781 else
2782 cb->cb_namewidth = max_width(zhp, nvroot, 0,
2783 cb->cb_namewidth);
2787 * The width must fall into the range [10,38]. The upper limit is the
2788 * maximum we can have and still fit in 80 columns.
2790 if (cb->cb_namewidth < 10)
2791 cb->cb_namewidth = 10;
2792 if (cb->cb_namewidth > 38)
2793 cb->cb_namewidth = 38;
2795 return (0);
2799 * Parse the input string, get the 'interval' and 'count' value if there is one.
2801 static void
2802 get_interval_count(int *argcp, char **argv, unsigned long *iv,
2803 unsigned long *cnt)
2805 unsigned long interval = 0, count = 0;
2806 int argc = *argcp, errno;
2809 * Determine if the last argument is an integer or a pool name
2811 if (argc > 0 && isdigit(argv[argc - 1][0])) {
2812 char *end;
2814 errno = 0;
2815 interval = strtoul(argv[argc - 1], &end, 10);
2817 if (*end == '\0' && errno == 0) {
2818 if (interval == 0) {
2819 (void) fprintf(stderr, gettext("interval "
2820 "cannot be zero\n"));
2821 usage(B_FALSE);
2824 * Ignore the last parameter
2826 argc--;
2827 } else {
2829 * If this is not a valid number, just plow on. The
2830 * user will get a more informative error message later
2831 * on.
2833 interval = 0;
2838 * If the last argument is also an integer, then we have both a count
2839 * and an interval.
2841 if (argc > 0 && isdigit(argv[argc - 1][0])) {
2842 char *end;
2844 errno = 0;
2845 count = interval;
2846 interval = strtoul(argv[argc - 1], &end, 10);
2848 if (*end == '\0' && errno == 0) {
2849 if (interval == 0) {
2850 (void) fprintf(stderr, gettext("interval "
2851 "cannot be zero\n"));
2852 usage(B_FALSE);
2856 * Ignore the last parameter
2858 argc--;
2859 } else {
2860 interval = 0;
2864 *iv = interval;
2865 *cnt = count;
2866 *argcp = argc;
2869 static void
2870 get_timestamp_arg(char c)
2872 if (c == 'u')
2873 timestamp_fmt = UDATE;
2874 else if (c == 'd')
2875 timestamp_fmt = DDATE;
2876 else
2877 usage(B_FALSE);
2881 * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
2883 * -v Display statistics for individual vdevs
2884 * -T Display a timestamp in date(1) or Unix format
2886 * This command can be tricky because we want to be able to deal with pool
2887 * creation/destruction as well as vdev configuration changes. The bulk of this
2888 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
2889 * on pool_list_update() to detect the addition of new pools. Configuration
2890 * changes are all handled within libzfs.
2893 zpool_do_iostat(int argc, char **argv)
2895 int c;
2896 int ret;
2897 int npools;
2898 unsigned long interval = 0, count = 0;
2899 zpool_list_t *list;
2900 boolean_t verbose = B_FALSE;
2901 iostat_cbdata_t cb;
2903 /* check options */
2904 while ((c = getopt(argc, argv, "T:v")) != -1) {
2905 switch (c) {
2906 case 'T':
2907 get_timestamp_arg(*optarg);
2908 break;
2909 case 'v':
2910 verbose = B_TRUE;
2911 break;
2912 case '?':
2913 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2914 optopt);
2915 usage(B_FALSE);
2919 argc -= optind;
2920 argv += optind;
2922 get_interval_count(&argc, argv, &interval, &count);
2925 * Construct the list of all interesting pools.
2927 ret = 0;
2928 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
2929 return (1);
2931 if (pool_list_count(list) == 0 && argc != 0) {
2932 pool_list_free(list);
2933 return (1);
2936 if (pool_list_count(list) == 0 && interval == 0) {
2937 pool_list_free(list);
2938 (void) fprintf(stderr, gettext("no pools available\n"));
2939 return (1);
2943 * Enter the main iostat loop.
2945 cb.cb_list = list;
2946 cb.cb_verbose = verbose;
2947 cb.cb_iteration = 0;
2948 cb.cb_namewidth = 0;
2950 for (;;) {
2951 pool_list_update(list);
2953 if ((npools = pool_list_count(list)) == 0)
2954 break;
2957 * Refresh all statistics. This is done as an explicit step
2958 * before calculating the maximum name width, so that any
2959 * configuration changes are properly accounted for.
2961 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
2964 * Iterate over all pools to determine the maximum width
2965 * for the pool / device name column across all pools.
2967 cb.cb_namewidth = 0;
2968 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2970 if (timestamp_fmt != NODATE)
2971 print_timestamp(timestamp_fmt);
2974 * If it's the first time, or verbose mode, print the header.
2976 if (++cb.cb_iteration == 1 || verbose)
2977 print_iostat_header(&cb);
2979 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
2982 * If there's more than one pool, and we're not in verbose mode
2983 * (which prints a separator for us), then print a separator.
2985 if (npools > 1 && !verbose)
2986 print_iostat_separator(&cb);
2988 if (verbose)
2989 (void) printf("\n");
2992 * Flush the output so that redirection to a file isn't buffered
2993 * indefinitely.
2995 (void) fflush(stdout);
2997 if (interval == 0)
2998 break;
3000 if (count != 0 && --count == 0)
3001 break;
3003 (void) sleep(interval);
3006 pool_list_free(list);
3008 return (ret);
3011 typedef struct list_cbdata {
3012 boolean_t cb_verbose;
3013 int cb_namewidth;
3014 boolean_t cb_scripted;
3015 zprop_list_t *cb_proplist;
3016 boolean_t cb_literal;
3017 } list_cbdata_t;
3020 * Given a list of columns to display, output appropriate headers for each one.
3022 static void
3023 print_header(list_cbdata_t *cb)
3025 zprop_list_t *pl = cb->cb_proplist;
3026 char headerbuf[ZPOOL_MAXPROPLEN];
3027 const char *header;
3028 boolean_t first = B_TRUE;
3029 boolean_t right_justify;
3030 size_t width = 0;
3032 for (; pl != NULL; pl = pl->pl_next) {
3033 width = pl->pl_width;
3034 if (first && cb->cb_verbose) {
3036 * Reset the width to accommodate the verbose listing
3037 * of devices.
3039 width = cb->cb_namewidth;
3042 if (!first)
3043 (void) printf(" ");
3044 else
3045 first = B_FALSE;
3047 right_justify = B_FALSE;
3048 if (pl->pl_prop != ZPROP_INVAL) {
3049 header = zpool_prop_column_name(pl->pl_prop);
3050 right_justify = zpool_prop_align_right(pl->pl_prop);
3051 } else {
3052 int i;
3054 for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
3055 headerbuf[i] = toupper(pl->pl_user_prop[i]);
3056 headerbuf[i] = '\0';
3057 header = headerbuf;
3060 if (pl->pl_next == NULL && !right_justify)
3061 (void) printf("%s", header);
3062 else if (right_justify)
3063 (void) printf("%*s", width, header);
3064 else
3065 (void) printf("%-*s", width, header);
3069 (void) printf("\n");
3073 * Given a pool and a list of properties, print out all the properties according
3074 * to the described layout.
3076 static void
3077 print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
3079 zprop_list_t *pl = cb->cb_proplist;
3080 boolean_t first = B_TRUE;
3081 char property[ZPOOL_MAXPROPLEN];
3082 char *propstr;
3083 boolean_t right_justify;
3084 size_t width;
3086 for (; pl != NULL; pl = pl->pl_next) {
3088 width = pl->pl_width;
3089 if (first && cb->cb_verbose) {
3091 * Reset the width to accommodate the verbose listing
3092 * of devices.
3094 width = cb->cb_namewidth;
3097 if (!first) {
3098 if (cb->cb_scripted)
3099 (void) printf("\t");
3100 else
3101 (void) printf(" ");
3102 } else {
3103 first = B_FALSE;
3106 right_justify = B_FALSE;
3107 if (pl->pl_prop != ZPROP_INVAL) {
3108 if (zpool_get_prop(zhp, pl->pl_prop, property,
3109 sizeof (property), NULL, cb->cb_literal) != 0)
3110 propstr = "-";
3111 else
3112 propstr = property;
3114 right_justify = zpool_prop_align_right(pl->pl_prop);
3115 } else if ((zpool_prop_feature(pl->pl_user_prop) ||
3116 zpool_prop_unsupported(pl->pl_user_prop)) &&
3117 zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
3118 sizeof (property)) == 0) {
3119 propstr = property;
3120 } else {
3121 propstr = "-";
3126 * If this is being called in scripted mode, or if this is the
3127 * last column and it is left-justified, don't include a width
3128 * format specifier.
3130 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
3131 (void) printf("%s", propstr);
3132 else if (right_justify)
3133 (void) printf("%*s", width, propstr);
3134 else
3135 (void) printf("%-*s", width, propstr);
3138 (void) printf("\n");
3141 static void
3142 print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
3143 boolean_t valid)
3145 char propval[64];
3146 boolean_t fixed;
3147 size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
3149 switch (prop) {
3150 case ZPOOL_PROP_EXPANDSZ:
3151 case ZPOOL_PROP_CHECKPOINT:
3152 if (value == 0)
3153 (void) strlcpy(propval, "-", sizeof (propval));
3154 else
3155 zfs_nicenum(value, propval, sizeof (propval));
3156 break;
3157 case ZPOOL_PROP_FRAGMENTATION:
3158 if (value == ZFS_FRAG_INVALID) {
3159 (void) strlcpy(propval, "-", sizeof (propval));
3160 } else {
3161 (void) snprintf(propval, sizeof (propval), "%llu%%",
3162 value);
3164 break;
3165 case ZPOOL_PROP_CAPACITY:
3166 (void) snprintf(propval, sizeof (propval), "%llu%%", value);
3167 break;
3168 default:
3169 zfs_nicenum(value, propval, sizeof (propval));
3172 if (!valid)
3173 (void) strlcpy(propval, "-", sizeof (propval));
3175 if (scripted)
3176 (void) printf("\t%s", propval);
3177 else
3178 (void) printf(" %*s", width, propval);
3181 void
3182 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
3183 list_cbdata_t *cb, int depth)
3185 nvlist_t **child;
3186 vdev_stat_t *vs;
3187 uint_t c, children;
3188 char *vname;
3189 boolean_t scripted = cb->cb_scripted;
3190 uint64_t islog = B_FALSE;
3191 boolean_t haslog = B_FALSE;
3192 char *dashes = "%-*s - - - - - -\n";
3194 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3195 (uint64_t **)&vs, &c) == 0);
3197 if (name != NULL) {
3198 boolean_t toplevel = (vs->vs_space != 0);
3199 uint64_t cap;
3201 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
3202 return;
3204 if (scripted)
3205 (void) printf("\t%s", name);
3206 else if (strlen(name) + depth > cb->cb_namewidth)
3207 (void) printf("%*s%s", depth, "", name);
3208 else
3209 (void) printf("%*s%s%*s", depth, "", name,
3210 (int)(cb->cb_namewidth - strlen(name) - depth), "");
3213 * Print the properties for the individual vdevs. Some
3214 * properties are only applicable to toplevel vdevs. The
3215 * 'toplevel' boolean value is passed to the print_one_column()
3216 * to indicate that the value is valid.
3218 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
3219 toplevel);
3220 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
3221 toplevel);
3222 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
3223 scripted, toplevel);
3224 print_one_column(ZPOOL_PROP_CHECKPOINT,
3225 vs->vs_checkpoint_space, scripted, toplevel);
3226 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
3227 B_TRUE);
3228 print_one_column(ZPOOL_PROP_FRAGMENTATION,
3229 vs->vs_fragmentation, scripted,
3230 (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel));
3231 cap = (vs->vs_space == 0) ? 0 :
3232 (vs->vs_alloc * 100 / vs->vs_space);
3233 print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel);
3234 (void) printf("\n");
3237 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
3238 &child, &children) != 0)
3239 return;
3241 for (c = 0; c < children; c++) {
3242 uint64_t ishole = B_FALSE;
3244 if (nvlist_lookup_uint64(child[c],
3245 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
3246 continue;
3248 if (nvlist_lookup_uint64(child[c],
3249 ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) {
3250 haslog = B_TRUE;
3251 continue;
3254 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3255 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3256 free(vname);
3259 if (haslog == B_TRUE) {
3260 /* LINTED E_SEC_PRINTF_VAR_FMT */
3261 (void) printf(dashes, cb->cb_namewidth, "log");
3262 for (c = 0; c < children; c++) {
3263 if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
3264 &islog) != 0 || !islog)
3265 continue;
3266 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3267 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3268 free(vname);
3272 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
3273 &child, &children) == 0 && children > 0) {
3274 /* LINTED E_SEC_PRINTF_VAR_FMT */
3275 (void) printf(dashes, cb->cb_namewidth, "cache");
3276 for (c = 0; c < children; c++) {
3277 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3278 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3279 free(vname);
3283 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
3284 &children) == 0 && children > 0) {
3285 /* LINTED E_SEC_PRINTF_VAR_FMT */
3286 (void) printf(dashes, cb->cb_namewidth, "spare");
3287 for (c = 0; c < children; c++) {
3288 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3289 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3290 free(vname);
3297 * Generic callback function to list a pool.
3300 list_callback(zpool_handle_t *zhp, void *data)
3302 list_cbdata_t *cbp = data;
3303 nvlist_t *config;
3304 nvlist_t *nvroot;
3306 config = zpool_get_config(zhp, NULL);
3308 print_pool(zhp, cbp);
3309 if (!cbp->cb_verbose)
3310 return (0);
3312 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3313 &nvroot) == 0);
3314 print_list_stats(zhp, NULL, nvroot, cbp, 0);
3316 return (0);
3320 * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3322 * -H Scripted mode. Don't display headers, and separate properties
3323 * by a single tab.
3324 * -o List of properties to display. Defaults to
3325 * "name,size,allocated,free,expandsize,fragmentation,capacity,"
3326 * "dedupratio,health,altroot"
3327 * -p Diplay values in parsable (exact) format.
3328 * -T Display a timestamp in date(1) or Unix format
3330 * List all pools in the system, whether or not they're healthy. Output space
3331 * statistics for each one, as well as health status summary.
3334 zpool_do_list(int argc, char **argv)
3336 int c;
3337 int ret;
3338 list_cbdata_t cb = { 0 };
3339 static char default_props[] =
3340 "name,size,allocated,free,checkpoint,expandsize,fragmentation,"
3341 "capacity,dedupratio,health,altroot";
3342 char *props = default_props;
3343 unsigned long interval = 0, count = 0;
3344 zpool_list_t *list;
3345 boolean_t first = B_TRUE;
3347 /* check options */
3348 while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
3349 switch (c) {
3350 case 'H':
3351 cb.cb_scripted = B_TRUE;
3352 break;
3353 case 'o':
3354 props = optarg;
3355 break;
3356 case 'p':
3357 cb.cb_literal = B_TRUE;
3358 break;
3359 case 'T':
3360 get_timestamp_arg(*optarg);
3361 break;
3362 case 'v':
3363 cb.cb_verbose = B_TRUE;
3364 break;
3365 case ':':
3366 (void) fprintf(stderr, gettext("missing argument for "
3367 "'%c' option\n"), optopt);
3368 usage(B_FALSE);
3369 break;
3370 case '?':
3371 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3372 optopt);
3373 usage(B_FALSE);
3377 argc -= optind;
3378 argv += optind;
3380 get_interval_count(&argc, argv, &interval, &count);
3382 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
3383 usage(B_FALSE);
3385 for (;;) {
3386 if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
3387 &ret)) == NULL)
3388 return (1);
3390 if (pool_list_count(list) == 0)
3391 break;
3393 cb.cb_namewidth = 0;
3394 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3396 if (timestamp_fmt != NODATE)
3397 print_timestamp(timestamp_fmt);
3399 if (!cb.cb_scripted && (first || cb.cb_verbose)) {
3400 print_header(&cb);
3401 first = B_FALSE;
3403 ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
3405 if (interval == 0)
3406 break;
3408 if (count != 0 && --count == 0)
3409 break;
3411 pool_list_free(list);
3412 (void) sleep(interval);
3415 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
3416 (void) printf(gettext("no pools available\n"));
3417 ret = 0;
3420 pool_list_free(list);
3421 zprop_free_list(cb.cb_proplist);
3422 return (ret);
3425 static int
3426 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
3428 boolean_t force = B_FALSE;
3429 int c;
3430 nvlist_t *nvroot;
3431 char *poolname, *old_disk, *new_disk;
3432 zpool_handle_t *zhp;
3433 zpool_boot_label_t boot_type;
3434 uint64_t boot_size;
3435 int ret;
3437 /* check options */
3438 while ((c = getopt(argc, argv, "f")) != -1) {
3439 switch (c) {
3440 case 'f':
3441 force = B_TRUE;
3442 break;
3443 case '?':
3444 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3445 optopt);
3446 usage(B_FALSE);
3450 argc -= optind;
3451 argv += optind;
3453 /* get pool name and check number of arguments */
3454 if (argc < 1) {
3455 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3456 usage(B_FALSE);
3459 poolname = argv[0];
3461 if (argc < 2) {
3462 (void) fprintf(stderr,
3463 gettext("missing <device> specification\n"));
3464 usage(B_FALSE);
3467 old_disk = argv[1];
3469 if (argc < 3) {
3470 if (!replacing) {
3471 (void) fprintf(stderr,
3472 gettext("missing <new_device> specification\n"));
3473 usage(B_FALSE);
3475 new_disk = old_disk;
3476 argc -= 1;
3477 argv += 1;
3478 } else {
3479 new_disk = argv[2];
3480 argc -= 2;
3481 argv += 2;
3484 if (argc > 1) {
3485 (void) fprintf(stderr, gettext("too many arguments\n"));
3486 usage(B_FALSE);
3489 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3490 return (1);
3492 if (zpool_get_config(zhp, NULL) == NULL) {
3493 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
3494 poolname);
3495 zpool_close(zhp);
3496 return (1);
3499 if (zpool_is_bootable(zhp))
3500 boot_type = ZPOOL_COPY_BOOT_LABEL;
3501 else
3502 boot_type = ZPOOL_NO_BOOT_LABEL;
3504 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
3505 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
3506 boot_type, boot_size, argc, argv);
3507 if (nvroot == NULL) {
3508 zpool_close(zhp);
3509 return (1);
3512 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
3514 nvlist_free(nvroot);
3515 zpool_close(zhp);
3517 return (ret);
3521 * zpool replace [-f] <pool> <device> <new_device>
3523 * -f Force attach, even if <new_device> appears to be in use.
3525 * Replace <device> with <new_device>.
3527 /* ARGSUSED */
3529 zpool_do_replace(int argc, char **argv)
3531 return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
3535 * zpool attach [-f] <pool> <device> <new_device>
3537 * -f Force attach, even if <new_device> appears to be in use.
3539 * Attach <new_device> to the mirror containing <device>. If <device> is not
3540 * part of a mirror, then <device> will be transformed into a mirror of
3541 * <device> and <new_device>. In either case, <new_device> will begin life
3542 * with a DTL of [0, now], and will immediately begin to resilver itself.
3545 zpool_do_attach(int argc, char **argv)
3547 return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
3551 * zpool detach [-f] <pool> <device>
3553 * -f Force detach of <device>, even if DTLs argue against it
3554 * (not supported yet)
3556 * Detach a device from a mirror. The operation will be refused if <device>
3557 * is the last device in the mirror, or if the DTLs indicate that this device
3558 * has the only valid copy of some data.
3560 /* ARGSUSED */
3562 zpool_do_detach(int argc, char **argv)
3564 int c;
3565 char *poolname, *path;
3566 zpool_handle_t *zhp;
3567 int ret;
3569 /* check options */
3570 while ((c = getopt(argc, argv, "f")) != -1) {
3571 switch (c) {
3572 case 'f':
3573 case '?':
3574 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3575 optopt);
3576 usage(B_FALSE);
3580 argc -= optind;
3581 argv += optind;
3583 /* get pool name and check number of arguments */
3584 if (argc < 1) {
3585 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3586 usage(B_FALSE);
3589 if (argc < 2) {
3590 (void) fprintf(stderr,
3591 gettext("missing <device> specification\n"));
3592 usage(B_FALSE);
3595 poolname = argv[0];
3596 path = argv[1];
3598 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3599 return (1);
3601 ret = zpool_vdev_detach(zhp, path);
3603 zpool_close(zhp);
3605 return (ret);
3609 * zpool split [-n] [-o prop=val] ...
3610 * [-o mntopt] ...
3611 * [-R altroot] <pool> <newpool> [<device> ...]
3613 * -n Do not split the pool, but display the resulting layout if
3614 * it were to be split.
3615 * -o Set property=value, or set mount options.
3616 * -R Mount the split-off pool under an alternate root.
3618 * Splits the named pool and gives it the new pool name. Devices to be split
3619 * off may be listed, provided that no more than one device is specified
3620 * per top-level vdev mirror. The newly split pool is left in an exported
3621 * state unless -R is specified.
3623 * Restrictions: the top-level of the pool pool must only be made up of
3624 * mirrors; all devices in the pool must be healthy; no device may be
3625 * undergoing a resilvering operation.
3628 zpool_do_split(int argc, char **argv)
3630 char *srcpool, *newpool, *propval;
3631 char *mntopts = NULL;
3632 splitflags_t flags;
3633 int c, ret = 0;
3634 zpool_handle_t *zhp;
3635 nvlist_t *config, *props = NULL;
3637 flags.dryrun = B_FALSE;
3638 flags.import = B_FALSE;
3640 /* check options */
3641 while ((c = getopt(argc, argv, ":R:no:")) != -1) {
3642 switch (c) {
3643 case 'R':
3644 flags.import = B_TRUE;
3645 if (add_prop_list(
3646 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
3647 &props, B_TRUE) != 0) {
3648 nvlist_free(props);
3649 usage(B_FALSE);
3651 break;
3652 case 'n':
3653 flags.dryrun = B_TRUE;
3654 break;
3655 case 'o':
3656 if ((propval = strchr(optarg, '=')) != NULL) {
3657 *propval = '\0';
3658 propval++;
3659 if (add_prop_list(optarg, propval,
3660 &props, B_TRUE) != 0) {
3661 nvlist_free(props);
3662 usage(B_FALSE);
3664 } else {
3665 mntopts = optarg;
3667 break;
3668 case ':':
3669 (void) fprintf(stderr, gettext("missing argument for "
3670 "'%c' option\n"), optopt);
3671 usage(B_FALSE);
3672 break;
3673 case '?':
3674 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3675 optopt);
3676 usage(B_FALSE);
3677 break;
3681 if (!flags.import && mntopts != NULL) {
3682 (void) fprintf(stderr, gettext("setting mntopts is only "
3683 "valid when importing the pool\n"));
3684 usage(B_FALSE);
3687 argc -= optind;
3688 argv += optind;
3690 if (argc < 1) {
3691 (void) fprintf(stderr, gettext("Missing pool name\n"));
3692 usage(B_FALSE);
3694 if (argc < 2) {
3695 (void) fprintf(stderr, gettext("Missing new pool name\n"));
3696 usage(B_FALSE);
3699 srcpool = argv[0];
3700 newpool = argv[1];
3702 argc -= 2;
3703 argv += 2;
3705 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
3706 return (1);
3708 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
3709 if (config == NULL) {
3710 ret = 1;
3711 } else {
3712 if (flags.dryrun) {
3713 (void) printf(gettext("would create '%s' with the "
3714 "following layout:\n\n"), newpool);
3715 print_vdev_tree(NULL, newpool, config, 0, B_FALSE);
3717 nvlist_free(config);
3720 zpool_close(zhp);
3722 if (ret != 0 || flags.dryrun || !flags.import)
3723 return (ret);
3726 * The split was successful. Now we need to open the new
3727 * pool and import it.
3729 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
3730 return (1);
3731 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
3732 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
3733 ret = 1;
3734 (void) fprintf(stderr, gettext("Split was successful, but "
3735 "the datasets could not all be mounted\n"));
3736 (void) fprintf(stderr, gettext("Try doing '%s' with a "
3737 "different altroot\n"), "zpool import");
3739 zpool_close(zhp);
3741 return (ret);
3747 * zpool online <pool> <device> ...
3750 zpool_do_online(int argc, char **argv)
3752 int c, i;
3753 char *poolname;
3754 zpool_handle_t *zhp;
3755 int ret = 0;
3756 vdev_state_t newstate;
3757 int flags = 0;
3759 /* check options */
3760 while ((c = getopt(argc, argv, "et")) != -1) {
3761 switch (c) {
3762 case 'e':
3763 flags |= ZFS_ONLINE_EXPAND;
3764 break;
3765 case 't':
3766 case '?':
3767 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3768 optopt);
3769 usage(B_FALSE);
3773 argc -= optind;
3774 argv += optind;
3776 /* get pool name and check number of arguments */
3777 if (argc < 1) {
3778 (void) fprintf(stderr, gettext("missing pool name\n"));
3779 usage(B_FALSE);
3781 if (argc < 2) {
3782 (void) fprintf(stderr, gettext("missing device name\n"));
3783 usage(B_FALSE);
3786 poolname = argv[0];
3788 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3789 return (1);
3791 for (i = 1; i < argc; i++) {
3792 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
3793 if (newstate != VDEV_STATE_HEALTHY) {
3794 (void) printf(gettext("warning: device '%s' "
3795 "onlined, but remains in faulted state\n"),
3796 argv[i]);
3797 if (newstate == VDEV_STATE_FAULTED)
3798 (void) printf(gettext("use 'zpool "
3799 "clear' to restore a faulted "
3800 "device\n"));
3801 else
3802 (void) printf(gettext("use 'zpool "
3803 "replace' to replace devices "
3804 "that are no longer present\n"));
3806 } else {
3807 ret = 1;
3811 zpool_close(zhp);
3813 return (ret);
3817 * zpool offline [-ft] <pool> <device> ...
3819 * -f Force the device into the offline state, even if doing
3820 * so would appear to compromise pool availability.
3821 * (not supported yet)
3823 * -t Only take the device off-line temporarily. The offline
3824 * state will not be persistent across reboots.
3826 /* ARGSUSED */
3828 zpool_do_offline(int argc, char **argv)
3830 int c, i;
3831 char *poolname;
3832 zpool_handle_t *zhp;
3833 int ret = 0;
3834 boolean_t istmp = B_FALSE;
3836 /* check options */
3837 while ((c = getopt(argc, argv, "ft")) != -1) {
3838 switch (c) {
3839 case 't':
3840 istmp = B_TRUE;
3841 break;
3842 case 'f':
3843 case '?':
3844 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3845 optopt);
3846 usage(B_FALSE);
3850 argc -= optind;
3851 argv += optind;
3853 /* get pool name and check number of arguments */
3854 if (argc < 1) {
3855 (void) fprintf(stderr, gettext("missing pool name\n"));
3856 usage(B_FALSE);
3858 if (argc < 2) {
3859 (void) fprintf(stderr, gettext("missing device name\n"));
3860 usage(B_FALSE);
3863 poolname = argv[0];
3865 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3866 return (1);
3868 for (i = 1; i < argc; i++) {
3869 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
3870 ret = 1;
3873 zpool_close(zhp);
3875 return (ret);
3879 * zpool clear <pool> [device]
3881 * Clear all errors associated with a pool or a particular device.
3884 zpool_do_clear(int argc, char **argv)
3886 int c;
3887 int ret = 0;
3888 boolean_t dryrun = B_FALSE;
3889 boolean_t do_rewind = B_FALSE;
3890 boolean_t xtreme_rewind = B_FALSE;
3891 uint32_t rewind_policy = ZPOOL_NO_REWIND;
3892 nvlist_t *policy = NULL;
3893 zpool_handle_t *zhp;
3894 char *pool, *device;
3896 /* check options */
3897 while ((c = getopt(argc, argv, "FnX")) != -1) {
3898 switch (c) {
3899 case 'F':
3900 do_rewind = B_TRUE;
3901 break;
3902 case 'n':
3903 dryrun = B_TRUE;
3904 break;
3905 case 'X':
3906 xtreme_rewind = B_TRUE;
3907 break;
3908 case '?':
3909 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3910 optopt);
3911 usage(B_FALSE);
3915 argc -= optind;
3916 argv += optind;
3918 if (argc < 1) {
3919 (void) fprintf(stderr, gettext("missing pool name\n"));
3920 usage(B_FALSE);
3923 if (argc > 2) {
3924 (void) fprintf(stderr, gettext("too many arguments\n"));
3925 usage(B_FALSE);
3928 if ((dryrun || xtreme_rewind) && !do_rewind) {
3929 (void) fprintf(stderr,
3930 gettext("-n or -X only meaningful with -F\n"));
3931 usage(B_FALSE);
3933 if (dryrun)
3934 rewind_policy = ZPOOL_TRY_REWIND;
3935 else if (do_rewind)
3936 rewind_policy = ZPOOL_DO_REWIND;
3937 if (xtreme_rewind)
3938 rewind_policy |= ZPOOL_EXTREME_REWIND;
3940 /* In future, further rewind policy choices can be passed along here */
3941 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
3942 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
3943 return (1);
3945 pool = argv[0];
3946 device = argc == 2 ? argv[1] : NULL;
3948 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
3949 nvlist_free(policy);
3950 return (1);
3953 if (zpool_clear(zhp, device, policy) != 0)
3954 ret = 1;
3956 zpool_close(zhp);
3958 nvlist_free(policy);
3960 return (ret);
3964 * zpool reguid <pool>
3967 zpool_do_reguid(int argc, char **argv)
3969 int c;
3970 char *poolname;
3971 zpool_handle_t *zhp;
3972 int ret = 0;
3974 /* check options */
3975 while ((c = getopt(argc, argv, "")) != -1) {
3976 switch (c) {
3977 case '?':
3978 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3979 optopt);
3980 usage(B_FALSE);
3984 argc -= optind;
3985 argv += optind;
3987 /* get pool name and check number of arguments */
3988 if (argc < 1) {
3989 (void) fprintf(stderr, gettext("missing pool name\n"));
3990 usage(B_FALSE);
3993 if (argc > 1) {
3994 (void) fprintf(stderr, gettext("too many arguments\n"));
3995 usage(B_FALSE);
3998 poolname = argv[0];
3999 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
4000 return (1);
4002 ret = zpool_reguid(zhp);
4004 zpool_close(zhp);
4005 return (ret);
4010 * zpool reopen <pool>
4012 * Reopen the pool so that the kernel can update the sizes of all vdevs.
4015 zpool_do_reopen(int argc, char **argv)
4017 int c;
4018 int ret = 0;
4019 zpool_handle_t *zhp;
4020 char *pool;
4022 /* check options */
4023 while ((c = getopt(argc, argv, "")) != -1) {
4024 switch (c) {
4025 case '?':
4026 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4027 optopt);
4028 usage(B_FALSE);
4032 argc--;
4033 argv++;
4035 if (argc < 1) {
4036 (void) fprintf(stderr, gettext("missing pool name\n"));
4037 usage(B_FALSE);
4040 if (argc > 1) {
4041 (void) fprintf(stderr, gettext("too many arguments\n"));
4042 usage(B_FALSE);
4045 pool = argv[0];
4046 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
4047 return (1);
4049 ret = zpool_reopen(zhp);
4050 zpool_close(zhp);
4051 return (ret);
4054 typedef struct scrub_cbdata {
4055 int cb_type;
4056 int cb_argc;
4057 char **cb_argv;
4058 pool_scrub_cmd_t cb_scrub_cmd;
4059 } scrub_cbdata_t;
4061 static boolean_t
4062 zpool_has_checkpoint(zpool_handle_t *zhp)
4064 nvlist_t *config, *nvroot;
4066 config = zpool_get_config(zhp, NULL);
4068 if (config != NULL) {
4069 pool_checkpoint_stat_t *pcs = NULL;
4070 uint_t c;
4072 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4073 (void) nvlist_lookup_uint64_array(nvroot,
4074 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
4076 if (pcs == NULL || pcs->pcs_state == CS_NONE)
4077 return (B_FALSE);
4079 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS ||
4080 pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
4081 return (B_TRUE);
4084 return (B_FALSE);
4088 scrub_callback(zpool_handle_t *zhp, void *data)
4090 scrub_cbdata_t *cb = data;
4091 int err;
4094 * Ignore faulted pools.
4096 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4097 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
4098 "currently unavailable\n"), zpool_get_name(zhp));
4099 return (1);
4102 err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
4104 if (err == 0 && zpool_has_checkpoint(zhp) &&
4105 cb->cb_type == POOL_SCAN_SCRUB) {
4106 (void) printf(gettext("warning: will not scrub state that "
4107 "belongs to the checkpoint of pool '%s'\n"),
4108 zpool_get_name(zhp));
4111 return (err != 0);
4115 * zpool scrub [-s | -p] <pool> ...
4117 * -s Stop. Stops any in-progress scrub.
4118 * -p Pause. Pause in-progress scrub.
4121 zpool_do_scrub(int argc, char **argv)
4123 int c;
4124 scrub_cbdata_t cb;
4126 cb.cb_type = POOL_SCAN_SCRUB;
4127 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
4129 /* check options */
4130 while ((c = getopt(argc, argv, "sp")) != -1) {
4131 switch (c) {
4132 case 's':
4133 cb.cb_type = POOL_SCAN_NONE;
4134 break;
4135 case 'p':
4136 cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
4137 break;
4138 case '?':
4139 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4140 optopt);
4141 usage(B_FALSE);
4145 if (cb.cb_type == POOL_SCAN_NONE &&
4146 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
4147 (void) fprintf(stderr, gettext("invalid option combination: "
4148 "-s and -p are mutually exclusive\n"));
4149 usage(B_FALSE);
4152 cb.cb_argc = argc;
4153 cb.cb_argv = argv;
4154 argc -= optind;
4155 argv += optind;
4157 if (argc < 1) {
4158 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4159 usage(B_FALSE);
4162 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
4165 typedef struct status_cbdata {
4166 int cb_count;
4167 boolean_t cb_allpools;
4168 boolean_t cb_verbose;
4169 boolean_t cb_explain;
4170 boolean_t cb_first;
4171 boolean_t cb_dedup_stats;
4172 } status_cbdata_t;
4175 * Print out detailed scrub status.
4177 static void
4178 print_scan_status(pool_scan_stat_t *ps)
4180 time_t start, end, pause;
4181 uint64_t elapsed, mins_left, hours_left;
4182 uint64_t pass_exam, examined, total;
4183 uint_t rate;
4184 double fraction_done;
4185 char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4187 (void) printf(gettext(" scan: "));
4189 /* If there's never been a scan, there's not much to say. */
4190 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
4191 ps->pss_func >= POOL_SCAN_FUNCS) {
4192 (void) printf(gettext("none requested\n"));
4193 return;
4196 start = ps->pss_start_time;
4197 end = ps->pss_end_time;
4198 pause = ps->pss_pass_scrub_pause;
4199 zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
4201 assert(ps->pss_func == POOL_SCAN_SCRUB ||
4202 ps->pss_func == POOL_SCAN_RESILVER);
4204 * Scan is finished or canceled.
4206 if (ps->pss_state == DSS_FINISHED) {
4207 uint64_t minutes_taken = (end - start) / 60;
4208 char *fmt = NULL;
4210 if (ps->pss_func == POOL_SCAN_SCRUB) {
4211 fmt = gettext("scrub repaired %s in %lluh%um with "
4212 "%llu errors on %s");
4213 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4214 fmt = gettext("resilvered %s in %lluh%um with "
4215 "%llu errors on %s");
4217 /* LINTED */
4218 (void) printf(fmt, processed_buf,
4219 (u_longlong_t)(minutes_taken / 60),
4220 (uint_t)(minutes_taken % 60),
4221 (u_longlong_t)ps->pss_errors,
4222 ctime((time_t *)&end));
4223 return;
4224 } else if (ps->pss_state == DSS_CANCELED) {
4225 if (ps->pss_func == POOL_SCAN_SCRUB) {
4226 (void) printf(gettext("scrub canceled on %s"),
4227 ctime(&end));
4228 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4229 (void) printf(gettext("resilver canceled on %s"),
4230 ctime(&end));
4232 return;
4235 assert(ps->pss_state == DSS_SCANNING);
4238 * Scan is in progress.
4240 if (ps->pss_func == POOL_SCAN_SCRUB) {
4241 if (pause == 0) {
4242 (void) printf(gettext("scrub in progress since %s"),
4243 ctime(&start));
4244 } else {
4245 char buf[32];
4246 struct tm *p = localtime(&pause);
4247 (void) strftime(buf, sizeof (buf), "%a %b %e %T %Y", p);
4248 (void) printf(gettext("scrub paused since %s\n"), buf);
4249 (void) printf(gettext("\tscrub started on %s"),
4250 ctime(&start));
4252 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4253 (void) printf(gettext("resilver in progress since %s"),
4254 ctime(&start));
4257 examined = ps->pss_examined ? ps->pss_examined : 1;
4258 total = ps->pss_to_examine;
4259 fraction_done = (double)examined / total;
4261 /* elapsed time for this pass */
4262 elapsed = time(NULL) - ps->pss_pass_start;
4263 elapsed -= ps->pss_pass_scrub_spent_paused;
4264 elapsed = elapsed ? elapsed : 1;
4265 pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1;
4266 rate = pass_exam / elapsed;
4267 rate = rate ? rate : 1;
4268 mins_left = ((total - examined) / rate) / 60;
4269 hours_left = mins_left / 60;
4271 zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
4272 zfs_nicenum(total, total_buf, sizeof (total_buf));
4275 * do not print estimated time if hours_left is more than 30 days
4276 * or we have a paused scrub
4278 if (pause == 0) {
4279 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4280 (void) printf(gettext("\t%s scanned out of %s at %s/s"),
4281 examined_buf, total_buf, rate_buf);
4282 if (hours_left < (30 * 24)) {
4283 (void) printf(gettext(", %lluh%um to go\n"),
4284 (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4285 } else {
4286 (void) printf(gettext(
4287 ", (scan is slow, no estimated time)\n"));
4289 } else {
4290 (void) printf(gettext("\t%s scanned out of %s\n"),
4291 examined_buf, total_buf);
4294 if (ps->pss_func == POOL_SCAN_RESILVER) {
4295 (void) printf(gettext(" %s resilvered, %.2f%% done\n"),
4296 processed_buf, 100 * fraction_done);
4297 } else if (ps->pss_func == POOL_SCAN_SCRUB) {
4298 (void) printf(gettext(" %s repaired, %.2f%% done\n"),
4299 processed_buf, 100 * fraction_done);
4304 * As we don't scrub checkpointed blocks, we want to warn the
4305 * user that we skipped scanning some blocks if a checkpoint exists
4306 * or existed at any time during the scan.
4308 static void
4309 print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs)
4311 if (ps == NULL || pcs == NULL)
4312 return;
4314 if (pcs->pcs_state == CS_NONE ||
4315 pcs->pcs_state == CS_CHECKPOINT_DISCARDING)
4316 return;
4318 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS);
4320 if (ps->pss_state == DSS_NONE)
4321 return;
4323 if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) &&
4324 ps->pss_end_time < pcs->pcs_start_time)
4325 return;
4327 if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) {
4328 (void) printf(gettext(" scan warning: skipped blocks "
4329 "that are only referenced by the checkpoint.\n"));
4330 } else {
4331 assert(ps->pss_state == DSS_SCANNING);
4332 (void) printf(gettext(" scan warning: skipping blocks "
4333 "that are only referenced by the checkpoint.\n"));
4338 * Print out detailed removal status.
4340 static void
4341 print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
4343 char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4344 time_t start, end;
4345 nvlist_t *config, *nvroot;
4346 nvlist_t **child;
4347 uint_t children;
4348 char *vdev_name;
4350 if (prs == NULL || prs->prs_state == DSS_NONE)
4351 return;
4354 * Determine name of vdev.
4356 config = zpool_get_config(zhp, NULL);
4357 nvroot = fnvlist_lookup_nvlist(config,
4358 ZPOOL_CONFIG_VDEV_TREE);
4359 verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4360 &child, &children) == 0);
4361 assert(prs->prs_removing_vdev < children);
4362 vdev_name = zpool_vdev_name(g_zfs, zhp,
4363 child[prs->prs_removing_vdev], B_TRUE);
4365 (void) printf(gettext("remove: "));
4367 start = prs->prs_start_time;
4368 end = prs->prs_end_time;
4369 zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
4372 * Removal is finished or canceled.
4374 if (prs->prs_state == DSS_FINISHED) {
4375 uint64_t minutes_taken = (end - start) / 60;
4377 (void) printf(gettext("Removal of vdev %llu copied %s "
4378 "in %lluh%um, completed on %s"),
4379 (longlong_t)prs->prs_removing_vdev,
4380 copied_buf,
4381 (u_longlong_t)(minutes_taken / 60),
4382 (uint_t)(minutes_taken % 60),
4383 ctime((time_t *)&end));
4384 } else if (prs->prs_state == DSS_CANCELED) {
4385 (void) printf(gettext("Removal of %s canceled on %s"),
4386 vdev_name, ctime(&end));
4387 } else {
4388 uint64_t copied, total, elapsed, mins_left, hours_left;
4389 double fraction_done;
4390 uint_t rate;
4392 assert(prs->prs_state == DSS_SCANNING);
4395 * Removal is in progress.
4397 (void) printf(gettext(
4398 "Evacuation of %s in progress since %s"),
4399 vdev_name, ctime(&start));
4401 copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
4402 total = prs->prs_to_copy;
4403 fraction_done = (double)copied / total;
4405 /* elapsed time for this pass */
4406 elapsed = time(NULL) - prs->prs_start_time;
4407 elapsed = elapsed > 0 ? elapsed : 1;
4408 rate = copied / elapsed;
4409 rate = rate > 0 ? rate : 1;
4410 mins_left = ((total - copied) / rate) / 60;
4411 hours_left = mins_left / 60;
4413 zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
4414 zfs_nicenum(total, total_buf, sizeof (total_buf));
4415 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4418 * do not print estimated time if hours_left is more than
4419 * 30 days
4421 (void) printf(gettext(" %s copied out of %s at %s/s, "
4422 "%.2f%% done"),
4423 examined_buf, total_buf, rate_buf, 100 * fraction_done);
4424 if (hours_left < (30 * 24)) {
4425 (void) printf(gettext(", %lluh%um to go\n"),
4426 (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4427 } else {
4428 (void) printf(gettext(
4429 ", (copy is slow, no estimated time)\n"));
4433 if (prs->prs_mapping_memory > 0) {
4434 char mem_buf[7];
4435 zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
4436 (void) printf(gettext(" %s memory used for "
4437 "removed device mappings\n"),
4438 mem_buf);
4442 static void
4443 print_checkpoint_status(pool_checkpoint_stat_t *pcs)
4445 time_t start;
4446 char space_buf[7];
4448 if (pcs == NULL || pcs->pcs_state == CS_NONE)
4449 return;
4451 (void) printf(gettext("checkpoint: "));
4453 start = pcs->pcs_start_time;
4454 zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf));
4456 if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) {
4457 char *date = ctime(&start);
4460 * ctime() adds a newline at the end of the generated
4461 * string, thus the weird format specifier and the
4462 * strlen() call used to chop it off from the output.
4464 (void) printf(gettext("created %.*s, consumes %s\n"),
4465 strlen(date) - 1, date, space_buf);
4466 return;
4469 assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
4471 (void) printf(gettext("discarding, %s remaining.\n"),
4472 space_buf);
4475 static void
4476 print_error_log(zpool_handle_t *zhp)
4478 nvlist_t *nverrlist = NULL;
4479 nvpair_t *elem;
4480 char *pathname;
4481 size_t len = MAXPATHLEN * 2;
4483 if (zpool_get_errlog(zhp, &nverrlist) != 0) {
4484 (void) printf("errors: List of errors unavailable "
4485 "(insufficient privileges)\n");
4486 return;
4489 (void) printf("errors: Permanent errors have been "
4490 "detected in the following files:\n\n");
4492 pathname = safe_malloc(len);
4493 elem = NULL;
4494 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
4495 nvlist_t *nv;
4496 uint64_t dsobj, obj;
4498 verify(nvpair_value_nvlist(elem, &nv) == 0);
4499 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
4500 &dsobj) == 0);
4501 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
4502 &obj) == 0);
4503 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
4504 (void) printf("%7s %s\n", "", pathname);
4506 free(pathname);
4507 nvlist_free(nverrlist);
4510 static void
4511 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
4512 int namewidth)
4514 uint_t i;
4515 char *name;
4517 if (nspares == 0)
4518 return;
4520 (void) printf(gettext("\tspares\n"));
4522 for (i = 0; i < nspares; i++) {
4523 name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE);
4524 print_status_config(zhp, name, spares[i],
4525 namewidth, 2, B_TRUE);
4526 free(name);
4530 static void
4531 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
4532 int namewidth)
4534 uint_t i;
4535 char *name;
4537 if (nl2cache == 0)
4538 return;
4540 (void) printf(gettext("\tcache\n"));
4542 for (i = 0; i < nl2cache; i++) {
4543 name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE);
4544 print_status_config(zhp, name, l2cache[i],
4545 namewidth, 2, B_FALSE);
4546 free(name);
4550 static void
4551 print_dedup_stats(nvlist_t *config)
4553 ddt_histogram_t *ddh;
4554 ddt_stat_t *dds;
4555 ddt_object_t *ddo;
4556 uint_t c;
4559 * If the pool was faulted then we may not have been able to
4560 * obtain the config. Otherwise, if we have anything in the dedup
4561 * table continue processing the stats.
4563 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
4564 (uint64_t **)&ddo, &c) != 0)
4565 return;
4567 (void) printf("\n");
4568 (void) printf(gettext(" dedup: "));
4569 if (ddo->ddo_count == 0) {
4570 (void) printf(gettext("no DDT entries\n"));
4571 return;
4574 (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
4575 (u_longlong_t)ddo->ddo_count,
4576 (u_longlong_t)ddo->ddo_dspace,
4577 (u_longlong_t)ddo->ddo_mspace);
4579 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
4580 (uint64_t **)&dds, &c) == 0);
4581 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
4582 (uint64_t **)&ddh, &c) == 0);
4583 zpool_dump_ddt(dds, ddh);
4587 * Display a summary of pool status. Displays a summary such as:
4589 * pool: tank
4590 * status: DEGRADED
4591 * reason: One or more devices ...
4592 * see: http://illumos.org/msg/ZFS-xxxx-01
4593 * config:
4594 * mirror DEGRADED
4595 * c1t0d0 OK
4596 * c2t0d0 UNAVAIL
4598 * When given the '-v' option, we print out the complete config. If the '-e'
4599 * option is specified, then we print out error rate information as well.
4602 status_callback(zpool_handle_t *zhp, void *data)
4604 status_cbdata_t *cbp = data;
4605 nvlist_t *config, *nvroot;
4606 char *msgid;
4607 int reason;
4608 const char *health;
4609 uint_t c;
4610 vdev_stat_t *vs;
4612 config = zpool_get_config(zhp, NULL);
4613 reason = zpool_get_status(zhp, &msgid);
4615 cbp->cb_count++;
4618 * If we were given 'zpool status -x', only report those pools with
4619 * problems.
4621 if (cbp->cb_explain &&
4622 (reason == ZPOOL_STATUS_OK ||
4623 reason == ZPOOL_STATUS_VERSION_OLDER ||
4624 reason == ZPOOL_STATUS_FEAT_DISABLED)) {
4625 if (!cbp->cb_allpools) {
4626 (void) printf(gettext("pool '%s' is healthy\n"),
4627 zpool_get_name(zhp));
4628 if (cbp->cb_first)
4629 cbp->cb_first = B_FALSE;
4631 return (0);
4634 if (cbp->cb_first)
4635 cbp->cb_first = B_FALSE;
4636 else
4637 (void) printf("\n");
4639 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4640 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
4641 (uint64_t **)&vs, &c) == 0);
4642 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
4644 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
4645 (void) printf(gettext(" state: %s\n"), health);
4647 switch (reason) {
4648 case ZPOOL_STATUS_MISSING_DEV_R:
4649 (void) printf(gettext("status: One or more devices could not "
4650 "be opened. Sufficient replicas exist for\n\tthe pool to "
4651 "continue functioning in a degraded state.\n"));
4652 (void) printf(gettext("action: Attach the missing device and "
4653 "online it using 'zpool online'.\n"));
4654 break;
4656 case ZPOOL_STATUS_MISSING_DEV_NR:
4657 (void) printf(gettext("status: One or more devices could not "
4658 "be opened. There are insufficient\n\treplicas for the "
4659 "pool to continue functioning.\n"));
4660 (void) printf(gettext("action: Attach the missing device and "
4661 "online it using 'zpool online'.\n"));
4662 break;
4664 case ZPOOL_STATUS_CORRUPT_LABEL_R:
4665 (void) printf(gettext("status: One or more devices could not "
4666 "be used because the label is missing or\n\tinvalid. "
4667 "Sufficient replicas exist for the pool to continue\n\t"
4668 "functioning in a degraded state.\n"));
4669 (void) printf(gettext("action: Replace the device using "
4670 "'zpool replace'.\n"));
4671 break;
4673 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
4674 (void) printf(gettext("status: One or more devices could not "
4675 "be used because the label is missing \n\tor invalid. "
4676 "There are insufficient replicas for the pool to "
4677 "continue\n\tfunctioning.\n"));
4678 zpool_explain_recover(zpool_get_handle(zhp),
4679 zpool_get_name(zhp), reason, config);
4680 break;
4682 case ZPOOL_STATUS_FAILING_DEV:
4683 (void) printf(gettext("status: One or more devices has "
4684 "experienced an unrecoverable error. An\n\tattempt was "
4685 "made to correct the error. Applications are "
4686 "unaffected.\n"));
4687 (void) printf(gettext("action: Determine if the device needs "
4688 "to be replaced, and clear the errors\n\tusing "
4689 "'zpool clear' or replace the device with 'zpool "
4690 "replace'.\n"));
4691 break;
4693 case ZPOOL_STATUS_OFFLINE_DEV:
4694 (void) printf(gettext("status: One or more devices has "
4695 "been taken offline by the administrator.\n\tSufficient "
4696 "replicas exist for the pool to continue functioning in "
4697 "a\n\tdegraded state.\n"));
4698 (void) printf(gettext("action: Online the device using "
4699 "'zpool online' or replace the device with\n\t'zpool "
4700 "replace'.\n"));
4701 break;
4703 case ZPOOL_STATUS_REMOVED_DEV:
4704 (void) printf(gettext("status: One or more devices has "
4705 "been removed by the administrator.\n\tSufficient "
4706 "replicas exist for the pool to continue functioning in "
4707 "a\n\tdegraded state.\n"));
4708 (void) printf(gettext("action: Online the device using "
4709 "'zpool online' or replace the device with\n\t'zpool "
4710 "replace'.\n"));
4711 break;
4713 case ZPOOL_STATUS_RESILVERING:
4714 (void) printf(gettext("status: One or more devices is "
4715 "currently being resilvered. The pool will\n\tcontinue "
4716 "to function, possibly in a degraded state.\n"));
4717 (void) printf(gettext("action: Wait for the resilver to "
4718 "complete.\n"));
4719 break;
4721 case ZPOOL_STATUS_CORRUPT_DATA:
4722 (void) printf(gettext("status: One or more devices has "
4723 "experienced an error resulting in data\n\tcorruption. "
4724 "Applications may be affected.\n"));
4725 (void) printf(gettext("action: Restore the file in question "
4726 "if possible. Otherwise restore the\n\tentire pool from "
4727 "backup.\n"));
4728 break;
4730 case ZPOOL_STATUS_CORRUPT_POOL:
4731 (void) printf(gettext("status: The pool metadata is corrupted "
4732 "and the pool cannot be opened.\n"));
4733 zpool_explain_recover(zpool_get_handle(zhp),
4734 zpool_get_name(zhp), reason, config);
4735 break;
4737 case ZPOOL_STATUS_VERSION_OLDER:
4738 (void) printf(gettext("status: The pool is formatted using a "
4739 "legacy on-disk format. The pool can\n\tstill be used, "
4740 "but some features are unavailable.\n"));
4741 (void) printf(gettext("action: Upgrade the pool using 'zpool "
4742 "upgrade'. Once this is done, the\n\tpool will no longer "
4743 "be accessible on software that does not support feature\n"
4744 "\tflags.\n"));
4745 break;
4747 case ZPOOL_STATUS_VERSION_NEWER:
4748 (void) printf(gettext("status: The pool has been upgraded to a "
4749 "newer, incompatible on-disk version.\n\tThe pool cannot "
4750 "be accessed on this system.\n"));
4751 (void) printf(gettext("action: Access the pool from a system "
4752 "running more recent software, or\n\trestore the pool from "
4753 "backup.\n"));
4754 break;
4756 case ZPOOL_STATUS_FEAT_DISABLED:
4757 (void) printf(gettext("status: Some supported features are not "
4758 "enabled on the pool. The pool can\n\tstill be used, but "
4759 "some features are unavailable.\n"));
4760 (void) printf(gettext("action: Enable all features using "
4761 "'zpool upgrade'. Once this is done,\n\tthe pool may no "
4762 "longer be accessible by software that does not support\n\t"
4763 "the features. See zpool-features(5) for details.\n"));
4764 break;
4766 case ZPOOL_STATUS_UNSUP_FEAT_READ:
4767 (void) printf(gettext("status: The pool cannot be accessed on "
4768 "this system because it uses the\n\tfollowing feature(s) "
4769 "not supported on this system:\n"));
4770 zpool_print_unsup_feat(config);
4771 (void) printf("\n");
4772 (void) printf(gettext("action: Access the pool from a system "
4773 "that supports the required feature(s),\n\tor restore the "
4774 "pool from backup.\n"));
4775 break;
4777 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
4778 (void) printf(gettext("status: The pool can only be accessed "
4779 "in read-only mode on this system. It\n\tcannot be "
4780 "accessed in read-write mode because it uses the "
4781 "following\n\tfeature(s) not supported on this system:\n"));
4782 zpool_print_unsup_feat(config);
4783 (void) printf("\n");
4784 (void) printf(gettext("action: The pool cannot be accessed in "
4785 "read-write mode. Import the pool with\n"
4786 "\t\"-o readonly=on\", access the pool from a system that "
4787 "supports the\n\trequired feature(s), or restore the "
4788 "pool from backup.\n"));
4789 break;
4791 case ZPOOL_STATUS_FAULTED_DEV_R:
4792 (void) printf(gettext("status: One or more devices are "
4793 "faulted in response to persistent errors.\n\tSufficient "
4794 "replicas exist for the pool to continue functioning "
4795 "in a\n\tdegraded state.\n"));
4796 (void) printf(gettext("action: Replace the faulted device, "
4797 "or use 'zpool clear' to mark the device\n\trepaired.\n"));
4798 break;
4800 case ZPOOL_STATUS_FAULTED_DEV_NR:
4801 (void) printf(gettext("status: One or more devices are "
4802 "faulted in response to persistent errors. There are "
4803 "insufficient replicas for the pool to\n\tcontinue "
4804 "functioning.\n"));
4805 (void) printf(gettext("action: Destroy and re-create the pool "
4806 "from a backup source. Manually marking the device\n"
4807 "\trepaired using 'zpool clear' may allow some data "
4808 "to be recovered.\n"));
4809 break;
4811 case ZPOOL_STATUS_IO_FAILURE_WAIT:
4812 case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
4813 (void) printf(gettext("status: One or more devices are "
4814 "faulted in response to IO failures.\n"));
4815 (void) printf(gettext("action: Make sure the affected devices "
4816 "are connected, then run 'zpool clear'.\n"));
4817 break;
4819 case ZPOOL_STATUS_BAD_LOG:
4820 (void) printf(gettext("status: An intent log record "
4821 "could not be read.\n"
4822 "\tWaiting for adminstrator intervention to fix the "
4823 "faulted pool.\n"));
4824 (void) printf(gettext("action: Either restore the affected "
4825 "device(s) and run 'zpool online',\n"
4826 "\tor ignore the intent log records by running "
4827 "'zpool clear'.\n"));
4828 break;
4830 default:
4832 * The remaining errors can't actually be generated, yet.
4834 assert(reason == ZPOOL_STATUS_OK);
4837 if (msgid != NULL)
4838 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
4839 msgid);
4841 if (config != NULL) {
4842 int namewidth;
4843 uint64_t nerr;
4844 nvlist_t **spares, **l2cache;
4845 uint_t nspares, nl2cache;
4846 pool_checkpoint_stat_t *pcs = NULL;
4847 pool_scan_stat_t *ps = NULL;
4848 pool_removal_stat_t *prs = NULL;
4850 (void) nvlist_lookup_uint64_array(nvroot,
4851 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
4852 (void) nvlist_lookup_uint64_array(nvroot,
4853 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4854 (void) nvlist_lookup_uint64_array(nvroot,
4855 ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
4857 print_scan_status(ps);
4858 print_checkpoint_scan_warning(ps, pcs);
4859 print_removal_status(zhp, prs);
4860 print_checkpoint_status(pcs);
4862 namewidth = max_width(zhp, nvroot, 0, 0);
4863 if (namewidth < 10)
4864 namewidth = 10;
4866 (void) printf(gettext("config:\n\n"));
4867 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth,
4868 "NAME", "STATE", "READ", "WRITE", "CKSUM");
4869 print_status_config(zhp, zpool_get_name(zhp), nvroot,
4870 namewidth, 0, B_FALSE);
4872 if (num_logs(nvroot) > 0)
4873 print_logs(zhp, nvroot, namewidth, B_TRUE);
4874 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
4875 &l2cache, &nl2cache) == 0)
4876 print_l2cache(zhp, l2cache, nl2cache, namewidth);
4878 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
4879 &spares, &nspares) == 0)
4880 print_spares(zhp, spares, nspares, namewidth);
4882 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
4883 &nerr) == 0) {
4884 nvlist_t *nverrlist = NULL;
4887 * If the approximate error count is small, get a
4888 * precise count by fetching the entire log and
4889 * uniquifying the results.
4891 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
4892 zpool_get_errlog(zhp, &nverrlist) == 0) {
4893 nvpair_t *elem;
4895 elem = NULL;
4896 nerr = 0;
4897 while ((elem = nvlist_next_nvpair(nverrlist,
4898 elem)) != NULL) {
4899 nerr++;
4902 nvlist_free(nverrlist);
4904 (void) printf("\n");
4906 if (nerr == 0)
4907 (void) printf(gettext("errors: No known data "
4908 "errors\n"));
4909 else if (!cbp->cb_verbose)
4910 (void) printf(gettext("errors: %llu data "
4911 "errors, use '-v' for a list\n"),
4912 (u_longlong_t)nerr);
4913 else
4914 print_error_log(zhp);
4917 if (cbp->cb_dedup_stats)
4918 print_dedup_stats(config);
4919 } else {
4920 (void) printf(gettext("config: The configuration cannot be "
4921 "determined.\n"));
4924 return (0);
4928 * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
4930 * -v Display complete error logs
4931 * -x Display only pools with potential problems
4932 * -D Display dedup status (undocumented)
4933 * -T Display a timestamp in date(1) or Unix format
4935 * Describes the health status of all pools or some subset.
4938 zpool_do_status(int argc, char **argv)
4940 int c;
4941 int ret;
4942 unsigned long interval = 0, count = 0;
4943 status_cbdata_t cb = { 0 };
4945 /* check options */
4946 while ((c = getopt(argc, argv, "vxDT:")) != -1) {
4947 switch (c) {
4948 case 'v':
4949 cb.cb_verbose = B_TRUE;
4950 break;
4951 case 'x':
4952 cb.cb_explain = B_TRUE;
4953 break;
4954 case 'D':
4955 cb.cb_dedup_stats = B_TRUE;
4956 break;
4957 case 'T':
4958 get_timestamp_arg(*optarg);
4959 break;
4960 case '?':
4961 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4962 optopt);
4963 usage(B_FALSE);
4967 argc -= optind;
4968 argv += optind;
4970 get_interval_count(&argc, argv, &interval, &count);
4972 if (argc == 0)
4973 cb.cb_allpools = B_TRUE;
4975 cb.cb_first = B_TRUE;
4977 for (;;) {
4978 if (timestamp_fmt != NODATE)
4979 print_timestamp(timestamp_fmt);
4981 ret = for_each_pool(argc, argv, B_TRUE, NULL,
4982 status_callback, &cb);
4984 if (argc == 0 && cb.cb_count == 0)
4985 (void) printf(gettext("no pools available\n"));
4986 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
4987 (void) printf(gettext("all pools are healthy\n"));
4989 if (ret != 0)
4990 return (ret);
4992 if (interval == 0)
4993 break;
4995 if (count != 0 && --count == 0)
4996 break;
4998 (void) sleep(interval);
5001 return (0);
5004 typedef struct upgrade_cbdata {
5005 int cb_first;
5006 int cb_argc;
5007 uint64_t cb_version;
5008 char **cb_argv;
5009 } upgrade_cbdata_t;
5011 static int
5012 upgrade_version(zpool_handle_t *zhp, uint64_t version)
5014 int ret;
5015 nvlist_t *config;
5016 uint64_t oldversion;
5018 config = zpool_get_config(zhp, NULL);
5019 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5020 &oldversion) == 0);
5022 assert(SPA_VERSION_IS_SUPPORTED(oldversion));
5023 assert(oldversion < version);
5025 ret = zpool_upgrade(zhp, version);
5026 if (ret != 0)
5027 return (ret);
5029 if (version >= SPA_VERSION_FEATURES) {
5030 (void) printf(gettext("Successfully upgraded "
5031 "'%s' from version %llu to feature flags.\n"),
5032 zpool_get_name(zhp), oldversion);
5033 } else {
5034 (void) printf(gettext("Successfully upgraded "
5035 "'%s' from version %llu to version %llu.\n"),
5036 zpool_get_name(zhp), oldversion, version);
5039 return (0);
5042 static int
5043 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
5045 int i, ret, count;
5046 boolean_t firstff = B_TRUE;
5047 nvlist_t *enabled = zpool_get_features(zhp);
5049 count = 0;
5050 for (i = 0; i < SPA_FEATURES; i++) {
5051 const char *fname = spa_feature_table[i].fi_uname;
5052 const char *fguid = spa_feature_table[i].fi_guid;
5053 if (!nvlist_exists(enabled, fguid)) {
5054 char *propname;
5055 verify(-1 != asprintf(&propname, "feature@%s", fname));
5056 ret = zpool_set_prop(zhp, propname,
5057 ZFS_FEATURE_ENABLED);
5058 if (ret != 0) {
5059 free(propname);
5060 return (ret);
5062 count++;
5064 if (firstff) {
5065 (void) printf(gettext("Enabled the "
5066 "following features on '%s':\n"),
5067 zpool_get_name(zhp));
5068 firstff = B_FALSE;
5070 (void) printf(gettext(" %s\n"), fname);
5071 free(propname);
5075 if (countp != NULL)
5076 *countp = count;
5077 return (0);
5080 static int
5081 upgrade_cb(zpool_handle_t *zhp, void *arg)
5083 upgrade_cbdata_t *cbp = arg;
5084 nvlist_t *config;
5085 uint64_t version;
5086 boolean_t printnl = B_FALSE;
5087 int ret;
5089 config = zpool_get_config(zhp, NULL);
5090 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5091 &version) == 0);
5093 assert(SPA_VERSION_IS_SUPPORTED(version));
5095 if (version < cbp->cb_version) {
5096 cbp->cb_first = B_FALSE;
5097 ret = upgrade_version(zhp, cbp->cb_version);
5098 if (ret != 0)
5099 return (ret);
5100 printnl = B_TRUE;
5103 * If they did "zpool upgrade -a", then we could
5104 * be doing ioctls to different pools. We need
5105 * to log this history once to each pool, and bypass
5106 * the normal history logging that happens in main().
5108 (void) zpool_log_history(g_zfs, history_str);
5109 log_history = B_FALSE;
5112 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5113 int count;
5114 ret = upgrade_enable_all(zhp, &count);
5115 if (ret != 0)
5116 return (ret);
5118 if (count > 0) {
5119 cbp->cb_first = B_FALSE;
5120 printnl = B_TRUE;
5124 if (printnl) {
5125 (void) printf(gettext("\n"));
5128 return (0);
5131 static int
5132 upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
5134 upgrade_cbdata_t *cbp = arg;
5135 nvlist_t *config;
5136 uint64_t version;
5138 config = zpool_get_config(zhp, NULL);
5139 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5140 &version) == 0);
5142 assert(SPA_VERSION_IS_SUPPORTED(version));
5144 if (version < SPA_VERSION_FEATURES) {
5145 if (cbp->cb_first) {
5146 (void) printf(gettext("The following pools are "
5147 "formatted with legacy version numbers and can\n"
5148 "be upgraded to use feature flags. After "
5149 "being upgraded, these pools\nwill no "
5150 "longer be accessible by software that does not "
5151 "support feature\nflags.\n\n"));
5152 (void) printf(gettext("VER POOL\n"));
5153 (void) printf(gettext("--- ------------\n"));
5154 cbp->cb_first = B_FALSE;
5157 (void) printf("%2llu %s\n", (u_longlong_t)version,
5158 zpool_get_name(zhp));
5161 return (0);
5164 static int
5165 upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
5167 upgrade_cbdata_t *cbp = arg;
5168 nvlist_t *config;
5169 uint64_t version;
5171 config = zpool_get_config(zhp, NULL);
5172 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5173 &version) == 0);
5175 if (version >= SPA_VERSION_FEATURES) {
5176 int i;
5177 boolean_t poolfirst = B_TRUE;
5178 nvlist_t *enabled = zpool_get_features(zhp);
5180 for (i = 0; i < SPA_FEATURES; i++) {
5181 const char *fguid = spa_feature_table[i].fi_guid;
5182 const char *fname = spa_feature_table[i].fi_uname;
5183 if (!nvlist_exists(enabled, fguid)) {
5184 if (cbp->cb_first) {
5185 (void) printf(gettext("\nSome "
5186 "supported features are not "
5187 "enabled on the following pools. "
5188 "Once a\nfeature is enabled the "
5189 "pool may become incompatible with "
5190 "software\nthat does not support "
5191 "the feature. See "
5192 "zpool-features(5) for "
5193 "details.\n\n"));
5194 (void) printf(gettext("POOL "
5195 "FEATURE\n"));
5196 (void) printf(gettext("------"
5197 "---------\n"));
5198 cbp->cb_first = B_FALSE;
5201 if (poolfirst) {
5202 (void) printf(gettext("%s\n"),
5203 zpool_get_name(zhp));
5204 poolfirst = B_FALSE;
5207 (void) printf(gettext(" %s\n"), fname);
5212 return (0);
5215 /* ARGSUSED */
5216 static int
5217 upgrade_one(zpool_handle_t *zhp, void *data)
5219 boolean_t printnl = B_FALSE;
5220 upgrade_cbdata_t *cbp = data;
5221 uint64_t cur_version;
5222 int ret;
5224 if (strcmp("log", zpool_get_name(zhp)) == 0) {
5225 (void) printf(gettext("'log' is now a reserved word\n"
5226 "Pool 'log' must be renamed using export and import"
5227 " to upgrade.\n"));
5228 return (1);
5231 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
5232 if (cur_version > cbp->cb_version) {
5233 (void) printf(gettext("Pool '%s' is already formatted "
5234 "using more current version '%llu'.\n\n"),
5235 zpool_get_name(zhp), cur_version);
5236 return (0);
5239 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
5240 (void) printf(gettext("Pool '%s' is already formatted "
5241 "using version %llu.\n\n"), zpool_get_name(zhp),
5242 cbp->cb_version);
5243 return (0);
5246 if (cur_version != cbp->cb_version) {
5247 printnl = B_TRUE;
5248 ret = upgrade_version(zhp, cbp->cb_version);
5249 if (ret != 0)
5250 return (ret);
5253 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5254 int count = 0;
5255 ret = upgrade_enable_all(zhp, &count);
5256 if (ret != 0)
5257 return (ret);
5259 if (count != 0) {
5260 printnl = B_TRUE;
5261 } else if (cur_version == SPA_VERSION) {
5262 (void) printf(gettext("Pool '%s' already has all "
5263 "supported features enabled.\n"),
5264 zpool_get_name(zhp));
5268 if (printnl) {
5269 (void) printf(gettext("\n"));
5272 return (0);
5276 * zpool upgrade
5277 * zpool upgrade -v
5278 * zpool upgrade [-V version] <-a | pool ...>
5280 * With no arguments, display downrev'd ZFS pool available for upgrade.
5281 * Individual pools can be upgraded by specifying the pool, and '-a' will
5282 * upgrade all pools.
5285 zpool_do_upgrade(int argc, char **argv)
5287 int c;
5288 upgrade_cbdata_t cb = { 0 };
5289 int ret = 0;
5290 boolean_t showversions = B_FALSE;
5291 boolean_t upgradeall = B_FALSE;
5292 char *end;
5295 /* check options */
5296 while ((c = getopt(argc, argv, ":avV:")) != -1) {
5297 switch (c) {
5298 case 'a':
5299 upgradeall = B_TRUE;
5300 break;
5301 case 'v':
5302 showversions = B_TRUE;
5303 break;
5304 case 'V':
5305 cb.cb_version = strtoll(optarg, &end, 10);
5306 if (*end != '\0' ||
5307 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
5308 (void) fprintf(stderr,
5309 gettext("invalid version '%s'\n"), optarg);
5310 usage(B_FALSE);
5312 break;
5313 case ':':
5314 (void) fprintf(stderr, gettext("missing argument for "
5315 "'%c' option\n"), optopt);
5316 usage(B_FALSE);
5317 break;
5318 case '?':
5319 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5320 optopt);
5321 usage(B_FALSE);
5325 cb.cb_argc = argc;
5326 cb.cb_argv = argv;
5327 argc -= optind;
5328 argv += optind;
5330 if (cb.cb_version == 0) {
5331 cb.cb_version = SPA_VERSION;
5332 } else if (!upgradeall && argc == 0) {
5333 (void) fprintf(stderr, gettext("-V option is "
5334 "incompatible with other arguments\n"));
5335 usage(B_FALSE);
5338 if (showversions) {
5339 if (upgradeall || argc != 0) {
5340 (void) fprintf(stderr, gettext("-v option is "
5341 "incompatible with other arguments\n"));
5342 usage(B_FALSE);
5344 } else if (upgradeall) {
5345 if (argc != 0) {
5346 (void) fprintf(stderr, gettext("-a option should not "
5347 "be used along with a pool name\n"));
5348 usage(B_FALSE);
5352 (void) printf(gettext("This system supports ZFS pool feature "
5353 "flags.\n\n"));
5354 if (showversions) {
5355 int i;
5357 (void) printf(gettext("The following features are "
5358 "supported:\n\n"));
5359 (void) printf(gettext("FEAT DESCRIPTION\n"));
5360 (void) printf("----------------------------------------------"
5361 "---------------\n");
5362 for (i = 0; i < SPA_FEATURES; i++) {
5363 zfeature_info_t *fi = &spa_feature_table[i];
5364 const char *ro =
5365 (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
5366 " (read-only compatible)" : "";
5368 (void) printf("%-37s%s\n", fi->fi_uname, ro);
5369 (void) printf(" %s\n", fi->fi_desc);
5371 (void) printf("\n");
5373 (void) printf(gettext("The following legacy versions are also "
5374 "supported:\n\n"));
5375 (void) printf(gettext("VER DESCRIPTION\n"));
5376 (void) printf("--- -----------------------------------------"
5377 "---------------\n");
5378 (void) printf(gettext(" 1 Initial ZFS version\n"));
5379 (void) printf(gettext(" 2 Ditto blocks "
5380 "(replicated metadata)\n"));
5381 (void) printf(gettext(" 3 Hot spares and double parity "
5382 "RAID-Z\n"));
5383 (void) printf(gettext(" 4 zpool history\n"));
5384 (void) printf(gettext(" 5 Compression using the gzip "
5385 "algorithm\n"));
5386 (void) printf(gettext(" 6 bootfs pool property\n"));
5387 (void) printf(gettext(" 7 Separate intent log devices\n"));
5388 (void) printf(gettext(" 8 Delegated administration\n"));
5389 (void) printf(gettext(" 9 refquota and refreservation "
5390 "properties\n"));
5391 (void) printf(gettext(" 10 Cache devices\n"));
5392 (void) printf(gettext(" 11 Improved scrub performance\n"));
5393 (void) printf(gettext(" 12 Snapshot properties\n"));
5394 (void) printf(gettext(" 13 snapused property\n"));
5395 (void) printf(gettext(" 14 passthrough-x aclinherit\n"));
5396 (void) printf(gettext(" 15 user/group space accounting\n"));
5397 (void) printf(gettext(" 16 stmf property support\n"));
5398 (void) printf(gettext(" 17 Triple-parity RAID-Z\n"));
5399 (void) printf(gettext(" 18 Snapshot user holds\n"));
5400 (void) printf(gettext(" 19 Log device removal\n"));
5401 (void) printf(gettext(" 20 Compression using zle "
5402 "(zero-length encoding)\n"));
5403 (void) printf(gettext(" 21 Deduplication\n"));
5404 (void) printf(gettext(" 22 Received properties\n"));
5405 (void) printf(gettext(" 23 Slim ZIL\n"));
5406 (void) printf(gettext(" 24 System attributes\n"));
5407 (void) printf(gettext(" 25 Improved scrub stats\n"));
5408 (void) printf(gettext(" 26 Improved snapshot deletion "
5409 "performance\n"));
5410 (void) printf(gettext(" 27 Improved snapshot creation "
5411 "performance\n"));
5412 (void) printf(gettext(" 28 Multiple vdev replacements\n"));
5413 (void) printf(gettext("\nFor more information on a particular "
5414 "version, including supported releases,\n"));
5415 (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
5416 } else if (argc == 0 && upgradeall) {
5417 cb.cb_first = B_TRUE;
5418 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
5419 if (ret == 0 && cb.cb_first) {
5420 if (cb.cb_version == SPA_VERSION) {
5421 (void) printf(gettext("All pools are already "
5422 "formatted using feature flags.\n\n"));
5423 (void) printf(gettext("Every feature flags "
5424 "pool already has all supported features "
5425 "enabled.\n"));
5426 } else {
5427 (void) printf(gettext("All pools are already "
5428 "formatted with version %llu or higher.\n"),
5429 cb.cb_version);
5432 } else if (argc == 0) {
5433 cb.cb_first = B_TRUE;
5434 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
5435 assert(ret == 0);
5437 if (cb.cb_first) {
5438 (void) printf(gettext("All pools are formatted "
5439 "using feature flags.\n\n"));
5440 } else {
5441 (void) printf(gettext("\nUse 'zpool upgrade -v' "
5442 "for a list of available legacy versions.\n"));
5445 cb.cb_first = B_TRUE;
5446 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
5447 assert(ret == 0);
5449 if (cb.cb_first) {
5450 (void) printf(gettext("Every feature flags pool has "
5451 "all supported features enabled.\n"));
5452 } else {
5453 (void) printf(gettext("\n"));
5455 } else {
5456 ret = for_each_pool(argc, argv, B_FALSE, NULL,
5457 upgrade_one, &cb);
5460 return (ret);
5463 typedef struct hist_cbdata {
5464 boolean_t first;
5465 boolean_t longfmt;
5466 boolean_t internal;
5467 } hist_cbdata_t;
5470 * Print out the command history for a specific pool.
5472 static int
5473 get_history_one(zpool_handle_t *zhp, void *data)
5475 nvlist_t *nvhis;
5476 nvlist_t **records;
5477 uint_t numrecords;
5478 int ret, i;
5479 hist_cbdata_t *cb = (hist_cbdata_t *)data;
5481 cb->first = B_FALSE;
5483 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
5485 if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
5486 return (ret);
5488 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
5489 &records, &numrecords) == 0);
5490 for (i = 0; i < numrecords; i++) {
5491 nvlist_t *rec = records[i];
5492 char tbuf[30] = "";
5494 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
5495 time_t tsec;
5496 struct tm t;
5498 tsec = fnvlist_lookup_uint64(records[i],
5499 ZPOOL_HIST_TIME);
5500 (void) localtime_r(&tsec, &t);
5501 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
5504 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
5505 (void) printf("%s %s", tbuf,
5506 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
5507 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
5508 int ievent =
5509 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
5510 if (!cb->internal)
5511 continue;
5512 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
5513 (void) printf("%s unrecognized record:\n",
5514 tbuf);
5515 dump_nvlist(rec, 4);
5516 continue;
5518 (void) printf("%s [internal %s txg:%lld] %s", tbuf,
5519 zfs_history_event_names[ievent],
5520 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5521 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
5522 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
5523 if (!cb->internal)
5524 continue;
5525 (void) printf("%s [txg:%lld] %s", tbuf,
5526 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5527 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
5528 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
5529 (void) printf(" %s (%llu)",
5530 fnvlist_lookup_string(rec,
5531 ZPOOL_HIST_DSNAME),
5532 fnvlist_lookup_uint64(rec,
5533 ZPOOL_HIST_DSID));
5535 (void) printf(" %s", fnvlist_lookup_string(rec,
5536 ZPOOL_HIST_INT_STR));
5537 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
5538 if (!cb->internal)
5539 continue;
5540 (void) printf("%s ioctl %s\n", tbuf,
5541 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
5542 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
5543 (void) printf(" input:\n");
5544 dump_nvlist(fnvlist_lookup_nvlist(rec,
5545 ZPOOL_HIST_INPUT_NVL), 8);
5547 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
5548 (void) printf(" output:\n");
5549 dump_nvlist(fnvlist_lookup_nvlist(rec,
5550 ZPOOL_HIST_OUTPUT_NVL), 8);
5552 if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
5553 (void) printf(" errno: %lld\n",
5554 fnvlist_lookup_int64(rec,
5555 ZPOOL_HIST_ERRNO));
5557 } else {
5558 if (!cb->internal)
5559 continue;
5560 (void) printf("%s unrecognized record:\n", tbuf);
5561 dump_nvlist(rec, 4);
5564 if (!cb->longfmt) {
5565 (void) printf("\n");
5566 continue;
5568 (void) printf(" [");
5569 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
5570 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
5571 struct passwd *pwd = getpwuid(who);
5572 (void) printf("user %d ", (int)who);
5573 if (pwd != NULL)
5574 (void) printf("(%s) ", pwd->pw_name);
5576 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
5577 (void) printf("on %s",
5578 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
5580 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
5581 (void) printf(":%s",
5582 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
5584 (void) printf("]");
5585 (void) printf("\n");
5587 (void) printf("\n");
5588 nvlist_free(nvhis);
5590 return (ret);
5594 * zpool history <pool>
5596 * Displays the history of commands that modified pools.
5599 zpool_do_history(int argc, char **argv)
5601 hist_cbdata_t cbdata = { 0 };
5602 int ret;
5603 int c;
5605 cbdata.first = B_TRUE;
5606 /* check options */
5607 while ((c = getopt(argc, argv, "li")) != -1) {
5608 switch (c) {
5609 case 'l':
5610 cbdata.longfmt = B_TRUE;
5611 break;
5612 case 'i':
5613 cbdata.internal = B_TRUE;
5614 break;
5615 case '?':
5616 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5617 optopt);
5618 usage(B_FALSE);
5621 argc -= optind;
5622 argv += optind;
5624 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one,
5625 &cbdata);
5627 if (argc == 0 && cbdata.first == B_TRUE) {
5628 (void) printf(gettext("no pools available\n"));
5629 return (0);
5632 return (ret);
5635 static int
5636 get_callback(zpool_handle_t *zhp, void *data)
5638 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
5639 char value[MAXNAMELEN];
5640 zprop_source_t srctype;
5641 zprop_list_t *pl;
5643 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
5646 * Skip the special fake placeholder. This will also skip
5647 * over the name property when 'all' is specified.
5649 if (pl->pl_prop == ZPOOL_PROP_NAME &&
5650 pl == cbp->cb_proplist)
5651 continue;
5653 if (pl->pl_prop == ZPROP_INVAL &&
5654 (zpool_prop_feature(pl->pl_user_prop) ||
5655 zpool_prop_unsupported(pl->pl_user_prop))) {
5656 srctype = ZPROP_SRC_LOCAL;
5658 if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
5659 value, sizeof (value)) == 0) {
5660 zprop_print_one_property(zpool_get_name(zhp),
5661 cbp, pl->pl_user_prop, value, srctype,
5662 NULL, NULL);
5664 } else {
5665 if (zpool_get_prop(zhp, pl->pl_prop, value,
5666 sizeof (value), &srctype, cbp->cb_literal) != 0)
5667 continue;
5669 zprop_print_one_property(zpool_get_name(zhp), cbp,
5670 zpool_prop_to_name(pl->pl_prop), value, srctype,
5671 NULL, NULL);
5674 return (0);
5678 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
5680 * -H Scripted mode. Don't display headers, and separate properties
5681 * by a single tab.
5682 * -o List of columns to display. Defaults to
5683 * "name,property,value,source".
5684 * -p Diplay values in parsable (exact) format.
5686 * Get properties of pools in the system. Output space statistics
5687 * for each one as well as other attributes.
5690 zpool_do_get(int argc, char **argv)
5692 zprop_get_cbdata_t cb = { 0 };
5693 zprop_list_t fake_name = { 0 };
5694 int ret;
5695 int c, i;
5696 char *value;
5698 cb.cb_first = B_TRUE;
5701 * Set up default columns and sources.
5703 cb.cb_sources = ZPROP_SRC_ALL;
5704 cb.cb_columns[0] = GET_COL_NAME;
5705 cb.cb_columns[1] = GET_COL_PROPERTY;
5706 cb.cb_columns[2] = GET_COL_VALUE;
5707 cb.cb_columns[3] = GET_COL_SOURCE;
5708 cb.cb_type = ZFS_TYPE_POOL;
5710 /* check options */
5711 while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
5712 switch (c) {
5713 case 'p':
5714 cb.cb_literal = B_TRUE;
5715 break;
5716 case 'H':
5717 cb.cb_scripted = B_TRUE;
5718 break;
5719 case 'o':
5720 bzero(&cb.cb_columns, sizeof (cb.cb_columns));
5721 i = 0;
5722 while (*optarg != '\0') {
5723 static char *col_subopts[] =
5724 { "name", "property", "value", "source",
5725 "all", NULL };
5727 if (i == ZFS_GET_NCOLS) {
5728 (void) fprintf(stderr, gettext("too "
5729 "many fields given to -o "
5730 "option\n"));
5731 usage(B_FALSE);
5734 switch (getsubopt(&optarg, col_subopts,
5735 &value)) {
5736 case 0:
5737 cb.cb_columns[i++] = GET_COL_NAME;
5738 break;
5739 case 1:
5740 cb.cb_columns[i++] = GET_COL_PROPERTY;
5741 break;
5742 case 2:
5743 cb.cb_columns[i++] = GET_COL_VALUE;
5744 break;
5745 case 3:
5746 cb.cb_columns[i++] = GET_COL_SOURCE;
5747 break;
5748 case 4:
5749 if (i > 0) {
5750 (void) fprintf(stderr,
5751 gettext("\"all\" conflicts "
5752 "with specific fields "
5753 "given to -o option\n"));
5754 usage(B_FALSE);
5756 cb.cb_columns[0] = GET_COL_NAME;
5757 cb.cb_columns[1] = GET_COL_PROPERTY;
5758 cb.cb_columns[2] = GET_COL_VALUE;
5759 cb.cb_columns[3] = GET_COL_SOURCE;
5760 i = ZFS_GET_NCOLS;
5761 break;
5762 default:
5763 (void) fprintf(stderr,
5764 gettext("invalid column name "
5765 "'%s'\n"), value);
5766 usage(B_FALSE);
5769 break;
5770 case '?':
5771 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5772 optopt);
5773 usage(B_FALSE);
5777 argc -= optind;
5778 argv += optind;
5780 if (argc < 1) {
5781 (void) fprintf(stderr, gettext("missing property "
5782 "argument\n"));
5783 usage(B_FALSE);
5786 if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
5787 ZFS_TYPE_POOL) != 0)
5788 usage(B_FALSE);
5790 argc--;
5791 argv++;
5793 if (cb.cb_proplist != NULL) {
5794 fake_name.pl_prop = ZPOOL_PROP_NAME;
5795 fake_name.pl_width = strlen(gettext("NAME"));
5796 fake_name.pl_next = cb.cb_proplist;
5797 cb.cb_proplist = &fake_name;
5800 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
5801 get_callback, &cb);
5803 if (cb.cb_proplist == &fake_name)
5804 zprop_free_list(fake_name.pl_next);
5805 else
5806 zprop_free_list(cb.cb_proplist);
5808 return (ret);
5811 typedef struct set_cbdata {
5812 char *cb_propname;
5813 char *cb_value;
5814 boolean_t cb_any_successful;
5815 } set_cbdata_t;
5818 set_callback(zpool_handle_t *zhp, void *data)
5820 int error;
5821 set_cbdata_t *cb = (set_cbdata_t *)data;
5823 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
5825 if (!error)
5826 cb->cb_any_successful = B_TRUE;
5828 return (error);
5832 zpool_do_set(int argc, char **argv)
5834 set_cbdata_t cb = { 0 };
5835 int error;
5837 if (argc > 1 && argv[1][0] == '-') {
5838 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5839 argv[1][1]);
5840 usage(B_FALSE);
5843 if (argc < 2) {
5844 (void) fprintf(stderr, gettext("missing property=value "
5845 "argument\n"));
5846 usage(B_FALSE);
5849 if (argc < 3) {
5850 (void) fprintf(stderr, gettext("missing pool name\n"));
5851 usage(B_FALSE);
5854 if (argc > 3) {
5855 (void) fprintf(stderr, gettext("too many pool names\n"));
5856 usage(B_FALSE);
5859 cb.cb_propname = argv[1];
5860 cb.cb_value = strchr(cb.cb_propname, '=');
5861 if (cb.cb_value == NULL) {
5862 (void) fprintf(stderr, gettext("missing value in "
5863 "property=value argument\n"));
5864 usage(B_FALSE);
5867 *(cb.cb_value) = '\0';
5868 cb.cb_value++;
5870 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
5871 set_callback, &cb);
5873 return (error);
5876 static int
5877 find_command_idx(char *command, int *idx)
5879 int i;
5881 for (i = 0; i < NCOMMAND; i++) {
5882 if (command_table[i].name == NULL)
5883 continue;
5885 if (strcmp(command, command_table[i].name) == 0) {
5886 *idx = i;
5887 return (0);
5890 return (1);
5894 main(int argc, char **argv)
5896 int ret = 0;
5897 int i;
5898 char *cmdname;
5900 (void) setlocale(LC_ALL, "");
5901 (void) textdomain(TEXT_DOMAIN);
5903 if ((g_zfs = libzfs_init()) == NULL) {
5904 (void) fprintf(stderr, gettext("internal error: failed to "
5905 "initialize ZFS library\n"));
5906 return (1);
5909 libzfs_print_on_error(g_zfs, B_TRUE);
5911 opterr = 0;
5914 * Make sure the user has specified some command.
5916 if (argc < 2) {
5917 (void) fprintf(stderr, gettext("missing command\n"));
5918 usage(B_FALSE);
5921 cmdname = argv[1];
5924 * Special case '-?'
5926 if (strcmp(cmdname, "-?") == 0)
5927 usage(B_TRUE);
5929 zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
5932 * Run the appropriate command.
5934 if (find_command_idx(cmdname, &i) == 0) {
5935 current_command = &command_table[i];
5936 ret = command_table[i].func(argc - 1, argv + 1);
5937 } else if (strchr(cmdname, '=')) {
5938 verify(find_command_idx("set", &i) == 0);
5939 current_command = &command_table[i];
5940 ret = command_table[i].func(argc, argv);
5941 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
5943 * 'freeze' is a vile debugging abomination, so we treat
5944 * it as such.
5946 char buf[16384];
5947 int fd = open(ZFS_DEV, O_RDWR);
5948 (void) strcpy((void *)buf, argv[2]);
5949 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
5950 } else {
5951 (void) fprintf(stderr, gettext("unrecognized "
5952 "command '%s'\n"), cmdname);
5953 usage(B_FALSE);
5956 if (ret == 0 && log_history)
5957 (void) zpool_log_history(g_zfs, history_str);
5959 libzfs_fini(g_zfs);
5962 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
5963 * for the purposes of running ::findleaks.
5965 if (getenv("ZFS_ABORT") != NULL) {
5966 (void) printf("dumping core by request\n");
5967 abort();
5970 return (ret);