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