]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / cddl / contrib / opensolaris / cmd / zpool / zpool_main.c
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26
27 #pragma ident   "%Z%%M% %I%     %E% SMI"
28
29 #include <solaris.h>
30 #include <assert.h>
31 #include <ctype.h>
32 #include <dirent.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <libgen.h>
36 #include <libintl.h>
37 #include <libuutil.h>
38 #include <locale.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <strings.h>
43 #include <unistd.h>
44 #include <priv.h>
45 #include <sys/time.h>
46 #include <sys/fs/zfs.h>
47
48 #include <sys/stat.h>
49
50 #include <libzfs.h>
51
52 #include "zpool_util.h"
53
54 static int zpool_do_create(int, char **);
55 static int zpool_do_destroy(int, char **);
56
57 static int zpool_do_add(int, char **);
58 static int zpool_do_remove(int, char **);
59
60 static int zpool_do_list(int, char **);
61 static int zpool_do_iostat(int, char **);
62 static int zpool_do_status(int, char **);
63
64 static int zpool_do_online(int, char **);
65 static int zpool_do_offline(int, char **);
66 static int zpool_do_clear(int, char **);
67
68 static int zpool_do_attach(int, char **);
69 static int zpool_do_detach(int, char **);
70 static int zpool_do_replace(int, char **);
71
72 static int zpool_do_scrub(int, char **);
73
74 static int zpool_do_import(int, char **);
75 static int zpool_do_export(int, char **);
76
77 static int zpool_do_upgrade(int, char **);
78
79 static int zpool_do_history(int, char **);
80
81 static int zpool_do_get(int, char **);
82 static int zpool_do_set(int, char **);
83
84 /*
85  * These libumem hooks provide a reasonable set of defaults for the allocator's
86  * debugging facilities.
87  */
88 const char *
89 _umem_debug_init(void)
90 {
91         return ("default,verbose"); /* $UMEM_DEBUG setting */
92 }
93
94 const char *
95 _umem_logging_init(void)
96 {
97         return ("fail,contents"); /* $UMEM_LOGGING setting */
98 }
99
100 typedef enum {
101         HELP_ADD,
102         HELP_ATTACH,
103         HELP_CLEAR,
104         HELP_CREATE,
105         HELP_DESTROY,
106         HELP_DETACH,
107         HELP_EXPORT,
108         HELP_HISTORY,
109         HELP_IMPORT,
110         HELP_IOSTAT,
111         HELP_LIST,
112         HELP_OFFLINE,
113         HELP_ONLINE,
114         HELP_REPLACE,
115         HELP_REMOVE,
116         HELP_SCRUB,
117         HELP_STATUS,
118         HELP_UPGRADE,
119         HELP_GET,
120         HELP_SET
121 } zpool_help_t;
122
123
124 typedef struct zpool_command {
125         const char      *name;
126         int             (*func)(int, char **);
127         zpool_help_t    usage;
128 } zpool_command_t;
129
130 /*
131  * Master command table.  Each ZFS command has a name, associated function, and
132  * usage message.  The usage messages need to be internationalized, so we have
133  * to have a function to return the usage message based on a command index.
134  *
135  * These commands are organized according to how they are displayed in the usage
136  * message.  An empty command (one with a NULL name) indicates an empty line in
137  * the generic usage message.
138  */
139 static zpool_command_t command_table[] = {
140         { "create",     zpool_do_create,        HELP_CREATE             },
141         { "destroy",    zpool_do_destroy,       HELP_DESTROY            },
142         { NULL },
143         { "add",        zpool_do_add,           HELP_ADD                },
144         { "remove",     zpool_do_remove,        HELP_REMOVE             },
145         { NULL },
146         { "list",       zpool_do_list,          HELP_LIST               },
147         { "iostat",     zpool_do_iostat,        HELP_IOSTAT             },
148         { "status",     zpool_do_status,        HELP_STATUS             },
149         { NULL },
150         { "online",     zpool_do_online,        HELP_ONLINE             },
151         { "offline",    zpool_do_offline,       HELP_OFFLINE            },
152         { "clear",      zpool_do_clear,         HELP_CLEAR              },
153         { NULL },
154         { "attach",     zpool_do_attach,        HELP_ATTACH             },
155         { "detach",     zpool_do_detach,        HELP_DETACH             },
156         { "replace",    zpool_do_replace,       HELP_REPLACE            },
157         { NULL },
158         { "scrub",      zpool_do_scrub,         HELP_SCRUB              },
159         { NULL },
160         { "import",     zpool_do_import,        HELP_IMPORT             },
161         { "export",     zpool_do_export,        HELP_EXPORT             },
162         { "upgrade",    zpool_do_upgrade,       HELP_UPGRADE            },
163         { NULL },
164         { "history",    zpool_do_history,       HELP_HISTORY            },
165         { "get",        zpool_do_get,           HELP_GET                },
166         { "set",        zpool_do_set,           HELP_SET                },
167 };
168
169 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
170
171 zpool_command_t *current_command;
172
173 static const char *
174 get_usage(zpool_help_t idx) {
175         switch (idx) {
176         case HELP_ADD:
177                 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
178         case HELP_ATTACH:
179                 return (gettext("\tattach [-f] <pool> <device> "
180                     "<new_device>\n"));
181         case HELP_CLEAR:
182                 return (gettext("\tclear <pool> [device]\n"));
183         case HELP_CREATE:
184                 return (gettext("\tcreate  [-fn] [-R root] [-m mountpoint] "
185                     "<pool> <vdev> ...\n"));
186         case HELP_DESTROY:
187                 return (gettext("\tdestroy [-f] <pool>\n"));
188         case HELP_DETACH:
189                 return (gettext("\tdetach <pool> <device>\n"));
190         case HELP_EXPORT:
191                 return (gettext("\texport [-f] <pool> ...\n"));
192         case HELP_HISTORY:
193                 return (gettext("\thistory [<pool>]\n"));
194         case HELP_IMPORT:
195                 return (gettext("\timport [-d dir] [-D]\n"
196                     "\timport [-d dir] [-D] [-f] [-o opts] [-R root] -a\n"
197                     "\timport [-d dir] [-D] [-f] [-o opts] [-R root ]"
198                     " <pool | id> [newpool]\n"));
199         case HELP_IOSTAT:
200                 return (gettext("\tiostat [-v] [pool] ... [interval "
201                     "[count]]\n"));
202         case HELP_LIST:
203                 return (gettext("\tlist [-H] [-o field[,field]*] "
204                     "[pool] ...\n"));
205         case HELP_OFFLINE:
206                 return (gettext("\toffline [-t] <pool> <device> ...\n"));
207         case HELP_ONLINE:
208                 return (gettext("\tonline <pool> <device> ...\n"));
209         case HELP_REPLACE:
210                 return (gettext("\treplace [-f] <pool> <device> "
211                     "[new_device]\n"));
212         case HELP_REMOVE:
213                 return (gettext("\tremove <pool> <device>\n"));
214         case HELP_SCRUB:
215                 return (gettext("\tscrub [-s] <pool> ...\n"));
216         case HELP_STATUS:
217                 return (gettext("\tstatus [-vx] [pool] ...\n"));
218         case HELP_UPGRADE:
219                 return (gettext("\tupgrade\n"
220                     "\tupgrade -v\n"
221                     "\tupgrade <-a | pool>\n"));
222         case HELP_GET:
223                 return (gettext("\tget <all | property[,property]...> "
224                     "<pool> ...\n"));
225         case HELP_SET:
226                 return (gettext("\tset <property=value> <pool> \n"));
227         }
228
229         abort();
230         /* NOTREACHED */
231 }
232
233 /*
234  * Fields available for 'zpool list'.
235  */
236 typedef enum {
237         ZPOOL_FIELD_NAME,
238         ZPOOL_FIELD_SIZE,
239         ZPOOL_FIELD_USED,
240         ZPOOL_FIELD_AVAILABLE,
241         ZPOOL_FIELD_CAPACITY,
242         ZPOOL_FIELD_HEALTH,
243         ZPOOL_FIELD_ROOT
244 } zpool_field_t;
245
246 #define MAX_FIELDS      10
247
248 typedef struct column_def {
249         const char      *cd_title;
250         size_t          cd_width;
251         enum {
252                 left_justify,
253                 right_justify
254         }               cd_justify;
255 } column_def_t;
256
257 static column_def_t column_table[] = {
258         { "NAME",       20,     left_justify    },
259         { "SIZE",       6,      right_justify   },
260         { "USED",       6,      right_justify   },
261         { "AVAIL",      6,      right_justify   },
262         { "CAP",        5,      right_justify   },
263         { "HEALTH",     9,      left_justify    },
264         { "ALTROOT",    15,     left_justify    }
265 };
266
267 static char *column_subopts[] = {
268         "name",
269         "size",
270         "used",
271         "available",
272         "capacity",
273         "health",
274         "root",
275         NULL
276 };
277
278 /*
279  * Callback routine that will print out a pool property value.
280  */
281 static zpool_prop_t
282 print_prop_cb(zpool_prop_t prop, void *cb)
283 {
284         FILE *fp = cb;
285
286         (void) fprintf(fp, "\t%-13s  ", zpool_prop_to_name(prop));
287
288         if (zpool_prop_values(prop) == NULL)
289                 (void) fprintf(fp, "-\n");
290         else
291                 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
292
293         return (ZFS_PROP_CONT);
294 }
295
296 /*
297  * Display usage message.  If we're inside a command, display only the usage for
298  * that command.  Otherwise, iterate over the entire command table and display
299  * a complete usage message.
300  */
301 void
302 usage(boolean_t requested)
303 {
304         int i;
305         FILE *fp = requested ? stdout : stderr;
306
307         if (current_command == NULL) {
308                 int i;
309
310                 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
311                 (void) fprintf(fp,
312                     gettext("where 'command' is one of the following:\n\n"));
313
314                 for (i = 0; i < NCOMMAND; i++) {
315                         if (command_table[i].name == NULL)
316                                 (void) fprintf(fp, "\n");
317                         else
318                                 (void) fprintf(fp, "%s",
319                                     get_usage(command_table[i].usage));
320                 }
321         } else {
322                 (void) fprintf(fp, gettext("usage:\n"));
323                 (void) fprintf(fp, "%s", get_usage(current_command->usage));
324
325                 if (strcmp(current_command->name, "list") == 0) {
326                         (void) fprintf(fp, gettext("\nwhere 'field' is one "
327                             "of the following:\n\n"));
328
329                         for (i = 0; column_subopts[i] != NULL; i++)
330                                 (void) fprintf(fp, "\t%s\n", column_subopts[i]);
331                 }
332         }
333
334         if (current_command != NULL &&
335             ((strcmp(current_command->name, "set") == 0) ||
336             (strcmp(current_command->name, "get") == 0))) {
337
338                 (void) fprintf(fp,
339                     gettext("\nthe following properties are supported:\n"));
340
341                 (void) fprintf(fp, "\n\t%-13s  %s\n\n",
342                     "PROPERTY", "VALUES");
343
344                 /* Iterate over all properties */
345                 (void) zpool_prop_iter(print_prop_cb, fp, B_FALSE);
346         }
347
348         /*
349          * See comments at end of main().
350          */
351         if (getenv("ZFS_ABORT") != NULL) {
352                 (void) printf("dumping core by request\n");
353                 abort();
354         }
355
356         exit(requested ? 0 : 2);
357 }
358
359 const char *
360 state_to_health(int vs_state)
361 {
362         switch (vs_state) {
363         case VDEV_STATE_CLOSED:
364         case VDEV_STATE_CANT_OPEN:
365         case VDEV_STATE_OFFLINE:
366                 return (dgettext(TEXT_DOMAIN, "FAULTED"));
367         case VDEV_STATE_DEGRADED:
368                 return (dgettext(TEXT_DOMAIN, "DEGRADED"));
369         case VDEV_STATE_HEALTHY:
370                 return (dgettext(TEXT_DOMAIN, "ONLINE"));
371         }
372
373         return (dgettext(TEXT_DOMAIN, "UNKNOWN"));
374 }
375
376 const char *
377 state_to_name(vdev_stat_t *vs)
378 {
379         switch (vs->vs_state) {
380         case VDEV_STATE_CLOSED:
381         case VDEV_STATE_CANT_OPEN:
382                 if (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)
383                         return (gettext("FAULTED"));
384                 else
385                         return (gettext("UNAVAIL"));
386         case VDEV_STATE_OFFLINE:
387                 return (gettext("OFFLINE"));
388         case VDEV_STATE_DEGRADED:
389                 return (gettext("DEGRADED"));
390         case VDEV_STATE_HEALTHY:
391                 return (gettext("ONLINE"));
392         }
393
394         return (gettext("UNKNOWN"));
395 }
396
397 void
398 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent)
399 {
400         nvlist_t **child;
401         uint_t c, children;
402         char *vname;
403
404         if (name != NULL)
405                 (void) printf("\t%*s%s\n", indent, "", name);
406
407         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
408             &child, &children) != 0)
409                 return;
410
411         for (c = 0; c < children; c++) {
412                 vname = zpool_vdev_name(g_zfs, zhp, child[c]);
413                 print_vdev_tree(zhp, vname, child[c], indent + 2);
414                 free(vname);
415         }
416 }
417
418 /*
419  * zpool add [-fn] <pool> <vdev> ...
420  *
421  *      -f      Force addition of devices, even if they appear in use
422  *      -n      Do not add the devices, but display the resulting layout if
423  *              they were to be added.
424  *
425  * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
426  * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
427  * libzfs.
428  */
429 int
430 zpool_do_add(int argc, char **argv)
431 {
432         boolean_t force = B_FALSE;
433         boolean_t dryrun = B_FALSE;
434         int c;
435         nvlist_t *nvroot;
436         char *poolname;
437         int ret;
438         zpool_handle_t *zhp;
439         nvlist_t *config;
440
441         /* check options */
442         while ((c = getopt(argc, argv, "fn")) != -1) {
443                 switch (c) {
444                 case 'f':
445                         force = B_TRUE;
446                         break;
447                 case 'n':
448                         dryrun = B_TRUE;
449                         break;
450                 case '?':
451                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
452                             optopt);
453                         usage(B_FALSE);
454                 }
455         }
456
457         argc -= optind;
458         argv += optind;
459
460         /* get pool name and check number of arguments */
461         if (argc < 1) {
462                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
463                 usage(B_FALSE);
464         }
465         if (argc < 2) {
466                 (void) fprintf(stderr, gettext("missing vdev specification\n"));
467                 usage(B_FALSE);
468         }
469
470         poolname = argv[0];
471
472         argc--;
473         argv++;
474
475         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
476                 return (1);
477
478         if ((config = zpool_get_config(zhp, NULL)) == NULL) {
479                 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
480                     poolname);
481                 zpool_close(zhp);
482                 return (1);
483         }
484
485         /* pass off to get_vdev_spec for processing */
486         nvroot = make_root_vdev(config, force, !force, B_FALSE, argc, argv);
487         if (nvroot == NULL) {
488                 zpool_close(zhp);
489                 return (1);
490         }
491
492         if (dryrun) {
493                 nvlist_t *poolnvroot;
494
495                 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
496                     &poolnvroot) == 0);
497
498                 (void) printf(gettext("would update '%s' to the following "
499                     "configuration:\n"), zpool_get_name(zhp));
500
501                 print_vdev_tree(zhp, poolname, poolnvroot, 0);
502                 print_vdev_tree(zhp, NULL, nvroot, 0);
503
504                 ret = 0;
505         } else {
506                 ret = (zpool_add(zhp, nvroot) != 0);
507                 if (!ret) {
508                         zpool_log_history(g_zfs, argc + 1 + optind,
509                             argv - 1 - optind, poolname, B_TRUE, B_FALSE);
510                 }
511         }
512
513         nvlist_free(nvroot);
514         zpool_close(zhp);
515
516         return (ret);
517 }
518
519 /*
520  * zpool remove <pool> <vdev>
521  *
522  * Removes the given vdev from the pool.  Currently, this only supports removing
523  * spares from the pool.  Eventually, we'll want to support removing leaf vdevs
524  * (as an alias for 'detach') as well as toplevel vdevs.
525  */
526 int
527 zpool_do_remove(int argc, char **argv)
528 {
529         char *poolname;
530         int ret;
531         zpool_handle_t *zhp;
532
533         argc--;
534         argv++;
535
536         /* get pool name and check number of arguments */
537         if (argc < 1) {
538                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
539                 usage(B_FALSE);
540         }
541         if (argc < 2) {
542                 (void) fprintf(stderr, gettext("missing device\n"));
543                 usage(B_FALSE);
544         }
545
546         poolname = argv[0];
547
548         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
549                 return (1);
550
551         ret = (zpool_vdev_remove(zhp, argv[1]) != 0);
552         if (!ret) {
553                 zpool_log_history(g_zfs, ++argc, --argv, poolname, B_TRUE,
554                     B_FALSE);
555         }
556
557         return (ret);
558 }
559
560 /*
561  * zpool create [-fn] [-R root] [-m mountpoint] <pool> <dev> ...
562  *
563  *      -f      Force creation, even if devices appear in use
564  *      -n      Do not create the pool, but display the resulting layout if it
565  *              were to be created.
566  *      -R      Create a pool under an alternate root
567  *      -m      Set default mountpoint for the root dataset.  By default it's
568  *              '/<pool>'
569  *
570  * Creates the named pool according to the given vdev specification.  The
571  * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c.  Once
572  * we get the nvlist back from get_vdev_spec(), we either print out the contents
573  * (if '-n' was specified), or pass it to libzfs to do the creation.
574  */
575 int
576 zpool_do_create(int argc, char **argv)
577 {
578         boolean_t force = B_FALSE;
579         boolean_t dryrun = B_FALSE;
580         int c;
581         nvlist_t *nvroot;
582         char *poolname;
583         int ret;
584         char *altroot = NULL;
585         char *mountpoint = NULL;
586         nvlist_t **child;
587         uint_t children;
588
589         /* check options */
590         while ((c = getopt(argc, argv, ":fnR:m:")) != -1) {
591                 switch (c) {
592                 case 'f':
593                         force = B_TRUE;
594                         break;
595                 case 'n':
596                         dryrun = B_TRUE;
597                         break;
598                 case 'R':
599                         altroot = optarg;
600                         break;
601                 case 'm':
602                         mountpoint = optarg;
603                         break;
604                 case ':':
605                         (void) fprintf(stderr, gettext("missing argument for "
606                             "'%c' option\n"), optopt);
607                         usage(B_FALSE);
608                         break;
609                 case '?':
610                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
611                             optopt);
612                         usage(B_FALSE);
613                 }
614         }
615
616         argc -= optind;
617         argv += optind;
618
619         /* get pool name and check number of arguments */
620         if (argc < 1) {
621                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
622                 usage(B_FALSE);
623         }
624         if (argc < 2) {
625                 (void) fprintf(stderr, gettext("missing vdev specification\n"));
626                 usage(B_FALSE);
627         }
628
629         poolname = argv[0];
630
631         /*
632          * As a special case, check for use of '/' in the name, and direct the
633          * user to use 'zfs create' instead.
634          */
635         if (strchr(poolname, '/') != NULL) {
636                 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
637                     "character '/' in pool name\n"), poolname);
638                 (void) fprintf(stderr, gettext("use 'zfs create' to "
639                     "create a dataset\n"));
640                 return (1);
641         }
642
643         /* pass off to get_vdev_spec for bulk processing */
644         nvroot = make_root_vdev(NULL, force, !force, B_FALSE, argc - 1,
645             argv + 1);
646         if (nvroot == NULL)
647                 return (1);
648
649         /* make_root_vdev() allows 0 toplevel children if there are spares */
650         verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
651             &child, &children) == 0);
652         if (children == 0) {
653                 (void) fprintf(stderr, gettext("invalid vdev "
654                     "specification: at least one toplevel vdev must be "
655                     "specified\n"));
656                 return (1);
657         }
658
659
660         if (altroot != NULL && altroot[0] != '/') {
661                 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
662                     "must be an absolute path\n"), altroot);
663                 nvlist_free(nvroot);
664                 return (1);
665         }
666
667         /*
668          * Check the validity of the mountpoint and direct the user to use the
669          * '-m' mountpoint option if it looks like its in use.
670          */
671         if (mountpoint == NULL ||
672             (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
673             strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
674                 char buf[MAXPATHLEN];
675                 struct stat64 statbuf;
676
677                 if (mountpoint && mountpoint[0] != '/') {
678                         (void) fprintf(stderr, gettext("invalid mountpoint "
679                             "'%s': must be an absolute path, 'legacy', or "
680                             "'none'\n"), mountpoint);
681                         nvlist_free(nvroot);
682                         return (1);
683                 }
684
685                 if (mountpoint == NULL) {
686                         if (altroot != NULL)
687                                 (void) snprintf(buf, sizeof (buf), "%s/%s",
688                                     altroot, poolname);
689                         else
690                                 (void) snprintf(buf, sizeof (buf), "/%s",
691                                     poolname);
692                 } else {
693                         if (altroot != NULL)
694                                 (void) snprintf(buf, sizeof (buf), "%s%s",
695                                     altroot, mountpoint);
696                         else
697                                 (void) snprintf(buf, sizeof (buf), "%s",
698                                     mountpoint);
699                 }
700
701                 if (stat64(buf, &statbuf) == 0 &&
702                     statbuf.st_nlink != 2) {
703                         if (mountpoint == NULL)
704                                 (void) fprintf(stderr, gettext("default "
705                                     "mountpoint '%s' exists and is not "
706                                     "empty\n"), buf);
707                         else
708                                 (void) fprintf(stderr, gettext("mountpoint "
709                                     "'%s' exists and is not empty\n"), buf);
710                         (void) fprintf(stderr, gettext("use '-m' "
711                             "option to provide a different default\n"));
712                         nvlist_free(nvroot);
713                         return (1);
714                 }
715         }
716
717
718         if (dryrun) {
719                 /*
720                  * For a dry run invocation, print out a basic message and run
721                  * through all the vdevs in the list and print out in an
722                  * appropriate hierarchy.
723                  */
724                 (void) printf(gettext("would create '%s' with the "
725                     "following layout:\n\n"), poolname);
726
727                 print_vdev_tree(NULL, poolname, nvroot, 0);
728
729                 ret = 0;
730         } else {
731                 ret = 1;
732                 /*
733                  * Hand off to libzfs.
734                  */
735                 if (zpool_create(g_zfs, poolname, nvroot, altroot) == 0) {
736                         zfs_handle_t *pool = zfs_open(g_zfs, poolname,
737                             ZFS_TYPE_FILESYSTEM);
738                         if (pool != NULL) {
739                                 if (mountpoint != NULL)
740                                         verify(zfs_prop_set(pool,
741                                             zfs_prop_to_name(
742                                             ZFS_PROP_MOUNTPOINT),
743                                             mountpoint) == 0);
744                                 if (zfs_mount(pool, NULL, 0) == 0)
745                                         ret = zfs_share_nfs(pool);
746                                 zfs_close(pool);
747                         }
748                         zpool_log_history(g_zfs, argc + optind, argv - optind,
749                             poolname, B_TRUE, B_TRUE);
750                 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
751                         (void) fprintf(stderr, gettext("pool name may have "
752                             "been omitted\n"));
753                 }
754         }
755
756         nvlist_free(nvroot);
757
758         return (ret);
759 }
760
761 /*
762  * zpool destroy <pool>
763  *
764  *      -f      Forcefully unmount any datasets
765  *
766  * Destroy the given pool.  Automatically unmounts any datasets in the pool.
767  */
768 int
769 zpool_do_destroy(int argc, char **argv)
770 {
771         boolean_t force = B_FALSE;
772         int c;
773         char *pool;
774         zpool_handle_t *zhp;
775         int ret;
776
777         /* check options */
778         while ((c = getopt(argc, argv, "f")) != -1) {
779                 switch (c) {
780                 case 'f':
781                         force = B_TRUE;
782                         break;
783                 case '?':
784                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
785                             optopt);
786                         usage(B_FALSE);
787                 }
788         }
789
790         argc -= optind;
791         argv += optind;
792
793         /* check arguments */
794         if (argc < 1) {
795                 (void) fprintf(stderr, gettext("missing pool argument\n"));
796                 usage(B_FALSE);
797         }
798         if (argc > 1) {
799                 (void) fprintf(stderr, gettext("too many arguments\n"));
800                 usage(B_FALSE);
801         }
802
803         pool = argv[0];
804
805         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
806                 /*
807                  * As a special case, check for use of '/' in the name, and
808                  * direct the user to use 'zfs destroy' instead.
809                  */
810                 if (strchr(pool, '/') != NULL)
811                         (void) fprintf(stderr, gettext("use 'zfs destroy' to "
812                             "destroy a dataset\n"));
813                 return (1);
814         }
815
816         if (zpool_disable_datasets(zhp, force) != 0) {
817                 (void) fprintf(stderr, gettext("could not destroy '%s': "
818                     "could not unmount datasets\n"), zpool_get_name(zhp));
819                 return (1);
820         }
821
822         zpool_log_history(g_zfs, argc + optind, argv - optind, pool, B_TRUE,
823             B_FALSE);
824
825         ret = (zpool_destroy(zhp) != 0);
826
827         zpool_close(zhp);
828
829         return (ret);
830 }
831
832 /*
833  * zpool export [-f] <pool> ...
834  *
835  *      -f      Forcefully unmount datasets
836  *
837  * Export the given pools.  By default, the command will attempt to cleanly
838  * unmount any active datasets within the pool.  If the '-f' flag is specified,
839  * then the datasets will be forcefully unmounted.
840  */
841 int
842 zpool_do_export(int argc, char **argv)
843 {
844         boolean_t force = B_FALSE;
845         int c;
846         zpool_handle_t *zhp;
847         int ret;
848         int i;
849
850         /* check options */
851         while ((c = getopt(argc, argv, "f")) != -1) {
852                 switch (c) {
853                 case 'f':
854                         force = B_TRUE;
855                         break;
856                 case '?':
857                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
858                             optopt);
859                         usage(B_FALSE);
860                 }
861         }
862
863         argc -= optind;
864         argv += optind;
865
866         /* check arguments */
867         if (argc < 1) {
868                 (void) fprintf(stderr, gettext("missing pool argument\n"));
869                 usage(B_FALSE);
870         }
871
872         ret = 0;
873         for (i = 0; i < argc; i++) {
874                 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
875                         ret = 1;
876                         continue;
877                 }
878
879                 if (zpool_disable_datasets(zhp, force) != 0) {
880                         ret = 1;
881                         zpool_close(zhp);
882                         continue;
883                 }
884
885                 zpool_log_history(g_zfs, argc + optind, argv - optind, argv[i],
886                     B_TRUE, B_FALSE);
887
888                 if (zpool_export(zhp) != 0)
889                         ret = 1;
890
891                 zpool_close(zhp);
892         }
893
894         return (ret);
895 }
896
897 /*
898  * Given a vdev configuration, determine the maximum width needed for the device
899  * name column.
900  */
901 static int
902 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
903 {
904         char *name = zpool_vdev_name(g_zfs, zhp, nv);
905         nvlist_t **child;
906         uint_t c, children;
907         int ret;
908
909         if (strlen(name) + depth > max)
910                 max = strlen(name) + depth;
911
912         free(name);
913
914         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
915             &child, &children) == 0) {
916                 for (c = 0; c < children; c++)
917                         if ((ret = max_width(zhp, child[c], depth + 2,
918                             max)) > max)
919                                 max = ret;
920         }
921
922         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
923             &child, &children) == 0) {
924                 for (c = 0; c < children; c++)
925                         if ((ret = max_width(zhp, child[c], depth + 2,
926                             max)) > max)
927                                 max = ret;
928         }
929
930
931         return (max);
932 }
933
934
935 /*
936  * Print the configuration of an exported pool.  Iterate over all vdevs in the
937  * pool, printing out the name and status for each one.
938  */
939 void
940 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
941 {
942         nvlist_t **child;
943         uint_t c, children;
944         vdev_stat_t *vs;
945         char *type, *vname;
946
947         verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
948         if (strcmp(type, VDEV_TYPE_MISSING) == 0)
949                 return;
950
951         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
952             (uint64_t **)&vs, &c) == 0);
953
954         (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
955
956         if (vs->vs_aux != 0) {
957                 (void) printf("  %-8s  ", state_to_name(vs));
958
959                 switch (vs->vs_aux) {
960                 case VDEV_AUX_OPEN_FAILED:
961                         (void) printf(gettext("cannot open"));
962                         break;
963
964                 case VDEV_AUX_BAD_GUID_SUM:
965                         (void) printf(gettext("missing device"));
966                         break;
967
968                 case VDEV_AUX_NO_REPLICAS:
969                         (void) printf(gettext("insufficient replicas"));
970                         break;
971
972                 case VDEV_AUX_VERSION_NEWER:
973                         (void) printf(gettext("newer version"));
974                         break;
975
976                 default:
977                         (void) printf(gettext("corrupted data"));
978                         break;
979                 }
980         } else {
981                 (void) printf("  %s", state_to_name(vs));
982         }
983         (void) printf("\n");
984
985         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
986             &child, &children) != 0)
987                 return;
988
989         for (c = 0; c < children; c++) {
990                 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
991                 print_import_config(vname, child[c],
992                     namewidth, depth + 2);
993                 free(vname);
994         }
995
996         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
997             &child, &children) != 0)
998                 return;
999
1000         (void) printf(gettext("\tspares\n"));
1001         for (c = 0; c < children; c++) {
1002                 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1003                 (void) printf("\t  %s\n", vname);
1004                 free(vname);
1005         }
1006 }
1007
1008 /*
1009  * Display the status for the given pool.
1010  */
1011 static void
1012 show_import(nvlist_t *config)
1013 {
1014         uint64_t pool_state;
1015         vdev_stat_t *vs;
1016         char *name;
1017         uint64_t guid;
1018         char *msgid;
1019         nvlist_t *nvroot;
1020         int reason;
1021         const char *health;
1022         uint_t vsc;
1023         int namewidth;
1024
1025         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1026             &name) == 0);
1027         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1028             &guid) == 0);
1029         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1030             &pool_state) == 0);
1031         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1032             &nvroot) == 0);
1033
1034         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
1035             (uint64_t **)&vs, &vsc) == 0);
1036         health = state_to_health(vs->vs_state);
1037
1038         reason = zpool_import_status(config, &msgid);
1039
1040         (void) printf(gettext("  pool: %s\n"), name);
1041         (void) printf(gettext("    id: %llu\n"), (u_longlong_t)guid);
1042         (void) printf(gettext(" state: %s"), health);
1043         if (pool_state == POOL_STATE_DESTROYED)
1044                 (void) printf(gettext(" (DESTROYED)"));
1045         (void) printf("\n");
1046
1047         switch (reason) {
1048         case ZPOOL_STATUS_MISSING_DEV_R:
1049         case ZPOOL_STATUS_MISSING_DEV_NR:
1050         case ZPOOL_STATUS_BAD_GUID_SUM:
1051                 (void) printf(gettext("status: One or more devices are missing "
1052                     "from the system.\n"));
1053                 break;
1054
1055         case ZPOOL_STATUS_CORRUPT_LABEL_R:
1056         case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1057                 (void) printf(gettext("status: One or more devices contains "
1058                     "corrupted data.\n"));
1059                 break;
1060
1061         case ZPOOL_STATUS_CORRUPT_DATA:
1062                 (void) printf(gettext("status: The pool data is corrupted.\n"));
1063                 break;
1064
1065         case ZPOOL_STATUS_OFFLINE_DEV:
1066                 (void) printf(gettext("status: One or more devices "
1067                     "are offlined.\n"));
1068                 break;
1069
1070         case ZPOOL_STATUS_CORRUPT_POOL:
1071                 (void) printf(gettext("status: The pool metadata is "
1072                     "corrupted.\n"));
1073                 break;
1074
1075         case ZPOOL_STATUS_VERSION_OLDER:
1076                 (void) printf(gettext("status: The pool is formatted using an "
1077                     "older on-disk version.\n"));
1078                 break;
1079
1080         case ZPOOL_STATUS_VERSION_NEWER:
1081                 (void) printf(gettext("status: The pool is formatted using an "
1082                     "incompatible version.\n"));
1083                 break;
1084
1085         case ZPOOL_STATUS_HOSTID_MISMATCH:
1086                 (void) printf(gettext("status: The pool was last accessed by "
1087                     "another system.\n"));
1088                 break;
1089         default:
1090                 /*
1091                  * No other status can be seen when importing pools.
1092                  */
1093                 assert(reason == ZPOOL_STATUS_OK);
1094         }
1095
1096         /*
1097          * Print out an action according to the overall state of the pool.
1098          */
1099         if (vs->vs_state == VDEV_STATE_HEALTHY) {
1100                 if (reason == ZPOOL_STATUS_VERSION_OLDER)
1101                         (void) printf(gettext("action: The pool can be "
1102                             "imported using its name or numeric identifier, "
1103                             "though\n\tsome features will not be available "
1104                             "without an explicit 'zpool upgrade'.\n"));
1105                 else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH)
1106                         (void) printf(gettext("action: The pool can be "
1107                             "imported using its name or numeric "
1108                             "identifier and\n\tthe '-f' flag.\n"));
1109                 else
1110                         (void) printf(gettext("action: The pool can be "
1111                             "imported using its name or numeric "
1112                             "identifier.\n"));
1113         } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1114                 (void) printf(gettext("action: The pool can be imported "
1115                     "despite missing or damaged devices.  The\n\tfault "
1116                     "tolerance of the pool may be compromised if imported.\n"));
1117         } else {
1118                 switch (reason) {
1119                 case ZPOOL_STATUS_VERSION_NEWER:
1120                         (void) printf(gettext("action: The pool cannot be "
1121                             "imported.  Access the pool on a system running "
1122                             "newer\n\tsoftware, or recreate the pool from "
1123                             "backup.\n"));
1124                         break;
1125                 case ZPOOL_STATUS_MISSING_DEV_R:
1126                 case ZPOOL_STATUS_MISSING_DEV_NR:
1127                 case ZPOOL_STATUS_BAD_GUID_SUM:
1128                         (void) printf(gettext("action: The pool cannot be "
1129                             "imported. Attach the missing\n\tdevices and try "
1130                             "again.\n"));
1131                         break;
1132                 default:
1133                         (void) printf(gettext("action: The pool cannot be "
1134                             "imported due to damaged devices or data.\n"));
1135                 }
1136         }
1137
1138         /*
1139          * If the state is "closed" or "can't open", and the aux state
1140          * is "corrupt data":
1141          */
1142         if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1143             (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1144             (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1145                 if (pool_state == POOL_STATE_DESTROYED)
1146                         (void) printf(gettext("\tThe pool was destroyed, "
1147                             "but can be imported using the '-Df' flags.\n"));
1148                 else if (pool_state != POOL_STATE_EXPORTED)
1149                         (void) printf(gettext("\tThe pool may be active on "
1150                             "on another system, but can be imported using\n\t"
1151                             "the '-f' flag.\n"));
1152         }
1153
1154         if (msgid != NULL)
1155                 (void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
1156                     msgid);
1157
1158         (void) printf(gettext("config:\n\n"));
1159
1160         namewidth = max_width(NULL, nvroot, 0, 0);
1161         if (namewidth < 10)
1162                 namewidth = 10;
1163         print_import_config(name, nvroot, namewidth, 0);
1164
1165         if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1166                 (void) printf(gettext("\n\tAdditional devices are known to "
1167                     "be part of this pool, though their\n\texact "
1168                     "configuration cannot be determined.\n"));
1169         }
1170 }
1171
1172 /*
1173  * Perform the import for the given configuration.  This passes the heavy
1174  * lifting off to zpool_import(), and then mounts the datasets contained within
1175  * the pool.
1176  */
1177 static int
1178 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1179     const char *altroot, int force, int argc, char **argv)
1180 {
1181         zpool_handle_t *zhp;
1182         char *name;
1183         uint64_t state;
1184         uint64_t version;
1185
1186         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1187             &name) == 0);
1188
1189         verify(nvlist_lookup_uint64(config,
1190             ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1191         verify(nvlist_lookup_uint64(config,
1192             ZPOOL_CONFIG_VERSION, &version) == 0);
1193         if (version > ZFS_VERSION) {
1194                 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1195                     "is formatted using a newer ZFS version\n"), name);
1196                 return (1);
1197         } else if (state != POOL_STATE_EXPORTED && !force) {
1198                 uint64_t hostid;
1199
1200                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
1201                     &hostid) == 0) {
1202                         if ((unsigned long)hostid != gethostid()) {
1203                                 char *hostname;
1204                                 uint64_t timestamp;
1205                                 time_t t;
1206
1207                                 verify(nvlist_lookup_string(config,
1208                                     ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
1209                                 verify(nvlist_lookup_uint64(config,
1210                                     ZPOOL_CONFIG_TIMESTAMP, &timestamp) == 0);
1211                                 t = timestamp;
1212                                 (void) fprintf(stderr, gettext("cannot import "
1213                                     "'%s': pool may be in use from other "
1214                                     "system, it was last accessed by %s "
1215                                     "(hostid: 0x%lx) on %s"), name, hostname,
1216                                     (unsigned long)hostid,
1217                                     asctime(localtime(&t)));
1218                                 (void) fprintf(stderr, gettext("use '-f' to "
1219                                     "import anyway\n"));
1220                                 return (1);
1221                         }
1222                 } else {
1223                         (void) fprintf(stderr, gettext("cannot import '%s': "
1224                             "pool may be in use from other system\n"), name);
1225                         (void) fprintf(stderr, gettext("use '-f' to import "
1226                             "anyway\n"));
1227                         return (1);
1228                 }
1229         }
1230
1231         if (zpool_import(g_zfs, config, newname, altroot) != 0)
1232                 return (1);
1233
1234         if (newname != NULL)
1235                 name = (char *)newname;
1236
1237         zpool_log_history(g_zfs, argc, argv, name, B_TRUE, B_FALSE);
1238
1239         verify((zhp = zpool_open(g_zfs, name)) != NULL);
1240
1241         if (zpool_enable_datasets(zhp, mntopts, 0) != 0) {
1242                 zpool_close(zhp);
1243                 return (1);
1244         }
1245
1246         zpool_close(zhp);
1247         return (0);
1248 }
1249
1250 /*
1251  * zpool import [-d dir] [-D]
1252  *       import [-R root] [-D] [-d dir] [-f] -a
1253  *       import [-R root] [-D] [-d dir] [-f] <pool | id> [newpool]
1254  *
1255  *       -d     Scan in a specific directory, other than /dev/dsk.  More than
1256  *              one directory can be specified using multiple '-d' options.
1257  *
1258  *       -D     Scan for previously destroyed pools or import all or only
1259  *              specified destroyed pools.
1260  *
1261  *       -R     Temporarily import the pool, with all mountpoints relative to
1262  *              the given root.  The pool will remain exported when the machine
1263  *              is rebooted.
1264  *
1265  *       -f     Force import, even if it appears that the pool is active.
1266  *
1267  *       -a     Import all pools found.
1268  *
1269  * The import command scans for pools to import, and import pools based on pool
1270  * name and GUID.  The pool can also be renamed as part of the import process.
1271  */
1272 int
1273 zpool_do_import(int argc, char **argv)
1274 {
1275         char **searchdirs = NULL;
1276         int nsearch = 0;
1277         int c;
1278         int err;
1279         nvlist_t *pools;
1280         boolean_t do_all = B_FALSE;
1281         boolean_t do_destroyed = B_FALSE;
1282         char *altroot = NULL;
1283         char *mntopts = NULL;
1284         boolean_t do_force = B_FALSE;
1285         nvpair_t *elem;
1286         nvlist_t *config;
1287         uint64_t searchguid;
1288         char *searchname;
1289         nvlist_t *found_config;
1290         boolean_t first;
1291         uint64_t pool_state;
1292
1293         /* check options */
1294         while ((c = getopt(argc, argv, ":Dfd:R:ao:")) != -1) {
1295                 switch (c) {
1296                 case 'a':
1297                         do_all = B_TRUE;
1298                         break;
1299                 case 'd':
1300                         if (searchdirs == NULL) {
1301                                 searchdirs = safe_malloc(sizeof (char *));
1302                         } else {
1303                                 char **tmp = safe_malloc((nsearch + 1) *
1304                                     sizeof (char *));
1305                                 bcopy(searchdirs, tmp, nsearch *
1306                                     sizeof (char *));
1307                                 free(searchdirs);
1308                                 searchdirs = tmp;
1309                         }
1310                         searchdirs[nsearch++] = optarg;
1311                         break;
1312                 case 'D':
1313                         do_destroyed = B_TRUE;
1314                         break;
1315                 case 'f':
1316                         do_force = B_TRUE;
1317                         break;
1318                 case 'o':
1319                         mntopts = optarg;
1320                         break;
1321                 case 'R':
1322                         altroot = optarg;
1323                         break;
1324                 case ':':
1325                         (void) fprintf(stderr, gettext("missing argument for "
1326                             "'%c' option\n"), optopt);
1327                         usage(B_FALSE);
1328                         break;
1329                 case '?':
1330                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1331                             optopt);
1332                         usage(B_FALSE);
1333                 }
1334         }
1335
1336         argc -= optind;
1337         argv += optind;
1338
1339         if (searchdirs == NULL) {
1340                 searchdirs = safe_malloc(sizeof (char *));
1341                 searchdirs[0] = "/dev";
1342                 nsearch = 1;
1343         }
1344
1345         /* check argument count */
1346         if (do_all) {
1347                 if (argc != 0) {
1348                         (void) fprintf(stderr, gettext("too many arguments\n"));
1349                         usage(B_FALSE);
1350                 }
1351         } else {
1352                 if (argc > 2) {
1353                         (void) fprintf(stderr, gettext("too many arguments\n"));
1354                         usage(B_FALSE);
1355                 }
1356
1357                 /*
1358                  * Check for the SYS_CONFIG privilege.  We do this explicitly
1359                  * here because otherwise any attempt to discover pools will
1360                  * silently fail.
1361                  */
1362                 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
1363                         (void) fprintf(stderr, gettext("cannot "
1364                             "discover pools: permission denied\n"));
1365                         free(searchdirs);
1366                         return (1);
1367                 }
1368         }
1369
1370         if ((pools = zpool_find_import(g_zfs, nsearch, searchdirs)) == NULL) {
1371                 free(searchdirs);
1372                 return (1);
1373         }
1374
1375         /*
1376          * We now have a list of all available pools in the given directories.
1377          * Depending on the arguments given, we do one of the following:
1378          *
1379          *      <none>  Iterate through all pools and display information about
1380          *              each one.
1381          *
1382          *      -a      Iterate through all pools and try to import each one.
1383          *
1384          *      <id>    Find the pool that corresponds to the given GUID/pool
1385          *              name and import that one.
1386          *
1387          *      -D      Above options applies only to destroyed pools.
1388          */
1389         if (argc != 0) {
1390                 char *endptr;
1391
1392                 errno = 0;
1393                 searchguid = strtoull(argv[0], &endptr, 10);
1394                 if (errno != 0 || *endptr != '\0')
1395                         searchname = argv[0];
1396                 else
1397                         searchname = NULL;
1398                 found_config = NULL;
1399         }
1400
1401         err = 0;
1402         elem = NULL;
1403         first = B_TRUE;
1404         while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
1405
1406                 verify(nvpair_value_nvlist(elem, &config) == 0);
1407
1408                 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1409                     &pool_state) == 0);
1410                 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
1411                         continue;
1412                 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
1413                         continue;
1414
1415                 if (argc == 0) {
1416                         if (first)
1417                                 first = B_FALSE;
1418                         else if (!do_all)
1419                                 (void) printf("\n");
1420
1421                         if (do_all)
1422                                 err |= do_import(config, NULL, mntopts,
1423                                     altroot, do_force, argc + optind,
1424                                     argv - optind);
1425                         else
1426                                 show_import(config);
1427                 } else if (searchname != NULL) {
1428                         char *name;
1429
1430                         /*
1431                          * We are searching for a pool based on name.
1432                          */
1433                         verify(nvlist_lookup_string(config,
1434                             ZPOOL_CONFIG_POOL_NAME, &name) == 0);
1435
1436                         if (strcmp(name, searchname) == 0) {
1437                                 if (found_config != NULL) {
1438                                         (void) fprintf(stderr, gettext(
1439                                             "cannot import '%s': more than "
1440                                             "one matching pool\n"), searchname);
1441                                         (void) fprintf(stderr, gettext(
1442                                             "import by numeric ID instead\n"));
1443                                         err = B_TRUE;
1444                                 }
1445                                 found_config = config;
1446                         }
1447                 } else {
1448                         uint64_t guid;
1449
1450                         /*
1451                          * Search for a pool by guid.
1452                          */
1453                         verify(nvlist_lookup_uint64(config,
1454                             ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
1455
1456                         if (guid == searchguid)
1457                                 found_config = config;
1458                 }
1459         }
1460
1461         /*
1462          * If we were searching for a specific pool, verify that we found a
1463          * pool, and then do the import.
1464          */
1465         if (argc != 0 && err == 0) {
1466                 if (found_config == NULL) {
1467                         (void) fprintf(stderr, gettext("cannot import '%s': "
1468                             "no such pool available\n"), argv[0]);
1469                         err = B_TRUE;
1470                 } else {
1471                         err |= do_import(found_config, argc == 1 ? NULL :
1472                             argv[1], mntopts, altroot, do_force, argc + optind,
1473                             argv - optind);
1474                 }
1475         }
1476
1477         /*
1478          * If we were just looking for pools, report an error if none were
1479          * found.
1480          */
1481         if (argc == 0 && first)
1482                 (void) fprintf(stderr,
1483                     gettext("no pools available to import\n"));
1484
1485         nvlist_free(pools);
1486         free(searchdirs);
1487
1488         return (err ? 1 : 0);
1489 }
1490
1491 typedef struct iostat_cbdata {
1492         zpool_list_t *cb_list;
1493         int cb_verbose;
1494         int cb_iteration;
1495         int cb_namewidth;
1496 } iostat_cbdata_t;
1497
1498 static void
1499 print_iostat_separator(iostat_cbdata_t *cb)
1500 {
1501         int i = 0;
1502
1503         for (i = 0; i < cb->cb_namewidth; i++)
1504                 (void) printf("-");
1505         (void) printf("  -----  -----  -----  -----  -----  -----\n");
1506 }
1507
1508 static void
1509 print_iostat_header(iostat_cbdata_t *cb)
1510 {
1511         (void) printf("%*s     capacity     operations    bandwidth\n",
1512             cb->cb_namewidth, "");
1513         (void) printf("%-*s   used  avail   read  write   read  write\n",
1514             cb->cb_namewidth, "pool");
1515         print_iostat_separator(cb);
1516 }
1517
1518 /*
1519  * Display a single statistic.
1520  */
1521 void
1522 print_one_stat(uint64_t value)
1523 {
1524         char buf[64];
1525
1526         zfs_nicenum(value, buf, sizeof (buf));
1527         (void) printf("  %5s", buf);
1528 }
1529
1530 /*
1531  * Print out all the statistics for the given vdev.  This can either be the
1532  * toplevel configuration, or called recursively.  If 'name' is NULL, then this
1533  * is a verbose output, and we don't want to display the toplevel pool stats.
1534  */
1535 void
1536 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
1537     nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
1538 {
1539         nvlist_t **oldchild, **newchild;
1540         uint_t c, children;
1541         vdev_stat_t *oldvs, *newvs;
1542         vdev_stat_t zerovs = { 0 };
1543         uint64_t tdelta;
1544         double scale;
1545         char *vname;
1546
1547         if (oldnv != NULL) {
1548                 verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS,
1549                     (uint64_t **)&oldvs, &c) == 0);
1550         } else {
1551                 oldvs = &zerovs;
1552         }
1553
1554         verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS,
1555             (uint64_t **)&newvs, &c) == 0);
1556
1557         if (strlen(name) + depth > cb->cb_namewidth)
1558                 (void) printf("%*s%s", depth, "", name);
1559         else
1560                 (void) printf("%*s%s%*s", depth, "", name,
1561                     (int)(cb->cb_namewidth - strlen(name) - depth), "");
1562
1563         tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
1564
1565         if (tdelta == 0)
1566                 scale = 1.0;
1567         else
1568                 scale = (double)NANOSEC / tdelta;
1569
1570         /* only toplevel vdevs have capacity stats */
1571         if (newvs->vs_space == 0) {
1572                 (void) printf("      -      -");
1573         } else {
1574                 print_one_stat(newvs->vs_alloc);
1575                 print_one_stat(newvs->vs_space - newvs->vs_alloc);
1576         }
1577
1578         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
1579             oldvs->vs_ops[ZIO_TYPE_READ])));
1580
1581         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
1582             oldvs->vs_ops[ZIO_TYPE_WRITE])));
1583
1584         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
1585             oldvs->vs_bytes[ZIO_TYPE_READ])));
1586
1587         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
1588             oldvs->vs_bytes[ZIO_TYPE_WRITE])));
1589
1590         (void) printf("\n");
1591
1592         if (!cb->cb_verbose)
1593                 return;
1594
1595         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
1596             &newchild, &children) != 0)
1597                 return;
1598
1599         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
1600             &oldchild, &c) != 0)
1601                 return;
1602
1603         for (c = 0; c < children; c++) {
1604                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1605                 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1606                     newchild[c], cb, depth + 2);
1607                 free(vname);
1608         }
1609 }
1610
1611 static int
1612 refresh_iostat(zpool_handle_t *zhp, void *data)
1613 {
1614         iostat_cbdata_t *cb = data;
1615         boolean_t missing;
1616
1617         /*
1618          * If the pool has disappeared, remove it from the list and continue.
1619          */
1620         if (zpool_refresh_stats(zhp, &missing) != 0)
1621                 return (-1);
1622
1623         if (missing)
1624                 pool_list_remove(cb->cb_list, zhp);
1625
1626         return (0);
1627 }
1628
1629 /*
1630  * Callback to print out the iostats for the given pool.
1631  */
1632 int
1633 print_iostat(zpool_handle_t *zhp, void *data)
1634 {
1635         iostat_cbdata_t *cb = data;
1636         nvlist_t *oldconfig, *newconfig;
1637         nvlist_t *oldnvroot, *newnvroot;
1638
1639         newconfig = zpool_get_config(zhp, &oldconfig);
1640
1641         if (cb->cb_iteration == 1)
1642                 oldconfig = NULL;
1643
1644         verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
1645             &newnvroot) == 0);
1646
1647         if (oldconfig == NULL)
1648                 oldnvroot = NULL;
1649         else
1650                 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
1651                     &oldnvroot) == 0);
1652
1653         /*
1654          * Print out the statistics for the pool.
1655          */
1656         print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
1657
1658         if (cb->cb_verbose)
1659                 print_iostat_separator(cb);
1660
1661         return (0);
1662 }
1663
1664 int
1665 get_namewidth(zpool_handle_t *zhp, void *data)
1666 {
1667         iostat_cbdata_t *cb = data;
1668         nvlist_t *config, *nvroot;
1669
1670         if ((config = zpool_get_config(zhp, NULL)) != NULL) {
1671                 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1672                     &nvroot) == 0);
1673                 if (!cb->cb_verbose)
1674                         cb->cb_namewidth = strlen(zpool_get_name(zhp));
1675                 else
1676                         cb->cb_namewidth = max_width(zhp, nvroot, 0, 0);
1677         }
1678
1679         /*
1680          * The width must fall into the range [10,38].  The upper limit is the
1681          * maximum we can have and still fit in 80 columns.
1682          */
1683         if (cb->cb_namewidth < 10)
1684                 cb->cb_namewidth = 10;
1685         if (cb->cb_namewidth > 38)
1686                 cb->cb_namewidth = 38;
1687
1688         return (0);
1689 }
1690
1691 /*
1692  * zpool iostat [-v] [pool] ... [interval [count]]
1693  *
1694  *      -v      Display statistics for individual vdevs
1695  *
1696  * This command can be tricky because we want to be able to deal with pool
1697  * creation/destruction as well as vdev configuration changes.  The bulk of this
1698  * processing is handled by the pool_list_* routines in zpool_iter.c.  We rely
1699  * on pool_list_update() to detect the addition of new pools.  Configuration
1700  * changes are all handled within libzfs.
1701  */
1702 int
1703 zpool_do_iostat(int argc, char **argv)
1704 {
1705         int c;
1706         int ret;
1707         int npools;
1708         unsigned long interval = 0, count = 0;
1709         zpool_list_t *list;
1710         boolean_t verbose = B_FALSE;
1711         iostat_cbdata_t cb;
1712
1713         /* check options */
1714         while ((c = getopt(argc, argv, "v")) != -1) {
1715                 switch (c) {
1716                 case 'v':
1717                         verbose = B_TRUE;
1718                         break;
1719                 case '?':
1720                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1721                             optopt);
1722                         usage(B_FALSE);
1723                 }
1724         }
1725
1726         argc -= optind;
1727         argv += optind;
1728
1729         /*
1730          * Determine if the last argument is an integer or a pool name
1731          */
1732         if (argc > 0 && isdigit(argv[argc - 1][0])) {
1733                 char *end;
1734
1735                 errno = 0;
1736                 interval = strtoul(argv[argc - 1], &end, 10);
1737
1738                 if (*end == '\0' && errno == 0) {
1739                         if (interval == 0) {
1740                                 (void) fprintf(stderr, gettext("interval "
1741                                     "cannot be zero\n"));
1742                                 usage(B_FALSE);
1743                         }
1744
1745                         /*
1746                          * Ignore the last parameter
1747                          */
1748                         argc--;
1749                 } else {
1750                         /*
1751                          * If this is not a valid number, just plow on.  The
1752                          * user will get a more informative error message later
1753                          * on.
1754                          */
1755                         interval = 0;
1756                 }
1757         }
1758
1759         /*
1760          * If the last argument is also an integer, then we have both a count
1761          * and an integer.
1762          */
1763         if (argc > 0 && isdigit(argv[argc - 1][0])) {
1764                 char *end;
1765
1766                 errno = 0;
1767                 count = interval;
1768                 interval = strtoul(argv[argc - 1], &end, 10);
1769
1770                 if (*end == '\0' && errno == 0) {
1771                         if (interval == 0) {
1772                                 (void) fprintf(stderr, gettext("interval "
1773                                     "cannot be zero\n"));
1774                                 usage(B_FALSE);
1775                         }
1776
1777                         /*
1778                          * Ignore the last parameter
1779                          */
1780                         argc--;
1781                 } else {
1782                         interval = 0;
1783                 }
1784         }
1785
1786         /*
1787          * Construct the list of all interesting pools.
1788          */
1789         ret = 0;
1790         if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
1791                 return (1);
1792
1793         if (pool_list_count(list) == 0 && argc != 0) {
1794                 pool_list_free(list);
1795                 return (1);
1796         }
1797
1798         if (pool_list_count(list) == 0 && interval == 0) {
1799                 pool_list_free(list);
1800                 (void) fprintf(stderr, gettext("no pools available\n"));
1801                 return (1);
1802         }
1803
1804         /*
1805          * Enter the main iostat loop.
1806          */
1807         cb.cb_list = list;
1808         cb.cb_verbose = verbose;
1809         cb.cb_iteration = 0;
1810         cb.cb_namewidth = 0;
1811
1812         for (;;) {
1813                 pool_list_update(list);
1814
1815                 if ((npools = pool_list_count(list)) == 0)
1816                         break;
1817
1818                 /*
1819                  * Refresh all statistics.  This is done as an explicit step
1820                  * before calculating the maximum name width, so that any
1821                  * configuration changes are properly accounted for.
1822                  */
1823                 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
1824
1825                 /*
1826                  * Iterate over all pools to determine the maximum width
1827                  * for the pool / device name column across all pools.
1828                  */
1829                 cb.cb_namewidth = 0;
1830                 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
1831
1832                 /*
1833                  * If it's the first time, or verbose mode, print the header.
1834                  */
1835                 if (++cb.cb_iteration == 1 || verbose)
1836                         print_iostat_header(&cb);
1837
1838                 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
1839
1840                 /*
1841                  * If there's more than one pool, and we're not in verbose mode
1842                  * (which prints a separator for us), then print a separator.
1843                  */
1844                 if (npools > 1 && !verbose)
1845                         print_iostat_separator(&cb);
1846
1847                 if (verbose)
1848                         (void) printf("\n");
1849
1850                 /*
1851                  * Flush the output so that redirection to a file isn't buffered
1852                  * indefinitely.
1853                  */
1854                 (void) fflush(stdout);
1855
1856                 if (interval == 0)
1857                         break;
1858
1859                 if (count != 0 && --count == 0)
1860                         break;
1861
1862                 (void) sleep(interval);
1863         }
1864
1865         pool_list_free(list);
1866
1867         return (ret);
1868 }
1869
1870 typedef struct list_cbdata {
1871         boolean_t       cb_scripted;
1872         boolean_t       cb_first;
1873         int             cb_fields[MAX_FIELDS];
1874         int             cb_fieldcount;
1875 } list_cbdata_t;
1876
1877 /*
1878  * Given a list of columns to display, output appropriate headers for each one.
1879  */
1880 void
1881 print_header(int *fields, size_t count)
1882 {
1883         int i;
1884         column_def_t *col;
1885         const char *fmt;
1886
1887         for (i = 0; i < count; i++) {
1888                 col = &column_table[fields[i]];
1889                 if (i != 0)
1890                         (void) printf("  ");
1891                 if (col->cd_justify == left_justify)
1892                         fmt = "%-*s";
1893                 else
1894                         fmt = "%*s";
1895
1896                 (void) printf(fmt, i == count - 1 ? strlen(col->cd_title) :
1897                     col->cd_width, col->cd_title);
1898         }
1899
1900         (void) printf("\n");
1901 }
1902
1903 int
1904 list_callback(zpool_handle_t *zhp, void *data)
1905 {
1906         list_cbdata_t *cbp = data;
1907         nvlist_t *config;
1908         int i;
1909         char buf[ZPOOL_MAXNAMELEN];
1910         uint64_t total;
1911         uint64_t used;
1912         const char *fmt;
1913         column_def_t *col;
1914
1915         if (cbp->cb_first) {
1916                 if (!cbp->cb_scripted)
1917                         print_header(cbp->cb_fields, cbp->cb_fieldcount);
1918                 cbp->cb_first = B_FALSE;
1919         }
1920
1921         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
1922                 config = NULL;
1923         } else {
1924                 config = zpool_get_config(zhp, NULL);
1925                 total = zpool_get_space_total(zhp);
1926                 used = zpool_get_space_used(zhp);
1927         }
1928
1929         for (i = 0; i < cbp->cb_fieldcount; i++) {
1930                 if (i != 0) {
1931                         if (cbp->cb_scripted)
1932                                 (void) printf("\t");
1933                         else
1934                                 (void) printf("  ");
1935                 }
1936
1937                 col = &column_table[cbp->cb_fields[i]];
1938
1939                 switch (cbp->cb_fields[i]) {
1940                 case ZPOOL_FIELD_NAME:
1941                         (void) strlcpy(buf, zpool_get_name(zhp), sizeof (buf));
1942                         break;
1943
1944                 case ZPOOL_FIELD_SIZE:
1945                         if (config == NULL)
1946                                 (void) strlcpy(buf, "-", sizeof (buf));
1947                         else
1948                                 zfs_nicenum(total, buf, sizeof (buf));
1949                         break;
1950
1951                 case ZPOOL_FIELD_USED:
1952                         if (config == NULL)
1953                                 (void) strlcpy(buf, "-", sizeof (buf));
1954                         else
1955                                 zfs_nicenum(used, buf, sizeof (buf));
1956                         break;
1957
1958                 case ZPOOL_FIELD_AVAILABLE:
1959                         if (config == NULL)
1960                                 (void) strlcpy(buf, "-", sizeof (buf));
1961                         else
1962                                 zfs_nicenum(total - used, buf, sizeof (buf));
1963                         break;
1964
1965                 case ZPOOL_FIELD_CAPACITY:
1966                         if (config == NULL) {
1967                                 (void) strlcpy(buf, "-", sizeof (buf));
1968                         } else {
1969                                 uint64_t capacity = (total == 0 ? 0 :
1970                                     (used * 100 / total));
1971                                 (void) snprintf(buf, sizeof (buf), "%llu%%",
1972                                     (u_longlong_t)capacity);
1973                         }
1974                         break;
1975
1976                 case ZPOOL_FIELD_HEALTH:
1977                         if (config == NULL) {
1978                                 (void) strlcpy(buf, "FAULTED", sizeof (buf));
1979                         } else {
1980                                 nvlist_t *nvroot;
1981                                 vdev_stat_t *vs;
1982                                 uint_t vsc;
1983
1984                                 verify(nvlist_lookup_nvlist(config,
1985                                     ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
1986                                 verify(nvlist_lookup_uint64_array(nvroot,
1987                                     ZPOOL_CONFIG_STATS, (uint64_t **)&vs,
1988                                     &vsc) == 0);
1989                                 (void) strlcpy(buf, state_to_name(vs),
1990                                     sizeof (buf));
1991                         }
1992                         break;
1993
1994                 case ZPOOL_FIELD_ROOT:
1995                         if (config == NULL)
1996                                 (void) strlcpy(buf, "-", sizeof (buf));
1997                         else if (zpool_get_root(zhp, buf, sizeof (buf)) != 0)
1998                                 (void) strlcpy(buf, "-", sizeof (buf));
1999                         break;
2000                 }
2001
2002                 if (cbp->cb_scripted)
2003                         (void) printf("%s", buf);
2004                 else {
2005                         if (col->cd_justify == left_justify)
2006                                 fmt = "%-*s";
2007                         else
2008                                 fmt = "%*s";
2009
2010                         (void) printf(fmt, i == cbp->cb_fieldcount - 1 ?
2011                             strlen(buf) : col->cd_width, buf);
2012                 }
2013         }
2014
2015         (void) printf("\n");
2016
2017         return (0);
2018 }
2019
2020 /*
2021  * zpool list [-H] [-o field[,field]*] [pool] ...
2022  *
2023  *      -H      Scripted mode.  Don't display headers, and separate fields by
2024  *              a single tab.
2025  *      -o      List of fields to display.  Defaults to all fields, or
2026  *              "name,size,used,available,capacity,health,root"
2027  *
2028  * List all pools in the system, whether or not they're healthy.  Output space
2029  * statistics for each one, as well as health status summary.
2030  */
2031 int
2032 zpool_do_list(int argc, char **argv)
2033 {
2034         int c;
2035         int ret;
2036         list_cbdata_t cb = { 0 };
2037         static char default_fields[] =
2038             "name,size,used,available,capacity,health,root";
2039         char *fields = default_fields;
2040         char *value;
2041
2042         /* check options */
2043         while ((c = getopt(argc, argv, ":Ho:")) != -1) {
2044                 switch (c) {
2045                 case 'H':
2046                         cb.cb_scripted = B_TRUE;
2047                         break;
2048                 case 'o':
2049                         fields = optarg;
2050                         break;
2051                 case ':':
2052                         (void) fprintf(stderr, gettext("missing argument for "
2053                             "'%c' option\n"), optopt);
2054                         usage(B_FALSE);
2055                         break;
2056                 case '?':
2057                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2058                             optopt);
2059                         usage(B_FALSE);
2060                 }
2061         }
2062
2063         argc -= optind;
2064         argv += optind;
2065
2066         while (*fields != '\0') {
2067                 if (cb.cb_fieldcount == MAX_FIELDS) {
2068                         (void) fprintf(stderr, gettext("too many "
2069                             "properties given to -o option\n"));
2070                         usage(B_FALSE);
2071                 }
2072
2073                 if ((cb.cb_fields[cb.cb_fieldcount] = getsubopt(&fields,
2074                     column_subopts, &value)) == -1) {
2075                         (void) fprintf(stderr, gettext("invalid property "
2076                             "'%s'\n"), value);
2077                         usage(B_FALSE);
2078                 }
2079
2080                 cb.cb_fieldcount++;
2081         }
2082
2083
2084         cb.cb_first = B_TRUE;
2085
2086         ret = for_each_pool(argc, argv, B_TRUE, NULL, list_callback, &cb);
2087
2088         if (argc == 0 && cb.cb_first) {
2089                 (void) printf(gettext("no pools available\n"));
2090                 return (0);
2091         }
2092
2093         return (ret);
2094 }
2095
2096 static nvlist_t *
2097 zpool_get_vdev_by_name(nvlist_t *nv, char *name)
2098 {
2099         nvlist_t **child;
2100         uint_t c, children;
2101         nvlist_t *match;
2102         char *path;
2103
2104         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2105             &child, &children) != 0) {
2106                 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2107                 if (strncmp(name, _PATH_DEV, sizeof(_PATH_DEV)-1) == 0)
2108                         name += sizeof(_PATH_DEV)-1;
2109                 if (strncmp(path, _PATH_DEV, sizeof(_PATH_DEV)-1) == 0)
2110                         path += sizeof(_PATH_DEV)-1;
2111                 if (strcmp(name, path) == 0)
2112                         return (nv);
2113                 return (NULL);
2114         }
2115
2116         for (c = 0; c < children; c++)
2117                 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL)
2118                         return (match);
2119
2120         return (NULL);
2121 }
2122
2123 static int
2124 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
2125 {
2126         boolean_t force = B_FALSE;
2127         int c;
2128         nvlist_t *nvroot;
2129         char *poolname, *old_disk, *new_disk;
2130         zpool_handle_t *zhp;
2131         nvlist_t *config;
2132         int ret;
2133         int log_argc;
2134         char **log_argv;
2135
2136         /* check options */
2137         while ((c = getopt(argc, argv, "f")) != -1) {
2138                 switch (c) {
2139                 case 'f':
2140                         force = B_TRUE;
2141                         break;
2142                 case '?':
2143                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2144                             optopt);
2145                         usage(B_FALSE);
2146                 }
2147         }
2148
2149         log_argc = argc;
2150         log_argv = argv;
2151         argc -= optind;
2152         argv += optind;
2153
2154         /* get pool name and check number of arguments */
2155         if (argc < 1) {
2156                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2157                 usage(B_FALSE);
2158         }
2159
2160         poolname = argv[0];
2161
2162         if (argc < 2) {
2163                 (void) fprintf(stderr,
2164                     gettext("missing <device> specification\n"));
2165                 usage(B_FALSE);
2166         }
2167
2168         old_disk = argv[1];
2169
2170         if (argc < 3) {
2171                 if (!replacing) {
2172                         (void) fprintf(stderr,
2173                             gettext("missing <new_device> specification\n"));
2174                         usage(B_FALSE);
2175                 }
2176                 new_disk = old_disk;
2177                 argc -= 1;
2178                 argv += 1;
2179         } else {
2180                 new_disk = argv[2];
2181                 argc -= 2;
2182                 argv += 2;
2183         }
2184
2185         if (argc > 1) {
2186                 (void) fprintf(stderr, gettext("too many arguments\n"));
2187                 usage(B_FALSE);
2188         }
2189
2190         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2191                 return (1);
2192
2193         if ((config = zpool_get_config(zhp, NULL)) == NULL) {
2194                 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
2195                     poolname);
2196                 zpool_close(zhp);
2197                 return (1);
2198         }
2199
2200         nvroot = make_root_vdev(config, force, B_FALSE, replacing, argc, argv);
2201         if (nvroot == NULL) {
2202                 zpool_close(zhp);
2203                 return (1);
2204         }
2205
2206         ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
2207
2208         if (!ret) {
2209                 zpool_log_history(g_zfs, log_argc, log_argv, poolname, B_TRUE,
2210                     B_FALSE);
2211         }
2212
2213         nvlist_free(nvroot);
2214         zpool_close(zhp);
2215
2216         return (ret);
2217 }
2218
2219 /*
2220  * zpool replace [-f] <pool> <device> <new_device>
2221  *
2222  *      -f      Force attach, even if <new_device> appears to be in use.
2223  *
2224  * Replace <device> with <new_device>.
2225  */
2226 /* ARGSUSED */
2227 int
2228 zpool_do_replace(int argc, char **argv)
2229 {
2230         return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
2231 }
2232
2233 /*
2234  * zpool attach [-f] <pool> <device> <new_device>
2235  *
2236  *      -f      Force attach, even if <new_device> appears to be in use.
2237  *
2238  * Attach <new_device> to the mirror containing <device>.  If <device> is not
2239  * part of a mirror, then <device> will be transformed into a mirror of
2240  * <device> and <new_device>.  In either case, <new_device> will begin life
2241  * with a DTL of [0, now], and will immediately begin to resilver itself.
2242  */
2243 int
2244 zpool_do_attach(int argc, char **argv)
2245 {
2246         return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
2247 }
2248
2249 /*
2250  * zpool detach [-f] <pool> <device>
2251  *
2252  *      -f      Force detach of <device>, even if DTLs argue against it
2253  *              (not supported yet)
2254  *
2255  * Detach a device from a mirror.  The operation will be refused if <device>
2256  * is the last device in the mirror, or if the DTLs indicate that this device
2257  * has the only valid copy of some data.
2258  */
2259 /* ARGSUSED */
2260 int
2261 zpool_do_detach(int argc, char **argv)
2262 {
2263         int c;
2264         char *poolname, *path;
2265         zpool_handle_t *zhp;
2266         int ret;
2267
2268         /* check options */
2269         while ((c = getopt(argc, argv, "f")) != -1) {
2270                 switch (c) {
2271                 case 'f':
2272                 case '?':
2273                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2274                             optopt);
2275                         usage(B_FALSE);
2276                 }
2277         }
2278
2279         argc -= optind;
2280         argv += optind;
2281
2282         /* get pool name and check number of arguments */
2283         if (argc < 1) {
2284                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2285                 usage(B_FALSE);
2286         }
2287
2288         if (argc < 2) {
2289                 (void) fprintf(stderr,
2290                     gettext("missing <device> specification\n"));
2291                 usage(B_FALSE);
2292         }
2293
2294         poolname = argv[0];
2295         path = argv[1];
2296
2297         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2298                 return (1);
2299
2300         ret = zpool_vdev_detach(zhp, path);
2301
2302         if (!ret) {
2303                 zpool_log_history(g_zfs, argc + optind, argv - optind, poolname,
2304                     B_TRUE, B_FALSE);
2305         }
2306         zpool_close(zhp);
2307
2308         return (ret);
2309 }
2310
2311 /*
2312  * zpool online <pool> <device> ...
2313  */
2314 /* ARGSUSED */
2315 int
2316 zpool_do_online(int argc, char **argv)
2317 {
2318         int c, i;
2319         char *poolname;
2320         zpool_handle_t *zhp;
2321         int ret = 0;
2322
2323         /* check options */
2324         while ((c = getopt(argc, argv, "t")) != -1) {
2325                 switch (c) {
2326                 case 't':
2327                 case '?':
2328                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2329                             optopt);
2330                         usage(B_FALSE);
2331                 }
2332         }
2333
2334         argc -= optind;
2335         argv += optind;
2336
2337         /* get pool name and check number of arguments */
2338         if (argc < 1) {
2339                 (void) fprintf(stderr, gettext("missing pool name\n"));
2340                 usage(B_FALSE);
2341         }
2342         if (argc < 2) {
2343                 (void) fprintf(stderr, gettext("missing device name\n"));
2344                 usage(B_FALSE);
2345         }
2346
2347         poolname = argv[0];
2348
2349         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2350                 return (1);
2351
2352         for (i = 1; i < argc; i++)
2353                 if (zpool_vdev_online(zhp, argv[i]) == 0)
2354                         (void) printf(gettext("Bringing device %s online\n"),
2355                             argv[i]);
2356                 else
2357                         ret = 1;
2358
2359         if (!ret) {
2360                 zpool_log_history(g_zfs, argc + optind, argv - optind, poolname,
2361                     B_TRUE, B_FALSE);
2362         }
2363         zpool_close(zhp);
2364
2365         return (ret);
2366 }
2367
2368 /*
2369  * zpool offline [-ft] <pool> <device> ...
2370  *
2371  *      -f      Force the device into the offline state, even if doing
2372  *              so would appear to compromise pool availability.
2373  *              (not supported yet)
2374  *
2375  *      -t      Only take the device off-line temporarily.  The offline
2376  *              state will not be persistent across reboots.
2377  */
2378 /* ARGSUSED */
2379 int
2380 zpool_do_offline(int argc, char **argv)
2381 {
2382         int c, i;
2383         char *poolname;
2384         zpool_handle_t *zhp;
2385         int ret = 0;
2386         boolean_t istmp = B_FALSE;
2387
2388         /* check options */
2389         while ((c = getopt(argc, argv, "ft")) != -1) {
2390                 switch (c) {
2391                 case 't':
2392                         istmp = B_TRUE;
2393                         break;
2394                 case 'f':
2395                 case '?':
2396                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2397                             optopt);
2398                         usage(B_FALSE);
2399                 }
2400         }
2401
2402         argc -= optind;
2403         argv += optind;
2404
2405         /* get pool name and check number of arguments */
2406         if (argc < 1) {
2407                 (void) fprintf(stderr, gettext("missing pool name\n"));
2408                 usage(B_FALSE);
2409         }
2410         if (argc < 2) {
2411                 (void) fprintf(stderr, gettext("missing device name\n"));
2412                 usage(B_FALSE);
2413         }
2414
2415         poolname = argv[0];
2416
2417         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2418                 return (1);
2419
2420         for (i = 1; i < argc; i++)
2421                 if (zpool_vdev_offline(zhp, argv[i], istmp) == 0)
2422                         (void) printf(gettext("Bringing device %s offline\n"),
2423                             argv[i]);
2424                 else
2425                         ret = 1;
2426
2427         if (!ret) {
2428                 zpool_log_history(g_zfs, argc + optind, argv - optind, poolname,
2429                     B_TRUE, B_FALSE);
2430         }
2431         zpool_close(zhp);
2432
2433         return (ret);
2434 }
2435
2436 /*
2437  * zpool clear <pool> [device]
2438  *
2439  * Clear all errors associated with a pool or a particular device.
2440  */
2441 int
2442 zpool_do_clear(int argc, char **argv)
2443 {
2444         int ret = 0;
2445         zpool_handle_t *zhp;
2446         char *pool, *device;
2447
2448         if (argc < 2) {
2449                 (void) fprintf(stderr, gettext("missing pool name\n"));
2450                 usage(B_FALSE);
2451         }
2452
2453         if (argc > 3) {
2454                 (void) fprintf(stderr, gettext("too many arguments\n"));
2455                 usage(B_FALSE);
2456         }
2457
2458         pool = argv[1];
2459         device = argc == 3 ? argv[2] : NULL;
2460
2461         if ((zhp = zpool_open(g_zfs, pool)) == NULL)
2462                 return (1);
2463
2464         if (zpool_clear(zhp, device) != 0)
2465                 ret = 1;
2466
2467         if (!ret)
2468                 zpool_log_history(g_zfs, argc, argv, pool, B_TRUE, B_FALSE);
2469         zpool_close(zhp);
2470
2471         return (ret);
2472 }
2473
2474 typedef struct scrub_cbdata {
2475         int     cb_type;
2476         int     cb_argc;
2477         char    **cb_argv;
2478 } scrub_cbdata_t;
2479
2480 int
2481 scrub_callback(zpool_handle_t *zhp, void *data)
2482 {
2483         scrub_cbdata_t *cb = data;
2484         int err;
2485
2486         /*
2487          * Ignore faulted pools.
2488          */
2489         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
2490                 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
2491                     "currently unavailable\n"), zpool_get_name(zhp));
2492                 return (1);
2493         }
2494
2495         err = zpool_scrub(zhp, cb->cb_type);
2496
2497         if (!err) {
2498                 zpool_log_history(g_zfs, cb->cb_argc, cb->cb_argv,
2499                     zpool_get_name(zhp), B_TRUE, B_FALSE);
2500         }
2501
2502         return (err != 0);
2503 }
2504
2505 /*
2506  * zpool scrub [-s] <pool> ...
2507  *
2508  *      -s      Stop.  Stops any in-progress scrub.
2509  */
2510 int
2511 zpool_do_scrub(int argc, char **argv)
2512 {
2513         int c;
2514         scrub_cbdata_t cb;
2515
2516         cb.cb_type = POOL_SCRUB_EVERYTHING;
2517
2518         /* check options */
2519         while ((c = getopt(argc, argv, "s")) != -1) {
2520                 switch (c) {
2521                 case 's':
2522                         cb.cb_type = POOL_SCRUB_NONE;
2523                         break;
2524                 case '?':
2525                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2526                             optopt);
2527                         usage(B_FALSE);
2528                 }
2529         }
2530
2531         cb.cb_argc = argc;
2532         cb.cb_argv = argv;
2533         argc -= optind;
2534         argv += optind;
2535
2536         if (argc < 1) {
2537                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2538                 usage(B_FALSE);
2539         }
2540
2541         return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
2542 }
2543
2544 typedef struct status_cbdata {
2545         int             cb_count;
2546         boolean_t       cb_allpools;
2547         boolean_t       cb_verbose;
2548         boolean_t       cb_explain;
2549         boolean_t       cb_first;
2550 } status_cbdata_t;
2551
2552 /*
2553  * Print out detailed scrub status.
2554  */
2555 void
2556 print_scrub_status(nvlist_t *nvroot)
2557 {
2558         vdev_stat_t *vs;
2559         uint_t vsc;
2560         time_t start, end, now;
2561         double fraction_done;
2562         uint64_t examined, total, minutes_left;
2563         char *scrub_type;
2564
2565         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
2566             (uint64_t **)&vs, &vsc) == 0);
2567
2568         /*
2569          * If there's never been a scrub, there's not much to say.
2570          */
2571         if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) {
2572                 (void) printf(gettext("none requested\n"));
2573                 return;
2574         }
2575
2576         scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2577             "resilver" : "scrub";
2578
2579         start = vs->vs_scrub_start;
2580         end = vs->vs_scrub_end;
2581         now = time(NULL);
2582         examined = vs->vs_scrub_examined;
2583         total = vs->vs_alloc;
2584
2585         if (end != 0) {
2586                 (void) printf(gettext("%s %s with %llu errors on %s"),
2587                     scrub_type, vs->vs_scrub_complete ? "completed" : "stopped",
2588                     (u_longlong_t)vs->vs_scrub_errors, ctime(&end));
2589                 return;
2590         }
2591
2592         if (examined == 0)
2593                 examined = 1;
2594         if (examined > total)
2595                 total = examined;
2596
2597         fraction_done = (double)examined / total;
2598         minutes_left = (uint64_t)((now - start) *
2599             (1 - fraction_done) / fraction_done / 60);
2600
2601         (void) printf(gettext("%s in progress, %.2f%% done, %lluh%um to go\n"),
2602             scrub_type, 100 * fraction_done,
2603             (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60));
2604 }
2605
2606 typedef struct spare_cbdata {
2607         uint64_t        cb_guid;
2608         zpool_handle_t  *cb_zhp;
2609 } spare_cbdata_t;
2610
2611 static boolean_t
2612 find_vdev(nvlist_t *nv, uint64_t search)
2613 {
2614         uint64_t guid;
2615         nvlist_t **child;
2616         uint_t c, children;
2617
2618         if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
2619             search == guid)
2620                 return (B_TRUE);
2621
2622         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2623             &child, &children) == 0) {
2624                 for (c = 0; c < children; c++)
2625                         if (find_vdev(child[c], search))
2626                                 return (B_TRUE);
2627         }
2628
2629         return (B_FALSE);
2630 }
2631
2632 static int
2633 find_spare(zpool_handle_t *zhp, void *data)
2634 {
2635         spare_cbdata_t *cbp = data;
2636         nvlist_t *config, *nvroot;
2637
2638         config = zpool_get_config(zhp, NULL);
2639         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2640             &nvroot) == 0);
2641
2642         if (find_vdev(nvroot, cbp->cb_guid)) {
2643                 cbp->cb_zhp = zhp;
2644                 return (1);
2645         }
2646
2647         zpool_close(zhp);
2648         return (0);
2649 }
2650
2651 /*
2652  * Print out configuration state as requested by status_callback.
2653  */
2654 void
2655 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
2656     int namewidth, int depth, boolean_t isspare)
2657 {
2658         nvlist_t **child;
2659         uint_t c, children;
2660         vdev_stat_t *vs;
2661         char rbuf[6], wbuf[6], cbuf[6], repaired[7];
2662         char *vname;
2663         uint64_t notpresent;
2664         spare_cbdata_t cb;
2665         const char *state;
2666
2667         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
2668             (uint64_t **)&vs, &c) == 0);
2669
2670         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2671             &child, &children) != 0)
2672                 children = 0;
2673
2674         state = state_to_name(vs);
2675         if (isspare) {
2676                 /*
2677                  * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
2678                  * online drives.
2679                  */
2680                 if (vs->vs_aux == VDEV_AUX_SPARED)
2681                         state = "INUSE";
2682                 else if (vs->vs_state == VDEV_STATE_HEALTHY)
2683                         state = "AVAIL";
2684         }
2685
2686         (void) printf("\t%*s%-*s  %-8s", depth, "", namewidth - depth,
2687             name, state);
2688
2689         if (!isspare) {
2690                 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
2691                 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
2692                 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
2693                 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
2694         }
2695
2696         if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
2697             &notpresent) == 0) {
2698                 char *path;
2699                 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2700                 (void) printf("  was %s", path);
2701         } else if (vs->vs_aux != 0) {
2702                 (void) printf("  ");
2703
2704                 switch (vs->vs_aux) {
2705                 case VDEV_AUX_OPEN_FAILED:
2706                         (void) printf(gettext("cannot open"));
2707                         break;
2708
2709                 case VDEV_AUX_BAD_GUID_SUM:
2710                         (void) printf(gettext("missing device"));
2711                         break;
2712
2713                 case VDEV_AUX_NO_REPLICAS:
2714                         (void) printf(gettext("insufficient replicas"));
2715                         break;
2716
2717                 case VDEV_AUX_VERSION_NEWER:
2718                         (void) printf(gettext("newer version"));
2719                         break;
2720
2721                 case VDEV_AUX_SPARED:
2722                         verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
2723                             &cb.cb_guid) == 0);
2724                         if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
2725                                 if (strcmp(zpool_get_name(cb.cb_zhp),
2726                                     zpool_get_name(zhp)) == 0)
2727                                         (void) printf(gettext("currently in "
2728                                             "use"));
2729                                 else
2730                                         (void) printf(gettext("in use by "
2731                                             "pool '%s'"),
2732                                             zpool_get_name(cb.cb_zhp));
2733                                 zpool_close(cb.cb_zhp);
2734                         } else {
2735                                 (void) printf(gettext("currently in use"));
2736                         }
2737                         break;
2738
2739                 default:
2740                         (void) printf(gettext("corrupted data"));
2741                         break;
2742                 }
2743         } else if (vs->vs_scrub_repaired != 0 && children == 0) {
2744                 /*
2745                  * Report bytes resilvered/repaired on leaf devices.
2746                  */
2747                 zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired));
2748                 (void) printf(gettext("  %s %s"), repaired,
2749                     (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2750                     "resilvered" : "repaired");
2751         }
2752
2753         (void) printf("\n");
2754
2755         for (c = 0; c < children; c++) {
2756                 vname = zpool_vdev_name(g_zfs, zhp, child[c]);
2757                 print_status_config(zhp, vname, child[c],
2758                     namewidth, depth + 2, isspare);
2759                 free(vname);
2760         }
2761 }
2762
2763 static void
2764 print_error_log(zpool_handle_t *zhp)
2765 {
2766         nvlist_t *nverrlist;
2767         nvpair_t *elem;
2768         char *pathname;
2769         size_t len = MAXPATHLEN * 2;
2770
2771         if (zpool_get_errlog(zhp, &nverrlist) != 0) {
2772                 (void) printf("errors: List of errors unavailable "
2773                     "(insufficient privileges)\n");
2774                 return;
2775         }
2776
2777         (void) printf("errors: Permanent errors have been "
2778             "detected in the following files:\n\n");
2779
2780         pathname = safe_malloc(len);
2781         elem = NULL;
2782         while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
2783                 nvlist_t *nv;
2784                 uint64_t dsobj, obj;
2785
2786                 verify(nvpair_value_nvlist(elem, &nv) == 0);
2787                 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
2788                     &dsobj) == 0);
2789                 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
2790                     &obj) == 0);
2791                 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
2792                 (void) printf("%7s %s\n", "", pathname);
2793         }
2794         free(pathname);
2795         nvlist_free(nverrlist);
2796 }
2797
2798 static void
2799 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
2800     int namewidth)
2801 {
2802         uint_t i;
2803         char *name;
2804
2805         if (nspares == 0)
2806                 return;
2807
2808         (void) printf(gettext("\tspares\n"));
2809
2810         for (i = 0; i < nspares; i++) {
2811                 name = zpool_vdev_name(g_zfs, zhp, spares[i]);
2812                 print_status_config(zhp, name, spares[i],
2813                     namewidth, 2, B_TRUE);
2814                 free(name);
2815         }
2816 }
2817
2818 /*
2819  * Display a summary of pool status.  Displays a summary such as:
2820  *
2821  *        pool: tank
2822  *      status: DEGRADED
2823  *      reason: One or more devices ...
2824  *         see: http://www.sun.com/msg/ZFS-xxxx-01
2825  *      config:
2826  *              mirror          DEGRADED
2827  *                c1t0d0        OK
2828  *                c2t0d0        UNAVAIL
2829  *
2830  * When given the '-v' option, we print out the complete config.  If the '-e'
2831  * option is specified, then we print out error rate information as well.
2832  */
2833 int
2834 status_callback(zpool_handle_t *zhp, void *data)
2835 {
2836         status_cbdata_t *cbp = data;
2837         nvlist_t *config, *nvroot;
2838         char *msgid;
2839         int reason;
2840         const char *health;
2841         uint_t c;
2842         vdev_stat_t *vs;
2843
2844         config = zpool_get_config(zhp, NULL);
2845         reason = zpool_get_status(zhp, &msgid);
2846
2847         cbp->cb_count++;
2848
2849         /*
2850          * If we were given 'zpool status -x', only report those pools with
2851          * problems.
2852          */
2853         if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) {
2854                 if (!cbp->cb_allpools) {
2855                         (void) printf(gettext("pool '%s' is healthy\n"),
2856                             zpool_get_name(zhp));
2857                         if (cbp->cb_first)
2858                                 cbp->cb_first = B_FALSE;
2859                 }
2860                 return (0);
2861         }
2862
2863         if (cbp->cb_first)
2864                 cbp->cb_first = B_FALSE;
2865         else
2866                 (void) printf("\n");
2867
2868         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2869             &nvroot) == 0);
2870         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
2871             (uint64_t **)&vs, &c) == 0);
2872         health = state_to_name(vs);
2873
2874         (void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
2875         (void) printf(gettext(" state: %s\n"), health);
2876
2877         switch (reason) {
2878         case ZPOOL_STATUS_MISSING_DEV_R:
2879                 (void) printf(gettext("status: One or more devices could not "
2880                     "be opened.  Sufficient replicas exist for\n\tthe pool to "
2881                     "continue functioning in a degraded state.\n"));
2882                 (void) printf(gettext("action: Attach the missing device and "
2883                     "online it using 'zpool online'.\n"));
2884                 break;
2885
2886         case ZPOOL_STATUS_MISSING_DEV_NR:
2887                 (void) printf(gettext("status: One or more devices could not "
2888                     "be opened.  There are insufficient\n\treplicas for the "
2889                     "pool to continue functioning.\n"));
2890                 (void) printf(gettext("action: Attach the missing device and "
2891                     "online it using 'zpool online'.\n"));
2892                 break;
2893
2894         case ZPOOL_STATUS_CORRUPT_LABEL_R:
2895                 (void) printf(gettext("status: One or more devices could not "
2896                     "be used because the label is missing or\n\tinvalid.  "
2897                     "Sufficient replicas exist for the pool to continue\n\t"
2898                     "functioning in a degraded state.\n"));
2899                 (void) printf(gettext("action: Replace the device using "
2900                     "'zpool replace'.\n"));
2901                 break;
2902
2903         case ZPOOL_STATUS_CORRUPT_LABEL_NR:
2904                 (void) printf(gettext("status: One or more devices could not "
2905                     "be used because the label is missing \n\tor invalid.  "
2906                     "There are insufficient replicas for the pool to "
2907                     "continue\n\tfunctioning.\n"));
2908                 (void) printf(gettext("action: Destroy and re-create the pool "
2909                     "from a backup source.\n"));
2910                 break;
2911
2912         case ZPOOL_STATUS_FAILING_DEV:
2913                 (void) printf(gettext("status: One or more devices has "
2914                     "experienced an unrecoverable error.  An\n\tattempt was "
2915                     "made to correct the error.  Applications are "
2916                     "unaffected.\n"));
2917                 (void) printf(gettext("action: Determine if the device needs "
2918                     "to be replaced, and clear the errors\n\tusing "
2919                     "'zpool clear' or replace the device with 'zpool "
2920                     "replace'.\n"));
2921                 break;
2922
2923         case ZPOOL_STATUS_OFFLINE_DEV:
2924                 (void) printf(gettext("status: One or more devices has "
2925                     "been taken offline by the administrator.\n\tSufficient "
2926                     "replicas exist for the pool to continue functioning in "
2927                     "a\n\tdegraded state.\n"));
2928                 (void) printf(gettext("action: Online the device using "
2929                     "'zpool online' or replace the device with\n\t'zpool "
2930                     "replace'.\n"));
2931                 break;
2932
2933         case ZPOOL_STATUS_RESILVERING:
2934                 (void) printf(gettext("status: One or more devices is "
2935                     "currently being resilvered.  The pool will\n\tcontinue "
2936                     "to function, possibly in a degraded state.\n"));
2937                 (void) printf(gettext("action: Wait for the resilver to "
2938                     "complete.\n"));
2939                 break;
2940
2941         case ZPOOL_STATUS_CORRUPT_DATA:
2942                 (void) printf(gettext("status: One or more devices has "
2943                     "experienced an error resulting in data\n\tcorruption.  "
2944                     "Applications may be affected.\n"));
2945                 (void) printf(gettext("action: Restore the file in question "
2946                     "if possible.  Otherwise restore the\n\tentire pool from "
2947                     "backup.\n"));
2948                 break;
2949
2950         case ZPOOL_STATUS_CORRUPT_POOL:
2951                 (void) printf(gettext("status: The pool metadata is corrupted "
2952                     "and the pool cannot be opened.\n"));
2953                 (void) printf(gettext("action: Destroy and re-create the pool "
2954                     "from a backup source.\n"));
2955                 break;
2956
2957         case ZPOOL_STATUS_VERSION_OLDER:
2958                 (void) printf(gettext("status: The pool is formatted using an "
2959                     "older on-disk format.  The pool can\n\tstill be used, but "
2960                     "some features are unavailable.\n"));
2961                 (void) printf(gettext("action: Upgrade the pool using 'zpool "
2962                     "upgrade'.  Once this is done, the\n\tpool will no longer "
2963                     "be accessible on older software versions.\n"));
2964                 break;
2965
2966         case ZPOOL_STATUS_VERSION_NEWER:
2967                 (void) printf(gettext("status: The pool has been upgraded to a "
2968                     "newer, incompatible on-disk version.\n\tThe pool cannot "
2969                     "be accessed on this system.\n"));
2970                 (void) printf(gettext("action: Access the pool from a system "
2971                     "running more recent software, or\n\trestore the pool from "
2972                     "backup.\n"));
2973                 break;
2974
2975         default:
2976                 /*
2977                  * The remaining errors can't actually be generated, yet.
2978                  */
2979                 assert(reason == ZPOOL_STATUS_OK);
2980         }
2981
2982         if (msgid != NULL)
2983                 (void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
2984                     msgid);
2985
2986         if (config != NULL) {
2987                 int namewidth;
2988                 uint64_t nerr;
2989                 nvlist_t **spares;
2990                 uint_t nspares;
2991
2992
2993                 (void) printf(gettext(" scrub: "));
2994                 print_scrub_status(nvroot);
2995
2996                 namewidth = max_width(zhp, nvroot, 0, 0);
2997                 if (namewidth < 10)
2998                         namewidth = 10;
2999
3000                 (void) printf(gettext("config:\n\n"));
3001                 (void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
3002                     "NAME", "STATE", "READ", "WRITE", "CKSUM");
3003                 print_status_config(zhp, zpool_get_name(zhp), nvroot,
3004                     namewidth, 0, B_FALSE);
3005
3006                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
3007                     &spares, &nspares) == 0)
3008                         print_spares(zhp, spares, nspares, namewidth);
3009
3010                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
3011                     &nerr) == 0) {
3012                         nvlist_t *nverrlist = NULL;
3013
3014                         /*
3015                          * If the approximate error count is small, get a
3016                          * precise count by fetching the entire log and
3017                          * uniquifying the results.
3018                          */
3019                         if (nerr < 100 && !cbp->cb_verbose &&
3020                             zpool_get_errlog(zhp, &nverrlist) == 0) {
3021                                 nvpair_t *elem;
3022
3023                                 elem = NULL;
3024                                 nerr = 0;
3025                                 while ((elem = nvlist_next_nvpair(nverrlist,
3026                                     elem)) != NULL) {
3027                                         nerr++;
3028                                 }
3029                         }
3030                         nvlist_free(nverrlist);
3031
3032                         (void) printf("\n");
3033
3034                         if (nerr == 0)
3035                                 (void) printf(gettext("errors: No known data "
3036                                     "errors\n"));
3037                         else if (!cbp->cb_verbose)
3038                                 (void) printf(gettext("errors: %llu data "
3039                                     "errors, use '-v' for a list\n"),
3040                                     (u_longlong_t)nerr);
3041                         else
3042                                 print_error_log(zhp);
3043                 }
3044         } else {
3045                 (void) printf(gettext("config: The configuration cannot be "
3046                     "determined.\n"));
3047         }
3048
3049         return (0);
3050 }
3051
3052 /*
3053  * zpool status [-vx] [pool] ...
3054  *
3055  *      -v      Display complete error logs
3056  *      -x      Display only pools with potential problems
3057  *
3058  * Describes the health status of all pools or some subset.
3059  */
3060 int
3061 zpool_do_status(int argc, char **argv)
3062 {
3063         int c;
3064         int ret;
3065         status_cbdata_t cb = { 0 };
3066
3067         /* check options */
3068         while ((c = getopt(argc, argv, "vx")) != -1) {
3069                 switch (c) {
3070                 case 'v':
3071                         cb.cb_verbose = B_TRUE;
3072                         break;
3073                 case 'x':
3074                         cb.cb_explain = B_TRUE;
3075                         break;
3076                 case '?':
3077                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3078                             optopt);
3079                         usage(B_FALSE);
3080                 }
3081         }
3082
3083         argc -= optind;
3084         argv += optind;
3085
3086         cb.cb_first = B_TRUE;
3087
3088         if (argc == 0)
3089                 cb.cb_allpools = B_TRUE;
3090
3091         ret = for_each_pool(argc, argv, B_TRUE, NULL, status_callback, &cb);
3092
3093         if (argc == 0 && cb.cb_count == 0)
3094                 (void) printf(gettext("no pools available\n"));
3095         else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
3096                 (void) printf(gettext("all pools are healthy\n"));
3097
3098         return (ret);
3099 }
3100
3101 typedef struct upgrade_cbdata {
3102         int     cb_all;
3103         int     cb_first;
3104         int     cb_newer;
3105         int     cb_argc;
3106         char    **cb_argv;
3107 } upgrade_cbdata_t;
3108
3109 static int
3110 upgrade_cb(zpool_handle_t *zhp, void *arg)
3111 {
3112         upgrade_cbdata_t *cbp = arg;
3113         nvlist_t *config;
3114         uint64_t version;
3115         int ret = 0;
3116
3117         config = zpool_get_config(zhp, NULL);
3118         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
3119             &version) == 0);
3120
3121         if (!cbp->cb_newer && version < ZFS_VERSION) {
3122                 if (!cbp->cb_all) {
3123                         if (cbp->cb_first) {
3124                                 (void) printf(gettext("The following pools are "
3125                                     "out of date, and can be upgraded.  After "
3126                                     "being\nupgraded, these pools will no "
3127                                     "longer be accessible by older software "
3128                                     "versions.\n\n"));
3129                                 (void) printf(gettext("VER  POOL\n"));
3130                                 (void) printf(gettext("---  ------------\n"));
3131                                 cbp->cb_first = B_FALSE;
3132                         }
3133
3134                         (void) printf("%2llu   %s\n", (u_longlong_t)version,
3135                             zpool_get_name(zhp));
3136                 } else {
3137                         cbp->cb_first = B_FALSE;
3138                         ret = zpool_upgrade(zhp);
3139                         if (!ret) {
3140                                 zpool_log_history(g_zfs, cbp->cb_argc,
3141                                     cbp->cb_argv, zpool_get_name(zhp), B_TRUE,
3142                                     B_FALSE);
3143                                 (void) printf(gettext("Successfully upgraded "
3144                                     "'%s'\n"), zpool_get_name(zhp));
3145                         }
3146                 }
3147         } else if (cbp->cb_newer && version > ZFS_VERSION) {
3148                 assert(!cbp->cb_all);
3149
3150                 if (cbp->cb_first) {
3151                         (void) printf(gettext("The following pools are "
3152                             "formatted using a newer software version and\n"
3153                             "cannot be accessed on the current system.\n\n"));
3154                         (void) printf(gettext("VER  POOL\n"));
3155                         (void) printf(gettext("---  ------------\n"));
3156                         cbp->cb_first = B_FALSE;
3157                 }
3158
3159                 (void) printf("%2llu   %s\n", (u_longlong_t)version,
3160                     zpool_get_name(zhp));
3161         }
3162
3163         zpool_close(zhp);
3164         return (ret);
3165 }
3166
3167 /* ARGSUSED */
3168 static int
3169 upgrade_one(zpool_handle_t *zhp, void *data)
3170 {
3171         nvlist_t *config;
3172         uint64_t version;
3173         int ret;
3174         upgrade_cbdata_t *cbp = data;
3175
3176         config = zpool_get_config(zhp, NULL);
3177         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
3178             &version) == 0);
3179
3180         if (version == ZFS_VERSION) {
3181                 (void) printf(gettext("Pool '%s' is already formatted "
3182                     "using the current version.\n"), zpool_get_name(zhp));
3183                 return (0);
3184         }
3185
3186         ret = zpool_upgrade(zhp);
3187
3188         if (!ret) {
3189                 zpool_log_history(g_zfs, cbp->cb_argc, cbp->cb_argv,
3190                     zpool_get_name(zhp), B_TRUE, B_FALSE);
3191                 (void) printf(gettext("Successfully upgraded '%s' "
3192                     "from version %llu to version %llu\n"), zpool_get_name(zhp),
3193                     (u_longlong_t)version, (u_longlong_t)ZFS_VERSION);
3194         }
3195
3196         return (ret != 0);
3197 }
3198
3199 /*
3200  * zpool upgrade
3201  * zpool upgrade -v
3202  * zpool upgrade <-a | pool>
3203  *
3204  * With no arguments, display downrev'd ZFS pool available for upgrade.
3205  * Individual pools can be upgraded by specifying the pool, and '-a' will
3206  * upgrade all pools.
3207  */
3208 int
3209 zpool_do_upgrade(int argc, char **argv)
3210 {
3211         int c;
3212         upgrade_cbdata_t cb = { 0 };
3213         int ret = 0;
3214         boolean_t showversions = B_FALSE;
3215
3216         /* check options */
3217         while ((c = getopt(argc, argv, "av")) != -1) {
3218                 switch (c) {
3219                 case 'a':
3220                         cb.cb_all = B_TRUE;
3221                         break;
3222                 case 'v':
3223                         showversions = B_TRUE;
3224                         break;
3225                 case '?':
3226                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3227                             optopt);
3228                         usage(B_FALSE);
3229                 }
3230         }
3231
3232         cb.cb_argc = argc;
3233         cb.cb_argv = argv;
3234         argc -= optind;
3235         argv += optind;
3236
3237         if (showversions) {
3238                 if (cb.cb_all || argc != 0) {
3239                         (void) fprintf(stderr, gettext("-v option is "
3240                             "incompatible with other arguments\n"));
3241                         usage(B_FALSE);
3242                 }
3243         } else if (cb.cb_all) {
3244                 if (argc != 0) {
3245                         (void) fprintf(stderr, gettext("-a option is "
3246                             "incompatible with other arguments\n"));
3247                         usage(B_FALSE);
3248                 }
3249         }
3250
3251         (void) printf(gettext("This system is currently running ZFS version "
3252             "%llu.\n\n"), ZFS_VERSION);
3253         cb.cb_first = B_TRUE;
3254         if (showversions) {
3255                 (void) printf(gettext("The following versions are "
3256                     "supported:\n\n"));
3257                 (void) printf(gettext("VER  DESCRIPTION\n"));
3258                 (void) printf("---  -----------------------------------------"
3259                     "---------------\n");
3260                 (void) printf(gettext(" 1   Initial ZFS version\n"));
3261                 (void) printf(gettext(" 2   Ditto blocks "
3262                     "(replicated metadata)\n"));
3263                 (void) printf(gettext(" 3   Hot spares and double parity "
3264                     "RAID-Z\n"));
3265                 (void) printf(gettext(" 4   zpool history\n"));
3266                 (void) printf(gettext(" 5   Compression using the gzip "
3267                     "algorithm\n"));
3268                 (void) printf(gettext(" 6   bootfs pool property "));
3269                 (void) printf(gettext("\nFor more information on a particular "
3270                     "version, including supported releases, see:\n\n"));
3271                 (void) printf("http://www.opensolaris.org/os/community/zfs/"
3272                     "version/N\n\n");
3273                 (void) printf(gettext("Where 'N' is the version number.\n"));
3274         } else if (argc == 0) {
3275                 int notfound;
3276
3277                 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3278                 notfound = cb.cb_first;
3279
3280                 if (!cb.cb_all && ret == 0) {
3281                         if (!cb.cb_first)
3282                                 (void) printf("\n");
3283                         cb.cb_first = B_TRUE;
3284                         cb.cb_newer = B_TRUE;
3285                         ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3286                         if (!cb.cb_first) {
3287                                 notfound = B_FALSE;
3288                                 (void) printf("\n");
3289                         }
3290                 }
3291
3292                 if (ret == 0) {
3293                         if (notfound)
3294                                 (void) printf(gettext("All pools are formatted "
3295                                     "using this version.\n"));
3296                         else if (!cb.cb_all)
3297                                 (void) printf(gettext("Use 'zpool upgrade -v' "
3298                                     "for a list of available versions and "
3299                                     "their associated\nfeatures.\n"));
3300                 }
3301         } else {
3302                 ret = for_each_pool(argc, argv, B_FALSE, NULL,
3303                     upgrade_one, &cb);
3304         }
3305
3306         return (ret);
3307 }
3308
3309 /*
3310  * Print out the command history for a specific pool.
3311  */
3312 static int
3313 get_history_one(zpool_handle_t *zhp, void *data)
3314 {
3315         nvlist_t *nvhis;
3316         nvlist_t **records;
3317         uint_t numrecords;
3318         char *cmdstr;
3319         uint64_t dst_time;
3320         time_t tsec;
3321         struct tm t;
3322         char tbuf[30];
3323         int ret, i;
3324
3325         *(boolean_t *)data = B_FALSE;
3326
3327         (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
3328
3329         if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
3330                 return (ret);
3331
3332         verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
3333             &records, &numrecords) == 0);
3334         for (i = 0; i < numrecords; i++) {
3335                 if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME,
3336                     &dst_time) == 0) {
3337                         verify(nvlist_lookup_string(records[i], ZPOOL_HIST_CMD,
3338                             &cmdstr) == 0);
3339                         tsec = dst_time;
3340                         (void) localtime_r(&tsec, &t);
3341                         (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
3342                         (void) printf("%s %s\n", tbuf, cmdstr);
3343                 }
3344         }
3345         (void) printf("\n");
3346         nvlist_free(nvhis);
3347
3348         return (ret);
3349 }
3350
3351 /*
3352  * zpool history <pool>
3353  *
3354  * Displays the history of commands that modified pools.
3355  */
3356 int
3357 zpool_do_history(int argc, char **argv)
3358 {
3359         boolean_t first = B_TRUE;
3360         int ret;
3361
3362         argc -= optind;
3363         argv += optind;
3364
3365         ret = for_each_pool(argc, argv, B_FALSE,  NULL, get_history_one,
3366             &first);
3367
3368         if (argc == 0 && first == B_TRUE) {
3369                 (void) printf(gettext("no pools available\n"));
3370                 return (0);
3371         }
3372
3373         return (ret);
3374 }
3375
3376 static int
3377 get_callback(zpool_handle_t *zhp, void *data)
3378 {
3379         libzfs_get_cbdata_t *cbp = (libzfs_get_cbdata_t *)data;
3380         char value[MAXNAMELEN];
3381         zfs_source_t srctype;
3382         zpool_proplist_t *pl;
3383
3384         for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
3385
3386                 /*
3387                  * Skip the special fake placeholder.
3388                  */
3389                 if (pl->pl_prop == ZFS_PROP_NAME &&
3390                     pl == cbp->cb_proplist)
3391                         continue;
3392
3393                 if (zpool_get_prop(zhp, pl->pl_prop,
3394                     value, sizeof (value), &srctype) != 0)
3395                         continue;
3396
3397                 libzfs_print_one_property(zpool_get_name(zhp), cbp,
3398                     zpool_prop_to_name(pl->pl_prop), value, srctype, NULL);
3399         }
3400         return (0);
3401 }
3402
3403 int
3404 zpool_do_get(int argc, char **argv)
3405 {
3406         libzfs_get_cbdata_t cb = { 0 };
3407         zpool_proplist_t fake_name = { 0 };
3408         int ret;
3409
3410         if (argc < 3)
3411                 usage(B_FALSE);
3412
3413         cb.cb_first = B_TRUE;
3414         cb.cb_sources = ZFS_SRC_ALL;
3415         cb.cb_columns[0] = GET_COL_NAME;
3416         cb.cb_columns[1] = GET_COL_PROPERTY;
3417         cb.cb_columns[2] = GET_COL_VALUE;
3418         cb.cb_columns[3] = GET_COL_SOURCE;
3419
3420         if (zpool_get_proplist(g_zfs, argv[1],  &cb.cb_proplist) != 0)
3421                 usage(B_FALSE);
3422
3423         if (cb.cb_proplist != NULL) {
3424                 fake_name.pl_prop = ZFS_PROP_NAME;
3425                 fake_name.pl_width = strlen(gettext("NAME"));
3426                 fake_name.pl_next = cb.cb_proplist;
3427                 cb.cb_proplist = &fake_name;
3428         }
3429
3430         ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist,
3431             get_callback, &cb);
3432
3433         if (cb.cb_proplist == &fake_name)
3434                 zfs_free_proplist(fake_name.pl_next);
3435         else
3436                 zfs_free_proplist(cb.cb_proplist);
3437
3438         return (ret);
3439 }
3440
3441 typedef struct set_cbdata {
3442         char *cb_propname;
3443         char *cb_value;
3444         boolean_t cb_any_successful;
3445 } set_cbdata_t;
3446
3447 int
3448 set_callback(zpool_handle_t *zhp, void *data)
3449 {
3450         int error;
3451         set_cbdata_t *cb = (set_cbdata_t *)data;
3452
3453         error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
3454
3455         if (!error)
3456                 cb->cb_any_successful = B_TRUE;
3457
3458         return (error);
3459 }
3460
3461 int
3462 zpool_do_set(int argc, char **argv)
3463 {
3464         set_cbdata_t cb = { 0 };
3465         int error;
3466
3467         if (argc > 1 && argv[1][0] == '-') {
3468                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3469                     argv[1][1]);
3470                 usage(B_FALSE);
3471         }
3472
3473         if (argc < 2) {
3474                 (void) fprintf(stderr, gettext("missing property=value "
3475                     "argument\n"));
3476                 usage(B_FALSE);
3477         }
3478
3479         if (argc < 3) {
3480                 (void) fprintf(stderr, gettext("missing pool name\n"));
3481                 usage(B_FALSE);
3482         }
3483
3484         if (argc > 3) {
3485                 (void) fprintf(stderr, gettext("too many pool names\n"));
3486                 usage(B_FALSE);
3487         }
3488
3489         cb.cb_propname = argv[1];
3490         cb.cb_value = strchr(cb.cb_propname, '=');
3491         if (cb.cb_value == NULL) {
3492                 (void) fprintf(stderr, gettext("missing value in "
3493                     "property=value argument\n"));
3494                 usage(B_FALSE);
3495         }
3496
3497         *(cb.cb_value) = '\0';
3498         cb.cb_value++;
3499
3500         error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
3501             set_callback, &cb);
3502
3503         if (cb.cb_any_successful) {
3504                 *(cb.cb_value - 1) = '=';
3505                 zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE);
3506         }
3507
3508         return (error);
3509 }
3510
3511 static int
3512 find_command_idx(char *command, int *idx)
3513 {
3514         int i;
3515
3516         for (i = 0; i < NCOMMAND; i++) {
3517                 if (command_table[i].name == NULL)
3518                         continue;
3519
3520                 if (strcmp(command, command_table[i].name) == 0) {
3521                         *idx = i;
3522                         return (0);
3523                 }
3524         }
3525         return (1);
3526 }
3527
3528 int
3529 main(int argc, char **argv)
3530 {
3531         int ret;
3532         int i;
3533         char *cmdname;
3534         int found = 0;
3535
3536         (void) setlocale(LC_ALL, "");
3537         (void) textdomain(TEXT_DOMAIN);
3538
3539         if ((g_zfs = libzfs_init()) == NULL) {
3540                 (void) fprintf(stderr, gettext("internal error: failed to "
3541                     "initialize ZFS library\n"));
3542                 return (1);
3543         }
3544
3545         libzfs_print_on_error(g_zfs, B_TRUE);
3546
3547         opterr = 0;
3548
3549         /*
3550          * Make sure the user has specified some command.
3551          */
3552         if (argc < 2) {
3553                 (void) fprintf(stderr, gettext("missing command\n"));
3554                 usage(B_FALSE);
3555         }
3556
3557         cmdname = argv[1];
3558
3559         /*
3560          * Special case '-?'
3561          */
3562         if (strcmp(cmdname, "-?") == 0)
3563                 usage(B_TRUE);
3564
3565         /*
3566          * Run the appropriate command.
3567          */
3568         if (find_command_idx(cmdname, &i) == 0) {
3569                 current_command = &command_table[i];
3570                 ret = command_table[i].func(argc - 1, argv + 1);
3571                 found++;
3572         }
3573
3574         /*
3575          * 'freeze' is a vile debugging abomination, so we treat it as such.
3576          */
3577         if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
3578                 char buf[16384];
3579                 int fd = open(ZFS_DEV, O_RDWR);
3580                 (void) strcpy((void *)buf, argv[2]);
3581                 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
3582         }
3583
3584         if (!found) {
3585                 (void) fprintf(stderr, gettext("unrecognized "
3586                     "command '%s'\n"), cmdname);
3587                 usage(B_FALSE);
3588         }
3589
3590         libzfs_fini(g_zfs);
3591
3592         /*
3593          * The 'ZFS_ABORT' environment variable causes us to dump core on exit
3594          * for the purposes of running ::findleaks.
3595          */
3596         if (getenv("ZFS_ABORT") != NULL) {
3597                 (void) printf("dumping core by request\n");
3598                 abort();
3599         }
3600
3601         return (ret);
3602 }