6775357 ZFS should have a way to export a pool without touching anything
[illumos-gate.git] / usr / src / cmd / zpool / zpool_main.c
blob1bca45c80f7b2b9fb4090c27c10121ab1b223fed
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 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <assert.h>
28 #include <ctype.h>
29 #include <dirent.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <libgen.h>
33 #include <libintl.h>
34 #include <libuutil.h>
35 #include <locale.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <strings.h>
40 #include <unistd.h>
41 #include <priv.h>
42 #include <pwd.h>
43 #include <zone.h>
44 #include <sys/fs/zfs.h>
46 #include <sys/stat.h>
48 #include <libzfs.h>
50 #include "zpool_util.h"
51 #include "zfs_comutil.h"
53 static int zpool_do_create(int, char **);
54 static int zpool_do_destroy(int, char **);
56 static int zpool_do_add(int, char **);
57 static int zpool_do_remove(int, char **);
59 static int zpool_do_list(int, char **);
60 static int zpool_do_iostat(int, char **);
61 static int zpool_do_status(int, char **);
63 static int zpool_do_online(int, char **);
64 static int zpool_do_offline(int, char **);
65 static int zpool_do_clear(int, char **);
67 static int zpool_do_attach(int, char **);
68 static int zpool_do_detach(int, char **);
69 static int zpool_do_replace(int, char **);
71 static int zpool_do_scrub(int, char **);
73 static int zpool_do_import(int, char **);
74 static int zpool_do_export(int, char **);
76 static int zpool_do_upgrade(int, char **);
78 static int zpool_do_history(int, char **);
80 static int zpool_do_get(int, char **);
81 static int zpool_do_set(int, char **);
84 * These libumem hooks provide a reasonable set of defaults for the allocator's
85 * debugging facilities.
88 #ifdef DEBUG
89 const char *
90 _umem_debug_init(void)
92 return ("default,verbose"); /* $UMEM_DEBUG setting */
95 const char *
96 _umem_logging_init(void)
98 return ("fail,contents"); /* $UMEM_LOGGING setting */
100 #endif
102 typedef enum {
103 HELP_ADD,
104 HELP_ATTACH,
105 HELP_CLEAR,
106 HELP_CREATE,
107 HELP_DESTROY,
108 HELP_DETACH,
109 HELP_EXPORT,
110 HELP_HISTORY,
111 HELP_IMPORT,
112 HELP_IOSTAT,
113 HELP_LIST,
114 HELP_OFFLINE,
115 HELP_ONLINE,
116 HELP_REPLACE,
117 HELP_REMOVE,
118 HELP_SCRUB,
119 HELP_STATUS,
120 HELP_UPGRADE,
121 HELP_GET,
122 HELP_SET
123 } zpool_help_t;
126 typedef struct zpool_command {
127 const char *name;
128 int (*func)(int, char **);
129 zpool_help_t usage;
130 } zpool_command_t;
133 * Master command table. Each ZFS command has a name, associated function, and
134 * usage message. The usage messages need to be internationalized, so we have
135 * to have a function to return the usage message based on a command index.
137 * These commands are organized according to how they are displayed in the usage
138 * message. An empty command (one with a NULL name) indicates an empty line in
139 * the generic usage message.
141 static zpool_command_t command_table[] = {
142 { "create", zpool_do_create, HELP_CREATE },
143 { "destroy", zpool_do_destroy, HELP_DESTROY },
144 { NULL },
145 { "add", zpool_do_add, HELP_ADD },
146 { "remove", zpool_do_remove, HELP_REMOVE },
147 { NULL },
148 { "list", zpool_do_list, HELP_LIST },
149 { "iostat", zpool_do_iostat, HELP_IOSTAT },
150 { "status", zpool_do_status, HELP_STATUS },
151 { NULL },
152 { "online", zpool_do_online, HELP_ONLINE },
153 { "offline", zpool_do_offline, HELP_OFFLINE },
154 { "clear", zpool_do_clear, HELP_CLEAR },
155 { NULL },
156 { "attach", zpool_do_attach, HELP_ATTACH },
157 { "detach", zpool_do_detach, HELP_DETACH },
158 { "replace", zpool_do_replace, HELP_REPLACE },
159 { NULL },
160 { "scrub", zpool_do_scrub, HELP_SCRUB },
161 { NULL },
162 { "import", zpool_do_import, HELP_IMPORT },
163 { "export", zpool_do_export, HELP_EXPORT },
164 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
165 { NULL },
166 { "history", zpool_do_history, HELP_HISTORY },
167 { "get", zpool_do_get, HELP_GET },
168 { "set", zpool_do_set, HELP_SET },
171 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
173 zpool_command_t *current_command;
174 static char history_str[HIS_MAX_RECORD_LEN];
176 static const char *
177 get_usage(zpool_help_t idx) {
178 switch (idx) {
179 case HELP_ADD:
180 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
181 case HELP_ATTACH:
182 return (gettext("\tattach [-f] <pool> <device> "
183 "<new-device>\n"));
184 case HELP_CLEAR:
185 return (gettext("\tclear <pool> [device]\n"));
186 case HELP_CREATE:
187 return (gettext("\tcreate [-fn] [-o property=value] ... \n"
188 "\t [-O file-system-property=value] ... \n"
189 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
190 case HELP_DESTROY:
191 return (gettext("\tdestroy [-f] <pool>\n"));
192 case HELP_DETACH:
193 return (gettext("\tdetach <pool> <device>\n"));
194 case HELP_EXPORT:
195 return (gettext("\texport [-f] <pool> ...\n"));
196 case HELP_HISTORY:
197 return (gettext("\thistory [-il] [<pool>] ...\n"));
198 case HELP_IMPORT:
199 return (gettext("\timport [-d dir] [-D]\n"
200 "\timport [-o mntopts] [-o property=value] ... \n"
201 "\t [-d dir | -c cachefile] [-D] [-f] [-R root] -a\n"
202 "\timport [-o mntopts] [-o property=value] ... \n"
203 "\t [-d dir | -c cachefile] [-D] [-f] [-R root] "
204 "<pool | id> [newpool]\n"));
205 case HELP_IOSTAT:
206 return (gettext("\tiostat [-v] [pool] ... [interval "
207 "[count]]\n"));
208 case HELP_LIST:
209 return (gettext("\tlist [-H] [-o property[,...]] "
210 "[pool] ...\n"));
211 case HELP_OFFLINE:
212 return (gettext("\toffline [-t] <pool> <device> ...\n"));
213 case HELP_ONLINE:
214 return (gettext("\tonline <pool> <device> ...\n"));
215 case HELP_REPLACE:
216 return (gettext("\treplace [-f] <pool> <device> "
217 "[new-device]\n"));
218 case HELP_REMOVE:
219 return (gettext("\tremove <pool> <device> ...\n"));
220 case HELP_SCRUB:
221 return (gettext("\tscrub [-s] <pool> ...\n"));
222 case HELP_STATUS:
223 return (gettext("\tstatus [-vx] [pool] ...\n"));
224 case HELP_UPGRADE:
225 return (gettext("\tupgrade\n"
226 "\tupgrade -v\n"
227 "\tupgrade [-V version] <-a | pool ...>\n"));
228 case HELP_GET:
229 return (gettext("\tget <\"all\" | property[,...]> "
230 "<pool> ...\n"));
231 case HELP_SET:
232 return (gettext("\tset <property=value> <pool> \n"));
235 abort();
236 /* NOTREACHED */
241 * Callback routine that will print out a pool property value.
243 static int
244 print_prop_cb(int prop, void *cb)
246 FILE *fp = cb;
248 (void) fprintf(fp, "\t%-13s ", zpool_prop_to_name(prop));
250 if (zpool_prop_readonly(prop))
251 (void) fprintf(fp, " NO ");
252 else
253 (void) fprintf(fp, " YES ");
255 if (zpool_prop_values(prop) == NULL)
256 (void) fprintf(fp, "-\n");
257 else
258 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
260 return (ZPROP_CONT);
264 * Display usage message. If we're inside a command, display only the usage for
265 * that command. Otherwise, iterate over the entire command table and display
266 * a complete usage message.
268 void
269 usage(boolean_t requested)
271 FILE *fp = requested ? stdout : stderr;
273 if (current_command == NULL) {
274 int i;
276 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
277 (void) fprintf(fp,
278 gettext("where 'command' is one of the following:\n\n"));
280 for (i = 0; i < NCOMMAND; i++) {
281 if (command_table[i].name == NULL)
282 (void) fprintf(fp, "\n");
283 else
284 (void) fprintf(fp, "%s",
285 get_usage(command_table[i].usage));
287 } else {
288 (void) fprintf(fp, gettext("usage:\n"));
289 (void) fprintf(fp, "%s", get_usage(current_command->usage));
292 if (current_command != NULL &&
293 ((strcmp(current_command->name, "set") == 0) ||
294 (strcmp(current_command->name, "get") == 0) ||
295 (strcmp(current_command->name, "list") == 0))) {
297 (void) fprintf(fp,
298 gettext("\nthe following properties are supported:\n"));
300 (void) fprintf(fp, "\n\t%-13s %s %s\n\n",
301 "PROPERTY", "EDIT", "VALUES");
303 /* Iterate over all properties */
304 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
305 ZFS_TYPE_POOL);
309 * See comments at end of main().
311 if (getenv("ZFS_ABORT") != NULL) {
312 (void) printf("dumping core by request\n");
313 abort();
316 exit(requested ? 0 : 2);
319 void
320 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
321 boolean_t print_logs)
323 nvlist_t **child;
324 uint_t c, children;
325 char *vname;
327 if (name != NULL)
328 (void) printf("\t%*s%s\n", indent, "", name);
330 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
331 &child, &children) != 0)
332 return;
334 for (c = 0; c < children; c++) {
335 uint64_t is_log = B_FALSE;
337 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
338 &is_log);
339 if ((is_log && !print_logs) || (!is_log && print_logs))
340 continue;
342 vname = zpool_vdev_name(g_zfs, zhp, child[c]);
343 print_vdev_tree(zhp, vname, child[c], indent + 2,
344 B_FALSE);
345 free(vname);
350 * Add a property pair (name, string-value) into a property nvlist.
352 static int
353 add_prop_list(const char *propname, char *propval, nvlist_t **props,
354 boolean_t poolprop)
356 zpool_prop_t prop = ZPROP_INVAL;
357 zfs_prop_t fprop;
358 nvlist_t *proplist;
359 const char *normnm;
360 char *strval;
362 if (*props == NULL &&
363 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
364 (void) fprintf(stderr,
365 gettext("internal error: out of memory\n"));
366 return (1);
369 proplist = *props;
371 if (poolprop) {
372 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
373 (void) fprintf(stderr, gettext("property '%s' is "
374 "not a valid pool property\n"), propname);
375 return (2);
377 normnm = zpool_prop_to_name(prop);
378 } else {
379 if ((fprop = zfs_name_to_prop(propname)) == ZPROP_INVAL) {
380 (void) fprintf(stderr, gettext("property '%s' is "
381 "not a valid file system property\n"), propname);
382 return (2);
384 normnm = zfs_prop_to_name(fprop);
387 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
388 prop != ZPOOL_PROP_CACHEFILE) {
389 (void) fprintf(stderr, gettext("property '%s' "
390 "specified multiple times\n"), propname);
391 return (2);
394 if (nvlist_add_string(proplist, normnm, propval) != 0) {
395 (void) fprintf(stderr, gettext("internal "
396 "error: out of memory\n"));
397 return (1);
400 return (0);
404 * zpool add [-fn] <pool> <vdev> ...
406 * -f Force addition of devices, even if they appear in use
407 * -n Do not add the devices, but display the resulting layout if
408 * they were to be added.
410 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
411 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
412 * libzfs.
415 zpool_do_add(int argc, char **argv)
417 boolean_t force = B_FALSE;
418 boolean_t dryrun = B_FALSE;
419 int c;
420 nvlist_t *nvroot;
421 char *poolname;
422 int ret;
423 zpool_handle_t *zhp;
424 nvlist_t *config;
426 /* check options */
427 while ((c = getopt(argc, argv, "fn")) != -1) {
428 switch (c) {
429 case 'f':
430 force = B_TRUE;
431 break;
432 case 'n':
433 dryrun = B_TRUE;
434 break;
435 case '?':
436 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
437 optopt);
438 usage(B_FALSE);
442 argc -= optind;
443 argv += optind;
445 /* get pool name and check number of arguments */
446 if (argc < 1) {
447 (void) fprintf(stderr, gettext("missing pool name argument\n"));
448 usage(B_FALSE);
450 if (argc < 2) {
451 (void) fprintf(stderr, gettext("missing vdev specification\n"));
452 usage(B_FALSE);
455 poolname = argv[0];
457 argc--;
458 argv++;
460 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
461 return (1);
463 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
464 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
465 poolname);
466 zpool_close(zhp);
467 return (1);
470 /* pass off to get_vdev_spec for processing */
471 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
472 argc, argv);
473 if (nvroot == NULL) {
474 zpool_close(zhp);
475 return (1);
478 if (dryrun) {
479 nvlist_t *poolnvroot;
481 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
482 &poolnvroot) == 0);
484 (void) printf(gettext("would update '%s' to the following "
485 "configuration:\n"), zpool_get_name(zhp));
487 /* print original main pool and new tree */
488 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
489 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
491 /* Do the same for the logs */
492 if (num_logs(poolnvroot) > 0) {
493 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
494 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
495 } else if (num_logs(nvroot) > 0) {
496 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
499 ret = 0;
500 } else {
501 ret = (zpool_add(zhp, nvroot) != 0);
504 nvlist_free(nvroot);
505 zpool_close(zhp);
507 return (ret);
511 * zpool remove <pool> <vdev> ...
513 * Removes the given vdev from the pool. Currently, this only supports removing
514 * spares and cache devices from the pool. Eventually, we'll want to support
515 * removing leaf vdevs (as an alias for 'detach') as well as toplevel vdevs.
518 zpool_do_remove(int argc, char **argv)
520 char *poolname;
521 int i, ret = 0;
522 zpool_handle_t *zhp;
524 argc--;
525 argv++;
527 /* get pool name and check number of arguments */
528 if (argc < 1) {
529 (void) fprintf(stderr, gettext("missing pool name argument\n"));
530 usage(B_FALSE);
532 if (argc < 2) {
533 (void) fprintf(stderr, gettext("missing device\n"));
534 usage(B_FALSE);
537 poolname = argv[0];
539 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
540 return (1);
542 for (i = 1; i < argc; i++) {
543 if (zpool_vdev_remove(zhp, argv[i]) != 0)
544 ret = 1;
547 return (ret);
551 * zpool create [-fn] [-o property=value] ...
552 * [-O file-system-property=value] ...
553 * [-R root] [-m mountpoint] <pool> <dev> ...
555 * -f Force creation, even if devices appear in use
556 * -n Do not create the pool, but display the resulting layout if it
557 * were to be created.
558 * -R Create a pool under an alternate root
559 * -m Set default mountpoint for the root dataset. By default it's
560 * '/<pool>'
561 * -o Set property=value.
562 * -O Set fsproperty=value in the pool's root file system
564 * Creates the named pool according to the given vdev specification. The
565 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once
566 * we get the nvlist back from get_vdev_spec(), we either print out the contents
567 * (if '-n' was specified), or pass it to libzfs to do the creation.
570 zpool_do_create(int argc, char **argv)
572 boolean_t force = B_FALSE;
573 boolean_t dryrun = B_FALSE;
574 int c;
575 nvlist_t *nvroot = NULL;
576 char *poolname;
577 int ret = 1;
578 char *altroot = NULL;
579 char *mountpoint = NULL;
580 nvlist_t *fsprops = NULL;
581 nvlist_t *props = NULL;
582 char *propval;
584 /* check options */
585 while ((c = getopt(argc, argv, ":fnR:m:o:O:")) != -1) {
586 switch (c) {
587 case 'f':
588 force = B_TRUE;
589 break;
590 case 'n':
591 dryrun = B_TRUE;
592 break;
593 case 'R':
594 altroot = optarg;
595 if (add_prop_list(zpool_prop_to_name(
596 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
597 goto errout;
598 if (nvlist_lookup_string(props,
599 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
600 &propval) == 0)
601 break;
602 if (add_prop_list(zpool_prop_to_name(
603 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
604 goto errout;
605 break;
606 case 'm':
607 mountpoint = optarg;
608 break;
609 case 'o':
610 if ((propval = strchr(optarg, '=')) == NULL) {
611 (void) fprintf(stderr, gettext("missing "
612 "'=' for -o option\n"));
613 goto errout;
615 *propval = '\0';
616 propval++;
618 if (add_prop_list(optarg, propval, &props, B_TRUE))
619 goto errout;
620 break;
621 case 'O':
622 if ((propval = strchr(optarg, '=')) == NULL) {
623 (void) fprintf(stderr, gettext("missing "
624 "'=' for -O option\n"));
625 goto errout;
627 *propval = '\0';
628 propval++;
630 if (add_prop_list(optarg, propval, &fsprops, B_FALSE))
631 goto errout;
632 break;
633 case ':':
634 (void) fprintf(stderr, gettext("missing argument for "
635 "'%c' option\n"), optopt);
636 goto badusage;
637 case '?':
638 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
639 optopt);
640 goto badusage;
644 argc -= optind;
645 argv += optind;
647 /* get pool name and check number of arguments */
648 if (argc < 1) {
649 (void) fprintf(stderr, gettext("missing pool name argument\n"));
650 goto badusage;
652 if (argc < 2) {
653 (void) fprintf(stderr, gettext("missing vdev specification\n"));
654 goto badusage;
657 poolname = argv[0];
660 * As a special case, check for use of '/' in the name, and direct the
661 * user to use 'zfs create' instead.
663 if (strchr(poolname, '/') != NULL) {
664 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
665 "character '/' in pool name\n"), poolname);
666 (void) fprintf(stderr, gettext("use 'zfs create' to "
667 "create a dataset\n"));
668 goto errout;
671 /* pass off to get_vdev_spec for bulk processing */
672 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
673 argc - 1, argv + 1);
674 if (nvroot == NULL)
675 goto errout;
677 /* make_root_vdev() allows 0 toplevel children if there are spares */
678 if (!zfs_allocatable_devs(nvroot)) {
679 (void) fprintf(stderr, gettext("invalid vdev "
680 "specification: at least one toplevel vdev must be "
681 "specified\n"));
682 goto errout;
686 if (altroot != NULL && altroot[0] != '/') {
687 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
688 "must be an absolute path\n"), altroot);
689 goto errout;
693 * Check the validity of the mountpoint and direct the user to use the
694 * '-m' mountpoint option if it looks like its in use.
696 if (mountpoint == NULL ||
697 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
698 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
699 char buf[MAXPATHLEN];
700 DIR *dirp;
702 if (mountpoint && mountpoint[0] != '/') {
703 (void) fprintf(stderr, gettext("invalid mountpoint "
704 "'%s': must be an absolute path, 'legacy', or "
705 "'none'\n"), mountpoint);
706 goto errout;
709 if (mountpoint == NULL) {
710 if (altroot != NULL)
711 (void) snprintf(buf, sizeof (buf), "%s/%s",
712 altroot, poolname);
713 else
714 (void) snprintf(buf, sizeof (buf), "/%s",
715 poolname);
716 } else {
717 if (altroot != NULL)
718 (void) snprintf(buf, sizeof (buf), "%s%s",
719 altroot, mountpoint);
720 else
721 (void) snprintf(buf, sizeof (buf), "%s",
722 mountpoint);
725 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
726 (void) fprintf(stderr, gettext("mountpoint '%s' : "
727 "%s\n"), buf, strerror(errno));
728 (void) fprintf(stderr, gettext("use '-m' "
729 "option to provide a different default\n"));
730 goto errout;
731 } else if (dirp) {
732 int count = 0;
734 while (count < 3 && readdir(dirp) != NULL)
735 count++;
736 (void) closedir(dirp);
738 if (count > 2) {
739 (void) fprintf(stderr, gettext("mountpoint "
740 "'%s' exists and is not empty\n"), buf);
741 (void) fprintf(stderr, gettext("use '-m' "
742 "option to provide a "
743 "different default\n"));
744 goto errout;
749 if (dryrun) {
751 * For a dry run invocation, print out a basic message and run
752 * through all the vdevs in the list and print out in an
753 * appropriate hierarchy.
755 (void) printf(gettext("would create '%s' with the "
756 "following layout:\n\n"), poolname);
758 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
759 if (num_logs(nvroot) > 0)
760 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
762 ret = 0;
763 } else {
765 * Hand off to libzfs.
767 if (zpool_create(g_zfs, poolname,
768 nvroot, props, fsprops) == 0) {
769 zfs_handle_t *pool = zfs_open(g_zfs, poolname,
770 ZFS_TYPE_FILESYSTEM);
771 if (pool != NULL) {
772 if (mountpoint != NULL)
773 verify(zfs_prop_set(pool,
774 zfs_prop_to_name(
775 ZFS_PROP_MOUNTPOINT),
776 mountpoint) == 0);
777 if (zfs_mount(pool, NULL, 0) == 0)
778 ret = zfs_shareall(pool);
779 zfs_close(pool);
781 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
782 (void) fprintf(stderr, gettext("pool name may have "
783 "been omitted\n"));
787 errout:
788 nvlist_free(nvroot);
789 nvlist_free(fsprops);
790 nvlist_free(props);
791 return (ret);
792 badusage:
793 nvlist_free(fsprops);
794 nvlist_free(props);
795 usage(B_FALSE);
796 return (2);
800 * zpool destroy <pool>
802 * -f Forcefully unmount any datasets
804 * Destroy the given pool. Automatically unmounts any datasets in the pool.
807 zpool_do_destroy(int argc, char **argv)
809 boolean_t force = B_FALSE;
810 int c;
811 char *pool;
812 zpool_handle_t *zhp;
813 int ret;
815 /* check options */
816 while ((c = getopt(argc, argv, "f")) != -1) {
817 switch (c) {
818 case 'f':
819 force = B_TRUE;
820 break;
821 case '?':
822 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
823 optopt);
824 usage(B_FALSE);
828 argc -= optind;
829 argv += optind;
831 /* check arguments */
832 if (argc < 1) {
833 (void) fprintf(stderr, gettext("missing pool argument\n"));
834 usage(B_FALSE);
836 if (argc > 1) {
837 (void) fprintf(stderr, gettext("too many arguments\n"));
838 usage(B_FALSE);
841 pool = argv[0];
843 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
845 * As a special case, check for use of '/' in the name, and
846 * direct the user to use 'zfs destroy' instead.
848 if (strchr(pool, '/') != NULL)
849 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
850 "destroy a dataset\n"));
851 return (1);
854 if (zpool_disable_datasets(zhp, force) != 0) {
855 (void) fprintf(stderr, gettext("could not destroy '%s': "
856 "could not unmount datasets\n"), zpool_get_name(zhp));
857 return (1);
860 ret = (zpool_destroy(zhp) != 0);
862 zpool_close(zhp);
864 return (ret);
868 * zpool export [-f] <pool> ...
870 * -f Forcefully unmount datasets
872 * Export the given pools. By default, the command will attempt to cleanly
873 * unmount any active datasets within the pool. If the '-f' flag is specified,
874 * then the datasets will be forcefully unmounted.
877 zpool_do_export(int argc, char **argv)
879 boolean_t force = B_FALSE;
880 boolean_t hardforce = B_FALSE;
881 int c;
882 zpool_handle_t *zhp;
883 int ret;
884 int i;
886 /* check options */
887 while ((c = getopt(argc, argv, "fF")) != -1) {
888 switch (c) {
889 case 'f':
890 force = B_TRUE;
891 break;
892 case 'F':
893 hardforce = B_TRUE;
894 break;
895 case '?':
896 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
897 optopt);
898 usage(B_FALSE);
902 argc -= optind;
903 argv += optind;
905 /* check arguments */
906 if (argc < 1) {
907 (void) fprintf(stderr, gettext("missing pool argument\n"));
908 usage(B_FALSE);
911 ret = 0;
912 for (i = 0; i < argc; i++) {
913 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
914 ret = 1;
915 continue;
918 if (zpool_disable_datasets(zhp, force) != 0) {
919 ret = 1;
920 zpool_close(zhp);
921 continue;
924 if (hardforce) {
925 if (zpool_export_force(zhp) != 0)
926 ret = 1;
927 } else if (zpool_export(zhp, force) != 0) {
928 ret = 1;
931 zpool_close(zhp);
934 return (ret);
938 * Given a vdev configuration, determine the maximum width needed for the device
939 * name column.
941 static int
942 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
944 char *name = zpool_vdev_name(g_zfs, zhp, nv);
945 nvlist_t **child;
946 uint_t c, children;
947 int ret;
949 if (strlen(name) + depth > max)
950 max = strlen(name) + depth;
952 free(name);
954 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
955 &child, &children) == 0) {
956 for (c = 0; c < children; c++)
957 if ((ret = max_width(zhp, child[c], depth + 2,
958 max)) > max)
959 max = ret;
962 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
963 &child, &children) == 0) {
964 for (c = 0; c < children; c++)
965 if ((ret = max_width(zhp, child[c], depth + 2,
966 max)) > max)
967 max = ret;
970 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
971 &child, &children) == 0) {
972 for (c = 0; c < children; c++)
973 if ((ret = max_width(zhp, child[c], depth + 2,
974 max)) > max)
975 max = ret;
979 return (max);
984 * Print the configuration of an exported pool. Iterate over all vdevs in the
985 * pool, printing out the name and status for each one.
987 void
988 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth,
989 boolean_t print_logs)
991 nvlist_t **child;
992 uint_t c, children;
993 vdev_stat_t *vs;
994 char *type, *vname;
996 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
997 if (strcmp(type, VDEV_TYPE_MISSING) == 0)
998 return;
1000 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
1001 (uint64_t **)&vs, &c) == 0);
1003 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1004 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1006 if (vs->vs_aux != 0) {
1007 (void) printf(" ");
1009 switch (vs->vs_aux) {
1010 case VDEV_AUX_OPEN_FAILED:
1011 (void) printf(gettext("cannot open"));
1012 break;
1014 case VDEV_AUX_BAD_GUID_SUM:
1015 (void) printf(gettext("missing device"));
1016 break;
1018 case VDEV_AUX_NO_REPLICAS:
1019 (void) printf(gettext("insufficient replicas"));
1020 break;
1022 case VDEV_AUX_VERSION_NEWER:
1023 (void) printf(gettext("newer version"));
1024 break;
1026 case VDEV_AUX_ERR_EXCEEDED:
1027 (void) printf(gettext("too many errors"));
1028 break;
1030 default:
1031 (void) printf(gettext("corrupted data"));
1032 break;
1035 (void) printf("\n");
1037 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1038 &child, &children) != 0)
1039 return;
1041 for (c = 0; c < children; c++) {
1042 uint64_t is_log = B_FALSE;
1044 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1045 &is_log);
1046 if ((is_log && !print_logs) || (!is_log && print_logs))
1047 continue;
1049 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1050 print_import_config(vname, child[c],
1051 namewidth, depth + 2, B_FALSE);
1052 free(vname);
1055 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1056 &child, &children) == 0) {
1057 (void) printf(gettext("\tcache\n"));
1058 for (c = 0; c < children; c++) {
1059 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1060 (void) printf("\t %s\n", vname);
1061 free(vname);
1065 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1066 &child, &children) == 0) {
1067 (void) printf(gettext("\tspares\n"));
1068 for (c = 0; c < children; c++) {
1069 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1070 (void) printf("\t %s\n", vname);
1071 free(vname);
1077 * Display the status for the given pool.
1079 static void
1080 show_import(nvlist_t *config)
1082 uint64_t pool_state;
1083 vdev_stat_t *vs;
1084 char *name;
1085 uint64_t guid;
1086 char *msgid;
1087 nvlist_t *nvroot;
1088 int reason;
1089 const char *health;
1090 uint_t vsc;
1091 int namewidth;
1093 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1094 &name) == 0);
1095 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1096 &guid) == 0);
1097 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1098 &pool_state) == 0);
1099 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1100 &nvroot) == 0);
1102 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
1103 (uint64_t **)&vs, &vsc) == 0);
1104 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1106 reason = zpool_import_status(config, &msgid);
1108 (void) printf(gettext(" pool: %s\n"), name);
1109 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
1110 (void) printf(gettext(" state: %s"), health);
1111 if (pool_state == POOL_STATE_DESTROYED)
1112 (void) printf(gettext(" (DESTROYED)"));
1113 (void) printf("\n");
1115 switch (reason) {
1116 case ZPOOL_STATUS_MISSING_DEV_R:
1117 case ZPOOL_STATUS_MISSING_DEV_NR:
1118 case ZPOOL_STATUS_BAD_GUID_SUM:
1119 (void) printf(gettext("status: One or more devices are missing "
1120 "from the system.\n"));
1121 break;
1123 case ZPOOL_STATUS_CORRUPT_LABEL_R:
1124 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1125 (void) printf(gettext("status: One or more devices contains "
1126 "corrupted data.\n"));
1127 break;
1129 case ZPOOL_STATUS_CORRUPT_DATA:
1130 (void) printf(gettext("status: The pool data is corrupted.\n"));
1131 break;
1133 case ZPOOL_STATUS_OFFLINE_DEV:
1134 (void) printf(gettext("status: One or more devices "
1135 "are offlined.\n"));
1136 break;
1138 case ZPOOL_STATUS_CORRUPT_POOL:
1139 (void) printf(gettext("status: The pool metadata is "
1140 "corrupted.\n"));
1141 break;
1143 case ZPOOL_STATUS_VERSION_OLDER:
1144 (void) printf(gettext("status: The pool is formatted using an "
1145 "older on-disk version.\n"));
1146 break;
1148 case ZPOOL_STATUS_VERSION_NEWER:
1149 (void) printf(gettext("status: The pool is formatted using an "
1150 "incompatible version.\n"));
1151 break;
1153 case ZPOOL_STATUS_HOSTID_MISMATCH:
1154 (void) printf(gettext("status: The pool was last accessed by "
1155 "another system.\n"));
1156 break;
1158 case ZPOOL_STATUS_FAULTED_DEV_R:
1159 case ZPOOL_STATUS_FAULTED_DEV_NR:
1160 (void) printf(gettext("status: One or more devices are "
1161 "faulted.\n"));
1162 break;
1164 case ZPOOL_STATUS_BAD_LOG:
1165 (void) printf(gettext("status: An intent log record cannot be "
1166 "read.\n"));
1167 break;
1169 default:
1171 * No other status can be seen when importing pools.
1173 assert(reason == ZPOOL_STATUS_OK);
1177 * Print out an action according to the overall state of the pool.
1179 if (vs->vs_state == VDEV_STATE_HEALTHY) {
1180 if (reason == ZPOOL_STATUS_VERSION_OLDER)
1181 (void) printf(gettext("action: The pool can be "
1182 "imported using its name or numeric identifier, "
1183 "though\n\tsome features will not be available "
1184 "without an explicit 'zpool upgrade'.\n"));
1185 else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH)
1186 (void) printf(gettext("action: The pool can be "
1187 "imported using its name or numeric "
1188 "identifier and\n\tthe '-f' flag.\n"));
1189 else
1190 (void) printf(gettext("action: The pool can be "
1191 "imported using its name or numeric "
1192 "identifier.\n"));
1193 } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1194 (void) printf(gettext("action: The pool can be imported "
1195 "despite missing or damaged devices. The\n\tfault "
1196 "tolerance of the pool may be compromised if imported.\n"));
1197 } else {
1198 switch (reason) {
1199 case ZPOOL_STATUS_VERSION_NEWER:
1200 (void) printf(gettext("action: The pool cannot be "
1201 "imported. Access the pool on a system running "
1202 "newer\n\tsoftware, or recreate the pool from "
1203 "backup.\n"));
1204 break;
1205 case ZPOOL_STATUS_MISSING_DEV_R:
1206 case ZPOOL_STATUS_MISSING_DEV_NR:
1207 case ZPOOL_STATUS_BAD_GUID_SUM:
1208 (void) printf(gettext("action: The pool cannot be "
1209 "imported. Attach the missing\n\tdevices and try "
1210 "again.\n"));
1211 break;
1212 default:
1213 (void) printf(gettext("action: The pool cannot be "
1214 "imported due to damaged devices or data.\n"));
1219 * If the state is "closed" or "can't open", and the aux state
1220 * is "corrupt data":
1222 if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1223 (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1224 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1225 if (pool_state == POOL_STATE_DESTROYED)
1226 (void) printf(gettext("\tThe pool was destroyed, "
1227 "but can be imported using the '-Df' flags.\n"));
1228 else if (pool_state != POOL_STATE_EXPORTED)
1229 (void) printf(gettext("\tThe pool may be active on "
1230 "another system, but can be imported using\n\t"
1231 "the '-f' flag.\n"));
1234 if (msgid != NULL)
1235 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"),
1236 msgid);
1238 (void) printf(gettext("config:\n\n"));
1240 namewidth = max_width(NULL, nvroot, 0, 0);
1241 if (namewidth < 10)
1242 namewidth = 10;
1244 print_import_config(name, nvroot, namewidth, 0, B_FALSE);
1245 if (num_logs(nvroot) > 0) {
1246 (void) printf(gettext("\tlogs\n"));
1247 print_import_config(name, nvroot, namewidth, 0, B_TRUE);
1250 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1251 (void) printf(gettext("\n\tAdditional devices are known to "
1252 "be part of this pool, though their\n\texact "
1253 "configuration cannot be determined.\n"));
1258 * Perform the import for the given configuration. This passes the heavy
1259 * lifting off to zpool_import_props(), and then mounts the datasets contained
1260 * within the pool.
1262 static int
1263 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1264 int force, nvlist_t *props, boolean_t allowfaulted)
1266 zpool_handle_t *zhp;
1267 char *name;
1268 uint64_t state;
1269 uint64_t version;
1270 int error = 0;
1272 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1273 &name) == 0);
1275 verify(nvlist_lookup_uint64(config,
1276 ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1277 verify(nvlist_lookup_uint64(config,
1278 ZPOOL_CONFIG_VERSION, &version) == 0);
1279 if (version > SPA_VERSION) {
1280 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1281 "is formatted using a newer ZFS version\n"), name);
1282 return (1);
1283 } else if (state != POOL_STATE_EXPORTED && !force) {
1284 uint64_t hostid;
1286 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
1287 &hostid) == 0) {
1288 if ((unsigned long)hostid != gethostid()) {
1289 char *hostname;
1290 uint64_t timestamp;
1291 time_t t;
1293 verify(nvlist_lookup_string(config,
1294 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
1295 verify(nvlist_lookup_uint64(config,
1296 ZPOOL_CONFIG_TIMESTAMP, &timestamp) == 0);
1297 t = timestamp;
1298 (void) fprintf(stderr, gettext("cannot import "
1299 "'%s': pool may be in use from other "
1300 "system, it was last accessed by %s "
1301 "(hostid: 0x%lx) on %s"), name, hostname,
1302 (unsigned long)hostid,
1303 asctime(localtime(&t)));
1304 (void) fprintf(stderr, gettext("use '-f' to "
1305 "import anyway\n"));
1306 return (1);
1308 } else {
1309 (void) fprintf(stderr, gettext("cannot import '%s': "
1310 "pool may be in use from other system\n"), name);
1311 (void) fprintf(stderr, gettext("use '-f' to import "
1312 "anyway\n"));
1313 return (1);
1317 if (zpool_import_props(g_zfs, config, newname, props,
1318 allowfaulted) != 0)
1319 return (1);
1321 if (newname != NULL)
1322 name = (char *)newname;
1324 verify((zhp = zpool_open_canfail(g_zfs, name)) != NULL);
1326 if (zpool_enable_datasets(zhp, mntopts, 0) != 0) {
1327 zpool_close(zhp);
1328 return (1);
1331 zpool_close(zhp);
1332 return (error);
1336 * zpool import [-d dir] [-D]
1337 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1338 * [-d dir | -c cachefile] [-f] -a
1339 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1340 * [-d dir | -c cachefile] [-f] <pool | id> [newpool]
1342 * -c Read pool information from a cachefile instead of searching
1343 * devices.
1345 * -d Scan in a specific directory, other than /dev/dsk. More than
1346 * one directory can be specified using multiple '-d' options.
1348 * -D Scan for previously destroyed pools or import all or only
1349 * specified destroyed pools.
1351 * -R Temporarily import the pool, with all mountpoints relative to
1352 * the given root. The pool will remain exported when the machine
1353 * is rebooted.
1355 * -f Force import, even if it appears that the pool is active.
1357 * -F Import even in the presence of faulted vdevs. This is an
1358 * intentionally undocumented option for testing purposes, and
1359 * treats the pool configuration as complete, leaving any bad
1360 * vdevs in the FAULTED state.
1362 * -a Import all pools found.
1364 * -o Set property=value and/or temporary mount options (without '=').
1366 * The import command scans for pools to import, and import pools based on pool
1367 * name and GUID. The pool can also be renamed as part of the import process.
1370 zpool_do_import(int argc, char **argv)
1372 char **searchdirs = NULL;
1373 int nsearch = 0;
1374 int c;
1375 int err;
1376 nvlist_t *pools = NULL;
1377 boolean_t do_all = B_FALSE;
1378 boolean_t do_destroyed = B_FALSE;
1379 char *mntopts = NULL;
1380 boolean_t do_force = B_FALSE;
1381 nvpair_t *elem;
1382 nvlist_t *config;
1383 uint64_t searchguid = 0;
1384 char *searchname = NULL;
1385 char *propval;
1386 nvlist_t *found_config;
1387 nvlist_t *props = NULL;
1388 boolean_t first;
1389 boolean_t allow_faulted = B_FALSE;
1390 uint64_t pool_state;
1391 char *cachefile = NULL;
1393 /* check options */
1394 while ((c = getopt(argc, argv, ":ac:d:DfFo:p:R:")) != -1) {
1395 switch (c) {
1396 case 'a':
1397 do_all = B_TRUE;
1398 break;
1399 case 'c':
1400 cachefile = optarg;
1401 break;
1402 case 'd':
1403 if (searchdirs == NULL) {
1404 searchdirs = safe_malloc(sizeof (char *));
1405 } else {
1406 char **tmp = safe_malloc((nsearch + 1) *
1407 sizeof (char *));
1408 bcopy(searchdirs, tmp, nsearch *
1409 sizeof (char *));
1410 free(searchdirs);
1411 searchdirs = tmp;
1413 searchdirs[nsearch++] = optarg;
1414 break;
1415 case 'D':
1416 do_destroyed = B_TRUE;
1417 break;
1418 case 'f':
1419 do_force = B_TRUE;
1420 break;
1421 case 'F':
1422 allow_faulted = B_TRUE;
1423 break;
1424 case 'o':
1425 if ((propval = strchr(optarg, '=')) != NULL) {
1426 *propval = '\0';
1427 propval++;
1428 if (add_prop_list(optarg, propval,
1429 &props, B_TRUE))
1430 goto error;
1431 } else {
1432 mntopts = optarg;
1434 break;
1435 case 'R':
1436 if (add_prop_list(zpool_prop_to_name(
1437 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
1438 goto error;
1439 if (nvlist_lookup_string(props,
1440 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
1441 &propval) == 0)
1442 break;
1443 if (add_prop_list(zpool_prop_to_name(
1444 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1445 goto error;
1446 break;
1447 case ':':
1448 (void) fprintf(stderr, gettext("missing argument for "
1449 "'%c' option\n"), optopt);
1450 usage(B_FALSE);
1451 break;
1452 case '?':
1453 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1454 optopt);
1455 usage(B_FALSE);
1459 argc -= optind;
1460 argv += optind;
1462 if (cachefile && nsearch != 0) {
1463 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
1464 usage(B_FALSE);
1467 if (searchdirs == NULL) {
1468 searchdirs = safe_malloc(sizeof (char *));
1469 searchdirs[0] = "/dev/dsk";
1470 nsearch = 1;
1473 /* check argument count */
1474 if (do_all) {
1475 if (argc != 0) {
1476 (void) fprintf(stderr, gettext("too many arguments\n"));
1477 usage(B_FALSE);
1479 } else {
1480 if (argc > 2) {
1481 (void) fprintf(stderr, gettext("too many arguments\n"));
1482 usage(B_FALSE);
1486 * Check for the SYS_CONFIG privilege. We do this explicitly
1487 * here because otherwise any attempt to discover pools will
1488 * silently fail.
1490 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
1491 (void) fprintf(stderr, gettext("cannot "
1492 "discover pools: permission denied\n"));
1493 free(searchdirs);
1494 return (1);
1499 * Depending on the arguments given, we do one of the following:
1501 * <none> Iterate through all pools and display information about
1502 * each one.
1504 * -a Iterate through all pools and try to import each one.
1506 * <id> Find the pool that corresponds to the given GUID/pool
1507 * name and import that one.
1509 * -D Above options applies only to destroyed pools.
1511 if (argc != 0) {
1512 char *endptr;
1514 errno = 0;
1515 searchguid = strtoull(argv[0], &endptr, 10);
1516 if (errno != 0 || *endptr != '\0')
1517 searchname = argv[0];
1518 found_config = NULL;
1521 if (cachefile) {
1522 pools = zpool_find_import_cached(g_zfs, cachefile, searchname,
1523 searchguid);
1524 } else if (searchname != NULL) {
1525 pools = zpool_find_import_byname(g_zfs, nsearch, searchdirs,
1526 searchname);
1527 } else {
1529 * It's OK to search by guid even if searchguid is 0.
1531 pools = zpool_find_import_byguid(g_zfs, nsearch, searchdirs,
1532 searchguid);
1535 if (pools == NULL) {
1536 if (argc != 0) {
1537 (void) fprintf(stderr, gettext("cannot import '%s': "
1538 "no such pool available\n"), argv[0]);
1540 free(searchdirs);
1541 return (1);
1545 * At this point we have a list of import candidate configs. Even if
1546 * we were searching by pool name or guid, we still need to
1547 * post-process the list to deal with pool state and possible
1548 * duplicate names.
1550 err = 0;
1551 elem = NULL;
1552 first = B_TRUE;
1553 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
1555 verify(nvpair_value_nvlist(elem, &config) == 0);
1557 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1558 &pool_state) == 0);
1559 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
1560 continue;
1561 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
1562 continue;
1564 if (argc == 0) {
1565 if (first)
1566 first = B_FALSE;
1567 else if (!do_all)
1568 (void) printf("\n");
1570 if (do_all)
1571 err |= do_import(config, NULL, mntopts,
1572 do_force, props, allow_faulted);
1573 else
1574 show_import(config);
1575 } else if (searchname != NULL) {
1576 char *name;
1579 * We are searching for a pool based on name.
1581 verify(nvlist_lookup_string(config,
1582 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
1584 if (strcmp(name, searchname) == 0) {
1585 if (found_config != NULL) {
1586 (void) fprintf(stderr, gettext(
1587 "cannot import '%s': more than "
1588 "one matching pool\n"), searchname);
1589 (void) fprintf(stderr, gettext(
1590 "import by numeric ID instead\n"));
1591 err = B_TRUE;
1593 found_config = config;
1595 } else {
1596 uint64_t guid;
1599 * Search for a pool by guid.
1601 verify(nvlist_lookup_uint64(config,
1602 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
1604 if (guid == searchguid)
1605 found_config = config;
1610 * If we were searching for a specific pool, verify that we found a
1611 * pool, and then do the import.
1613 if (argc != 0 && err == 0) {
1614 if (found_config == NULL) {
1615 (void) fprintf(stderr, gettext("cannot import '%s': "
1616 "no such pool available\n"), argv[0]);
1617 err = B_TRUE;
1618 } else {
1619 err |= do_import(found_config, argc == 1 ? NULL :
1620 argv[1], mntopts, do_force, props, allow_faulted);
1625 * If we were just looking for pools, report an error if none were
1626 * found.
1628 if (argc == 0 && first)
1629 (void) fprintf(stderr,
1630 gettext("no pools available to import\n"));
1632 error:
1633 nvlist_free(props);
1634 nvlist_free(pools);
1635 free(searchdirs);
1637 return (err ? 1 : 0);
1640 typedef struct iostat_cbdata {
1641 zpool_list_t *cb_list;
1642 int cb_verbose;
1643 int cb_iteration;
1644 int cb_namewidth;
1645 } iostat_cbdata_t;
1647 static void
1648 print_iostat_separator(iostat_cbdata_t *cb)
1650 int i = 0;
1652 for (i = 0; i < cb->cb_namewidth; i++)
1653 (void) printf("-");
1654 (void) printf(" ----- ----- ----- ----- ----- -----\n");
1657 static void
1658 print_iostat_header(iostat_cbdata_t *cb)
1660 (void) printf("%*s capacity operations bandwidth\n",
1661 cb->cb_namewidth, "");
1662 (void) printf("%-*s used avail read write read write\n",
1663 cb->cb_namewidth, "pool");
1664 print_iostat_separator(cb);
1668 * Display a single statistic.
1670 static void
1671 print_one_stat(uint64_t value)
1673 char buf[64];
1675 zfs_nicenum(value, buf, sizeof (buf));
1676 (void) printf(" %5s", buf);
1680 * Print out all the statistics for the given vdev. This can either be the
1681 * toplevel configuration, or called recursively. If 'name' is NULL, then this
1682 * is a verbose output, and we don't want to display the toplevel pool stats.
1684 void
1685 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
1686 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
1688 nvlist_t **oldchild, **newchild;
1689 uint_t c, children;
1690 vdev_stat_t *oldvs, *newvs;
1691 vdev_stat_t zerovs = { 0 };
1692 uint64_t tdelta;
1693 double scale;
1694 char *vname;
1696 if (oldnv != NULL) {
1697 verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS,
1698 (uint64_t **)&oldvs, &c) == 0);
1699 } else {
1700 oldvs = &zerovs;
1703 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS,
1704 (uint64_t **)&newvs, &c) == 0);
1706 if (strlen(name) + depth > cb->cb_namewidth)
1707 (void) printf("%*s%s", depth, "", name);
1708 else
1709 (void) printf("%*s%s%*s", depth, "", name,
1710 (int)(cb->cb_namewidth - strlen(name) - depth), "");
1712 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
1714 if (tdelta == 0)
1715 scale = 1.0;
1716 else
1717 scale = (double)NANOSEC / tdelta;
1719 /* only toplevel vdevs have capacity stats */
1720 if (newvs->vs_space == 0) {
1721 (void) printf(" - -");
1722 } else {
1723 print_one_stat(newvs->vs_alloc);
1724 print_one_stat(newvs->vs_space - newvs->vs_alloc);
1727 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
1728 oldvs->vs_ops[ZIO_TYPE_READ])));
1730 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
1731 oldvs->vs_ops[ZIO_TYPE_WRITE])));
1733 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
1734 oldvs->vs_bytes[ZIO_TYPE_READ])));
1736 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
1737 oldvs->vs_bytes[ZIO_TYPE_WRITE])));
1739 (void) printf("\n");
1741 if (!cb->cb_verbose)
1742 return;
1744 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
1745 &newchild, &children) != 0)
1746 return;
1748 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
1749 &oldchild, &c) != 0)
1750 return;
1752 for (c = 0; c < children; c++) {
1753 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1754 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1755 newchild[c], cb, depth + 2);
1756 free(vname);
1760 * Include level 2 ARC devices in iostat output
1762 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
1763 &newchild, &children) != 0)
1764 return;
1766 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
1767 &oldchild, &c) != 0)
1768 return;
1770 if (children > 0) {
1771 (void) printf("%-*s - - - - - "
1772 "-\n", cb->cb_namewidth, "cache");
1773 for (c = 0; c < children; c++) {
1774 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1775 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1776 newchild[c], cb, depth + 2);
1777 free(vname);
1782 static int
1783 refresh_iostat(zpool_handle_t *zhp, void *data)
1785 iostat_cbdata_t *cb = data;
1786 boolean_t missing;
1789 * If the pool has disappeared, remove it from the list and continue.
1791 if (zpool_refresh_stats(zhp, &missing) != 0)
1792 return (-1);
1794 if (missing)
1795 pool_list_remove(cb->cb_list, zhp);
1797 return (0);
1801 * Callback to print out the iostats for the given pool.
1804 print_iostat(zpool_handle_t *zhp, void *data)
1806 iostat_cbdata_t *cb = data;
1807 nvlist_t *oldconfig, *newconfig;
1808 nvlist_t *oldnvroot, *newnvroot;
1810 newconfig = zpool_get_config(zhp, &oldconfig);
1812 if (cb->cb_iteration == 1)
1813 oldconfig = NULL;
1815 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
1816 &newnvroot) == 0);
1818 if (oldconfig == NULL)
1819 oldnvroot = NULL;
1820 else
1821 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
1822 &oldnvroot) == 0);
1825 * Print out the statistics for the pool.
1827 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
1829 if (cb->cb_verbose)
1830 print_iostat_separator(cb);
1832 return (0);
1836 get_namewidth(zpool_handle_t *zhp, void *data)
1838 iostat_cbdata_t *cb = data;
1839 nvlist_t *config, *nvroot;
1841 if ((config = zpool_get_config(zhp, NULL)) != NULL) {
1842 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1843 &nvroot) == 0);
1844 if (!cb->cb_verbose)
1845 cb->cb_namewidth = strlen(zpool_get_name(zhp));
1846 else
1847 cb->cb_namewidth = max_width(zhp, nvroot, 0, 0);
1851 * The width must fall into the range [10,38]. The upper limit is the
1852 * maximum we can have and still fit in 80 columns.
1854 if (cb->cb_namewidth < 10)
1855 cb->cb_namewidth = 10;
1856 if (cb->cb_namewidth > 38)
1857 cb->cb_namewidth = 38;
1859 return (0);
1863 * zpool iostat [-v] [pool] ... [interval [count]]
1865 * -v Display statistics for individual vdevs
1867 * This command can be tricky because we want to be able to deal with pool
1868 * creation/destruction as well as vdev configuration changes. The bulk of this
1869 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
1870 * on pool_list_update() to detect the addition of new pools. Configuration
1871 * changes are all handled within libzfs.
1874 zpool_do_iostat(int argc, char **argv)
1876 int c;
1877 int ret;
1878 int npools;
1879 unsigned long interval = 0, count = 0;
1880 zpool_list_t *list;
1881 boolean_t verbose = B_FALSE;
1882 iostat_cbdata_t cb;
1884 /* check options */
1885 while ((c = getopt(argc, argv, "v")) != -1) {
1886 switch (c) {
1887 case 'v':
1888 verbose = B_TRUE;
1889 break;
1890 case '?':
1891 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1892 optopt);
1893 usage(B_FALSE);
1897 argc -= optind;
1898 argv += optind;
1901 * Determine if the last argument is an integer or a pool name
1903 if (argc > 0 && isdigit(argv[argc - 1][0])) {
1904 char *end;
1906 errno = 0;
1907 interval = strtoul(argv[argc - 1], &end, 10);
1909 if (*end == '\0' && errno == 0) {
1910 if (interval == 0) {
1911 (void) fprintf(stderr, gettext("interval "
1912 "cannot be zero\n"));
1913 usage(B_FALSE);
1917 * Ignore the last parameter
1919 argc--;
1920 } else {
1922 * If this is not a valid number, just plow on. The
1923 * user will get a more informative error message later
1924 * on.
1926 interval = 0;
1931 * If the last argument is also an integer, then we have both a count
1932 * and an integer.
1934 if (argc > 0 && isdigit(argv[argc - 1][0])) {
1935 char *end;
1937 errno = 0;
1938 count = interval;
1939 interval = strtoul(argv[argc - 1], &end, 10);
1941 if (*end == '\0' && errno == 0) {
1942 if (interval == 0) {
1943 (void) fprintf(stderr, gettext("interval "
1944 "cannot be zero\n"));
1945 usage(B_FALSE);
1949 * Ignore the last parameter
1951 argc--;
1952 } else {
1953 interval = 0;
1958 * Construct the list of all interesting pools.
1960 ret = 0;
1961 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
1962 return (1);
1964 if (pool_list_count(list) == 0 && argc != 0) {
1965 pool_list_free(list);
1966 return (1);
1969 if (pool_list_count(list) == 0 && interval == 0) {
1970 pool_list_free(list);
1971 (void) fprintf(stderr, gettext("no pools available\n"));
1972 return (1);
1976 * Enter the main iostat loop.
1978 cb.cb_list = list;
1979 cb.cb_verbose = verbose;
1980 cb.cb_iteration = 0;
1981 cb.cb_namewidth = 0;
1983 for (;;) {
1984 pool_list_update(list);
1986 if ((npools = pool_list_count(list)) == 0)
1987 break;
1990 * Refresh all statistics. This is done as an explicit step
1991 * before calculating the maximum name width, so that any
1992 * configuration changes are properly accounted for.
1994 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
1997 * Iterate over all pools to determine the maximum width
1998 * for the pool / device name column across all pools.
2000 cb.cb_namewidth = 0;
2001 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2004 * If it's the first time, or verbose mode, print the header.
2006 if (++cb.cb_iteration == 1 || verbose)
2007 print_iostat_header(&cb);
2009 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
2012 * If there's more than one pool, and we're not in verbose mode
2013 * (which prints a separator for us), then print a separator.
2015 if (npools > 1 && !verbose)
2016 print_iostat_separator(&cb);
2018 if (verbose)
2019 (void) printf("\n");
2022 * Flush the output so that redirection to a file isn't buffered
2023 * indefinitely.
2025 (void) fflush(stdout);
2027 if (interval == 0)
2028 break;
2030 if (count != 0 && --count == 0)
2031 break;
2033 (void) sleep(interval);
2036 pool_list_free(list);
2038 return (ret);
2041 typedef struct list_cbdata {
2042 boolean_t cb_scripted;
2043 boolean_t cb_first;
2044 zprop_list_t *cb_proplist;
2045 } list_cbdata_t;
2048 * Given a list of columns to display, output appropriate headers for each one.
2050 static void
2051 print_header(zprop_list_t *pl)
2053 const char *header;
2054 boolean_t first = B_TRUE;
2055 boolean_t right_justify;
2057 for (; pl != NULL; pl = pl->pl_next) {
2058 if (pl->pl_prop == ZPROP_INVAL)
2059 continue;
2061 if (!first)
2062 (void) printf(" ");
2063 else
2064 first = B_FALSE;
2066 header = zpool_prop_column_name(pl->pl_prop);
2067 right_justify = zpool_prop_align_right(pl->pl_prop);
2069 if (pl->pl_next == NULL && !right_justify)
2070 (void) printf("%s", header);
2071 else if (right_justify)
2072 (void) printf("%*s", pl->pl_width, header);
2073 else
2074 (void) printf("%-*s", pl->pl_width, header);
2077 (void) printf("\n");
2081 * Given a pool and a list of properties, print out all the properties according
2082 * to the described layout.
2084 static void
2085 print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
2087 boolean_t first = B_TRUE;
2088 char property[ZPOOL_MAXPROPLEN];
2089 char *propstr;
2090 boolean_t right_justify;
2091 int width;
2093 for (; pl != NULL; pl = pl->pl_next) {
2094 if (!first) {
2095 if (scripted)
2096 (void) printf("\t");
2097 else
2098 (void) printf(" ");
2099 } else {
2100 first = B_FALSE;
2103 right_justify = B_FALSE;
2104 if (pl->pl_prop != ZPROP_INVAL) {
2105 if (zpool_get_prop(zhp, pl->pl_prop, property,
2106 sizeof (property), NULL) != 0)
2107 propstr = "-";
2108 else
2109 propstr = property;
2111 right_justify = zpool_prop_align_right(pl->pl_prop);
2112 } else {
2113 propstr = "-";
2116 width = pl->pl_width;
2119 * If this is being called in scripted mode, or if this is the
2120 * last column and it is left-justified, don't include a width
2121 * format specifier.
2123 if (scripted || (pl->pl_next == NULL && !right_justify))
2124 (void) printf("%s", propstr);
2125 else if (right_justify)
2126 (void) printf("%*s", width, propstr);
2127 else
2128 (void) printf("%-*s", width, propstr);
2131 (void) printf("\n");
2135 * Generic callback function to list a pool.
2138 list_callback(zpool_handle_t *zhp, void *data)
2140 list_cbdata_t *cbp = data;
2142 if (cbp->cb_first) {
2143 if (!cbp->cb_scripted)
2144 print_header(cbp->cb_proplist);
2145 cbp->cb_first = B_FALSE;
2148 print_pool(zhp, cbp->cb_proplist, cbp->cb_scripted);
2150 return (0);
2154 * zpool list [-H] [-o prop[,prop]*] [pool] ...
2156 * -H Scripted mode. Don't display headers, and separate properties
2157 * by a single tab.
2158 * -o List of properties to display. Defaults to
2159 * "name,size,used,available,capacity,health,altroot"
2161 * List all pools in the system, whether or not they're healthy. Output space
2162 * statistics for each one, as well as health status summary.
2165 zpool_do_list(int argc, char **argv)
2167 int c;
2168 int ret;
2169 list_cbdata_t cb = { 0 };
2170 static char default_props[] =
2171 "name,size,used,available,capacity,health,altroot";
2172 char *props = default_props;
2174 /* check options */
2175 while ((c = getopt(argc, argv, ":Ho:")) != -1) {
2176 switch (c) {
2177 case 'H':
2178 cb.cb_scripted = B_TRUE;
2179 break;
2180 case 'o':
2181 props = optarg;
2182 break;
2183 case ':':
2184 (void) fprintf(stderr, gettext("missing argument for "
2185 "'%c' option\n"), optopt);
2186 usage(B_FALSE);
2187 break;
2188 case '?':
2189 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2190 optopt);
2191 usage(B_FALSE);
2195 argc -= optind;
2196 argv += optind;
2198 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
2199 usage(B_FALSE);
2201 cb.cb_first = B_TRUE;
2203 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
2204 list_callback, &cb);
2206 zprop_free_list(cb.cb_proplist);
2208 if (argc == 0 && cb.cb_first && !cb.cb_scripted) {
2209 (void) printf(gettext("no pools available\n"));
2210 return (0);
2213 return (ret);
2216 static nvlist_t *
2217 zpool_get_vdev_by_name(nvlist_t *nv, char *name)
2219 nvlist_t **child;
2220 uint_t c, children;
2221 nvlist_t *match;
2222 char *path;
2224 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2225 &child, &children) != 0) {
2226 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2227 if (strncmp(name, "/dev/dsk/", 9) == 0)
2228 name += 9;
2229 if (strncmp(path, "/dev/dsk/", 9) == 0)
2230 path += 9;
2231 if (strcmp(name, path) == 0)
2232 return (nv);
2233 return (NULL);
2236 for (c = 0; c < children; c++)
2237 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL)
2238 return (match);
2240 return (NULL);
2243 static int
2244 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
2246 boolean_t force = B_FALSE;
2247 int c;
2248 nvlist_t *nvroot;
2249 char *poolname, *old_disk, *new_disk;
2250 zpool_handle_t *zhp;
2251 int ret;
2253 /* check options */
2254 while ((c = getopt(argc, argv, "f")) != -1) {
2255 switch (c) {
2256 case 'f':
2257 force = B_TRUE;
2258 break;
2259 case '?':
2260 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2261 optopt);
2262 usage(B_FALSE);
2266 argc -= optind;
2267 argv += optind;
2269 /* get pool name and check number of arguments */
2270 if (argc < 1) {
2271 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2272 usage(B_FALSE);
2275 poolname = argv[0];
2277 if (argc < 2) {
2278 (void) fprintf(stderr,
2279 gettext("missing <device> specification\n"));
2280 usage(B_FALSE);
2283 old_disk = argv[1];
2285 if (argc < 3) {
2286 if (!replacing) {
2287 (void) fprintf(stderr,
2288 gettext("missing <new_device> specification\n"));
2289 usage(B_FALSE);
2291 new_disk = old_disk;
2292 argc -= 1;
2293 argv += 1;
2294 } else {
2295 new_disk = argv[2];
2296 argc -= 2;
2297 argv += 2;
2300 if (argc > 1) {
2301 (void) fprintf(stderr, gettext("too many arguments\n"));
2302 usage(B_FALSE);
2305 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2306 return (1);
2308 if (zpool_get_config(zhp, NULL) == NULL) {
2309 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
2310 poolname);
2311 zpool_close(zhp);
2312 return (1);
2315 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
2316 argc, argv);
2317 if (nvroot == NULL) {
2318 zpool_close(zhp);
2319 return (1);
2322 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
2324 nvlist_free(nvroot);
2325 zpool_close(zhp);
2327 return (ret);
2331 * zpool replace [-f] <pool> <device> <new_device>
2333 * -f Force attach, even if <new_device> appears to be in use.
2335 * Replace <device> with <new_device>.
2337 /* ARGSUSED */
2339 zpool_do_replace(int argc, char **argv)
2341 return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
2345 * zpool attach [-f] <pool> <device> <new_device>
2347 * -f Force attach, even if <new_device> appears to be in use.
2349 * Attach <new_device> to the mirror containing <device>. If <device> is not
2350 * part of a mirror, then <device> will be transformed into a mirror of
2351 * <device> and <new_device>. In either case, <new_device> will begin life
2352 * with a DTL of [0, now], and will immediately begin to resilver itself.
2355 zpool_do_attach(int argc, char **argv)
2357 return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
2361 * zpool detach [-f] <pool> <device>
2363 * -f Force detach of <device>, even if DTLs argue against it
2364 * (not supported yet)
2366 * Detach a device from a mirror. The operation will be refused if <device>
2367 * is the last device in the mirror, or if the DTLs indicate that this device
2368 * has the only valid copy of some data.
2370 /* ARGSUSED */
2372 zpool_do_detach(int argc, char **argv)
2374 int c;
2375 char *poolname, *path;
2376 zpool_handle_t *zhp;
2377 int ret;
2379 /* check options */
2380 while ((c = getopt(argc, argv, "f")) != -1) {
2381 switch (c) {
2382 case 'f':
2383 case '?':
2384 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2385 optopt);
2386 usage(B_FALSE);
2390 argc -= optind;
2391 argv += optind;
2393 /* get pool name and check number of arguments */
2394 if (argc < 1) {
2395 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2396 usage(B_FALSE);
2399 if (argc < 2) {
2400 (void) fprintf(stderr,
2401 gettext("missing <device> specification\n"));
2402 usage(B_FALSE);
2405 poolname = argv[0];
2406 path = argv[1];
2408 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2409 return (1);
2411 ret = zpool_vdev_detach(zhp, path);
2413 zpool_close(zhp);
2415 return (ret);
2419 * zpool online <pool> <device> ...
2422 zpool_do_online(int argc, char **argv)
2424 int c, i;
2425 char *poolname;
2426 zpool_handle_t *zhp;
2427 int ret = 0;
2428 vdev_state_t newstate;
2430 /* check options */
2431 while ((c = getopt(argc, argv, "t")) != -1) {
2432 switch (c) {
2433 case 't':
2434 case '?':
2435 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2436 optopt);
2437 usage(B_FALSE);
2441 argc -= optind;
2442 argv += optind;
2444 /* get pool name and check number of arguments */
2445 if (argc < 1) {
2446 (void) fprintf(stderr, gettext("missing pool name\n"));
2447 usage(B_FALSE);
2449 if (argc < 2) {
2450 (void) fprintf(stderr, gettext("missing device name\n"));
2451 usage(B_FALSE);
2454 poolname = argv[0];
2456 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2457 return (1);
2459 for (i = 1; i < argc; i++) {
2460 if (zpool_vdev_online(zhp, argv[i], 0, &newstate) == 0) {
2461 if (newstate != VDEV_STATE_HEALTHY) {
2462 (void) printf(gettext("warning: device '%s' "
2463 "onlined, but remains in faulted state\n"),
2464 argv[i]);
2465 if (newstate == VDEV_STATE_FAULTED)
2466 (void) printf(gettext("use 'zpool "
2467 "clear' to restore a faulted "
2468 "device\n"));
2469 else
2470 (void) printf(gettext("use 'zpool "
2471 "replace' to replace devices "
2472 "that are no longer present\n"));
2474 } else {
2475 ret = 1;
2479 zpool_close(zhp);
2481 return (ret);
2485 * zpool offline [-ft] <pool> <device> ...
2487 * -f Force the device into the offline state, even if doing
2488 * so would appear to compromise pool availability.
2489 * (not supported yet)
2491 * -t Only take the device off-line temporarily. The offline
2492 * state will not be persistent across reboots.
2494 /* ARGSUSED */
2496 zpool_do_offline(int argc, char **argv)
2498 int c, i;
2499 char *poolname;
2500 zpool_handle_t *zhp;
2501 int ret = 0;
2502 boolean_t istmp = B_FALSE;
2504 /* check options */
2505 while ((c = getopt(argc, argv, "ft")) != -1) {
2506 switch (c) {
2507 case 't':
2508 istmp = B_TRUE;
2509 break;
2510 case 'f':
2511 case '?':
2512 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2513 optopt);
2514 usage(B_FALSE);
2518 argc -= optind;
2519 argv += optind;
2521 /* get pool name and check number of arguments */
2522 if (argc < 1) {
2523 (void) fprintf(stderr, gettext("missing pool name\n"));
2524 usage(B_FALSE);
2526 if (argc < 2) {
2527 (void) fprintf(stderr, gettext("missing device name\n"));
2528 usage(B_FALSE);
2531 poolname = argv[0];
2533 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2534 return (1);
2536 for (i = 1; i < argc; i++) {
2537 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
2538 ret = 1;
2541 zpool_close(zhp);
2543 return (ret);
2547 * zpool clear <pool> [device]
2549 * Clear all errors associated with a pool or a particular device.
2552 zpool_do_clear(int argc, char **argv)
2554 int ret = 0;
2555 zpool_handle_t *zhp;
2556 char *pool, *device;
2558 if (argc < 2) {
2559 (void) fprintf(stderr, gettext("missing pool name\n"));
2560 usage(B_FALSE);
2563 if (argc > 3) {
2564 (void) fprintf(stderr, gettext("too many arguments\n"));
2565 usage(B_FALSE);
2568 pool = argv[1];
2569 device = argc == 3 ? argv[2] : NULL;
2571 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
2572 return (1);
2574 if (zpool_clear(zhp, device) != 0)
2575 ret = 1;
2577 zpool_close(zhp);
2579 return (ret);
2582 typedef struct scrub_cbdata {
2583 int cb_type;
2584 int cb_argc;
2585 char **cb_argv;
2586 } scrub_cbdata_t;
2589 scrub_callback(zpool_handle_t *zhp, void *data)
2591 scrub_cbdata_t *cb = data;
2592 int err;
2595 * Ignore faulted pools.
2597 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
2598 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
2599 "currently unavailable\n"), zpool_get_name(zhp));
2600 return (1);
2603 err = zpool_scrub(zhp, cb->cb_type);
2605 return (err != 0);
2609 * zpool scrub [-s] <pool> ...
2611 * -s Stop. Stops any in-progress scrub.
2614 zpool_do_scrub(int argc, char **argv)
2616 int c;
2617 scrub_cbdata_t cb;
2619 cb.cb_type = POOL_SCRUB_EVERYTHING;
2621 /* check options */
2622 while ((c = getopt(argc, argv, "s")) != -1) {
2623 switch (c) {
2624 case 's':
2625 cb.cb_type = POOL_SCRUB_NONE;
2626 break;
2627 case '?':
2628 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2629 optopt);
2630 usage(B_FALSE);
2634 cb.cb_argc = argc;
2635 cb.cb_argv = argv;
2636 argc -= optind;
2637 argv += optind;
2639 if (argc < 1) {
2640 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2641 usage(B_FALSE);
2644 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
2647 typedef struct status_cbdata {
2648 int cb_count;
2649 boolean_t cb_allpools;
2650 boolean_t cb_verbose;
2651 boolean_t cb_explain;
2652 boolean_t cb_first;
2653 } status_cbdata_t;
2656 * Print out detailed scrub status.
2658 void
2659 print_scrub_status(nvlist_t *nvroot)
2661 vdev_stat_t *vs;
2662 uint_t vsc;
2663 time_t start, end, now;
2664 double fraction_done;
2665 uint64_t examined, total, minutes_left, minutes_taken;
2666 char *scrub_type;
2668 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
2669 (uint64_t **)&vs, &vsc) == 0);
2672 * If there's never been a scrub, there's not much to say.
2674 if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) {
2675 (void) printf(gettext("none requested\n"));
2676 return;
2679 scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2680 "resilver" : "scrub";
2682 start = vs->vs_scrub_start;
2683 end = vs->vs_scrub_end;
2684 now = time(NULL);
2685 examined = vs->vs_scrub_examined;
2686 total = vs->vs_alloc;
2688 if (end != 0) {
2689 minutes_taken = (uint64_t)((end - start) / 60);
2691 (void) printf(gettext("%s %s after %lluh%um with %llu errors "
2692 "on %s"),
2693 scrub_type, vs->vs_scrub_complete ? "completed" : "stopped",
2694 (u_longlong_t)(minutes_taken / 60),
2695 (uint_t)(minutes_taken % 60),
2696 (u_longlong_t)vs->vs_scrub_errors, ctime(&end));
2697 return;
2700 if (examined == 0)
2701 examined = 1;
2702 if (examined > total)
2703 total = examined;
2705 fraction_done = (double)examined / total;
2706 minutes_left = (uint64_t)((now - start) *
2707 (1 - fraction_done) / fraction_done / 60);
2708 minutes_taken = (uint64_t)((now - start) / 60);
2710 (void) printf(gettext("%s in progress for %lluh%um, %.2f%% done, "
2711 "%lluh%um to go\n"),
2712 scrub_type, (u_longlong_t)(minutes_taken / 60),
2713 (uint_t)(minutes_taken % 60), 100 * fraction_done,
2714 (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60));
2717 typedef struct spare_cbdata {
2718 uint64_t cb_guid;
2719 zpool_handle_t *cb_zhp;
2720 } spare_cbdata_t;
2722 static boolean_t
2723 find_vdev(nvlist_t *nv, uint64_t search)
2725 uint64_t guid;
2726 nvlist_t **child;
2727 uint_t c, children;
2729 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
2730 search == guid)
2731 return (B_TRUE);
2733 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2734 &child, &children) == 0) {
2735 for (c = 0; c < children; c++)
2736 if (find_vdev(child[c], search))
2737 return (B_TRUE);
2740 return (B_FALSE);
2743 static int
2744 find_spare(zpool_handle_t *zhp, void *data)
2746 spare_cbdata_t *cbp = data;
2747 nvlist_t *config, *nvroot;
2749 config = zpool_get_config(zhp, NULL);
2750 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2751 &nvroot) == 0);
2753 if (find_vdev(nvroot, cbp->cb_guid)) {
2754 cbp->cb_zhp = zhp;
2755 return (1);
2758 zpool_close(zhp);
2759 return (0);
2763 * Print out configuration state as requested by status_callback.
2765 void
2766 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
2767 int namewidth, int depth, boolean_t isspare, boolean_t print_logs)
2769 nvlist_t **child;
2770 uint_t c, children;
2771 vdev_stat_t *vs;
2772 char rbuf[6], wbuf[6], cbuf[6], repaired[7];
2773 char *vname;
2774 uint64_t notpresent;
2775 spare_cbdata_t cb;
2776 char *state;
2778 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
2779 (uint64_t **)&vs, &c) == 0);
2781 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2782 &child, &children) != 0)
2783 children = 0;
2785 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
2786 if (isspare) {
2788 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
2789 * online drives.
2791 if (vs->vs_aux == VDEV_AUX_SPARED)
2792 state = "INUSE";
2793 else if (vs->vs_state == VDEV_STATE_HEALTHY)
2794 state = "AVAIL";
2797 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth,
2798 name, state);
2800 if (!isspare) {
2801 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
2802 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
2803 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
2804 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
2807 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
2808 &notpresent) == 0) {
2809 char *path;
2810 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2811 (void) printf(" was %s", path);
2812 } else if (vs->vs_aux != 0) {
2813 (void) printf(" ");
2815 switch (vs->vs_aux) {
2816 case VDEV_AUX_OPEN_FAILED:
2817 (void) printf(gettext("cannot open"));
2818 break;
2820 case VDEV_AUX_BAD_GUID_SUM:
2821 (void) printf(gettext("missing device"));
2822 break;
2824 case VDEV_AUX_NO_REPLICAS:
2825 (void) printf(gettext("insufficient replicas"));
2826 break;
2828 case VDEV_AUX_VERSION_NEWER:
2829 (void) printf(gettext("newer version"));
2830 break;
2832 case VDEV_AUX_SPARED:
2833 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
2834 &cb.cb_guid) == 0);
2835 if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
2836 if (strcmp(zpool_get_name(cb.cb_zhp),
2837 zpool_get_name(zhp)) == 0)
2838 (void) printf(gettext("currently in "
2839 "use"));
2840 else
2841 (void) printf(gettext("in use by "
2842 "pool '%s'"),
2843 zpool_get_name(cb.cb_zhp));
2844 zpool_close(cb.cb_zhp);
2845 } else {
2846 (void) printf(gettext("currently in use"));
2848 break;
2850 case VDEV_AUX_ERR_EXCEEDED:
2851 (void) printf(gettext("too many errors"));
2852 break;
2854 case VDEV_AUX_IO_FAILURE:
2855 (void) printf(gettext("experienced I/O failures"));
2856 break;
2858 case VDEV_AUX_BAD_LOG:
2859 (void) printf(gettext("bad intent log"));
2860 break;
2862 default:
2863 (void) printf(gettext("corrupted data"));
2864 break;
2866 } else if (vs->vs_scrub_repaired != 0 && children == 0) {
2868 * Report bytes resilvered/repaired on leaf devices.
2870 zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired));
2871 (void) printf(gettext(" %s %s"), repaired,
2872 (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2873 "resilvered" : "repaired");
2876 (void) printf("\n");
2878 for (c = 0; c < children; c++) {
2879 uint64_t is_log = B_FALSE;
2881 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2882 &is_log);
2883 if ((is_log && !print_logs) || (!is_log && print_logs))
2884 continue;
2885 vname = zpool_vdev_name(g_zfs, zhp, child[c]);
2886 print_status_config(zhp, vname, child[c],
2887 namewidth, depth + 2, isspare, B_FALSE);
2888 free(vname);
2892 static void
2893 print_error_log(zpool_handle_t *zhp)
2895 nvlist_t *nverrlist = NULL;
2896 nvpair_t *elem;
2897 char *pathname;
2898 size_t len = MAXPATHLEN * 2;
2900 if (zpool_get_errlog(zhp, &nverrlist) != 0) {
2901 (void) printf("errors: List of errors unavailable "
2902 "(insufficient privileges)\n");
2903 return;
2906 (void) printf("errors: Permanent errors have been "
2907 "detected in the following files:\n\n");
2909 pathname = safe_malloc(len);
2910 elem = NULL;
2911 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
2912 nvlist_t *nv;
2913 uint64_t dsobj, obj;
2915 verify(nvpair_value_nvlist(elem, &nv) == 0);
2916 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
2917 &dsobj) == 0);
2918 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
2919 &obj) == 0);
2920 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
2921 (void) printf("%7s %s\n", "", pathname);
2923 free(pathname);
2924 nvlist_free(nverrlist);
2927 static void
2928 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
2929 int namewidth)
2931 uint_t i;
2932 char *name;
2934 if (nspares == 0)
2935 return;
2937 (void) printf(gettext("\tspares\n"));
2939 for (i = 0; i < nspares; i++) {
2940 name = zpool_vdev_name(g_zfs, zhp, spares[i]);
2941 print_status_config(zhp, name, spares[i],
2942 namewidth, 2, B_TRUE, B_FALSE);
2943 free(name);
2947 static void
2948 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
2949 int namewidth)
2951 uint_t i;
2952 char *name;
2954 if (nl2cache == 0)
2955 return;
2957 (void) printf(gettext("\tcache\n"));
2959 for (i = 0; i < nl2cache; i++) {
2960 name = zpool_vdev_name(g_zfs, zhp, l2cache[i]);
2961 print_status_config(zhp, name, l2cache[i],
2962 namewidth, 2, B_FALSE, B_FALSE);
2963 free(name);
2968 * Display a summary of pool status. Displays a summary such as:
2970 * pool: tank
2971 * status: DEGRADED
2972 * reason: One or more devices ...
2973 * see: http://www.sun.com/msg/ZFS-xxxx-01
2974 * config:
2975 * mirror DEGRADED
2976 * c1t0d0 OK
2977 * c2t0d0 UNAVAIL
2979 * When given the '-v' option, we print out the complete config. If the '-e'
2980 * option is specified, then we print out error rate information as well.
2983 status_callback(zpool_handle_t *zhp, void *data)
2985 status_cbdata_t *cbp = data;
2986 nvlist_t *config, *nvroot;
2987 char *msgid;
2988 int reason;
2989 const char *health;
2990 uint_t c;
2991 vdev_stat_t *vs;
2993 config = zpool_get_config(zhp, NULL);
2994 reason = zpool_get_status(zhp, &msgid);
2996 cbp->cb_count++;
2999 * If we were given 'zpool status -x', only report those pools with
3000 * problems.
3002 if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) {
3003 if (!cbp->cb_allpools) {
3004 (void) printf(gettext("pool '%s' is healthy\n"),
3005 zpool_get_name(zhp));
3006 if (cbp->cb_first)
3007 cbp->cb_first = B_FALSE;
3009 return (0);
3012 if (cbp->cb_first)
3013 cbp->cb_first = B_FALSE;
3014 else
3015 (void) printf("\n");
3017 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3018 &nvroot) == 0);
3019 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
3020 (uint64_t **)&vs, &c) == 0);
3021 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
3023 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
3024 (void) printf(gettext(" state: %s\n"), health);
3026 switch (reason) {
3027 case ZPOOL_STATUS_MISSING_DEV_R:
3028 (void) printf(gettext("status: One or more devices could not "
3029 "be opened. Sufficient replicas exist for\n\tthe pool to "
3030 "continue functioning in a degraded state.\n"));
3031 (void) printf(gettext("action: Attach the missing device and "
3032 "online it using 'zpool online'.\n"));
3033 break;
3035 case ZPOOL_STATUS_MISSING_DEV_NR:
3036 (void) printf(gettext("status: One or more devices could not "
3037 "be opened. There are insufficient\n\treplicas for the "
3038 "pool to continue functioning.\n"));
3039 (void) printf(gettext("action: Attach the missing device and "
3040 "online it using 'zpool online'.\n"));
3041 break;
3043 case ZPOOL_STATUS_CORRUPT_LABEL_R:
3044 (void) printf(gettext("status: One or more devices could not "
3045 "be used because the label is missing or\n\tinvalid. "
3046 "Sufficient replicas exist for the pool to continue\n\t"
3047 "functioning in a degraded state.\n"));
3048 (void) printf(gettext("action: Replace the device using "
3049 "'zpool replace'.\n"));
3050 break;
3052 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
3053 (void) printf(gettext("status: One or more devices could not "
3054 "be used because the label is missing \n\tor invalid. "
3055 "There are insufficient replicas for the pool to "
3056 "continue\n\tfunctioning.\n"));
3057 (void) printf(gettext("action: Destroy and re-create the pool "
3058 "from a backup source.\n"));
3059 break;
3061 case ZPOOL_STATUS_FAILING_DEV:
3062 (void) printf(gettext("status: One or more devices has "
3063 "experienced an unrecoverable error. An\n\tattempt was "
3064 "made to correct the error. Applications are "
3065 "unaffected.\n"));
3066 (void) printf(gettext("action: Determine if the device needs "
3067 "to be replaced, and clear the errors\n\tusing "
3068 "'zpool clear' or replace the device with 'zpool "
3069 "replace'.\n"));
3070 break;
3072 case ZPOOL_STATUS_OFFLINE_DEV:
3073 (void) printf(gettext("status: One or more devices has "
3074 "been taken offline by the administrator.\n\tSufficient "
3075 "replicas exist for the pool to continue functioning in "
3076 "a\n\tdegraded state.\n"));
3077 (void) printf(gettext("action: Online the device using "
3078 "'zpool online' or replace the device with\n\t'zpool "
3079 "replace'.\n"));
3080 break;
3082 case ZPOOL_STATUS_RESILVERING:
3083 (void) printf(gettext("status: One or more devices is "
3084 "currently being resilvered. The pool will\n\tcontinue "
3085 "to function, possibly in a degraded state.\n"));
3086 (void) printf(gettext("action: Wait for the resilver to "
3087 "complete.\n"));
3088 break;
3090 case ZPOOL_STATUS_CORRUPT_DATA:
3091 (void) printf(gettext("status: One or more devices has "
3092 "experienced an error resulting in data\n\tcorruption. "
3093 "Applications may be affected.\n"));
3094 (void) printf(gettext("action: Restore the file in question "
3095 "if possible. Otherwise restore the\n\tentire pool from "
3096 "backup.\n"));
3097 break;
3099 case ZPOOL_STATUS_CORRUPT_POOL:
3100 (void) printf(gettext("status: The pool metadata is corrupted "
3101 "and the pool cannot be opened.\n"));
3102 (void) printf(gettext("action: Destroy and re-create the pool "
3103 "from a backup source.\n"));
3104 break;
3106 case ZPOOL_STATUS_VERSION_OLDER:
3107 (void) printf(gettext("status: The pool is formatted using an "
3108 "older on-disk format. The pool can\n\tstill be used, but "
3109 "some features are unavailable.\n"));
3110 (void) printf(gettext("action: Upgrade the pool using 'zpool "
3111 "upgrade'. Once this is done, the\n\tpool will no longer "
3112 "be accessible on older software versions.\n"));
3113 break;
3115 case ZPOOL_STATUS_VERSION_NEWER:
3116 (void) printf(gettext("status: The pool has been upgraded to a "
3117 "newer, incompatible on-disk version.\n\tThe pool cannot "
3118 "be accessed on this system.\n"));
3119 (void) printf(gettext("action: Access the pool from a system "
3120 "running more recent software, or\n\trestore the pool from "
3121 "backup.\n"));
3122 break;
3124 case ZPOOL_STATUS_FAULTED_DEV_R:
3125 (void) printf(gettext("status: One or more devices are "
3126 "faulted in response to persistent errors.\n\tSufficient "
3127 "replicas exist for the pool to continue functioning "
3128 "in a\n\tdegraded state.\n"));
3129 (void) printf(gettext("action: Replace the faulted device, "
3130 "or use 'zpool clear' to mark the device\n\trepaired.\n"));
3131 break;
3133 case ZPOOL_STATUS_FAULTED_DEV_NR:
3134 (void) printf(gettext("status: One or more devices are "
3135 "faulted in response to persistent errors. There are "
3136 "insufficient replicas for the pool to\n\tcontinue "
3137 "functioning.\n"));
3138 (void) printf(gettext("action: Destroy and re-create the pool "
3139 "from a backup source. Manually marking the device\n"
3140 "\trepaired using 'zpool clear' may allow some data "
3141 "to be recovered.\n"));
3142 break;
3144 case ZPOOL_STATUS_IO_FAILURE_WAIT:
3145 case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
3146 (void) printf(gettext("status: One or more devices are "
3147 "faulted in response to IO failures.\n"));
3148 (void) printf(gettext("action: Make sure the affected devices "
3149 "are connected, then run 'zpool clear'.\n"));
3150 break;
3152 case ZPOOL_STATUS_BAD_LOG:
3153 (void) printf(gettext("status: An intent log record "
3154 "could not be read.\n"
3155 "\tWaiting for adminstrator intervention to fix the "
3156 "faulted pool.\n"));
3157 (void) printf(gettext("action: Either restore the affected "
3158 "device(s) and run 'zpool online',\n"
3159 "\tor ignore the intent log records by running "
3160 "'zpool clear'.\n"));
3161 break;
3163 default:
3165 * The remaining errors can't actually be generated, yet.
3167 assert(reason == ZPOOL_STATUS_OK);
3170 if (msgid != NULL)
3171 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"),
3172 msgid);
3174 if (config != NULL) {
3175 int namewidth;
3176 uint64_t nerr;
3177 nvlist_t **spares, **l2cache;
3178 uint_t nspares, nl2cache;
3181 (void) printf(gettext(" scrub: "));
3182 print_scrub_status(nvroot);
3184 namewidth = max_width(zhp, nvroot, 0, 0);
3185 if (namewidth < 10)
3186 namewidth = 10;
3188 (void) printf(gettext("config:\n\n"));
3189 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth,
3190 "NAME", "STATE", "READ", "WRITE", "CKSUM");
3191 print_status_config(zhp, zpool_get_name(zhp), nvroot,
3192 namewidth, 0, B_FALSE, B_FALSE);
3193 if (num_logs(nvroot) > 0)
3194 print_status_config(zhp, "logs", nvroot, namewidth, 0,
3195 B_FALSE, B_TRUE);
3197 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
3198 &l2cache, &nl2cache) == 0)
3199 print_l2cache(zhp, l2cache, nl2cache, namewidth);
3201 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
3202 &spares, &nspares) == 0)
3203 print_spares(zhp, spares, nspares, namewidth);
3205 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
3206 &nerr) == 0) {
3207 nvlist_t *nverrlist = NULL;
3210 * If the approximate error count is small, get a
3211 * precise count by fetching the entire log and
3212 * uniquifying the results.
3214 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
3215 zpool_get_errlog(zhp, &nverrlist) == 0) {
3216 nvpair_t *elem;
3218 elem = NULL;
3219 nerr = 0;
3220 while ((elem = nvlist_next_nvpair(nverrlist,
3221 elem)) != NULL) {
3222 nerr++;
3225 nvlist_free(nverrlist);
3227 (void) printf("\n");
3229 if (nerr == 0)
3230 (void) printf(gettext("errors: No known data "
3231 "errors\n"));
3232 else if (!cbp->cb_verbose)
3233 (void) printf(gettext("errors: %llu data "
3234 "errors, use '-v' for a list\n"),
3235 (u_longlong_t)nerr);
3236 else
3237 print_error_log(zhp);
3239 } else {
3240 (void) printf(gettext("config: The configuration cannot be "
3241 "determined.\n"));
3244 return (0);
3248 * zpool status [-vx] [pool] ...
3250 * -v Display complete error logs
3251 * -x Display only pools with potential problems
3253 * Describes the health status of all pools or some subset.
3256 zpool_do_status(int argc, char **argv)
3258 int c;
3259 int ret;
3260 status_cbdata_t cb = { 0 };
3262 /* check options */
3263 while ((c = getopt(argc, argv, "vx")) != -1) {
3264 switch (c) {
3265 case 'v':
3266 cb.cb_verbose = B_TRUE;
3267 break;
3268 case 'x':
3269 cb.cb_explain = B_TRUE;
3270 break;
3271 case '?':
3272 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3273 optopt);
3274 usage(B_FALSE);
3278 argc -= optind;
3279 argv += optind;
3281 cb.cb_first = B_TRUE;
3283 if (argc == 0)
3284 cb.cb_allpools = B_TRUE;
3286 ret = for_each_pool(argc, argv, B_TRUE, NULL, status_callback, &cb);
3288 if (argc == 0 && cb.cb_count == 0)
3289 (void) printf(gettext("no pools available\n"));
3290 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
3291 (void) printf(gettext("all pools are healthy\n"));
3293 return (ret);
3296 typedef struct upgrade_cbdata {
3297 int cb_all;
3298 int cb_first;
3299 int cb_newer;
3300 int cb_argc;
3301 uint64_t cb_version;
3302 char **cb_argv;
3303 } upgrade_cbdata_t;
3305 static int
3306 upgrade_cb(zpool_handle_t *zhp, void *arg)
3308 upgrade_cbdata_t *cbp = arg;
3309 nvlist_t *config;
3310 uint64_t version;
3311 int ret = 0;
3313 config = zpool_get_config(zhp, NULL);
3314 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
3315 &version) == 0);
3317 if (!cbp->cb_newer && version < SPA_VERSION) {
3318 if (!cbp->cb_all) {
3319 if (cbp->cb_first) {
3320 (void) printf(gettext("The following pools are "
3321 "out of date, and can be upgraded. After "
3322 "being\nupgraded, these pools will no "
3323 "longer be accessible by older software "
3324 "versions.\n\n"));
3325 (void) printf(gettext("VER POOL\n"));
3326 (void) printf(gettext("--- ------------\n"));
3327 cbp->cb_first = B_FALSE;
3330 (void) printf("%2llu %s\n", (u_longlong_t)version,
3331 zpool_get_name(zhp));
3332 } else {
3333 cbp->cb_first = B_FALSE;
3334 ret = zpool_upgrade(zhp, cbp->cb_version);
3335 if (!ret) {
3336 (void) printf(gettext("Successfully upgraded "
3337 "'%s'\n\n"), zpool_get_name(zhp));
3340 } else if (cbp->cb_newer && version > SPA_VERSION) {
3341 assert(!cbp->cb_all);
3343 if (cbp->cb_first) {
3344 (void) printf(gettext("The following pools are "
3345 "formatted using a newer software version and\n"
3346 "cannot be accessed on the current system.\n\n"));
3347 (void) printf(gettext("VER POOL\n"));
3348 (void) printf(gettext("--- ------------\n"));
3349 cbp->cb_first = B_FALSE;
3352 (void) printf("%2llu %s\n", (u_longlong_t)version,
3353 zpool_get_name(zhp));
3356 zpool_close(zhp);
3357 return (ret);
3360 /* ARGSUSED */
3361 static int
3362 upgrade_one(zpool_handle_t *zhp, void *data)
3364 upgrade_cbdata_t *cbp = data;
3365 uint64_t cur_version;
3366 int ret;
3368 if (strcmp("log", zpool_get_name(zhp)) == 0) {
3369 (void) printf(gettext("'log' is now a reserved word\n"
3370 "Pool 'log' must be renamed using export and import"
3371 " to upgrade.\n"));
3372 return (1);
3375 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
3376 if (cur_version > cbp->cb_version) {
3377 (void) printf(gettext("Pool '%s' is already formatted "
3378 "using more current version '%llu'.\n"),
3379 zpool_get_name(zhp), cur_version);
3380 return (0);
3382 if (cur_version == cbp->cb_version) {
3383 (void) printf(gettext("Pool '%s' is already formatted "
3384 "using the current version.\n"), zpool_get_name(zhp));
3385 return (0);
3388 ret = zpool_upgrade(zhp, cbp->cb_version);
3390 if (!ret) {
3391 (void) printf(gettext("Successfully upgraded '%s' "
3392 "from version %llu to version %llu\n\n"),
3393 zpool_get_name(zhp), (u_longlong_t)cur_version,
3394 (u_longlong_t)cbp->cb_version);
3397 return (ret != 0);
3401 * zpool upgrade
3402 * zpool upgrade -v
3403 * zpool upgrade [-V version] <-a | pool ...>
3405 * With no arguments, display downrev'd ZFS pool available for upgrade.
3406 * Individual pools can be upgraded by specifying the pool, and '-a' will
3407 * upgrade all pools.
3410 zpool_do_upgrade(int argc, char **argv)
3412 int c;
3413 upgrade_cbdata_t cb = { 0 };
3414 int ret = 0;
3415 boolean_t showversions = B_FALSE;
3416 char *end;
3419 /* check options */
3420 while ((c = getopt(argc, argv, "avV:")) != -1) {
3421 switch (c) {
3422 case 'a':
3423 cb.cb_all = B_TRUE;
3424 break;
3425 case 'v':
3426 showversions = B_TRUE;
3427 break;
3428 case 'V':
3429 cb.cb_version = strtoll(optarg, &end, 10);
3430 if (*end != '\0' || cb.cb_version > SPA_VERSION ||
3431 cb.cb_version < SPA_VERSION_1) {
3432 (void) fprintf(stderr,
3433 gettext("invalid version '%s'\n"), optarg);
3434 usage(B_FALSE);
3436 break;
3437 case '?':
3438 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3439 optopt);
3440 usage(B_FALSE);
3444 cb.cb_argc = argc;
3445 cb.cb_argv = argv;
3446 argc -= optind;
3447 argv += optind;
3449 if (cb.cb_version == 0) {
3450 cb.cb_version = SPA_VERSION;
3451 } else if (!cb.cb_all && argc == 0) {
3452 (void) fprintf(stderr, gettext("-V option is "
3453 "incompatible with other arguments\n"));
3454 usage(B_FALSE);
3457 if (showversions) {
3458 if (cb.cb_all || argc != 0) {
3459 (void) fprintf(stderr, gettext("-v option is "
3460 "incompatible with other arguments\n"));
3461 usage(B_FALSE);
3463 } else if (cb.cb_all) {
3464 if (argc != 0) {
3465 (void) fprintf(stderr, gettext("-a option should not "
3466 "be used along with a pool name\n"));
3467 usage(B_FALSE);
3471 (void) printf(gettext("This system is currently running "
3472 "ZFS pool version %llu.\n\n"), SPA_VERSION);
3473 cb.cb_first = B_TRUE;
3474 if (showversions) {
3475 (void) printf(gettext("The following versions are "
3476 "supported:\n\n"));
3477 (void) printf(gettext("VER DESCRIPTION\n"));
3478 (void) printf("--- -----------------------------------------"
3479 "---------------\n");
3480 (void) printf(gettext(" 1 Initial ZFS version\n"));
3481 (void) printf(gettext(" 2 Ditto blocks "
3482 "(replicated metadata)\n"));
3483 (void) printf(gettext(" 3 Hot spares and double parity "
3484 "RAID-Z\n"));
3485 (void) printf(gettext(" 4 zpool history\n"));
3486 (void) printf(gettext(" 5 Compression using the gzip "
3487 "algorithm\n"));
3488 (void) printf(gettext(" 6 bootfs pool property\n"));
3489 (void) printf(gettext(" 7 Separate intent log devices\n"));
3490 (void) printf(gettext(" 8 Delegated administration\n"));
3491 (void) printf(gettext(" 9 refquota and refreservation "
3492 "properties\n"));
3493 (void) printf(gettext(" 10 Cache devices\n"));
3494 (void) printf(gettext(" 11 Improved scrub performance\n"));
3495 (void) printf(gettext(" 12 Snapshot properties\n"));
3496 (void) printf(gettext(" 13 snapused property\n"));
3497 (void) printf(gettext(" 14 passthrough-x aclinherit "
3498 "support\n"));
3499 (void) printf(gettext("For more information on a particular "
3500 "version, including supported releases, see:\n\n"));
3501 (void) printf("http://www.opensolaris.org/os/community/zfs/"
3502 "version/N\n\n");
3503 (void) printf(gettext("Where 'N' is the version number.\n"));
3504 } else if (argc == 0) {
3505 int notfound;
3507 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3508 notfound = cb.cb_first;
3510 if (!cb.cb_all && ret == 0) {
3511 if (!cb.cb_first)
3512 (void) printf("\n");
3513 cb.cb_first = B_TRUE;
3514 cb.cb_newer = B_TRUE;
3515 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3516 if (!cb.cb_first) {
3517 notfound = B_FALSE;
3518 (void) printf("\n");
3522 if (ret == 0) {
3523 if (notfound)
3524 (void) printf(gettext("All pools are formatted "
3525 "using this version.\n"));
3526 else if (!cb.cb_all)
3527 (void) printf(gettext("Use 'zpool upgrade -v' "
3528 "for a list of available versions and "
3529 "their associated\nfeatures.\n"));
3531 } else {
3532 ret = for_each_pool(argc, argv, B_FALSE, NULL,
3533 upgrade_one, &cb);
3536 return (ret);
3539 typedef struct hist_cbdata {
3540 boolean_t first;
3541 int longfmt;
3542 int internal;
3543 } hist_cbdata_t;
3545 char *hist_event_table[LOG_END] = {
3546 "invalid event",
3547 "pool create",
3548 "vdev add",
3549 "pool remove",
3550 "pool destroy",
3551 "pool export",
3552 "pool import",
3553 "vdev attach",
3554 "vdev replace",
3555 "vdev detach",
3556 "vdev online",
3557 "vdev offline",
3558 "vdev upgrade",
3559 "pool clear",
3560 "pool scrub",
3561 "pool property set",
3562 "create",
3563 "clone",
3564 "destroy",
3565 "destroy_begin_sync",
3566 "inherit",
3567 "property set",
3568 "quota set",
3569 "permission update",
3570 "permission remove",
3571 "permission who remove",
3572 "promote",
3573 "receive",
3574 "rename",
3575 "reservation set",
3576 "replay_inc_sync",
3577 "replay_full_sync",
3578 "rollback",
3579 "snapshot",
3580 "filesystem version upgrade",
3581 "refquota set",
3582 "refreservation set",
3583 "pool scrub done",
3587 * Print out the command history for a specific pool.
3589 static int
3590 get_history_one(zpool_handle_t *zhp, void *data)
3592 nvlist_t *nvhis;
3593 nvlist_t **records;
3594 uint_t numrecords;
3595 char *cmdstr;
3596 char *pathstr;
3597 uint64_t dst_time;
3598 time_t tsec;
3599 struct tm t;
3600 char tbuf[30];
3601 int ret, i;
3602 uint64_t who;
3603 struct passwd *pwd;
3604 char *hostname;
3605 char *zonename;
3606 char internalstr[MAXPATHLEN];
3607 hist_cbdata_t *cb = (hist_cbdata_t *)data;
3608 uint64_t txg;
3609 uint64_t ievent;
3611 cb->first = B_FALSE;
3613 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
3615 if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
3616 return (ret);
3618 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
3619 &records, &numrecords) == 0);
3620 for (i = 0; i < numrecords; i++) {
3621 if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME,
3622 &dst_time) != 0)
3623 continue;
3625 /* is it an internal event or a standard event? */
3626 if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD,
3627 &cmdstr) != 0) {
3628 if (cb->internal == 0)
3629 continue;
3631 if (nvlist_lookup_uint64(records[i],
3632 ZPOOL_HIST_INT_EVENT, &ievent) != 0)
3633 continue;
3634 verify(nvlist_lookup_uint64(records[i],
3635 ZPOOL_HIST_TXG, &txg) == 0);
3636 verify(nvlist_lookup_string(records[i],
3637 ZPOOL_HIST_INT_STR, &pathstr) == 0);
3638 if (ievent >= LOG_END)
3639 continue;
3640 (void) snprintf(internalstr,
3641 sizeof (internalstr),
3642 "[internal %s txg:%lld] %s",
3643 hist_event_table[ievent], txg,
3644 pathstr);
3645 cmdstr = internalstr;
3647 tsec = dst_time;
3648 (void) localtime_r(&tsec, &t);
3649 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
3650 (void) printf("%s %s", tbuf, cmdstr);
3652 if (!cb->longfmt) {
3653 (void) printf("\n");
3654 continue;
3656 (void) printf(" [");
3657 if (nvlist_lookup_uint64(records[i],
3658 ZPOOL_HIST_WHO, &who) == 0) {
3659 pwd = getpwuid((uid_t)who);
3660 if (pwd)
3661 (void) printf("user %s on",
3662 pwd->pw_name);
3663 else
3664 (void) printf("user %d on",
3665 (int)who);
3666 } else {
3667 (void) printf(gettext("no info]\n"));
3668 continue;
3670 if (nvlist_lookup_string(records[i],
3671 ZPOOL_HIST_HOST, &hostname) == 0) {
3672 (void) printf(" %s", hostname);
3674 if (nvlist_lookup_string(records[i],
3675 ZPOOL_HIST_ZONE, &zonename) == 0) {
3676 (void) printf(":%s", zonename);
3679 (void) printf("]");
3680 (void) printf("\n");
3682 (void) printf("\n");
3683 nvlist_free(nvhis);
3685 return (ret);
3689 * zpool history <pool>
3691 * Displays the history of commands that modified pools.
3696 zpool_do_history(int argc, char **argv)
3698 hist_cbdata_t cbdata = { 0 };
3699 int ret;
3700 int c;
3702 cbdata.first = B_TRUE;
3703 /* check options */
3704 while ((c = getopt(argc, argv, "li")) != -1) {
3705 switch (c) {
3706 case 'l':
3707 cbdata.longfmt = 1;
3708 break;
3709 case 'i':
3710 cbdata.internal = 1;
3711 break;
3712 case '?':
3713 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3714 optopt);
3715 usage(B_FALSE);
3718 argc -= optind;
3719 argv += optind;
3721 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one,
3722 &cbdata);
3724 if (argc == 0 && cbdata.first == B_TRUE) {
3725 (void) printf(gettext("no pools available\n"));
3726 return (0);
3729 return (ret);
3732 static int
3733 get_callback(zpool_handle_t *zhp, void *data)
3735 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
3736 char value[MAXNAMELEN];
3737 zprop_source_t srctype;
3738 zprop_list_t *pl;
3740 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
3743 * Skip the special fake placeholder. This will also skip
3744 * over the name property when 'all' is specified.
3746 if (pl->pl_prop == ZPOOL_PROP_NAME &&
3747 pl == cbp->cb_proplist)
3748 continue;
3750 if (zpool_get_prop(zhp, pl->pl_prop,
3751 value, sizeof (value), &srctype) != 0)
3752 continue;
3754 zprop_print_one_property(zpool_get_name(zhp), cbp,
3755 zpool_prop_to_name(pl->pl_prop), value, srctype, NULL);
3757 return (0);
3761 zpool_do_get(int argc, char **argv)
3763 zprop_get_cbdata_t cb = { 0 };
3764 zprop_list_t fake_name = { 0 };
3765 int ret;
3767 if (argc < 3)
3768 usage(B_FALSE);
3770 cb.cb_first = B_TRUE;
3771 cb.cb_sources = ZPROP_SRC_ALL;
3772 cb.cb_columns[0] = GET_COL_NAME;
3773 cb.cb_columns[1] = GET_COL_PROPERTY;
3774 cb.cb_columns[2] = GET_COL_VALUE;
3775 cb.cb_columns[3] = GET_COL_SOURCE;
3776 cb.cb_type = ZFS_TYPE_POOL;
3778 if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist,
3779 ZFS_TYPE_POOL) != 0)
3780 usage(B_FALSE);
3782 if (cb.cb_proplist != NULL) {
3783 fake_name.pl_prop = ZPOOL_PROP_NAME;
3784 fake_name.pl_width = strlen(gettext("NAME"));
3785 fake_name.pl_next = cb.cb_proplist;
3786 cb.cb_proplist = &fake_name;
3789 ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist,
3790 get_callback, &cb);
3792 if (cb.cb_proplist == &fake_name)
3793 zprop_free_list(fake_name.pl_next);
3794 else
3795 zprop_free_list(cb.cb_proplist);
3797 return (ret);
3800 typedef struct set_cbdata {
3801 char *cb_propname;
3802 char *cb_value;
3803 boolean_t cb_any_successful;
3804 } set_cbdata_t;
3807 set_callback(zpool_handle_t *zhp, void *data)
3809 int error;
3810 set_cbdata_t *cb = (set_cbdata_t *)data;
3812 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
3814 if (!error)
3815 cb->cb_any_successful = B_TRUE;
3817 return (error);
3821 zpool_do_set(int argc, char **argv)
3823 set_cbdata_t cb = { 0 };
3824 int error;
3826 if (argc > 1 && argv[1][0] == '-') {
3827 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3828 argv[1][1]);
3829 usage(B_FALSE);
3832 if (argc < 2) {
3833 (void) fprintf(stderr, gettext("missing property=value "
3834 "argument\n"));
3835 usage(B_FALSE);
3838 if (argc < 3) {
3839 (void) fprintf(stderr, gettext("missing pool name\n"));
3840 usage(B_FALSE);
3843 if (argc > 3) {
3844 (void) fprintf(stderr, gettext("too many pool names\n"));
3845 usage(B_FALSE);
3848 cb.cb_propname = argv[1];
3849 cb.cb_value = strchr(cb.cb_propname, '=');
3850 if (cb.cb_value == NULL) {
3851 (void) fprintf(stderr, gettext("missing value in "
3852 "property=value argument\n"));
3853 usage(B_FALSE);
3856 *(cb.cb_value) = '\0';
3857 cb.cb_value++;
3859 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
3860 set_callback, &cb);
3862 return (error);
3865 static int
3866 find_command_idx(char *command, int *idx)
3868 int i;
3870 for (i = 0; i < NCOMMAND; i++) {
3871 if (command_table[i].name == NULL)
3872 continue;
3874 if (strcmp(command, command_table[i].name) == 0) {
3875 *idx = i;
3876 return (0);
3879 return (1);
3883 main(int argc, char **argv)
3885 int ret;
3886 int i;
3887 char *cmdname;
3889 (void) setlocale(LC_ALL, "");
3890 (void) textdomain(TEXT_DOMAIN);
3892 if ((g_zfs = libzfs_init()) == NULL) {
3893 (void) fprintf(stderr, gettext("internal error: failed to "
3894 "initialize ZFS library\n"));
3895 return (1);
3898 libzfs_print_on_error(g_zfs, B_TRUE);
3900 opterr = 0;
3903 * Make sure the user has specified some command.
3905 if (argc < 2) {
3906 (void) fprintf(stderr, gettext("missing command\n"));
3907 usage(B_FALSE);
3910 cmdname = argv[1];
3913 * Special case '-?'
3915 if (strcmp(cmdname, "-?") == 0)
3916 usage(B_TRUE);
3918 zpool_set_history_str("zpool", argc, argv, history_str);
3919 verify(zpool_stage_history(g_zfs, history_str) == 0);
3922 * Run the appropriate command.
3924 if (find_command_idx(cmdname, &i) == 0) {
3925 current_command = &command_table[i];
3926 ret = command_table[i].func(argc - 1, argv + 1);
3927 } else if (strchr(cmdname, '=')) {
3928 verify(find_command_idx("set", &i) == 0);
3929 current_command = &command_table[i];
3930 ret = command_table[i].func(argc, argv);
3931 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
3933 * 'freeze' is a vile debugging abomination, so we treat
3934 * it as such.
3936 char buf[16384];
3937 int fd = open(ZFS_DEV, O_RDWR);
3938 (void) strcpy((void *)buf, argv[2]);
3939 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
3940 } else {
3941 (void) fprintf(stderr, gettext("unrecognized "
3942 "command '%s'\n"), cmdname);
3943 usage(B_FALSE);
3946 libzfs_fini(g_zfs);
3949 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
3950 * for the purposes of running ::findleaks.
3952 if (getenv("ZFS_ABORT") != NULL) {
3953 (void) printf("dumping core by request\n");
3954 abort();
3957 return (ret);