]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.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         boolean_t hardforce = B_FALSE;
883         int c;
884         zpool_handle_t *zhp;
885         int ret;
886         int i;
887
888         /* check options */
889         while ((c = getopt(argc, argv, "fF")) != -1) {
890                 switch (c) {
891                 case 'f':
892                         force = B_TRUE;
893                         break;
894                 case 'F':
895                         hardforce = B_TRUE;
896                         break;
897                 case '?':
898                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
899                             optopt);
900                         usage(B_FALSE);
901                 }
902         }
903
904         argc -= optind;
905         argv += optind;
906
907         /* check arguments */
908         if (argc < 1) {
909                 (void) fprintf(stderr, gettext("missing pool argument\n"));
910                 usage(B_FALSE);
911         }
912
913         ret = 0;
914         for (i = 0; i < argc; i++) {
915                 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
916                         ret = 1;
917                         continue;
918                 }
919
920                 if (zpool_disable_datasets(zhp, force) != 0) {
921                         ret = 1;
922                         zpool_close(zhp);
923                         continue;
924                 }
925
926                 if (hardforce) {
927                         if (zpool_export_force(zhp) != 0)
928                                 ret = 1;
929                 } else if (zpool_export(zhp, force) != 0) {
930                         ret = 1;
931                 }
932
933                 zpool_close(zhp);
934         }
935
936         return (ret);
937 }
938
939 /*
940  * Given a vdev configuration, determine the maximum width needed for the device
941  * name column.
942  */
943 static int
944 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
945 {
946         char *name = zpool_vdev_name(g_zfs, zhp, nv);
947         nvlist_t **child;
948         uint_t c, children;
949         int ret;
950
951         if (strlen(name) + depth > max)
952                 max = strlen(name) + depth;
953
954         free(name);
955
956         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
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_L2CACHE,
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         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
973             &child, &children) == 0) {
974                 for (c = 0; c < children; c++)
975                         if ((ret = max_width(zhp, child[c], depth + 2,
976                             max)) > max)
977                                 max = ret;
978         }
979
980
981         return (max);
982 }
983
984
985 /*
986  * Print the configuration of an exported pool.  Iterate over all vdevs in the
987  * pool, printing out the name and status for each one.
988  */
989 void
990 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth,
991     boolean_t print_logs)
992 {
993         nvlist_t **child;
994         uint_t c, children;
995         vdev_stat_t *vs;
996         char *type, *vname;
997
998         verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
999         if (strcmp(type, VDEV_TYPE_MISSING) == 0)
1000                 return;
1001
1002         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
1003             (uint64_t **)&vs, &c) == 0);
1004
1005         (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1006         (void) printf("  %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1007
1008         if (vs->vs_aux != 0) {
1009                 (void) printf("  ");
1010
1011                 switch (vs->vs_aux) {
1012                 case VDEV_AUX_OPEN_FAILED:
1013                         (void) printf(gettext("cannot open"));
1014                         break;
1015
1016                 case VDEV_AUX_BAD_GUID_SUM:
1017                         (void) printf(gettext("missing device"));
1018                         break;
1019
1020                 case VDEV_AUX_NO_REPLICAS:
1021                         (void) printf(gettext("insufficient replicas"));
1022                         break;
1023
1024                 case VDEV_AUX_VERSION_NEWER:
1025                         (void) printf(gettext("newer version"));
1026                         break;
1027
1028                 case VDEV_AUX_ERR_EXCEEDED:
1029                         (void) printf(gettext("too many errors"));
1030                         break;
1031
1032                 default:
1033                         (void) printf(gettext("corrupted data"));
1034                         break;
1035                 }
1036         }
1037         (void) printf("\n");
1038
1039         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1040             &child, &children) != 0)
1041                 return;
1042
1043         for (c = 0; c < children; c++) {
1044                 uint64_t is_log = B_FALSE;
1045
1046                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1047                     &is_log);
1048                 if ((is_log && !print_logs) || (!is_log && print_logs))
1049                         continue;
1050
1051                 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1052                 print_import_config(vname, child[c],
1053                     namewidth, depth + 2, B_FALSE);
1054                 free(vname);
1055         }
1056
1057         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1058             &child, &children) == 0) {
1059                 (void) printf(gettext("\tcache\n"));
1060                 for (c = 0; c < children; c++) {
1061                         vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1062                         (void) printf("\t  %s\n", vname);
1063                         free(vname);
1064                 }
1065         }
1066
1067         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1068             &child, &children) == 0) {
1069                 (void) printf(gettext("\tspares\n"));
1070                 for (c = 0; c < children; c++) {
1071                         vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1072                         (void) printf("\t  %s\n", vname);
1073                         free(vname);
1074                 }
1075         }
1076 }
1077
1078 /*
1079  * Display the status for the given pool.
1080  */
1081 static void
1082 show_import(nvlist_t *config)
1083 {
1084         uint64_t pool_state;
1085         vdev_stat_t *vs;
1086         char *name;
1087         uint64_t guid;
1088         char *msgid;
1089         nvlist_t *nvroot;
1090         int reason;
1091         const char *health;
1092         uint_t vsc;
1093         int namewidth;
1094
1095         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1096             &name) == 0);
1097         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1098             &guid) == 0);
1099         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1100             &pool_state) == 0);
1101         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1102             &nvroot) == 0);
1103
1104         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
1105             (uint64_t **)&vs, &vsc) == 0);
1106         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1107
1108         reason = zpool_import_status(config, &msgid);
1109
1110         (void) printf(gettext("  pool: %s\n"), name);
1111         (void) printf(gettext("    id: %llu\n"), (u_longlong_t)guid);
1112         (void) printf(gettext(" state: %s"), health);
1113         if (pool_state == POOL_STATE_DESTROYED)
1114                 (void) printf(gettext(" (DESTROYED)"));
1115         (void) printf("\n");
1116
1117         switch (reason) {
1118         case ZPOOL_STATUS_MISSING_DEV_R:
1119         case ZPOOL_STATUS_MISSING_DEV_NR:
1120         case ZPOOL_STATUS_BAD_GUID_SUM:
1121                 (void) printf(gettext("status: One or more devices are missing "
1122                     "from the system.\n"));
1123                 break;
1124
1125         case ZPOOL_STATUS_CORRUPT_LABEL_R:
1126         case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1127                 (void) printf(gettext("status: One or more devices contains "
1128                     "corrupted data.\n"));
1129                 break;
1130
1131         case ZPOOL_STATUS_CORRUPT_DATA:
1132                 (void) printf(gettext("status: The pool data is corrupted.\n"));
1133                 break;
1134
1135         case ZPOOL_STATUS_OFFLINE_DEV:
1136                 (void) printf(gettext("status: One or more devices "
1137                     "are offlined.\n"));
1138                 break;
1139
1140         case ZPOOL_STATUS_CORRUPT_POOL:
1141                 (void) printf(gettext("status: The pool metadata is "
1142                     "corrupted.\n"));
1143                 break;
1144
1145         case ZPOOL_STATUS_VERSION_OLDER:
1146                 (void) printf(gettext("status: The pool is formatted using an "
1147                     "older on-disk version.\n"));
1148                 break;
1149
1150         case ZPOOL_STATUS_VERSION_NEWER:
1151                 (void) printf(gettext("status: The pool is formatted using an "
1152                     "incompatible version.\n"));
1153                 break;
1154
1155         case ZPOOL_STATUS_HOSTID_MISMATCH:
1156                 (void) printf(gettext("status: The pool was last accessed by "
1157                     "another system.\n"));
1158                 break;
1159
1160         case ZPOOL_STATUS_FAULTED_DEV_R:
1161         case ZPOOL_STATUS_FAULTED_DEV_NR:
1162                 (void) printf(gettext("status: One or more devices are "
1163                     "faulted.\n"));
1164                 break;
1165
1166         case ZPOOL_STATUS_BAD_LOG:
1167                 (void) printf(gettext("status: An intent log record cannot be "
1168                     "read.\n"));
1169                 break;
1170
1171         default:
1172                 /*
1173                  * No other status can be seen when importing pools.
1174                  */
1175                 assert(reason == ZPOOL_STATUS_OK);
1176         }
1177
1178         /*
1179          * Print out an action according to the overall state of the pool.
1180          */
1181         if (vs->vs_state == VDEV_STATE_HEALTHY) {
1182                 if (reason == ZPOOL_STATUS_VERSION_OLDER)
1183                         (void) printf(gettext("action: The pool can be "
1184                             "imported using its name or numeric identifier, "
1185                             "though\n\tsome features will not be available "
1186                             "without an explicit 'zpool upgrade'.\n"));
1187                 else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH)
1188                         (void) printf(gettext("action: The pool can be "
1189                             "imported using its name or numeric "
1190                             "identifier and\n\tthe '-f' flag.\n"));
1191                 else
1192                         (void) printf(gettext("action: The pool can be "
1193                             "imported using its name or numeric "
1194                             "identifier.\n"));
1195         } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1196                 (void) printf(gettext("action: The pool can be imported "
1197                     "despite missing or damaged devices.  The\n\tfault "
1198                     "tolerance of the pool may be compromised if imported.\n"));
1199         } else {
1200                 switch (reason) {
1201                 case ZPOOL_STATUS_VERSION_NEWER:
1202                         (void) printf(gettext("action: The pool cannot be "
1203                             "imported.  Access the pool on a system running "
1204                             "newer\n\tsoftware, or recreate the pool from "
1205                             "backup.\n"));
1206                         break;
1207                 case ZPOOL_STATUS_MISSING_DEV_R:
1208                 case ZPOOL_STATUS_MISSING_DEV_NR:
1209                 case ZPOOL_STATUS_BAD_GUID_SUM:
1210                         (void) printf(gettext("action: The pool cannot be "
1211                             "imported. Attach the missing\n\tdevices and try "
1212                             "again.\n"));
1213                         break;
1214                 default:
1215                         (void) printf(gettext("action: The pool cannot be "
1216                             "imported due to damaged devices or data.\n"));
1217                 }
1218         }
1219
1220         /*
1221          * If the state is "closed" or "can't open", and the aux state
1222          * is "corrupt data":
1223          */
1224         if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1225             (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1226             (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1227                 if (pool_state == POOL_STATE_DESTROYED)
1228                         (void) printf(gettext("\tThe pool was destroyed, "
1229                             "but can be imported using the '-Df' flags.\n"));
1230                 else if (pool_state != POOL_STATE_EXPORTED)
1231                         (void) printf(gettext("\tThe pool may be active on "
1232                             "another system, but can be imported using\n\t"
1233                             "the '-f' flag.\n"));
1234         }
1235
1236         if (msgid != NULL)
1237                 (void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
1238                     msgid);
1239
1240         (void) printf(gettext("config:\n\n"));
1241
1242         namewidth = max_width(NULL, nvroot, 0, 0);
1243         if (namewidth < 10)
1244                 namewidth = 10;
1245
1246         print_import_config(name, nvroot, namewidth, 0, B_FALSE);
1247         if (num_logs(nvroot) > 0) {
1248                 (void) printf(gettext("\tlogs\n"));
1249                 print_import_config(name, nvroot, namewidth, 0, B_TRUE);
1250         }
1251
1252         if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1253                 (void) printf(gettext("\n\tAdditional devices are known to "
1254                     "be part of this pool, though their\n\texact "
1255                     "configuration cannot be determined.\n"));
1256         }
1257 }
1258
1259 /*
1260  * Perform the import for the given configuration.  This passes the heavy
1261  * lifting off to zpool_import_props(), and then mounts the datasets contained
1262  * within the pool.
1263  */
1264 static int
1265 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1266     int force, nvlist_t *props, boolean_t allowfaulted)
1267 {
1268         zpool_handle_t *zhp;
1269         char *name;
1270         uint64_t state;
1271         uint64_t version;
1272         int error = 0;
1273
1274         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1275             &name) == 0);
1276
1277         verify(nvlist_lookup_uint64(config,
1278             ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1279         verify(nvlist_lookup_uint64(config,
1280             ZPOOL_CONFIG_VERSION, &version) == 0);
1281         if (version > SPA_VERSION) {
1282                 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1283                     "is formatted using a newer ZFS version\n"), name);
1284                 return (1);
1285         } else if (state != POOL_STATE_EXPORTED && !force) {
1286                 uint64_t hostid;
1287
1288                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
1289                     &hostid) == 0) {
1290                         if ((unsigned long)hostid != gethostid()) {
1291                                 char *hostname;
1292                                 uint64_t timestamp;
1293                                 time_t t;
1294
1295                                 verify(nvlist_lookup_string(config,
1296                                     ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
1297                                 verify(nvlist_lookup_uint64(config,
1298                                     ZPOOL_CONFIG_TIMESTAMP, &timestamp) == 0);
1299                                 t = timestamp;
1300                                 (void) fprintf(stderr, gettext("cannot import "
1301                                     "'%s': pool may be in use from other "
1302                                     "system, it was last accessed by %s "
1303                                     "(hostid: 0x%lx) on %s"), name, hostname,
1304                                     (unsigned long)hostid,
1305                                     asctime(localtime(&t)));
1306                                 (void) fprintf(stderr, gettext("use '-f' to "
1307                                     "import anyway\n"));
1308                                 return (1);
1309                         }
1310                 } else {
1311                         (void) fprintf(stderr, gettext("cannot import '%s': "
1312                             "pool may be in use from other system\n"), name);
1313                         (void) fprintf(stderr, gettext("use '-f' to import "
1314                             "anyway\n"));
1315                         return (1);
1316                 }
1317         }
1318
1319         if (zpool_import_props(g_zfs, config, newname, props,
1320             allowfaulted) != 0)
1321                 return (1);
1322
1323         if (newname != NULL)
1324                 name = (char *)newname;
1325
1326         verify((zhp = zpool_open_canfail(g_zfs, name)) != NULL);
1327
1328         if (zpool_enable_datasets(zhp, mntopts, 0) != 0) {
1329                 zpool_close(zhp);
1330                 return (1);
1331         }
1332
1333         zpool_close(zhp);
1334         return (error);
1335 }
1336
1337 /*
1338  * zpool import [-d dir] [-D]
1339  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1340  *              [-d dir | -c cachefile] [-f] -a
1341  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1342  *              [-d dir | -c cachefile] [-f] <pool | id> [newpool]
1343  *
1344  *       -c     Read pool information from a cachefile instead of searching
1345  *              devices.
1346  *
1347  *       -d     Scan in a specific directory, other than /dev/dsk.  More than
1348  *              one directory can be specified using multiple '-d' options.
1349  *
1350  *       -D     Scan for previously destroyed pools or import all or only
1351  *              specified destroyed pools.
1352  *
1353  *       -R     Temporarily import the pool, with all mountpoints relative to
1354  *              the given root.  The pool will remain exported when the machine
1355  *              is rebooted.
1356  *
1357  *       -f     Force import, even if it appears that the pool is active.
1358  *
1359  *       -F     Import even in the presence of faulted vdevs.  This is an
1360  *              intentionally undocumented option for testing purposes, and
1361  *              treats the pool configuration as complete, leaving any bad
1362  *              vdevs in the FAULTED state.
1363  *
1364  *       -a     Import all pools found.
1365  *
1366  *       -o     Set property=value and/or temporary mount options (without '=').
1367  *
1368  * The import command scans for pools to import, and import pools based on pool
1369  * name and GUID.  The pool can also be renamed as part of the import process.
1370  */
1371 int
1372 zpool_do_import(int argc, char **argv)
1373 {
1374         char **searchdirs = NULL;
1375         int nsearch = 0;
1376         int c;
1377         int err;
1378         nvlist_t *pools = NULL;
1379         boolean_t do_all = B_FALSE;
1380         boolean_t do_destroyed = B_FALSE;
1381         char *mntopts = NULL;
1382         boolean_t do_force = B_FALSE;
1383         nvpair_t *elem;
1384         nvlist_t *config;
1385         uint64_t searchguid = 0;
1386         char *searchname = NULL;
1387         char *propval;
1388         nvlist_t *found_config;
1389         nvlist_t *props = NULL;
1390         boolean_t first;
1391         boolean_t allow_faulted = B_FALSE;
1392         uint64_t pool_state;
1393         char *cachefile = NULL;
1394
1395         /* check options */
1396         while ((c = getopt(argc, argv, ":ac:d:DfFo:p:R:")) != -1) {
1397                 switch (c) {
1398                 case 'a':
1399                         do_all = B_TRUE;
1400                         break;
1401                 case 'c':
1402                         cachefile = optarg;
1403                         break;
1404                 case 'd':
1405                         if (searchdirs == NULL) {
1406                                 searchdirs = safe_malloc(sizeof (char *));
1407                         } else {
1408                                 char **tmp = safe_malloc((nsearch + 1) *
1409                                     sizeof (char *));
1410                                 bcopy(searchdirs, tmp, nsearch *
1411                                     sizeof (char *));
1412                                 free(searchdirs);
1413                                 searchdirs = tmp;
1414                         }
1415                         searchdirs[nsearch++] = optarg;
1416                         break;
1417                 case 'D':
1418                         do_destroyed = B_TRUE;
1419                         break;
1420                 case 'f':
1421                         do_force = B_TRUE;
1422                         break;
1423                 case 'F':
1424                         allow_faulted = B_TRUE;
1425                         break;
1426                 case 'o':
1427                         if ((propval = strchr(optarg, '=')) != NULL) {
1428                                 *propval = '\0';
1429                                 propval++;
1430                                 if (add_prop_list(optarg, propval,
1431                                     &props, B_TRUE))
1432                                         goto error;
1433                         } else {
1434                                 mntopts = optarg;
1435                         }
1436                         break;
1437                 case 'R':
1438                         if (add_prop_list(zpool_prop_to_name(
1439                             ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
1440                                 goto error;
1441                         if (nvlist_lookup_string(props,
1442                             zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
1443                             &propval) == 0)
1444                                 break;
1445                         if (add_prop_list(zpool_prop_to_name(
1446                             ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1447                                 goto error;
1448                         break;
1449                 case ':':
1450                         (void) fprintf(stderr, gettext("missing argument for "
1451                             "'%c' option\n"), optopt);
1452                         usage(B_FALSE);
1453                         break;
1454                 case '?':
1455                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1456                             optopt);
1457                         usage(B_FALSE);
1458                 }
1459         }
1460
1461         argc -= optind;
1462         argv += optind;
1463
1464         if (cachefile && nsearch != 0) {
1465                 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
1466                 usage(B_FALSE);
1467         }
1468
1469         if (searchdirs == NULL) {
1470                 searchdirs = safe_malloc(sizeof (char *));
1471                 searchdirs[0] = "/dev/dsk";
1472                 nsearch = 1;
1473         }
1474
1475         /* check argument count */
1476         if (do_all) {
1477                 if (argc != 0) {
1478                         (void) fprintf(stderr, gettext("too many arguments\n"));
1479                         usage(B_FALSE);
1480                 }
1481         } else {
1482                 if (argc > 2) {
1483                         (void) fprintf(stderr, gettext("too many arguments\n"));
1484                         usage(B_FALSE);
1485                 }
1486
1487                 /*
1488                  * Check for the SYS_CONFIG privilege.  We do this explicitly
1489                  * here because otherwise any attempt to discover pools will
1490                  * silently fail.
1491                  */
1492                 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
1493                         (void) fprintf(stderr, gettext("cannot "
1494                             "discover pools: permission denied\n"));
1495                         free(searchdirs);
1496                         return (1);
1497                 }
1498         }
1499
1500         /*
1501          * Depending on the arguments given, we do one of the following:
1502          *
1503          *      <none>  Iterate through all pools and display information about
1504          *              each one.
1505          *
1506          *      -a      Iterate through all pools and try to import each one.
1507          *
1508          *      <id>    Find the pool that corresponds to the given GUID/pool
1509          *              name and import that one.
1510          *
1511          *      -D      Above options applies only to destroyed pools.
1512          */
1513         if (argc != 0) {
1514                 char *endptr;
1515
1516                 errno = 0;
1517                 searchguid = strtoull(argv[0], &endptr, 10);
1518                 if (errno != 0 || *endptr != '\0')
1519                         searchname = argv[0];
1520                 found_config = NULL;
1521         }
1522
1523         if (cachefile) {
1524                 pools = zpool_find_import_cached(g_zfs, cachefile, searchname,
1525                     searchguid);
1526         } else if (searchname != NULL) {
1527                 pools = zpool_find_import_byname(g_zfs, nsearch, searchdirs,
1528                     searchname);
1529         } else {
1530                 /*
1531                  * It's OK to search by guid even if searchguid is 0.
1532                  */
1533                 pools = zpool_find_import_byguid(g_zfs, nsearch, searchdirs,
1534                     searchguid);
1535         }
1536
1537         if (pools == NULL) {
1538                 if (argc != 0) {
1539                         (void) fprintf(stderr, gettext("cannot import '%s': "
1540                             "no such pool available\n"), argv[0]);
1541                 }
1542                 free(searchdirs);
1543                 return (1);
1544         }
1545
1546         /*
1547          * At this point we have a list of import candidate configs. Even if
1548          * we were searching by pool name or guid, we still need to
1549          * post-process the list to deal with pool state and possible
1550          * duplicate names.
1551          */
1552         err = 0;
1553         elem = NULL;
1554         first = B_TRUE;
1555         while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
1556
1557                 verify(nvpair_value_nvlist(elem, &config) == 0);
1558
1559                 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1560                     &pool_state) == 0);
1561                 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
1562                         continue;
1563                 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
1564                         continue;
1565
1566                 if (argc == 0) {
1567                         if (first)
1568                                 first = B_FALSE;
1569                         else if (!do_all)
1570                                 (void) printf("\n");
1571
1572                         if (do_all)
1573                                 err |= do_import(config, NULL, mntopts,
1574                                     do_force, props, allow_faulted);
1575                         else
1576                                 show_import(config);
1577                 } else if (searchname != NULL) {
1578                         char *name;
1579
1580                         /*
1581                          * We are searching for a pool based on name.
1582                          */
1583                         verify(nvlist_lookup_string(config,
1584                             ZPOOL_CONFIG_POOL_NAME, &name) == 0);
1585
1586                         if (strcmp(name, searchname) == 0) {
1587                                 if (found_config != NULL) {
1588                                         (void) fprintf(stderr, gettext(
1589                                             "cannot import '%s': more than "
1590                                             "one matching pool\n"), searchname);
1591                                         (void) fprintf(stderr, gettext(
1592                                             "import by numeric ID instead\n"));
1593                                         err = B_TRUE;
1594                                 }
1595                                 found_config = config;
1596                         }
1597                 } else {
1598                         uint64_t guid;
1599
1600                         /*
1601                          * Search for a pool by guid.
1602                          */
1603                         verify(nvlist_lookup_uint64(config,
1604                             ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
1605
1606                         if (guid == searchguid)
1607                                 found_config = config;
1608                 }
1609         }
1610
1611         /*
1612          * If we were searching for a specific pool, verify that we found a
1613          * pool, and then do the import.
1614          */
1615         if (argc != 0 && err == 0) {
1616                 if (found_config == NULL) {
1617                         (void) fprintf(stderr, gettext("cannot import '%s': "
1618                             "no such pool available\n"), argv[0]);
1619                         err = B_TRUE;
1620                 } else {
1621                         err |= do_import(found_config, argc == 1 ? NULL :
1622                             argv[1], mntopts, do_force, props, allow_faulted);
1623                 }
1624         }
1625
1626         /*
1627          * If we were just looking for pools, report an error if none were
1628          * found.
1629          */
1630         if (argc == 0 && first)
1631                 (void) fprintf(stderr,
1632                     gettext("no pools available to import\n"));
1633
1634 error:
1635         nvlist_free(props);
1636         nvlist_free(pools);
1637         free(searchdirs);
1638
1639         return (err ? 1 : 0);
1640 }
1641
1642 typedef struct iostat_cbdata {
1643         zpool_list_t *cb_list;
1644         int cb_verbose;
1645         int cb_iteration;
1646         int cb_namewidth;
1647 } iostat_cbdata_t;
1648
1649 static void
1650 print_iostat_separator(iostat_cbdata_t *cb)
1651 {
1652         int i = 0;
1653
1654         for (i = 0; i < cb->cb_namewidth; i++)
1655                 (void) printf("-");
1656         (void) printf("  -----  -----  -----  -----  -----  -----\n");
1657 }
1658
1659 static void
1660 print_iostat_header(iostat_cbdata_t *cb)
1661 {
1662         (void) printf("%*s     capacity     operations    bandwidth\n",
1663             cb->cb_namewidth, "");
1664         (void) printf("%-*s   used  avail   read  write   read  write\n",
1665             cb->cb_namewidth, "pool");
1666         print_iostat_separator(cb);
1667 }
1668
1669 /*
1670  * Display a single statistic.
1671  */
1672 static void
1673 print_one_stat(uint64_t value)
1674 {
1675         char buf[64];
1676
1677         zfs_nicenum(value, buf, sizeof (buf));
1678         (void) printf("  %5s", buf);
1679 }
1680
1681 /*
1682  * Print out all the statistics for the given vdev.  This can either be the
1683  * toplevel configuration, or called recursively.  If 'name' is NULL, then this
1684  * is a verbose output, and we don't want to display the toplevel pool stats.
1685  */
1686 void
1687 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
1688     nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
1689 {
1690         nvlist_t **oldchild, **newchild;
1691         uint_t c, children;
1692         vdev_stat_t *oldvs, *newvs;
1693         vdev_stat_t zerovs = { 0 };
1694         uint64_t tdelta;
1695         double scale;
1696         char *vname;
1697
1698         if (oldnv != NULL) {
1699                 verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS,
1700                     (uint64_t **)&oldvs, &c) == 0);
1701         } else {
1702                 oldvs = &zerovs;
1703         }
1704
1705         verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS,
1706             (uint64_t **)&newvs, &c) == 0);
1707
1708         if (strlen(name) + depth > cb->cb_namewidth)
1709                 (void) printf("%*s%s", depth, "", name);
1710         else
1711                 (void) printf("%*s%s%*s", depth, "", name,
1712                     (int)(cb->cb_namewidth - strlen(name) - depth), "");
1713
1714         tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
1715
1716         if (tdelta == 0)
1717                 scale = 1.0;
1718         else
1719                 scale = (double)NANOSEC / tdelta;
1720
1721         /* only toplevel vdevs have capacity stats */
1722         if (newvs->vs_space == 0) {
1723                 (void) printf("      -      -");
1724         } else {
1725                 print_one_stat(newvs->vs_alloc);
1726                 print_one_stat(newvs->vs_space - newvs->vs_alloc);
1727         }
1728
1729         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
1730             oldvs->vs_ops[ZIO_TYPE_READ])));
1731
1732         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
1733             oldvs->vs_ops[ZIO_TYPE_WRITE])));
1734
1735         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
1736             oldvs->vs_bytes[ZIO_TYPE_READ])));
1737
1738         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
1739             oldvs->vs_bytes[ZIO_TYPE_WRITE])));
1740
1741         (void) printf("\n");
1742
1743         if (!cb->cb_verbose)
1744                 return;
1745
1746         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
1747             &newchild, &children) != 0)
1748                 return;
1749
1750         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
1751             &oldchild, &c) != 0)
1752                 return;
1753
1754         for (c = 0; c < children; c++) {
1755                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1756                 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1757                     newchild[c], cb, depth + 2);
1758                 free(vname);
1759         }
1760
1761         /*
1762          * Include level 2 ARC devices in iostat output
1763          */
1764         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
1765             &newchild, &children) != 0)
1766                 return;
1767
1768         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
1769             &oldchild, &c) != 0)
1770                 return;
1771
1772         if (children > 0) {
1773                 (void) printf("%-*s      -      -      -      -      -      "
1774                     "-\n", cb->cb_namewidth, "cache");
1775                 for (c = 0; c < children; c++) {
1776                         vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1777                         print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1778                             newchild[c], cb, depth + 2);
1779                         free(vname);
1780                 }
1781         }
1782 }
1783
1784 static int
1785 refresh_iostat(zpool_handle_t *zhp, void *data)
1786 {
1787         iostat_cbdata_t *cb = data;
1788         boolean_t missing;
1789
1790         /*
1791          * If the pool has disappeared, remove it from the list and continue.
1792          */
1793         if (zpool_refresh_stats(zhp, &missing) != 0)
1794                 return (-1);
1795
1796         if (missing)
1797                 pool_list_remove(cb->cb_list, zhp);
1798
1799         return (0);
1800 }
1801
1802 /*
1803  * Callback to print out the iostats for the given pool.
1804  */
1805 int
1806 print_iostat(zpool_handle_t *zhp, void *data)
1807 {
1808         iostat_cbdata_t *cb = data;
1809         nvlist_t *oldconfig, *newconfig;
1810         nvlist_t *oldnvroot, *newnvroot;
1811
1812         newconfig = zpool_get_config(zhp, &oldconfig);
1813
1814         if (cb->cb_iteration == 1)
1815                 oldconfig = NULL;
1816
1817         verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
1818             &newnvroot) == 0);
1819
1820         if (oldconfig == NULL)
1821                 oldnvroot = NULL;
1822         else
1823                 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
1824                     &oldnvroot) == 0);
1825
1826         /*
1827          * Print out the statistics for the pool.
1828          */
1829         print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
1830
1831         if (cb->cb_verbose)
1832                 print_iostat_separator(cb);
1833
1834         return (0);
1835 }
1836
1837 int
1838 get_namewidth(zpool_handle_t *zhp, void *data)
1839 {
1840         iostat_cbdata_t *cb = data;
1841         nvlist_t *config, *nvroot;
1842
1843         if ((config = zpool_get_config(zhp, NULL)) != NULL) {
1844                 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1845                     &nvroot) == 0);
1846                 if (!cb->cb_verbose)
1847                         cb->cb_namewidth = strlen(zpool_get_name(zhp));
1848                 else
1849                         cb->cb_namewidth = max_width(zhp, nvroot, 0, 0);
1850         }
1851
1852         /*
1853          * The width must fall into the range [10,38].  The upper limit is the
1854          * maximum we can have and still fit in 80 columns.
1855          */
1856         if (cb->cb_namewidth < 10)
1857                 cb->cb_namewidth = 10;
1858         if (cb->cb_namewidth > 38)
1859                 cb->cb_namewidth = 38;
1860
1861         return (0);
1862 }
1863
1864 /*
1865  * zpool iostat [-v] [pool] ... [interval [count]]
1866  *
1867  *      -v      Display statistics for individual vdevs
1868  *
1869  * This command can be tricky because we want to be able to deal with pool
1870  * creation/destruction as well as vdev configuration changes.  The bulk of this
1871  * processing is handled by the pool_list_* routines in zpool_iter.c.  We rely
1872  * on pool_list_update() to detect the addition of new pools.  Configuration
1873  * changes are all handled within libzfs.
1874  */
1875 int
1876 zpool_do_iostat(int argc, char **argv)
1877 {
1878         int c;
1879         int ret;
1880         int npools;
1881         unsigned long interval = 0, count = 0;
1882         zpool_list_t *list;
1883         boolean_t verbose = B_FALSE;
1884         iostat_cbdata_t cb;
1885
1886         /* check options */
1887         while ((c = getopt(argc, argv, "v")) != -1) {
1888                 switch (c) {
1889                 case 'v':
1890                         verbose = B_TRUE;
1891                         break;
1892                 case '?':
1893                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1894                             optopt);
1895                         usage(B_FALSE);
1896                 }
1897         }
1898
1899         argc -= optind;
1900         argv += optind;
1901
1902         /*
1903          * Determine if the last argument is an integer or a pool name
1904          */
1905         if (argc > 0 && isdigit(argv[argc - 1][0])) {
1906                 char *end;
1907
1908                 errno = 0;
1909                 interval = strtoul(argv[argc - 1], &end, 10);
1910
1911                 if (*end == '\0' && errno == 0) {
1912                         if (interval == 0) {
1913                                 (void) fprintf(stderr, gettext("interval "
1914                                     "cannot be zero\n"));
1915                                 usage(B_FALSE);
1916                         }
1917
1918                         /*
1919                          * Ignore the last parameter
1920                          */
1921                         argc--;
1922                 } else {
1923                         /*
1924                          * If this is not a valid number, just plow on.  The
1925                          * user will get a more informative error message later
1926                          * on.
1927                          */
1928                         interval = 0;
1929                 }
1930         }
1931
1932         /*
1933          * If the last argument is also an integer, then we have both a count
1934          * and an integer.
1935          */
1936         if (argc > 0 && isdigit(argv[argc - 1][0])) {
1937                 char *end;
1938
1939                 errno = 0;
1940                 count = interval;
1941                 interval = strtoul(argv[argc - 1], &end, 10);
1942
1943                 if (*end == '\0' && errno == 0) {
1944                         if (interval == 0) {
1945                                 (void) fprintf(stderr, gettext("interval "
1946                                     "cannot be zero\n"));
1947                                 usage(B_FALSE);
1948                         }
1949
1950                         /*
1951                          * Ignore the last parameter
1952                          */
1953                         argc--;
1954                 } else {
1955                         interval = 0;
1956                 }
1957         }
1958
1959         /*
1960          * Construct the list of all interesting pools.
1961          */
1962         ret = 0;
1963         if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
1964                 return (1);
1965
1966         if (pool_list_count(list) == 0 && argc != 0) {
1967                 pool_list_free(list);
1968                 return (1);
1969         }
1970
1971         if (pool_list_count(list) == 0 && interval == 0) {
1972                 pool_list_free(list);
1973                 (void) fprintf(stderr, gettext("no pools available\n"));
1974                 return (1);
1975         }
1976
1977         /*
1978          * Enter the main iostat loop.
1979          */
1980         cb.cb_list = list;
1981         cb.cb_verbose = verbose;
1982         cb.cb_iteration = 0;
1983         cb.cb_namewidth = 0;
1984
1985         for (;;) {
1986                 pool_list_update(list);
1987
1988                 if ((npools = pool_list_count(list)) == 0)
1989                         break;
1990
1991                 /*
1992                  * Refresh all statistics.  This is done as an explicit step
1993                  * before calculating the maximum name width, so that any
1994                  * configuration changes are properly accounted for.
1995                  */
1996                 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
1997
1998                 /*
1999                  * Iterate over all pools to determine the maximum width
2000                  * for the pool / device name column across all pools.
2001                  */
2002                 cb.cb_namewidth = 0;
2003                 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2004
2005                 /*
2006                  * If it's the first time, or verbose mode, print the header.
2007                  */
2008                 if (++cb.cb_iteration == 1 || verbose)
2009                         print_iostat_header(&cb);
2010
2011                 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
2012
2013                 /*
2014                  * If there's more than one pool, and we're not in verbose mode
2015                  * (which prints a separator for us), then print a separator.
2016                  */
2017                 if (npools > 1 && !verbose)
2018                         print_iostat_separator(&cb);
2019
2020                 if (verbose)
2021                         (void) printf("\n");
2022
2023                 /*
2024                  * Flush the output so that redirection to a file isn't buffered
2025                  * indefinitely.
2026                  */
2027                 (void) fflush(stdout);
2028
2029                 if (interval == 0)
2030                         break;
2031
2032                 if (count != 0 && --count == 0)
2033                         break;
2034
2035                 (void) sleep(interval);
2036         }
2037
2038         pool_list_free(list);
2039
2040         return (ret);
2041 }
2042
2043 typedef struct list_cbdata {
2044         boolean_t       cb_scripted;
2045         boolean_t       cb_first;
2046         zprop_list_t    *cb_proplist;
2047 } list_cbdata_t;
2048
2049 /*
2050  * Given a list of columns to display, output appropriate headers for each one.
2051  */
2052 static void
2053 print_header(zprop_list_t *pl)
2054 {
2055         const char *header;
2056         boolean_t first = B_TRUE;
2057         boolean_t right_justify;
2058
2059         for (; pl != NULL; pl = pl->pl_next) {
2060                 if (pl->pl_prop == ZPROP_INVAL)
2061                         continue;
2062
2063                 if (!first)
2064                         (void) printf("  ");
2065                 else
2066                         first = B_FALSE;
2067
2068                 header = zpool_prop_column_name(pl->pl_prop);
2069                 right_justify = zpool_prop_align_right(pl->pl_prop);
2070
2071                 if (pl->pl_next == NULL && !right_justify)
2072                         (void) printf("%s", header);
2073                 else if (right_justify)
2074                         (void) printf("%*s", pl->pl_width, header);
2075                 else
2076                         (void) printf("%-*s", pl->pl_width, header);
2077         }
2078
2079         (void) printf("\n");
2080 }
2081
2082 /*
2083  * Given a pool and a list of properties, print out all the properties according
2084  * to the described layout.
2085  */
2086 static void
2087 print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
2088 {
2089         boolean_t first = B_TRUE;
2090         char property[ZPOOL_MAXPROPLEN];
2091         char *propstr;
2092         boolean_t right_justify;
2093         int width;
2094
2095         for (; pl != NULL; pl = pl->pl_next) {
2096                 if (!first) {
2097                         if (scripted)
2098                                 (void) printf("\t");
2099                         else
2100                                 (void) printf("  ");
2101                 } else {
2102                         first = B_FALSE;
2103                 }
2104
2105                 right_justify = B_FALSE;
2106                 if (pl->pl_prop != ZPROP_INVAL) {
2107                         if (zpool_get_prop(zhp, pl->pl_prop, property,
2108                             sizeof (property), NULL) != 0)
2109                                 propstr = "-";
2110                         else
2111                                 propstr = property;
2112
2113                         right_justify = zpool_prop_align_right(pl->pl_prop);
2114                 } else {
2115                         propstr = "-";
2116                 }
2117
2118                 width = pl->pl_width;
2119
2120                 /*
2121                  * If this is being called in scripted mode, or if this is the
2122                  * last column and it is left-justified, don't include a width
2123                  * format specifier.
2124                  */
2125                 if (scripted || (pl->pl_next == NULL && !right_justify))
2126                         (void) printf("%s", propstr);
2127                 else if (right_justify)
2128                         (void) printf("%*s", width, propstr);
2129                 else
2130                         (void) printf("%-*s", width, propstr);
2131         }
2132
2133         (void) printf("\n");
2134 }
2135
2136 /*
2137  * Generic callback function to list a pool.
2138  */
2139 int
2140 list_callback(zpool_handle_t *zhp, void *data)
2141 {
2142         list_cbdata_t *cbp = data;
2143
2144         if (cbp->cb_first) {
2145                 if (!cbp->cb_scripted)
2146                         print_header(cbp->cb_proplist);
2147                 cbp->cb_first = B_FALSE;
2148         }
2149
2150         print_pool(zhp, cbp->cb_proplist, cbp->cb_scripted);
2151
2152         return (0);
2153 }
2154
2155 /*
2156  * zpool list [-H] [-o prop[,prop]*] [pool] ...
2157  *
2158  *      -H      Scripted mode.  Don't display headers, and separate properties
2159  *              by a single tab.
2160  *      -o      List of properties to display.  Defaults to
2161  *              "name,size,used,available,capacity,health,altroot"
2162  *
2163  * List all pools in the system, whether or not they're healthy.  Output space
2164  * statistics for each one, as well as health status summary.
2165  */
2166 int
2167 zpool_do_list(int argc, char **argv)
2168 {
2169         int c;
2170         int ret;
2171         list_cbdata_t cb = { 0 };
2172         static char default_props[] =
2173             "name,size,used,available,capacity,health,altroot";
2174         char *props = default_props;
2175
2176         /* check options */
2177         while ((c = getopt(argc, argv, ":Ho:")) != -1) {
2178                 switch (c) {
2179                 case 'H':
2180                         cb.cb_scripted = B_TRUE;
2181                         break;
2182                 case 'o':
2183                         props = optarg;
2184                         break;
2185                 case ':':
2186                         (void) fprintf(stderr, gettext("missing argument for "
2187                             "'%c' option\n"), optopt);
2188                         usage(B_FALSE);
2189                         break;
2190                 case '?':
2191                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2192                             optopt);
2193                         usage(B_FALSE);
2194                 }
2195         }
2196
2197         argc -= optind;
2198         argv += optind;
2199
2200         if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
2201                 usage(B_FALSE);
2202
2203         cb.cb_first = B_TRUE;
2204
2205         ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
2206             list_callback, &cb);
2207
2208         zprop_free_list(cb.cb_proplist);
2209
2210         if (argc == 0 && cb.cb_first && !cb.cb_scripted) {
2211                 (void) printf(gettext("no pools available\n"));
2212                 return (0);
2213         }
2214
2215         return (ret);
2216 }
2217
2218 static nvlist_t *
2219 zpool_get_vdev_by_name(nvlist_t *nv, char *name)
2220 {
2221         nvlist_t **child;
2222         uint_t c, children;
2223         nvlist_t *match;
2224         char *path;
2225
2226         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2227             &child, &children) != 0) {
2228                 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2229                 if (strncmp(name, _PATH_DEV, sizeof(_PATH_DEV)-1) == 0)
2230                         name += sizeof(_PATH_DEV)-1;
2231                 if (strncmp(path, _PATH_DEV, sizeof(_PATH_DEV)-1) == 0)
2232                         path += sizeof(_PATH_DEV)-1;
2233                 if (strcmp(name, path) == 0)
2234                         return (nv);
2235                 return (NULL);
2236         }
2237
2238         for (c = 0; c < children; c++)
2239                 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL)
2240                         return (match);
2241
2242         return (NULL);
2243 }
2244
2245 static int
2246 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
2247 {
2248         boolean_t force = B_FALSE;
2249         int c;
2250         nvlist_t *nvroot;
2251         char *poolname, *old_disk, *new_disk;
2252         zpool_handle_t *zhp;
2253         int ret;
2254
2255         /* check options */
2256         while ((c = getopt(argc, argv, "f")) != -1) {
2257                 switch (c) {
2258                 case 'f':
2259                         force = B_TRUE;
2260                         break;
2261                 case '?':
2262                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2263                             optopt);
2264                         usage(B_FALSE);
2265                 }
2266         }
2267
2268         argc -= optind;
2269         argv += optind;
2270
2271         /* get pool name and check number of arguments */
2272         if (argc < 1) {
2273                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2274                 usage(B_FALSE);
2275         }
2276
2277         poolname = argv[0];
2278
2279         if (argc < 2) {
2280                 (void) fprintf(stderr,
2281                     gettext("missing <device> specification\n"));
2282                 usage(B_FALSE);
2283         }
2284
2285         old_disk = argv[1];
2286
2287         if (argc < 3) {
2288                 if (!replacing) {
2289                         (void) fprintf(stderr,
2290                             gettext("missing <new_device> specification\n"));
2291                         usage(B_FALSE);
2292                 }
2293                 new_disk = old_disk;
2294                 argc -= 1;
2295                 argv += 1;
2296         } else {
2297                 new_disk = argv[2];
2298                 argc -= 2;
2299                 argv += 2;
2300         }
2301
2302         if (argc > 1) {
2303                 (void) fprintf(stderr, gettext("too many arguments\n"));
2304                 usage(B_FALSE);
2305         }
2306
2307         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2308                 return (1);
2309
2310         if (zpool_get_config(zhp, NULL) == NULL) {
2311                 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
2312                     poolname);
2313                 zpool_close(zhp);
2314                 return (1);
2315         }
2316
2317         nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
2318             argc, argv);
2319         if (nvroot == NULL) {
2320                 zpool_close(zhp);
2321                 return (1);
2322         }
2323
2324         ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
2325
2326         nvlist_free(nvroot);
2327         zpool_close(zhp);
2328
2329         return (ret);
2330 }
2331
2332 /*
2333  * zpool replace [-f] <pool> <device> <new_device>
2334  *
2335  *      -f      Force attach, even if <new_device> appears to be in use.
2336  *
2337  * Replace <device> with <new_device>.
2338  */
2339 /* ARGSUSED */
2340 int
2341 zpool_do_replace(int argc, char **argv)
2342 {
2343         return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
2344 }
2345
2346 /*
2347  * zpool attach [-f] <pool> <device> <new_device>
2348  *
2349  *      -f      Force attach, even if <new_device> appears to be in use.
2350  *
2351  * Attach <new_device> to the mirror containing <device>.  If <device> is not
2352  * part of a mirror, then <device> will be transformed into a mirror of
2353  * <device> and <new_device>.  In either case, <new_device> will begin life
2354  * with a DTL of [0, now], and will immediately begin to resilver itself.
2355  */
2356 int
2357 zpool_do_attach(int argc, char **argv)
2358 {
2359         return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
2360 }
2361
2362 /*
2363  * zpool detach [-f] <pool> <device>
2364  *
2365  *      -f      Force detach of <device>, even if DTLs argue against it
2366  *              (not supported yet)
2367  *
2368  * Detach a device from a mirror.  The operation will be refused if <device>
2369  * is the last device in the mirror, or if the DTLs indicate that this device
2370  * has the only valid copy of some data.
2371  */
2372 /* ARGSUSED */
2373 int
2374 zpool_do_detach(int argc, char **argv)
2375 {
2376         int c;
2377         char *poolname, *path;
2378         zpool_handle_t *zhp;
2379         int ret;
2380
2381         /* check options */
2382         while ((c = getopt(argc, argv, "f")) != -1) {
2383                 switch (c) {
2384                 case 'f':
2385                 case '?':
2386                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2387                             optopt);
2388                         usage(B_FALSE);
2389                 }
2390         }
2391
2392         argc -= optind;
2393         argv += optind;
2394
2395         /* get pool name and check number of arguments */
2396         if (argc < 1) {
2397                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2398                 usage(B_FALSE);
2399         }
2400
2401         if (argc < 2) {
2402                 (void) fprintf(stderr,
2403                     gettext("missing <device> specification\n"));
2404                 usage(B_FALSE);
2405         }
2406
2407         poolname = argv[0];
2408         path = argv[1];
2409
2410         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2411                 return (1);
2412
2413         ret = zpool_vdev_detach(zhp, path);
2414
2415         zpool_close(zhp);
2416
2417         return (ret);
2418 }
2419
2420 /*
2421  * zpool online <pool> <device> ...
2422  */
2423 int
2424 zpool_do_online(int argc, char **argv)
2425 {
2426         int c, i;
2427         char *poolname;
2428         zpool_handle_t *zhp;
2429         int ret = 0;
2430         vdev_state_t newstate;
2431
2432         /* check options */
2433         while ((c = getopt(argc, argv, "t")) != -1) {
2434                 switch (c) {
2435                 case 't':
2436                 case '?':
2437                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2438                             optopt);
2439                         usage(B_FALSE);
2440                 }
2441         }
2442
2443         argc -= optind;
2444         argv += optind;
2445
2446         /* get pool name and check number of arguments */
2447         if (argc < 1) {
2448                 (void) fprintf(stderr, gettext("missing pool name\n"));
2449                 usage(B_FALSE);
2450         }
2451         if (argc < 2) {
2452                 (void) fprintf(stderr, gettext("missing device name\n"));
2453                 usage(B_FALSE);
2454         }
2455
2456         poolname = argv[0];
2457
2458         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2459                 return (1);
2460
2461         for (i = 1; i < argc; i++) {
2462                 if (zpool_vdev_online(zhp, argv[i], 0, &newstate) == 0) {
2463                         if (newstate != VDEV_STATE_HEALTHY) {
2464                                 (void) printf(gettext("warning: device '%s' "
2465                                     "onlined, but remains in faulted state\n"),
2466                                     argv[i]);
2467                                 if (newstate == VDEV_STATE_FAULTED)
2468                                         (void) printf(gettext("use 'zpool "
2469                                             "clear' to restore a faulted "
2470                                             "device\n"));
2471                                 else
2472                                         (void) printf(gettext("use 'zpool "
2473                                             "replace' to replace devices "
2474                                             "that are no longer present\n"));
2475                         }
2476                 } else {
2477                         ret = 1;
2478                 }
2479         }
2480
2481         zpool_close(zhp);
2482
2483         return (ret);
2484 }
2485
2486 /*
2487  * zpool offline [-ft] <pool> <device> ...
2488  *
2489  *      -f      Force the device into the offline state, even if doing
2490  *              so would appear to compromise pool availability.
2491  *              (not supported yet)
2492  *
2493  *      -t      Only take the device off-line temporarily.  The offline
2494  *              state will not be persistent across reboots.
2495  */
2496 /* ARGSUSED */
2497 int
2498 zpool_do_offline(int argc, char **argv)
2499 {
2500         int c, i;
2501         char *poolname;
2502         zpool_handle_t *zhp;
2503         int ret = 0;
2504         boolean_t istmp = B_FALSE;
2505
2506         /* check options */
2507         while ((c = getopt(argc, argv, "ft")) != -1) {
2508                 switch (c) {
2509                 case 't':
2510                         istmp = B_TRUE;
2511                         break;
2512                 case 'f':
2513                 case '?':
2514                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2515                             optopt);
2516                         usage(B_FALSE);
2517                 }
2518         }
2519
2520         argc -= optind;
2521         argv += optind;
2522
2523         /* get pool name and check number of arguments */
2524         if (argc < 1) {
2525                 (void) fprintf(stderr, gettext("missing pool name\n"));
2526                 usage(B_FALSE);
2527         }
2528         if (argc < 2) {
2529                 (void) fprintf(stderr, gettext("missing device name\n"));
2530                 usage(B_FALSE);
2531         }
2532
2533         poolname = argv[0];
2534
2535         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2536                 return (1);
2537
2538         for (i = 1; i < argc; i++) {
2539                 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
2540                         ret = 1;
2541         }
2542
2543         zpool_close(zhp);
2544
2545         return (ret);
2546 }
2547
2548 /*
2549  * zpool clear <pool> [device]
2550  *
2551  * Clear all errors associated with a pool or a particular device.
2552  */
2553 int
2554 zpool_do_clear(int argc, char **argv)
2555 {
2556         int ret = 0;
2557         zpool_handle_t *zhp;
2558         char *pool, *device;
2559
2560         if (argc < 2) {
2561                 (void) fprintf(stderr, gettext("missing pool name\n"));
2562                 usage(B_FALSE);
2563         }
2564
2565         if (argc > 3) {
2566                 (void) fprintf(stderr, gettext("too many arguments\n"));
2567                 usage(B_FALSE);
2568         }
2569
2570         pool = argv[1];
2571         device = argc == 3 ? argv[2] : NULL;
2572
2573         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
2574                 return (1);
2575
2576         if (zpool_clear(zhp, device) != 0)
2577                 ret = 1;
2578
2579         zpool_close(zhp);
2580
2581         return (ret);
2582 }
2583
2584 typedef struct scrub_cbdata {
2585         int     cb_type;
2586         int     cb_argc;
2587         char    **cb_argv;
2588 } scrub_cbdata_t;
2589
2590 int
2591 scrub_callback(zpool_handle_t *zhp, void *data)
2592 {
2593         scrub_cbdata_t *cb = data;
2594         int err;
2595
2596         /*
2597          * Ignore faulted pools.
2598          */
2599         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
2600                 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
2601                     "currently unavailable\n"), zpool_get_name(zhp));
2602                 return (1);
2603         }
2604
2605         err = zpool_scrub(zhp, cb->cb_type);
2606
2607         return (err != 0);
2608 }
2609
2610 /*
2611  * zpool scrub [-s] <pool> ...
2612  *
2613  *      -s      Stop.  Stops any in-progress scrub.
2614  */
2615 int
2616 zpool_do_scrub(int argc, char **argv)
2617 {
2618         int c;
2619         scrub_cbdata_t cb;
2620
2621         cb.cb_type = POOL_SCRUB_EVERYTHING;
2622
2623         /* check options */
2624         while ((c = getopt(argc, argv, "s")) != -1) {
2625                 switch (c) {
2626                 case 's':
2627                         cb.cb_type = POOL_SCRUB_NONE;
2628                         break;
2629                 case '?':
2630                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2631                             optopt);
2632                         usage(B_FALSE);
2633                 }
2634         }
2635
2636         cb.cb_argc = argc;
2637         cb.cb_argv = argv;
2638         argc -= optind;
2639         argv += optind;
2640
2641         if (argc < 1) {
2642                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2643                 usage(B_FALSE);
2644         }
2645
2646         return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
2647 }
2648
2649 typedef struct status_cbdata {
2650         int             cb_count;
2651         boolean_t       cb_allpools;
2652         boolean_t       cb_verbose;
2653         boolean_t       cb_explain;
2654         boolean_t       cb_first;
2655 } status_cbdata_t;
2656
2657 /*
2658  * Print out detailed scrub status.
2659  */
2660 void
2661 print_scrub_status(nvlist_t *nvroot)
2662 {
2663         vdev_stat_t *vs;
2664         uint_t vsc;
2665         time_t start, end, now;
2666         double fraction_done;
2667         uint64_t examined, total, minutes_left, minutes_taken;
2668         char *scrub_type;
2669
2670         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
2671             (uint64_t **)&vs, &vsc) == 0);
2672
2673         /*
2674          * If there's never been a scrub, there's not much to say.
2675          */
2676         if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) {
2677                 (void) printf(gettext("none requested\n"));
2678                 return;
2679         }
2680
2681         scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2682             "resilver" : "scrub";
2683
2684         start = vs->vs_scrub_start;
2685         end = vs->vs_scrub_end;
2686         now = time(NULL);
2687         examined = vs->vs_scrub_examined;
2688         total = vs->vs_alloc;
2689
2690         if (end != 0) {
2691                 minutes_taken = (uint64_t)((end - start) / 60);
2692
2693                 (void) printf(gettext("%s %s after %lluh%um with %llu errors "
2694                     "on %s"),
2695                     scrub_type, vs->vs_scrub_complete ? "completed" : "stopped",
2696                     (u_longlong_t)(minutes_taken / 60),
2697                     (uint_t)(minutes_taken % 60),
2698                     (u_longlong_t)vs->vs_scrub_errors, ctime(&end));
2699                 return;
2700         }
2701
2702         if (examined == 0)
2703                 examined = 1;
2704         if (examined > total)
2705                 total = examined;
2706
2707         fraction_done = (double)examined / total;
2708         minutes_left = (uint64_t)((now - start) *
2709             (1 - fraction_done) / fraction_done / 60);
2710         minutes_taken = (uint64_t)((now - start) / 60);
2711
2712         (void) printf(gettext("%s in progress for %lluh%um, %.2f%% done, "
2713             "%lluh%um to go\n"),
2714             scrub_type, (u_longlong_t)(minutes_taken / 60),
2715             (uint_t)(minutes_taken % 60), 100 * fraction_done,
2716             (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60));
2717 }
2718
2719 typedef struct spare_cbdata {
2720         uint64_t        cb_guid;
2721         zpool_handle_t  *cb_zhp;
2722 } spare_cbdata_t;
2723
2724 static boolean_t
2725 find_vdev(nvlist_t *nv, uint64_t search)
2726 {
2727         uint64_t guid;
2728         nvlist_t **child;
2729         uint_t c, children;
2730
2731         if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
2732             search == guid)
2733                 return (B_TRUE);
2734
2735         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2736             &child, &children) == 0) {
2737                 for (c = 0; c < children; c++)
2738                         if (find_vdev(child[c], search))
2739                                 return (B_TRUE);
2740         }
2741
2742         return (B_FALSE);
2743 }
2744
2745 static int
2746 find_spare(zpool_handle_t *zhp, void *data)
2747 {
2748         spare_cbdata_t *cbp = data;
2749         nvlist_t *config, *nvroot;
2750
2751         config = zpool_get_config(zhp, NULL);
2752         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2753             &nvroot) == 0);
2754
2755         if (find_vdev(nvroot, cbp->cb_guid)) {
2756                 cbp->cb_zhp = zhp;
2757                 return (1);
2758         }
2759
2760         zpool_close(zhp);
2761         return (0);
2762 }
2763
2764 /*
2765  * Print out configuration state as requested by status_callback.
2766  */
2767 void
2768 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
2769     int namewidth, int depth, boolean_t isspare, boolean_t print_logs)
2770 {
2771         nvlist_t **child;
2772         uint_t c, children;
2773         vdev_stat_t *vs;
2774         char rbuf[6], wbuf[6], cbuf[6], repaired[7];
2775         char *vname;
2776         uint64_t notpresent;
2777         spare_cbdata_t cb;
2778         char *state;
2779
2780         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
2781             (uint64_t **)&vs, &c) == 0);
2782
2783         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2784             &child, &children) != 0)
2785                 children = 0;
2786
2787         state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
2788         if (isspare) {
2789                 /*
2790                  * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
2791                  * online drives.
2792                  */
2793                 if (vs->vs_aux == VDEV_AUX_SPARED)
2794                         state = "INUSE";
2795                 else if (vs->vs_state == VDEV_STATE_HEALTHY)
2796                         state = "AVAIL";
2797         }
2798
2799         (void) printf("\t%*s%-*s  %-8s", depth, "", namewidth - depth,
2800             name, state);
2801
2802         if (!isspare) {
2803                 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
2804                 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
2805                 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
2806                 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
2807         }
2808
2809         if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
2810             &notpresent) == 0) {
2811                 char *path;
2812                 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2813                 (void) printf("  was %s", path);
2814         } else if (vs->vs_aux != 0) {
2815                 (void) printf("  ");
2816
2817                 switch (vs->vs_aux) {
2818                 case VDEV_AUX_OPEN_FAILED:
2819                         (void) printf(gettext("cannot open"));
2820                         break;
2821
2822                 case VDEV_AUX_BAD_GUID_SUM:
2823                         (void) printf(gettext("missing device"));
2824                         break;
2825
2826                 case VDEV_AUX_NO_REPLICAS:
2827                         (void) printf(gettext("insufficient replicas"));
2828                         break;
2829
2830                 case VDEV_AUX_VERSION_NEWER:
2831                         (void) printf(gettext("newer version"));
2832                         break;
2833
2834                 case VDEV_AUX_SPARED:
2835                         verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
2836                             &cb.cb_guid) == 0);
2837                         if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
2838                                 if (strcmp(zpool_get_name(cb.cb_zhp),
2839                                     zpool_get_name(zhp)) == 0)
2840                                         (void) printf(gettext("currently in "
2841                                             "use"));
2842                                 else
2843                                         (void) printf(gettext("in use by "
2844                                             "pool '%s'"),
2845                                             zpool_get_name(cb.cb_zhp));
2846                                 zpool_close(cb.cb_zhp);
2847                         } else {
2848                                 (void) printf(gettext("currently in use"));
2849                         }
2850                         break;
2851
2852                 case VDEV_AUX_ERR_EXCEEDED:
2853                         (void) printf(gettext("too many errors"));
2854                         break;
2855
2856                 case VDEV_AUX_IO_FAILURE:
2857                         (void) printf(gettext("experienced I/O failures"));
2858                         break;
2859
2860                 case VDEV_AUX_BAD_LOG:
2861                         (void) printf(gettext("bad intent log"));
2862                         break;
2863
2864                 default:
2865                         (void) printf(gettext("corrupted data"));
2866                         break;
2867                 }
2868         } else if (vs->vs_scrub_repaired != 0 && children == 0) {
2869                 /*
2870                  * Report bytes resilvered/repaired on leaf devices.
2871                  */
2872                 zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired));
2873                 (void) printf(gettext("  %s %s"), repaired,
2874                     (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2875                     "resilvered" : "repaired");
2876         }
2877
2878         (void) printf("\n");
2879
2880         for (c = 0; c < children; c++) {
2881                 uint64_t is_log = B_FALSE;
2882
2883                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2884                     &is_log);
2885                 if ((is_log && !print_logs) || (!is_log && print_logs))
2886                         continue;
2887                 vname = zpool_vdev_name(g_zfs, zhp, child[c]);
2888                 print_status_config(zhp, vname, child[c],
2889                     namewidth, depth + 2, isspare, B_FALSE);
2890                 free(vname);
2891         }
2892 }
2893
2894 static void
2895 print_error_log(zpool_handle_t *zhp)
2896 {
2897         nvlist_t *nverrlist = NULL;
2898         nvpair_t *elem;
2899         char *pathname;
2900         size_t len = MAXPATHLEN * 2;
2901
2902         if (zpool_get_errlog(zhp, &nverrlist) != 0) {
2903                 (void) printf("errors: List of errors unavailable "
2904                     "(insufficient privileges)\n");
2905                 return;
2906         }
2907
2908         (void) printf("errors: Permanent errors have been "
2909             "detected in the following files:\n\n");
2910
2911         pathname = safe_malloc(len);
2912         elem = NULL;
2913         while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
2914                 nvlist_t *nv;
2915                 uint64_t dsobj, obj;
2916
2917                 verify(nvpair_value_nvlist(elem, &nv) == 0);
2918                 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
2919                     &dsobj) == 0);
2920                 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
2921                     &obj) == 0);
2922                 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
2923                 (void) printf("%7s %s\n", "", pathname);
2924         }
2925         free(pathname);
2926         nvlist_free(nverrlist);
2927 }
2928
2929 static void
2930 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
2931     int namewidth)
2932 {
2933         uint_t i;
2934         char *name;
2935
2936         if (nspares == 0)
2937                 return;
2938
2939         (void) printf(gettext("\tspares\n"));
2940
2941         for (i = 0; i < nspares; i++) {
2942                 name = zpool_vdev_name(g_zfs, zhp, spares[i]);
2943                 print_status_config(zhp, name, spares[i],
2944                     namewidth, 2, B_TRUE, B_FALSE);
2945                 free(name);
2946         }
2947 }
2948
2949 static void
2950 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
2951     int namewidth)
2952 {
2953         uint_t i;
2954         char *name;
2955
2956         if (nl2cache == 0)
2957                 return;
2958
2959         (void) printf(gettext("\tcache\n"));
2960
2961         for (i = 0; i < nl2cache; i++) {
2962                 name = zpool_vdev_name(g_zfs, zhp, l2cache[i]);
2963                 print_status_config(zhp, name, l2cache[i],
2964                     namewidth, 2, B_FALSE, B_FALSE);
2965                 free(name);
2966         }
2967 }
2968
2969 /*
2970  * Display a summary of pool status.  Displays a summary such as:
2971  *
2972  *        pool: tank
2973  *      status: DEGRADED
2974  *      reason: One or more devices ...
2975  *         see: http://www.sun.com/msg/ZFS-xxxx-01
2976  *      config:
2977  *              mirror          DEGRADED
2978  *                c1t0d0        OK
2979  *                c2t0d0        UNAVAIL
2980  *
2981  * When given the '-v' option, we print out the complete config.  If the '-e'
2982  * option is specified, then we print out error rate information as well.
2983  */
2984 int
2985 status_callback(zpool_handle_t *zhp, void *data)
2986 {
2987         status_cbdata_t *cbp = data;
2988         nvlist_t *config, *nvroot;
2989         char *msgid;
2990         int reason;
2991         const char *health;
2992         uint_t c;
2993         vdev_stat_t *vs;
2994
2995         config = zpool_get_config(zhp, NULL);
2996         reason = zpool_get_status(zhp, &msgid);
2997
2998         cbp->cb_count++;
2999
3000         /*
3001          * If we were given 'zpool status -x', only report those pools with
3002          * problems.
3003          */
3004         if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) {
3005                 if (!cbp->cb_allpools) {
3006                         (void) printf(gettext("pool '%s' is healthy\n"),
3007                             zpool_get_name(zhp));
3008                         if (cbp->cb_first)
3009                                 cbp->cb_first = B_FALSE;
3010                 }
3011                 return (0);
3012         }
3013
3014         if (cbp->cb_first)
3015                 cbp->cb_first = B_FALSE;
3016         else
3017                 (void) printf("\n");
3018
3019         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3020             &nvroot) == 0);
3021         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
3022             (uint64_t **)&vs, &c) == 0);
3023         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
3024
3025         (void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
3026         (void) printf(gettext(" state: %s\n"), health);
3027
3028         switch (reason) {
3029         case ZPOOL_STATUS_MISSING_DEV_R:
3030                 (void) printf(gettext("status: One or more devices could not "
3031                     "be opened.  Sufficient replicas exist for\n\tthe pool to "
3032                     "continue functioning in a degraded state.\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_MISSING_DEV_NR:
3038                 (void) printf(gettext("status: One or more devices could not "
3039                     "be opened.  There are insufficient\n\treplicas for the "
3040                     "pool to continue functioning.\n"));
3041                 (void) printf(gettext("action: Attach the missing device and "
3042                     "online it using 'zpool online'.\n"));
3043                 break;
3044
3045         case ZPOOL_STATUS_CORRUPT_LABEL_R:
3046                 (void) printf(gettext("status: One or more devices could not "
3047                     "be used because the label is missing or\n\tinvalid.  "
3048                     "Sufficient replicas exist for the pool to continue\n\t"
3049                     "functioning in a degraded state.\n"));
3050                 (void) printf(gettext("action: Replace the device using "
3051                     "'zpool replace'.\n"));
3052                 break;
3053
3054         case ZPOOL_STATUS_CORRUPT_LABEL_NR:
3055                 (void) printf(gettext("status: One or more devices could not "
3056                     "be used because the label is missing \n\tor invalid.  "
3057                     "There are insufficient replicas for the pool to "
3058                     "continue\n\tfunctioning.\n"));
3059                 (void) printf(gettext("action: Destroy and re-create the pool "
3060                     "from a backup source.\n"));
3061                 break;
3062
3063         case ZPOOL_STATUS_FAILING_DEV:
3064                 (void) printf(gettext("status: One or more devices has "
3065                     "experienced an unrecoverable error.  An\n\tattempt was "
3066                     "made to correct the error.  Applications are "
3067                     "unaffected.\n"));
3068                 (void) printf(gettext("action: Determine if the device needs "
3069                     "to be replaced, and clear the errors\n\tusing "
3070                     "'zpool clear' or replace the device with 'zpool "
3071                     "replace'.\n"));
3072                 break;
3073
3074         case ZPOOL_STATUS_OFFLINE_DEV:
3075                 (void) printf(gettext("status: One or more devices has "
3076                     "been taken offline by the administrator.\n\tSufficient "
3077                     "replicas exist for the pool to continue functioning in "
3078                     "a\n\tdegraded state.\n"));
3079                 (void) printf(gettext("action: Online the device using "
3080                     "'zpool online' or replace the device with\n\t'zpool "
3081                     "replace'.\n"));
3082                 break;
3083
3084         case ZPOOL_STATUS_RESILVERING:
3085                 (void) printf(gettext("status: One or more devices is "
3086                     "currently being resilvered.  The pool will\n\tcontinue "
3087                     "to function, possibly in a degraded state.\n"));
3088                 (void) printf(gettext("action: Wait for the resilver to "
3089                     "complete.\n"));
3090                 break;
3091
3092         case ZPOOL_STATUS_CORRUPT_DATA:
3093                 (void) printf(gettext("status: One or more devices has "
3094                     "experienced an error resulting in data\n\tcorruption.  "
3095                     "Applications may be affected.\n"));
3096                 (void) printf(gettext("action: Restore the file in question "
3097                     "if possible.  Otherwise restore the\n\tentire pool from "
3098                     "backup.\n"));
3099                 break;
3100
3101         case ZPOOL_STATUS_CORRUPT_POOL:
3102                 (void) printf(gettext("status: The pool metadata is corrupted "
3103                     "and the pool cannot be opened.\n"));
3104                 (void) printf(gettext("action: Destroy and re-create the pool "
3105                     "from a backup source.\n"));
3106                 break;
3107
3108         case ZPOOL_STATUS_VERSION_OLDER:
3109                 (void) printf(gettext("status: The pool is formatted using an "
3110                     "older on-disk format.  The pool can\n\tstill be used, but "
3111                     "some features are unavailable.\n"));
3112                 (void) printf(gettext("action: Upgrade the pool using 'zpool "
3113                     "upgrade'.  Once this is done, the\n\tpool will no longer "
3114                     "be accessible on older software versions.\n"));
3115                 break;
3116
3117         case ZPOOL_STATUS_VERSION_NEWER:
3118                 (void) printf(gettext("status: The pool has been upgraded to a "
3119                     "newer, incompatible on-disk version.\n\tThe pool cannot "
3120                     "be accessed on this system.\n"));
3121                 (void) printf(gettext("action: Access the pool from a system "
3122                     "running more recent software, or\n\trestore the pool from "
3123                     "backup.\n"));
3124                 break;
3125
3126         case ZPOOL_STATUS_FAULTED_DEV_R:
3127                 (void) printf(gettext("status: One or more devices are "
3128                     "faulted in response to persistent errors.\n\tSufficient "
3129                     "replicas exist for the pool to continue functioning "
3130                     "in a\n\tdegraded state.\n"));
3131                 (void) printf(gettext("action: Replace the faulted device, "
3132                     "or use 'zpool clear' to mark the device\n\trepaired.\n"));
3133                 break;
3134
3135         case ZPOOL_STATUS_FAULTED_DEV_NR:
3136                 (void) printf(gettext("status: One or more devices are "
3137                     "faulted in response to persistent errors.  There are "
3138                     "insufficient replicas for the pool to\n\tcontinue "
3139                     "functioning.\n"));
3140                 (void) printf(gettext("action: Destroy and re-create the pool "
3141                     "from a backup source.  Manually marking the device\n"
3142                     "\trepaired using 'zpool clear' may allow some data "
3143                     "to be recovered.\n"));
3144                 break;
3145
3146         case ZPOOL_STATUS_IO_FAILURE_WAIT:
3147         case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
3148                 (void) printf(gettext("status: One or more devices are "
3149                     "faulted in response to IO failures.\n"));
3150                 (void) printf(gettext("action: Make sure the affected devices "
3151                     "are connected, then run 'zpool clear'.\n"));
3152                 break;
3153
3154         case ZPOOL_STATUS_BAD_LOG:
3155                 (void) printf(gettext("status: An intent log record "
3156                     "could not be read.\n"
3157                     "\tWaiting for adminstrator intervention to fix the "
3158                     "faulted pool.\n"));
3159                 (void) printf(gettext("action: Either restore the affected "
3160                     "device(s) and run 'zpool online',\n"
3161                     "\tor ignore the intent log records by running "
3162                     "'zpool clear'.\n"));
3163                 break;
3164
3165         default:
3166                 /*
3167                  * The remaining errors can't actually be generated, yet.
3168                  */
3169                 assert(reason == ZPOOL_STATUS_OK);
3170         }
3171
3172         if (msgid != NULL)
3173                 (void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
3174                     msgid);
3175
3176         if (config != NULL) {
3177                 int namewidth;
3178                 uint64_t nerr;
3179                 nvlist_t **spares, **l2cache;
3180                 uint_t nspares, nl2cache;
3181
3182
3183                 (void) printf(gettext(" scrub: "));
3184                 print_scrub_status(nvroot);
3185
3186                 namewidth = max_width(zhp, nvroot, 0, 0);
3187                 if (namewidth < 10)
3188                         namewidth = 10;
3189
3190                 (void) printf(gettext("config:\n\n"));
3191                 (void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
3192                     "NAME", "STATE", "READ", "WRITE", "CKSUM");
3193                 print_status_config(zhp, zpool_get_name(zhp), nvroot,
3194                     namewidth, 0, B_FALSE, B_FALSE);
3195                 if (num_logs(nvroot) > 0)
3196                         print_status_config(zhp, "logs", nvroot, namewidth, 0,
3197                             B_FALSE, B_TRUE);
3198
3199                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
3200                     &l2cache, &nl2cache) == 0)
3201                         print_l2cache(zhp, l2cache, nl2cache, namewidth);
3202
3203                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
3204                     &spares, &nspares) == 0)
3205                         print_spares(zhp, spares, nspares, namewidth);
3206
3207                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
3208                     &nerr) == 0) {
3209                         nvlist_t *nverrlist = NULL;
3210
3211                         /*
3212                          * If the approximate error count is small, get a
3213                          * precise count by fetching the entire log and
3214                          * uniquifying the results.
3215                          */
3216                         if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
3217                             zpool_get_errlog(zhp, &nverrlist) == 0) {
3218                                 nvpair_t *elem;
3219
3220                                 elem = NULL;
3221                                 nerr = 0;
3222                                 while ((elem = nvlist_next_nvpair(nverrlist,
3223                                     elem)) != NULL) {
3224                                         nerr++;
3225                                 }
3226                         }
3227                         nvlist_free(nverrlist);
3228
3229                         (void) printf("\n");
3230
3231                         if (nerr == 0)
3232                                 (void) printf(gettext("errors: No known data "
3233                                     "errors\n"));
3234                         else if (!cbp->cb_verbose)
3235                                 (void) printf(gettext("errors: %llu data "
3236                                     "errors, use '-v' for a list\n"),
3237                                     (u_longlong_t)nerr);
3238                         else
3239                                 print_error_log(zhp);
3240                 }
3241         } else {
3242                 (void) printf(gettext("config: The configuration cannot be "
3243                     "determined.\n"));
3244         }
3245
3246         return (0);
3247 }
3248
3249 /*
3250  * zpool status [-vx] [pool] ...
3251  *
3252  *      -v      Display complete error logs
3253  *      -x      Display only pools with potential problems
3254  *
3255  * Describes the health status of all pools or some subset.
3256  */
3257 int
3258 zpool_do_status(int argc, char **argv)
3259 {
3260         int c;
3261         int ret;
3262         status_cbdata_t cb = { 0 };
3263
3264         /* check options */
3265         while ((c = getopt(argc, argv, "vx")) != -1) {
3266                 switch (c) {
3267                 case 'v':
3268                         cb.cb_verbose = B_TRUE;
3269                         break;
3270                 case 'x':
3271                         cb.cb_explain = B_TRUE;
3272                         break;
3273                 case '?':
3274                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3275                             optopt);
3276                         usage(B_FALSE);
3277                 }
3278         }
3279
3280         argc -= optind;
3281         argv += optind;
3282
3283         cb.cb_first = B_TRUE;
3284
3285         if (argc == 0)
3286                 cb.cb_allpools = B_TRUE;
3287
3288         ret = for_each_pool(argc, argv, B_TRUE, NULL, status_callback, &cb);
3289
3290         if (argc == 0 && cb.cb_count == 0)
3291                 (void) printf(gettext("no pools available\n"));
3292         else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
3293                 (void) printf(gettext("all pools are healthy\n"));
3294
3295         return (ret);
3296 }
3297
3298 typedef struct upgrade_cbdata {
3299         int     cb_all;
3300         int     cb_first;
3301         int     cb_newer;
3302         int     cb_argc;
3303         uint64_t cb_version;
3304         char    **cb_argv;
3305 } upgrade_cbdata_t;
3306
3307 static int
3308 upgrade_cb(zpool_handle_t *zhp, void *arg)
3309 {
3310         upgrade_cbdata_t *cbp = arg;
3311         nvlist_t *config;
3312         uint64_t version;
3313         int ret = 0;
3314
3315         config = zpool_get_config(zhp, NULL);
3316         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
3317             &version) == 0);
3318
3319         if (!cbp->cb_newer && version < SPA_VERSION) {
3320                 if (!cbp->cb_all) {
3321                         if (cbp->cb_first) {
3322                                 (void) printf(gettext("The following pools are "
3323                                     "out of date, and can be upgraded.  After "
3324                                     "being\nupgraded, these pools will no "
3325                                     "longer be accessible by older software "
3326                                     "versions.\n\n"));
3327                                 (void) printf(gettext("VER  POOL\n"));
3328                                 (void) printf(gettext("---  ------------\n"));
3329                                 cbp->cb_first = B_FALSE;
3330                         }
3331
3332                         (void) printf("%2llu   %s\n", (u_longlong_t)version,
3333                             zpool_get_name(zhp));
3334                 } else {
3335                         cbp->cb_first = B_FALSE;
3336                         ret = zpool_upgrade(zhp, cbp->cb_version);
3337                         if (!ret) {
3338                                 (void) printf(gettext("Successfully upgraded "
3339                                     "'%s'\n\n"), zpool_get_name(zhp));
3340                         }
3341                 }
3342         } else if (cbp->cb_newer && version > SPA_VERSION) {
3343                 assert(!cbp->cb_all);
3344
3345                 if (cbp->cb_first) {
3346                         (void) printf(gettext("The following pools are "
3347                             "formatted using a newer software version and\n"
3348                             "cannot be accessed on the current system.\n\n"));
3349                         (void) printf(gettext("VER  POOL\n"));
3350                         (void) printf(gettext("---  ------------\n"));
3351                         cbp->cb_first = B_FALSE;
3352                 }
3353
3354                 (void) printf("%2llu   %s\n", (u_longlong_t)version,
3355                     zpool_get_name(zhp));
3356         }
3357
3358         zpool_close(zhp);
3359         return (ret);
3360 }
3361
3362 /* ARGSUSED */
3363 static int
3364 upgrade_one(zpool_handle_t *zhp, void *data)
3365 {
3366         upgrade_cbdata_t *cbp = data;
3367         uint64_t cur_version;
3368         int ret;
3369
3370         if (strcmp("log", zpool_get_name(zhp)) == 0) {
3371                 (void) printf(gettext("'log' is now a reserved word\n"
3372                     "Pool 'log' must be renamed using export and import"
3373                     " to upgrade.\n"));
3374                 return (1);
3375         }
3376
3377         cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
3378         if (cur_version > cbp->cb_version) {
3379                 (void) printf(gettext("Pool '%s' is already formatted "
3380                     "using more current version '%llu'.\n"),
3381                     zpool_get_name(zhp), cur_version);
3382                 return (0);
3383         }
3384         if (cur_version == cbp->cb_version) {
3385                 (void) printf(gettext("Pool '%s' is already formatted "
3386                     "using the current version.\n"), zpool_get_name(zhp));
3387                 return (0);
3388         }
3389
3390         ret = zpool_upgrade(zhp, cbp->cb_version);
3391
3392         if (!ret) {
3393                 (void) printf(gettext("Successfully upgraded '%s' "
3394                     "from version %llu to version %llu\n\n"),
3395                     zpool_get_name(zhp), (u_longlong_t)cur_version,
3396                     (u_longlong_t)cbp->cb_version);
3397         }
3398
3399         return (ret != 0);
3400 }
3401
3402 /*
3403  * zpool upgrade
3404  * zpool upgrade -v
3405  * zpool upgrade [-V version] <-a | pool ...>
3406  *
3407  * With no arguments, display downrev'd ZFS pool available for upgrade.
3408  * Individual pools can be upgraded by specifying the pool, and '-a' will
3409  * upgrade all pools.
3410  */
3411 int
3412 zpool_do_upgrade(int argc, char **argv)
3413 {
3414         int c;
3415         upgrade_cbdata_t cb = { 0 };
3416         int ret = 0;
3417         boolean_t showversions = B_FALSE;
3418         char *end;
3419
3420
3421         /* check options */
3422         while ((c = getopt(argc, argv, "avV:")) != -1) {
3423                 switch (c) {
3424                 case 'a':
3425                         cb.cb_all = B_TRUE;
3426                         break;
3427                 case 'v':
3428                         showversions = B_TRUE;
3429                         break;
3430                 case 'V':
3431                         cb.cb_version = strtoll(optarg, &end, 10);
3432                         if (*end != '\0' || cb.cb_version > SPA_VERSION ||
3433                             cb.cb_version < SPA_VERSION_1) {
3434                                 (void) fprintf(stderr,
3435                                     gettext("invalid version '%s'\n"), optarg);
3436                                 usage(B_FALSE);
3437                         }
3438                         break;
3439                 case '?':
3440                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3441                             optopt);
3442                         usage(B_FALSE);
3443                 }
3444         }
3445
3446         cb.cb_argc = argc;
3447         cb.cb_argv = argv;
3448         argc -= optind;
3449         argv += optind;
3450
3451         if (cb.cb_version == 0) {
3452                 cb.cb_version = SPA_VERSION;
3453         } else if (!cb.cb_all && argc == 0) {
3454                 (void) fprintf(stderr, gettext("-V option is "
3455                     "incompatible with other arguments\n"));
3456                 usage(B_FALSE);
3457         }
3458
3459         if (showversions) {
3460                 if (cb.cb_all || argc != 0) {
3461                         (void) fprintf(stderr, gettext("-v option is "
3462                             "incompatible with other arguments\n"));
3463                         usage(B_FALSE);
3464                 }
3465         } else if (cb.cb_all) {
3466                 if (argc != 0) {
3467                         (void) fprintf(stderr, gettext("-a option should not "
3468                             "be used along with a pool name\n"));
3469                         usage(B_FALSE);
3470                 }
3471         }
3472
3473         (void) printf(gettext("This system is currently running "
3474             "ZFS pool version %llu.\n\n"), SPA_VERSION);
3475         cb.cb_first = B_TRUE;
3476         if (showversions) {
3477                 (void) printf(gettext("The following versions are "
3478                     "supported:\n\n"));
3479                 (void) printf(gettext("VER  DESCRIPTION\n"));
3480                 (void) printf("---  -----------------------------------------"
3481                     "---------------\n");
3482                 (void) printf(gettext(" 1   Initial ZFS version\n"));
3483                 (void) printf(gettext(" 2   Ditto blocks "
3484                     "(replicated metadata)\n"));
3485                 (void) printf(gettext(" 3   Hot spares and double parity "
3486                     "RAID-Z\n"));
3487                 (void) printf(gettext(" 4   zpool history\n"));
3488                 (void) printf(gettext(" 5   Compression using the gzip "
3489                     "algorithm\n"));
3490                 (void) printf(gettext(" 6   bootfs pool property\n"));
3491                 (void) printf(gettext(" 7   Separate intent log devices\n"));
3492                 (void) printf(gettext(" 8   Delegated administration\n"));
3493                 (void) printf(gettext(" 9   refquota and refreservation "
3494                     "properties\n"));
3495                 (void) printf(gettext(" 10  Cache devices\n"));
3496                 (void) printf(gettext(" 11  Improved scrub performance\n"));
3497                 (void) printf(gettext(" 12  Snapshot properties\n"));
3498                 (void) printf(gettext(" 13  snapused property\n"));
3499                 (void) printf(gettext(" 14  passthrough-x aclinherit "
3500                     "support\n"));
3501                 (void) printf(gettext("For more information on a particular "
3502                     "version, including supported releases, see:\n\n"));
3503                 (void) printf("http://www.opensolaris.org/os/community/zfs/"
3504                     "version/N\n\n");
3505                 (void) printf(gettext("Where 'N' is the version number.\n"));
3506         } else if (argc == 0) {
3507                 int notfound;
3508
3509                 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3510                 notfound = cb.cb_first;
3511
3512                 if (!cb.cb_all && ret == 0) {
3513                         if (!cb.cb_first)
3514                                 (void) printf("\n");
3515                         cb.cb_first = B_TRUE;
3516                         cb.cb_newer = B_TRUE;
3517                         ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3518                         if (!cb.cb_first) {
3519                                 notfound = B_FALSE;
3520                                 (void) printf("\n");
3521                         }
3522                 }
3523
3524                 if (ret == 0) {
3525                         if (notfound)
3526                                 (void) printf(gettext("All pools are formatted "
3527                                     "using this version.\n"));
3528                         else if (!cb.cb_all)
3529                                 (void) printf(gettext("Use 'zpool upgrade -v' "
3530                                     "for a list of available versions and "
3531                                     "their associated\nfeatures.\n"));
3532                 }
3533         } else {
3534                 ret = for_each_pool(argc, argv, B_FALSE, NULL,
3535                     upgrade_one, &cb);
3536         }
3537
3538         return (ret);
3539 }
3540
3541 typedef struct hist_cbdata {
3542         boolean_t first;
3543         int longfmt;
3544         int internal;
3545 } hist_cbdata_t;
3546
3547 char *hist_event_table[LOG_END] = {
3548         "invalid event",
3549         "pool create",
3550         "vdev add",
3551         "pool remove",
3552         "pool destroy",
3553         "pool export",
3554         "pool import",
3555         "vdev attach",
3556         "vdev replace",
3557         "vdev detach",
3558         "vdev online",
3559         "vdev offline",
3560         "vdev upgrade",
3561         "pool clear",
3562         "pool scrub",
3563         "pool property set",
3564         "create",
3565         "clone",
3566         "destroy",
3567         "destroy_begin_sync",
3568         "inherit",
3569         "property set",
3570         "quota set",
3571         "permission update",
3572         "permission remove",
3573         "permission who remove",
3574         "promote",
3575         "receive",
3576         "rename",
3577         "reservation set",
3578         "replay_inc_sync",
3579         "replay_full_sync",
3580         "rollback",
3581         "snapshot",
3582         "filesystem version upgrade",
3583         "refquota set",
3584         "refreservation set",
3585         "pool scrub done",
3586 };
3587
3588 /*
3589  * Print out the command history for a specific pool.
3590  */
3591 static int
3592 get_history_one(zpool_handle_t *zhp, void *data)
3593 {
3594         nvlist_t *nvhis;
3595         nvlist_t **records;
3596         uint_t numrecords;
3597         char *cmdstr;
3598         char *pathstr;
3599         uint64_t dst_time;
3600         time_t tsec;
3601         struct tm t;
3602         char tbuf[30];
3603         int ret, i;
3604         uint64_t who;
3605         struct passwd *pwd;
3606         char *hostname;
3607         char *zonename;
3608         char internalstr[MAXPATHLEN];
3609         hist_cbdata_t *cb = (hist_cbdata_t *)data;
3610         uint64_t txg;
3611         uint64_t ievent;
3612
3613         cb->first = B_FALSE;
3614
3615         (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
3616
3617         if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
3618                 return (ret);
3619
3620         verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
3621             &records, &numrecords) == 0);
3622         for (i = 0; i < numrecords; i++) {
3623                 if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME,
3624                     &dst_time) != 0)
3625                         continue;
3626
3627                 /* is it an internal event or a standard event? */
3628                 if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD,
3629                     &cmdstr) != 0) {
3630                         if (cb->internal == 0)
3631                                 continue;
3632
3633                         if (nvlist_lookup_uint64(records[i],
3634                             ZPOOL_HIST_INT_EVENT, &ievent) != 0)
3635                                 continue;
3636                         verify(nvlist_lookup_uint64(records[i],
3637                             ZPOOL_HIST_TXG, &txg) == 0);
3638                         verify(nvlist_lookup_string(records[i],
3639                             ZPOOL_HIST_INT_STR, &pathstr) == 0);
3640                         if (ievent >= LOG_END)
3641                                 continue;
3642                         (void) snprintf(internalstr,
3643                             sizeof (internalstr),
3644                             "[internal %s txg:%lld] %s",
3645                             hist_event_table[ievent], txg,
3646                             pathstr);
3647                         cmdstr = internalstr;
3648                 }
3649                 tsec = dst_time;
3650                 (void) localtime_r(&tsec, &t);
3651                 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
3652                 (void) printf("%s %s", tbuf, cmdstr);
3653
3654                 if (!cb->longfmt) {
3655                         (void) printf("\n");
3656                         continue;
3657                 }
3658                 (void) printf(" [");
3659                 if (nvlist_lookup_uint64(records[i],
3660                     ZPOOL_HIST_WHO, &who) == 0) {
3661                         pwd = getpwuid((uid_t)who);
3662                         if (pwd)
3663                                 (void) printf("user %s on",
3664                                     pwd->pw_name);
3665                         else
3666                                 (void) printf("user %d on",
3667                                     (int)who);
3668                 } else {
3669                         (void) printf(gettext("no info]\n"));
3670                         continue;
3671                 }
3672                 if (nvlist_lookup_string(records[i],
3673                     ZPOOL_HIST_HOST, &hostname) == 0) {
3674                         (void) printf(" %s", hostname);
3675                 }
3676                 if (nvlist_lookup_string(records[i],
3677                     ZPOOL_HIST_ZONE, &zonename) == 0) {
3678                         (void) printf(":%s", zonename);
3679                 }
3680
3681                 (void) printf("]");
3682                 (void) printf("\n");
3683         }
3684         (void) printf("\n");
3685         nvlist_free(nvhis);
3686
3687         return (ret);
3688 }
3689
3690 /*
3691  * zpool history <pool>
3692  *
3693  * Displays the history of commands that modified pools.
3694  */
3695
3696
3697 int
3698 zpool_do_history(int argc, char **argv)
3699 {
3700         hist_cbdata_t cbdata = { 0 };
3701         int ret;
3702         int c;
3703
3704         cbdata.first = B_TRUE;
3705         /* check options */
3706         while ((c = getopt(argc, argv, "li")) != -1) {
3707                 switch (c) {
3708                 case 'l':
3709                         cbdata.longfmt = 1;
3710                         break;
3711                 case 'i':
3712                         cbdata.internal = 1;
3713                         break;
3714                 case '?':
3715                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3716                             optopt);
3717                         usage(B_FALSE);
3718                 }
3719         }
3720         argc -= optind;
3721         argv += optind;
3722
3723         ret = for_each_pool(argc, argv, B_FALSE,  NULL, get_history_one,
3724             &cbdata);
3725
3726         if (argc == 0 && cbdata.first == B_TRUE) {
3727                 (void) printf(gettext("no pools available\n"));
3728                 return (0);
3729         }
3730
3731         return (ret);
3732 }
3733
3734 static int
3735 get_callback(zpool_handle_t *zhp, void *data)
3736 {
3737         zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
3738         char value[MAXNAMELEN];
3739         zprop_source_t srctype;
3740         zprop_list_t *pl;
3741
3742         for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
3743
3744                 /*
3745                  * Skip the special fake placeholder. This will also skip
3746                  * over the name property when 'all' is specified.
3747                  */
3748                 if (pl->pl_prop == ZPOOL_PROP_NAME &&
3749                     pl == cbp->cb_proplist)
3750                         continue;
3751
3752                 if (zpool_get_prop(zhp, pl->pl_prop,
3753                     value, sizeof (value), &srctype) != 0)
3754                         continue;
3755
3756                 zprop_print_one_property(zpool_get_name(zhp), cbp,
3757                     zpool_prop_to_name(pl->pl_prop), value, srctype, NULL);
3758         }
3759         return (0);
3760 }
3761
3762 int
3763 zpool_do_get(int argc, char **argv)
3764 {
3765         zprop_get_cbdata_t cb = { 0 };
3766         zprop_list_t fake_name = { 0 };
3767         int ret;
3768
3769         if (argc < 3)
3770                 usage(B_FALSE);
3771
3772         cb.cb_first = B_TRUE;
3773         cb.cb_sources = ZPROP_SRC_ALL;
3774         cb.cb_columns[0] = GET_COL_NAME;
3775         cb.cb_columns[1] = GET_COL_PROPERTY;
3776         cb.cb_columns[2] = GET_COL_VALUE;
3777         cb.cb_columns[3] = GET_COL_SOURCE;
3778         cb.cb_type = ZFS_TYPE_POOL;
3779
3780         if (zprop_get_list(g_zfs, argv[1],  &cb.cb_proplist,
3781             ZFS_TYPE_POOL) != 0)
3782                 usage(B_FALSE);
3783
3784         if (cb.cb_proplist != NULL) {
3785                 fake_name.pl_prop = ZPOOL_PROP_NAME;
3786                 fake_name.pl_width = strlen(gettext("NAME"));
3787                 fake_name.pl_next = cb.cb_proplist;
3788                 cb.cb_proplist = &fake_name;
3789         }
3790
3791         ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist,
3792             get_callback, &cb);
3793
3794         if (cb.cb_proplist == &fake_name)
3795                 zprop_free_list(fake_name.pl_next);
3796         else
3797                 zprop_free_list(cb.cb_proplist);
3798
3799         return (ret);
3800 }
3801
3802 typedef struct set_cbdata {
3803         char *cb_propname;
3804         char *cb_value;
3805         boolean_t cb_any_successful;
3806 } set_cbdata_t;
3807
3808 int
3809 set_callback(zpool_handle_t *zhp, void *data)
3810 {
3811         int error;
3812         set_cbdata_t *cb = (set_cbdata_t *)data;
3813
3814         error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
3815
3816         if (!error)
3817                 cb->cb_any_successful = B_TRUE;
3818
3819         return (error);
3820 }
3821
3822 int
3823 zpool_do_set(int argc, char **argv)
3824 {
3825         set_cbdata_t cb = { 0 };
3826         int error;
3827
3828         if (argc > 1 && argv[1][0] == '-') {
3829                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3830                     argv[1][1]);
3831                 usage(B_FALSE);
3832         }
3833
3834         if (argc < 2) {
3835                 (void) fprintf(stderr, gettext("missing property=value "
3836                     "argument\n"));
3837                 usage(B_FALSE);
3838         }
3839
3840         if (argc < 3) {
3841                 (void) fprintf(stderr, gettext("missing pool name\n"));
3842                 usage(B_FALSE);
3843         }
3844
3845         if (argc > 3) {
3846                 (void) fprintf(stderr, gettext("too many pool names\n"));
3847                 usage(B_FALSE);
3848         }
3849
3850         cb.cb_propname = argv[1];
3851         cb.cb_value = strchr(cb.cb_propname, '=');
3852         if (cb.cb_value == NULL) {
3853                 (void) fprintf(stderr, gettext("missing value in "
3854                     "property=value argument\n"));
3855                 usage(B_FALSE);
3856         }
3857
3858         *(cb.cb_value) = '\0';
3859         cb.cb_value++;
3860
3861         error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
3862             set_callback, &cb);
3863
3864         return (error);
3865 }
3866
3867 static int
3868 find_command_idx(char *command, int *idx)
3869 {
3870         int i;
3871
3872         for (i = 0; i < NCOMMAND; i++) {
3873                 if (command_table[i].name == NULL)
3874                         continue;
3875
3876                 if (strcmp(command, command_table[i].name) == 0) {
3877                         *idx = i;
3878                         return (0);
3879                 }
3880         }
3881         return (1);
3882 }
3883
3884 int
3885 main(int argc, char **argv)
3886 {
3887         int ret;
3888         int i;
3889         char *cmdname;
3890
3891         (void) setlocale(LC_ALL, "");
3892         (void) textdomain(TEXT_DOMAIN);
3893
3894         if ((g_zfs = libzfs_init()) == NULL) {
3895                 (void) fprintf(stderr, gettext("internal error: failed to "
3896                     "initialize ZFS library\n"));
3897                 return (1);
3898         }
3899
3900         libzfs_print_on_error(g_zfs, B_TRUE);
3901
3902         opterr = 0;
3903
3904         /*
3905          * Make sure the user has specified some command.
3906          */
3907         if (argc < 2) {
3908                 (void) fprintf(stderr, gettext("missing command\n"));
3909                 usage(B_FALSE);
3910         }
3911
3912         cmdname = argv[1];
3913
3914         /*
3915          * Special case '-?'
3916          */
3917         if (strcmp(cmdname, "-?") == 0)
3918                 usage(B_TRUE);
3919
3920         zpool_set_history_str("zpool", argc, argv, history_str);
3921         verify(zpool_stage_history(g_zfs, history_str) == 0);
3922
3923         /*
3924          * Run the appropriate command.
3925          */
3926         if (find_command_idx(cmdname, &i) == 0) {
3927                 current_command = &command_table[i];
3928                 ret = command_table[i].func(argc - 1, argv + 1);
3929         } else if (strchr(cmdname, '=')) {
3930                 verify(find_command_idx("set", &i) == 0);
3931                 current_command = &command_table[i];
3932                 ret = command_table[i].func(argc, argv);
3933         } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
3934                 /*
3935                  * 'freeze' is a vile debugging abomination, so we treat
3936                  * it as such.
3937                  */
3938                 char buf[16384];
3939                 int fd = open(ZFS_DEV, O_RDWR);
3940                 (void) strcpy((void *)buf, argv[2]);
3941                 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
3942         } else {
3943                 (void) fprintf(stderr, gettext("unrecognized "
3944                     "command '%s'\n"), cmdname);
3945                 usage(B_FALSE);
3946         }
3947
3948         libzfs_fini(g_zfs);
3949
3950         /*
3951          * The 'ZFS_ABORT' environment variable causes us to dump core on exit
3952          * for the purposes of running ::findleaks.
3953          */
3954         if (getenv("ZFS_ABORT") != NULL) {
3955                 (void) printf("dumping core by request\n");
3956                 abort();
3957         }
3958
3959         return (ret);
3960 }