]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
MFV r331706:
[FreeBSD/FreeBSD.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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
25  * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
26  * Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
27  * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
28  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
29  * Copyright 2016 Nexenta Systems, Inc.
30  * Copyright (c) 2017 Datto Inc.
31  */
32
33 #include <solaris.h>
34 #include <assert.h>
35 #include <ctype.h>
36 #include <dirent.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <getopt.h>
40 #include <libgen.h>
41 #include <libintl.h>
42 #include <libuutil.h>
43 #include <locale.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <strings.h>
48 #include <unistd.h>
49 #include <priv.h>
50 #include <pwd.h>
51 #include <zone.h>
52 #include <sys/time.h>
53 #include <zfs_prop.h>
54 #include <sys/fs/zfs.h>
55 #include <sys/stat.h>
56
57 #include <libzfs.h>
58
59 #include "zpool_util.h"
60 #include "zfs_comutil.h"
61 #include "zfeature_common.h"
62
63 #include "statcommon.h"
64
65 static int zpool_do_create(int, char **);
66 static int zpool_do_destroy(int, char **);
67
68 static int zpool_do_add(int, char **);
69 static int zpool_do_remove(int, char **);
70 static int zpool_do_labelclear(int, char **);
71
72 static int zpool_do_checkpoint(int, char **);
73
74 static int zpool_do_list(int, char **);
75 static int zpool_do_iostat(int, char **);
76 static int zpool_do_status(int, char **);
77
78 static int zpool_do_online(int, char **);
79 static int zpool_do_offline(int, char **);
80 static int zpool_do_clear(int, char **);
81 static int zpool_do_reopen(int, char **);
82
83 static int zpool_do_reguid(int, char **);
84
85 static int zpool_do_attach(int, char **);
86 static int zpool_do_detach(int, char **);
87 static int zpool_do_replace(int, char **);
88 static int zpool_do_split(int, char **);
89
90 static int zpool_do_scrub(int, char **);
91
92 static int zpool_do_import(int, char **);
93 static int zpool_do_export(int, char **);
94
95 static int zpool_do_upgrade(int, char **);
96
97 static int zpool_do_history(int, char **);
98
99 static int zpool_do_get(int, char **);
100 static int zpool_do_set(int, char **);
101
102 /*
103  * These libumem hooks provide a reasonable set of defaults for the allocator's
104  * debugging facilities.
105  */
106
107 #ifdef DEBUG
108 const char *
109 _umem_debug_init(void)
110 {
111         return ("default,verbose"); /* $UMEM_DEBUG setting */
112 }
113
114 const char *
115 _umem_logging_init(void)
116 {
117         return ("fail,contents"); /* $UMEM_LOGGING setting */
118 }
119 #endif
120
121 typedef enum {
122         HELP_ADD,
123         HELP_ATTACH,
124         HELP_CLEAR,
125         HELP_CREATE,
126         HELP_CHECKPOINT,
127         HELP_DESTROY,
128         HELP_DETACH,
129         HELP_EXPORT,
130         HELP_HISTORY,
131         HELP_IMPORT,
132         HELP_IOSTAT,
133         HELP_LABELCLEAR,
134         HELP_LIST,
135         HELP_OFFLINE,
136         HELP_ONLINE,
137         HELP_REPLACE,
138         HELP_REMOVE,
139         HELP_SCRUB,
140         HELP_STATUS,
141         HELP_UPGRADE,
142         HELP_GET,
143         HELP_SET,
144         HELP_SPLIT,
145         HELP_REGUID,
146         HELP_REOPEN
147 } zpool_help_t;
148
149
150 typedef struct zpool_command {
151         const char      *name;
152         int             (*func)(int, char **);
153         zpool_help_t    usage;
154 } zpool_command_t;
155
156 /*
157  * Master command table.  Each ZFS command has a name, associated function, and
158  * usage message.  The usage messages need to be internationalized, so we have
159  * to have a function to return the usage message based on a command index.
160  *
161  * These commands are organized according to how they are displayed in the usage
162  * message.  An empty command (one with a NULL name) indicates an empty line in
163  * the generic usage message.
164  */
165 static zpool_command_t command_table[] = {
166         { "create",     zpool_do_create,        HELP_CREATE             },
167         { "destroy",    zpool_do_destroy,       HELP_DESTROY            },
168         { NULL },
169         { "add",        zpool_do_add,           HELP_ADD                },
170         { "remove",     zpool_do_remove,        HELP_REMOVE             },
171         { NULL },
172         { "labelclear", zpool_do_labelclear,    HELP_LABELCLEAR         },
173         { NULL },
174         { "checkpoint", zpool_do_checkpoint,    HELP_CHECKPOINT         },
175         { NULL },
176         { "list",       zpool_do_list,          HELP_LIST               },
177         { "iostat",     zpool_do_iostat,        HELP_IOSTAT             },
178         { "status",     zpool_do_status,        HELP_STATUS             },
179         { NULL },
180         { "online",     zpool_do_online,        HELP_ONLINE             },
181         { "offline",    zpool_do_offline,       HELP_OFFLINE            },
182         { "clear",      zpool_do_clear,         HELP_CLEAR              },
183         { "reopen",     zpool_do_reopen,        HELP_REOPEN             },
184         { NULL },
185         { "attach",     zpool_do_attach,        HELP_ATTACH             },
186         { "detach",     zpool_do_detach,        HELP_DETACH             },
187         { "replace",    zpool_do_replace,       HELP_REPLACE            },
188         { "split",      zpool_do_split,         HELP_SPLIT              },
189         { NULL },
190         { "scrub",      zpool_do_scrub,         HELP_SCRUB              },
191         { NULL },
192         { "import",     zpool_do_import,        HELP_IMPORT             },
193         { "export",     zpool_do_export,        HELP_EXPORT             },
194         { "upgrade",    zpool_do_upgrade,       HELP_UPGRADE            },
195         { "reguid",     zpool_do_reguid,        HELP_REGUID             },
196         { NULL },
197         { "history",    zpool_do_history,       HELP_HISTORY            },
198         { "get",        zpool_do_get,           HELP_GET                },
199         { "set",        zpool_do_set,           HELP_SET                },
200 };
201
202 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
203
204 static zpool_command_t *current_command;
205 static char history_str[HIS_MAX_RECORD_LEN];
206 static boolean_t log_history = B_TRUE;
207 static uint_t timestamp_fmt = NODATE;
208
209 static const char *
210 get_usage(zpool_help_t idx)
211 {
212         switch (idx) {
213         case HELP_ADD:
214                 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
215         case HELP_ATTACH:
216                 return (gettext("\tattach [-f] <pool> <device> "
217                     "<new-device>\n"));
218         case HELP_CLEAR:
219                 return (gettext("\tclear [-nF] <pool> [device]\n"));
220         case HELP_CREATE:
221                 return (gettext("\tcreate [-fnd] [-B] "
222                     "[-o property=value] ... \n"
223                     "\t    [-O file-system-property=value] ... \n"
224                     "\t    [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
225         case HELP_CHECKPOINT:
226                 return (gettext("\tcheckpoint [--discard] <pool> ...\n"));
227         case HELP_DESTROY:
228                 return (gettext("\tdestroy [-f] <pool>\n"));
229         case HELP_DETACH:
230                 return (gettext("\tdetach <pool> <device>\n"));
231         case HELP_EXPORT:
232                 return (gettext("\texport [-f] <pool> ...\n"));
233         case HELP_HISTORY:
234                 return (gettext("\thistory [-il] [<pool>] ...\n"));
235         case HELP_IMPORT:
236                 return (gettext("\timport [-d dir] [-D]\n"
237                     "\timport [-o mntopts] [-o property=value] ... \n"
238                     "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
239                     "[-R root] [-F [-n]] -a\n"
240                     "\timport [-o mntopts] [-o property=value] ... \n"
241                     "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
242                     "[-R root] [-F [-n]]\n"
243                     "\t    [--rewind-to-checkpoint] <pool | id> [newpool]\n"));
244         case HELP_IOSTAT:
245                 return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
246                     "[count]]\n"));
247         case HELP_LABELCLEAR:
248                 return (gettext("\tlabelclear [-f] <vdev>\n"));
249         case HELP_LIST:
250                 return (gettext("\tlist [-Hpv] [-o property[,...]] "
251                     "[-T d|u] [pool] ... [interval [count]]\n"));
252         case HELP_OFFLINE:
253                 return (gettext("\toffline [-t] <pool> <device> ...\n"));
254         case HELP_ONLINE:
255                 return (gettext("\tonline [-e] <pool> <device> ...\n"));
256         case HELP_REPLACE:
257                 return (gettext("\treplace [-f] <pool> <device> "
258                     "[new-device]\n"));
259         case HELP_REMOVE:
260                 return (gettext("\tremove [-nps] <pool> <device> ...\n"));
261         case HELP_REOPEN:
262                 return (gettext("\treopen <pool>\n"));
263         case HELP_SCRUB:
264                 return (gettext("\tscrub [-s | -p] <pool> ...\n"));
265         case HELP_STATUS:
266                 return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
267                     "[count]]\n"));
268         case HELP_UPGRADE:
269                 return (gettext("\tupgrade [-v]\n"
270                     "\tupgrade [-V version] <-a | pool ...>\n"));
271         case HELP_GET:
272                 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
273                     "<\"all\" | property[,...]> <pool> ...\n"));
274         case HELP_SET:
275                 return (gettext("\tset <property=value> <pool> \n"));
276         case HELP_SPLIT:
277                 return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
278                     "\t    [-o property=value] <pool> <newpool> "
279                     "[<device> ...]\n"));
280         case HELP_REGUID:
281                 return (gettext("\treguid <pool>\n"));
282         }
283
284         abort();
285         /* NOTREACHED */
286 }
287
288
289 /*
290  * Callback routine that will print out a pool property value.
291  */
292 static int
293 print_prop_cb(int prop, void *cb)
294 {
295         FILE *fp = cb;
296
297         (void) fprintf(fp, "\t%-15s  ", zpool_prop_to_name(prop));
298
299         if (zpool_prop_readonly(prop))
300                 (void) fprintf(fp, "  NO   ");
301         else
302                 (void) fprintf(fp, " YES   ");
303
304         if (zpool_prop_values(prop) == NULL)
305                 (void) fprintf(fp, "-\n");
306         else
307                 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
308
309         return (ZPROP_CONT);
310 }
311
312 /*
313  * Display usage message.  If we're inside a command, display only the usage for
314  * that command.  Otherwise, iterate over the entire command table and display
315  * a complete usage message.
316  */
317 void
318 usage(boolean_t requested)
319 {
320         FILE *fp = requested ? stdout : stderr;
321
322         if (current_command == NULL) {
323                 int i;
324
325                 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
326                 (void) fprintf(fp,
327                     gettext("where 'command' is one of the following:\n\n"));
328
329                 for (i = 0; i < NCOMMAND; i++) {
330                         if (command_table[i].name == NULL)
331                                 (void) fprintf(fp, "\n");
332                         else
333                                 (void) fprintf(fp, "%s",
334                                     get_usage(command_table[i].usage));
335                 }
336         } else {
337                 (void) fprintf(fp, gettext("usage:\n"));
338                 (void) fprintf(fp, "%s", get_usage(current_command->usage));
339         }
340
341         if (current_command != NULL &&
342             ((strcmp(current_command->name, "set") == 0) ||
343             (strcmp(current_command->name, "get") == 0) ||
344             (strcmp(current_command->name, "list") == 0))) {
345
346                 (void) fprintf(fp,
347                     gettext("\nthe following properties are supported:\n"));
348
349                 (void) fprintf(fp, "\n\t%-15s  %s   %s\n\n",
350                     "PROPERTY", "EDIT", "VALUES");
351
352                 /* Iterate over all properties */
353                 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
354                     ZFS_TYPE_POOL);
355
356                 (void) fprintf(fp, "\t%-15s   ", "feature@...");
357                 (void) fprintf(fp, "YES   disabled | enabled | active\n");
358
359                 (void) fprintf(fp, gettext("\nThe feature@ properties must be "
360                     "appended with a feature name.\nSee zpool-features(7).\n"));
361         }
362
363         /*
364          * See comments at end of main().
365          */
366         if (getenv("ZFS_ABORT") != NULL) {
367                 (void) printf("dumping core by request\n");
368                 abort();
369         }
370
371         exit(requested ? 0 : 2);
372 }
373
374 void
375 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
376     boolean_t print_logs)
377 {
378         nvlist_t **child;
379         uint_t c, children;
380         char *vname;
381
382         if (name != NULL)
383                 (void) printf("\t%*s%s\n", indent, "", name);
384
385         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
386             &child, &children) != 0)
387                 return;
388
389         for (c = 0; c < children; c++) {
390                 uint64_t is_log = B_FALSE;
391
392                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
393                     &is_log);
394                 if ((is_log && !print_logs) || (!is_log && print_logs))
395                         continue;
396
397                 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
398                 print_vdev_tree(zhp, vname, child[c], indent + 2,
399                     B_FALSE);
400                 free(vname);
401         }
402 }
403
404 static boolean_t
405 prop_list_contains_feature(nvlist_t *proplist)
406 {
407         nvpair_t *nvp;
408         for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
409             nvp = nvlist_next_nvpair(proplist, nvp)) {
410                 if (zpool_prop_feature(nvpair_name(nvp)))
411                         return (B_TRUE);
412         }
413         return (B_FALSE);
414 }
415
416 /*
417  * Add a property pair (name, string-value) into a property nvlist.
418  */
419 static int
420 add_prop_list(const char *propname, char *propval, nvlist_t **props,
421     boolean_t poolprop)
422 {
423         zpool_prop_t prop = ZPROP_INVAL;
424         zfs_prop_t fprop;
425         nvlist_t *proplist;
426         const char *normnm;
427         char *strval;
428
429         if (*props == NULL &&
430             nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
431                 (void) fprintf(stderr,
432                     gettext("internal error: out of memory\n"));
433                 return (1);
434         }
435
436         proplist = *props;
437
438         if (poolprop) {
439                 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
440
441                 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
442                     !zpool_prop_feature(propname)) {
443                         (void) fprintf(stderr, gettext("property '%s' is "
444                             "not a valid pool property\n"), propname);
445                         return (2);
446                 }
447
448                 /*
449                  * feature@ properties and version should not be specified
450                  * at the same time.
451                  */
452                 if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
453                     nvlist_exists(proplist, vname)) ||
454                     (prop == ZPOOL_PROP_VERSION &&
455                     prop_list_contains_feature(proplist))) {
456                         (void) fprintf(stderr, gettext("'feature@' and "
457                             "'version' properties cannot be specified "
458                             "together\n"));
459                         return (2);
460                 }
461
462
463                 if (zpool_prop_feature(propname))
464                         normnm = propname;
465                 else
466                         normnm = zpool_prop_to_name(prop);
467         } else {
468                 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
469                         normnm = zfs_prop_to_name(fprop);
470                 } else {
471                         normnm = propname;
472                 }
473         }
474
475         if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
476             prop != ZPOOL_PROP_CACHEFILE) {
477                 (void) fprintf(stderr, gettext("property '%s' "
478                     "specified multiple times\n"), propname);
479                 return (2);
480         }
481
482         if (nvlist_add_string(proplist, normnm, propval) != 0) {
483                 (void) fprintf(stderr, gettext("internal "
484                     "error: out of memory\n"));
485                 return (1);
486         }
487
488         return (0);
489 }
490
491 /*
492  * zpool add [-fn] <pool> <vdev> ...
493  *
494  *      -f      Force addition of devices, even if they appear in use
495  *      -n      Do not add the devices, but display the resulting layout if
496  *              they were to be added.
497  *
498  * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
499  * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
500  * libzfs.
501  */
502 int
503 zpool_do_add(int argc, char **argv)
504 {
505         boolean_t force = B_FALSE;
506         boolean_t dryrun = B_FALSE;
507         int c;
508         nvlist_t *nvroot;
509         char *poolname;
510         zpool_boot_label_t boot_type;
511         uint64_t boot_size;
512         int ret;
513         zpool_handle_t *zhp;
514         nvlist_t *config;
515
516         /* check options */
517         while ((c = getopt(argc, argv, "fn")) != -1) {
518                 switch (c) {
519                 case 'f':
520                         force = B_TRUE;
521                         break;
522                 case 'n':
523                         dryrun = B_TRUE;
524                         break;
525                 case '?':
526                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
527                             optopt);
528                         usage(B_FALSE);
529                 }
530         }
531
532         argc -= optind;
533         argv += optind;
534
535         /* get pool name and check number of arguments */
536         if (argc < 1) {
537                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
538                 usage(B_FALSE);
539         }
540         if (argc < 2) {
541                 (void) fprintf(stderr, gettext("missing vdev specification\n"));
542                 usage(B_FALSE);
543         }
544
545         poolname = argv[0];
546
547         argc--;
548         argv++;
549
550         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
551                 return (1);
552
553         if ((config = zpool_get_config(zhp, NULL)) == NULL) {
554                 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
555                     poolname);
556                 zpool_close(zhp);
557                 return (1);
558         }
559
560         if (zpool_is_bootable(zhp))
561                 boot_type = ZPOOL_COPY_BOOT_LABEL;
562         else
563                 boot_type = ZPOOL_NO_BOOT_LABEL;
564
565         /* pass off to get_vdev_spec for processing */
566         boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
567         nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
568             boot_type, boot_size, argc, argv);
569         if (nvroot == NULL) {
570                 zpool_close(zhp);
571                 return (1);
572         }
573
574         if (dryrun) {
575                 nvlist_t *poolnvroot;
576
577                 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
578                     &poolnvroot) == 0);
579
580                 (void) printf(gettext("would update '%s' to the following "
581                     "configuration:\n"), zpool_get_name(zhp));
582
583                 /* print original main pool and new tree */
584                 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
585                 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
586
587                 /* Do the same for the logs */
588                 if (num_logs(poolnvroot) > 0) {
589                         print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
590                         print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
591                 } else if (num_logs(nvroot) > 0) {
592                         print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
593                 }
594
595                 ret = 0;
596         } else {
597                 ret = (zpool_add(zhp, nvroot) != 0);
598         }
599
600         nvlist_free(nvroot);
601         zpool_close(zhp);
602
603         return (ret);
604 }
605
606 /*
607  * zpool remove  <pool> <vdev> ...
608  *
609  * Removes the given vdev from the pool.
610  */
611 int
612 zpool_do_remove(int argc, char **argv)
613 {
614         char *poolname;
615         int i, ret = 0;
616         zpool_handle_t *zhp;
617         boolean_t stop = B_FALSE;
618         boolean_t noop = B_FALSE;
619         boolean_t parsable = B_FALSE;
620         char c;
621
622         /* check options */
623         while ((c = getopt(argc, argv, "nps")) != -1) {
624                 switch (c) {
625                 case 'n':
626                         noop = B_TRUE;
627                         break;
628                 case 'p':
629                         parsable = B_TRUE;
630                         break;
631                 case 's':
632                         stop = B_TRUE;
633                         break;
634                 case '?':
635                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
636                             optopt);
637                         usage(B_FALSE);
638                 }
639         }
640
641         argc -= optind;
642         argv += optind;
643
644         /* get pool name and check number of arguments */
645         if (argc < 1) {
646                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
647                 usage(B_FALSE);
648         }
649
650         poolname = argv[0];
651
652         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
653                 return (1);
654
655         if (stop && noop) {
656                 (void) fprintf(stderr, gettext("stop request ignored\n"));
657                 return (0);
658         }
659
660         if (stop) {
661                 if (argc > 1) {
662                         (void) fprintf(stderr, gettext("too many arguments\n"));
663                         usage(B_FALSE);
664                 }
665                 if (zpool_vdev_remove_cancel(zhp) != 0)
666                         ret = 1;
667         } else {
668                 if (argc < 2) {
669                         (void) fprintf(stderr, gettext("missing device\n"));
670                         usage(B_FALSE);
671                 }
672
673                 for (i = 1; i < argc; i++) {
674                         if (noop) {
675                                 uint64_t size;
676
677                                 if (zpool_vdev_indirect_size(zhp, argv[i],
678                                     &size) != 0) {
679                                         ret = 1;
680                                         break;
681                                 }
682                                 if (parsable) {
683                                         (void) printf("%s %llu\n",
684                                             argv[i], size);
685                                 } else {
686                                         char valstr[32];
687                                         zfs_nicenum(size, valstr,
688                                             sizeof (valstr));
689                                         (void) printf("Memory that will be "
690                                             "used after removing %s: %s\n",
691                                             argv[i], valstr);
692                                 }
693                         } else {
694                                 if (zpool_vdev_remove(zhp, argv[i]) != 0)
695                                         ret = 1;
696                         }
697                 }
698         }
699
700         return (ret);
701 }
702
703 /*
704  * zpool labelclear [-f] <vdev>
705  *
706  *      -f      Force clearing the label for the vdevs which are members of
707  *              the exported or foreign pools.
708  *
709  * Verifies that the vdev is not active and zeros out the label information
710  * on the device.
711  */
712 int
713 zpool_do_labelclear(int argc, char **argv)
714 {
715         char vdev[MAXPATHLEN];
716         char *name = NULL;
717         struct stat st;
718         int c, fd, ret = 0;
719         nvlist_t *config;
720         pool_state_t state;
721         boolean_t inuse = B_FALSE;
722         boolean_t force = B_FALSE;
723
724         /* check options */
725         while ((c = getopt(argc, argv, "f")) != -1) {
726                 switch (c) {
727                 case 'f':
728                         force = B_TRUE;
729                         break;
730                 default:
731                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
732                             optopt);
733                         usage(B_FALSE);
734                 }
735         }
736
737         argc -= optind;
738         argv += optind;
739
740         /* get vdev name */
741         if (argc < 1) {
742                 (void) fprintf(stderr, gettext("missing vdev name\n"));
743                 usage(B_FALSE);
744         }
745         if (argc > 1) {
746                 (void) fprintf(stderr, gettext("too many arguments\n"));
747                 usage(B_FALSE);
748         }
749
750         /*
751          * Check if we were given absolute path and use it as is.
752          * Otherwise if the provided vdev name doesn't point to a file,
753          * try prepending dsk path and appending s0.
754          */
755         (void) strlcpy(vdev, argv[0], sizeof (vdev));
756         if (vdev[0] != '/' && stat(vdev, &st) != 0) {
757                 char *s;
758
759                 (void) snprintf(vdev, sizeof (vdev), "%s/%s",
760 #ifdef illumos
761                     ZFS_DISK_ROOT, argv[0]);
762                 if ((s = strrchr(argv[0], 's')) == NULL ||
763                     !isdigit(*(s + 1)))
764                         (void) strlcat(vdev, "s0", sizeof (vdev));
765 #else
766                     "/dev", argv[0]);
767 #endif
768                 if (stat(vdev, &st) != 0) {
769                         (void) fprintf(stderr, gettext(
770                             "failed to find device %s, try specifying absolute "
771                             "path instead\n"), argv[0]);
772                         return (1);
773                 }
774         }
775
776         if ((fd = open(vdev, O_RDWR)) < 0) {
777                 (void) fprintf(stderr, gettext("failed to open %s: %s\n"),
778                     vdev, strerror(errno));
779                 return (1);
780         }
781
782         if (zpool_read_label(fd, &config) != 0) {
783                 (void) fprintf(stderr,
784                     gettext("failed to read label from %s\n"), vdev);
785                 return (1);
786         }
787         nvlist_free(config);
788
789         ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse);
790         if (ret != 0) {
791                 (void) fprintf(stderr,
792                     gettext("failed to check state for %s\n"), vdev);
793                 return (1);
794         }
795
796         if (!inuse)
797                 goto wipe_label;
798
799         switch (state) {
800         default:
801         case POOL_STATE_ACTIVE:
802         case POOL_STATE_SPARE:
803         case POOL_STATE_L2CACHE:
804                 (void) fprintf(stderr, gettext(
805                     "%s is a member (%s) of pool \"%s\"\n"),
806                     vdev, zpool_pool_state_to_name(state), name);
807                 ret = 1;
808                 goto errout;
809
810         case POOL_STATE_EXPORTED:
811                 if (force)
812                         break;
813                 (void) fprintf(stderr, gettext(
814                     "use '-f' to override the following error:\n"
815                     "%s is a member of exported pool \"%s\"\n"),
816                     vdev, name);
817                 ret = 1;
818                 goto errout;
819
820         case POOL_STATE_POTENTIALLY_ACTIVE:
821                 if (force)
822                         break;
823                 (void) fprintf(stderr, gettext(
824                     "use '-f' to override the following error:\n"
825                     "%s is a member of potentially active pool \"%s\"\n"),
826                     vdev, name);
827                 ret = 1;
828                 goto errout;
829
830         case POOL_STATE_DESTROYED:
831                 /* inuse should never be set for a destroyed pool */
832                 assert(0);
833                 break;
834         }
835
836 wipe_label:
837         ret = zpool_clear_label(fd);
838         if (ret != 0) {
839                 (void) fprintf(stderr,
840                     gettext("failed to clear label for %s\n"), vdev);
841         }
842
843 errout:
844         free(name);
845         (void) close(fd);
846
847         return (ret);
848 }
849
850 /*
851  * zpool create [-fnd] [-B] [-o property=value] ...
852  *              [-O file-system-property=value] ...
853  *              [-R root] [-m mountpoint] <pool> <dev> ...
854  *
855  *      -B      Create boot partition.
856  *      -f      Force creation, even if devices appear in use
857  *      -n      Do not create the pool, but display the resulting layout if it
858  *              were to be created.
859  *      -R      Create a pool under an alternate root
860  *      -m      Set default mountpoint for the root dataset.  By default it's
861  *              '/<pool>'
862  *      -o      Set property=value.
863  *      -d      Don't automatically enable all supported pool features
864  *              (individual features can be enabled with -o).
865  *      -O      Set fsproperty=value in the pool's root file system
866  *
867  * Creates the named pool according to the given vdev specification.  The
868  * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c.  Once
869  * we get the nvlist back from get_vdev_spec(), we either print out the contents
870  * (if '-n' was specified), or pass it to libzfs to do the creation.
871  */
872
873 #define SYSTEM256       (256 * 1024 * 1024)
874 int
875 zpool_do_create(int argc, char **argv)
876 {
877         boolean_t force = B_FALSE;
878         boolean_t dryrun = B_FALSE;
879         boolean_t enable_all_pool_feat = B_TRUE;
880         zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL;
881         uint64_t boot_size = 0;
882         int c;
883         nvlist_t *nvroot = NULL;
884         char *poolname;
885         int ret = 1;
886         char *altroot = NULL;
887         char *mountpoint = NULL;
888         nvlist_t *fsprops = NULL;
889         nvlist_t *props = NULL;
890         char *propval;
891
892         /* check options */
893         while ((c = getopt(argc, argv, ":fndBR:m:o:O:")) != -1) {
894                 switch (c) {
895                 case 'f':
896                         force = B_TRUE;
897                         break;
898                 case 'n':
899                         dryrun = B_TRUE;
900                         break;
901                 case 'd':
902                         enable_all_pool_feat = B_FALSE;
903                         break;
904                 case 'B':
905 #ifdef illumos
906                         /*
907                          * We should create the system partition.
908                          * Also make sure the size is set.
909                          */
910                         boot_type = ZPOOL_CREATE_BOOT_LABEL;
911                         if (boot_size == 0)
912                                 boot_size = SYSTEM256;
913                         break;
914 #else
915                         (void) fprintf(stderr,
916                             gettext("option '%c' is not supported\n"),
917                             optopt);
918                         goto badusage;
919 #endif
920                 case 'R':
921                         altroot = optarg;
922                         if (add_prop_list(zpool_prop_to_name(
923                             ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
924                                 goto errout;
925                         if (nvlist_lookup_string(props,
926                             zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
927                             &propval) == 0)
928                                 break;
929                         if (add_prop_list(zpool_prop_to_name(
930                             ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
931                                 goto errout;
932                         break;
933                 case 'm':
934                         /* Equivalent to -O mountpoint=optarg */
935                         mountpoint = optarg;
936                         break;
937                 case 'o':
938                         if ((propval = strchr(optarg, '=')) == NULL) {
939                                 (void) fprintf(stderr, gettext("missing "
940                                     "'=' for -o option\n"));
941                                 goto errout;
942                         }
943                         *propval = '\0';
944                         propval++;
945
946                         if (add_prop_list(optarg, propval, &props, B_TRUE))
947                                 goto errout;
948
949                         /*
950                          * Get bootsize value for make_root_vdev().
951                          */
952                         if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) {
953                                 if (zfs_nicestrtonum(g_zfs, propval,
954                                     &boot_size) < 0 || boot_size == 0) {
955                                         (void) fprintf(stderr,
956                                             gettext("bad boot partition size "
957                                             "'%s': %s\n"),  propval,
958                                             libzfs_error_description(g_zfs));
959                                         goto errout;
960                                 }
961                         }
962
963                         /*
964                          * If the user is creating a pool that doesn't support
965                          * feature flags, don't enable any features.
966                          */
967                         if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
968                                 char *end;
969                                 u_longlong_t ver;
970
971                                 ver = strtoull(propval, &end, 10);
972                                 if (*end == '\0' &&
973                                     ver < SPA_VERSION_FEATURES) {
974                                         enable_all_pool_feat = B_FALSE;
975                                 }
976                         }
977                         if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
978                                 altroot = propval;
979                         break;
980                 case 'O':
981                         if ((propval = strchr(optarg, '=')) == NULL) {
982                                 (void) fprintf(stderr, gettext("missing "
983                                     "'=' for -O option\n"));
984                                 goto errout;
985                         }
986                         *propval = '\0';
987                         propval++;
988
989                         /*
990                          * Mountpoints are checked and then added later.
991                          * Uniquely among properties, they can be specified
992                          * more than once, to avoid conflict with -m.
993                          */
994                         if (0 == strcmp(optarg,
995                             zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
996                                 mountpoint = propval;
997                         } else if (add_prop_list(optarg, propval, &fsprops,
998                             B_FALSE)) {
999                                 goto errout;
1000                         }
1001                         break;
1002                 case ':':
1003                         (void) fprintf(stderr, gettext("missing argument for "
1004                             "'%c' option\n"), optopt);
1005                         goto badusage;
1006                 case '?':
1007                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1008                             optopt);
1009                         goto badusage;
1010                 }
1011         }
1012
1013         argc -= optind;
1014         argv += optind;
1015
1016         /* get pool name and check number of arguments */
1017         if (argc < 1) {
1018                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
1019                 goto badusage;
1020         }
1021         if (argc < 2) {
1022                 (void) fprintf(stderr, gettext("missing vdev specification\n"));
1023                 goto badusage;
1024         }
1025
1026         poolname = argv[0];
1027
1028         /*
1029          * As a special case, check for use of '/' in the name, and direct the
1030          * user to use 'zfs create' instead.
1031          */
1032         if (strchr(poolname, '/') != NULL) {
1033                 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
1034                     "character '/' in pool name\n"), poolname);
1035                 (void) fprintf(stderr, gettext("use 'zfs create' to "
1036                     "create a dataset\n"));
1037                 goto errout;
1038         }
1039
1040         /*
1041          * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used,
1042          * and not set otherwise.
1043          */
1044         if (boot_type == ZPOOL_CREATE_BOOT_LABEL) {
1045                 const char *propname;
1046                 char *strptr, *buf = NULL;
1047                 int rv;
1048
1049                 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1050                 if (nvlist_lookup_string(props, propname, &strptr) != 0) {
1051                         (void) asprintf(&buf, "%" PRIu64, boot_size);
1052                         if (buf == NULL) {
1053                                 (void) fprintf(stderr,
1054                                     gettext("internal error: out of memory\n"));
1055                                 goto errout;
1056                         }
1057                         rv = add_prop_list(propname, buf, &props, B_TRUE);
1058                         free(buf);
1059                         if (rv != 0)
1060                                 goto errout;
1061                 }
1062         } else {
1063                 const char *propname;
1064                 char *strptr;
1065
1066                 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1067                 if (nvlist_lookup_string(props, propname, &strptr) == 0) {
1068                         (void) fprintf(stderr, gettext("error: setting boot "
1069                             "partition size requires option '-B'\n"));
1070                         goto errout;
1071                 }
1072         }
1073
1074         /* pass off to get_vdev_spec for bulk processing */
1075         nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
1076             boot_type, boot_size, argc - 1, argv + 1);
1077         if (nvroot == NULL)
1078                 goto errout;
1079
1080         /* make_root_vdev() allows 0 toplevel children if there are spares */
1081         if (!zfs_allocatable_devs(nvroot)) {
1082                 (void) fprintf(stderr, gettext("invalid vdev "
1083                     "specification: at least one toplevel vdev must be "
1084                     "specified\n"));
1085                 goto errout;
1086         }
1087
1088         if (altroot != NULL && altroot[0] != '/') {
1089                 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
1090                     "must be an absolute path\n"), altroot);
1091                 goto errout;
1092         }
1093
1094         /*
1095          * Check the validity of the mountpoint and direct the user to use the
1096          * '-m' mountpoint option if it looks like its in use.
1097          * Ignore the checks if the '-f' option is given.
1098          */
1099         if (!force && (mountpoint == NULL ||
1100             (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
1101             strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0))) {
1102                 char buf[MAXPATHLEN];
1103                 DIR *dirp;
1104
1105                 if (mountpoint && mountpoint[0] != '/') {
1106                         (void) fprintf(stderr, gettext("invalid mountpoint "
1107                             "'%s': must be an absolute path, 'legacy', or "
1108                             "'none'\n"), mountpoint);
1109                         goto errout;
1110                 }
1111
1112                 if (mountpoint == NULL) {
1113                         if (altroot != NULL)
1114                                 (void) snprintf(buf, sizeof (buf), "%s/%s",
1115                                     altroot, poolname);
1116                         else
1117                                 (void) snprintf(buf, sizeof (buf), "/%s",
1118                                     poolname);
1119                 } else {
1120                         if (altroot != NULL)
1121                                 (void) snprintf(buf, sizeof (buf), "%s%s",
1122                                     altroot, mountpoint);
1123                         else
1124                                 (void) snprintf(buf, sizeof (buf), "%s",
1125                                     mountpoint);
1126                 }
1127
1128                 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
1129                         (void) fprintf(stderr, gettext("mountpoint '%s' : "
1130                             "%s\n"), buf, strerror(errno));
1131                         (void) fprintf(stderr, gettext("use '-m' "
1132                             "option to provide a different default\n"));
1133                         goto errout;
1134                 } else if (dirp) {
1135                         int count = 0;
1136
1137                         while (count < 3 && readdir(dirp) != NULL)
1138                                 count++;
1139                         (void) closedir(dirp);
1140
1141                         if (count > 2) {
1142                                 (void) fprintf(stderr, gettext("mountpoint "
1143                                     "'%s' exists and is not empty\n"), buf);
1144                                 (void) fprintf(stderr, gettext("use '-m' "
1145                                     "option to provide a "
1146                                     "different default\n"));
1147                                 goto errout;
1148                         }
1149                 }
1150         }
1151
1152         /*
1153          * Now that the mountpoint's validity has been checked, ensure that
1154          * the property is set appropriately prior to creating the pool.
1155          */
1156         if (mountpoint != NULL) {
1157                 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
1158                     mountpoint, &fsprops, B_FALSE);
1159                 if (ret != 0)
1160                         goto errout;
1161         }
1162
1163         ret = 1;
1164         if (dryrun) {
1165                 /*
1166                  * For a dry run invocation, print out a basic message and run
1167                  * through all the vdevs in the list and print out in an
1168                  * appropriate hierarchy.
1169                  */
1170                 (void) printf(gettext("would create '%s' with the "
1171                     "following layout:\n\n"), poolname);
1172
1173                 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
1174                 if (num_logs(nvroot) > 0)
1175                         print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
1176
1177                 ret = 0;
1178         } else {
1179                 /*
1180                  * Hand off to libzfs.
1181                  */
1182                 if (enable_all_pool_feat) {
1183                         spa_feature_t i;
1184                         for (i = 0; i < SPA_FEATURES; i++) {
1185                                 char propname[MAXPATHLEN];
1186                                 zfeature_info_t *feat = &spa_feature_table[i];
1187
1188                                 (void) snprintf(propname, sizeof (propname),
1189                                     "feature@%s", feat->fi_uname);
1190
1191                                 /*
1192                                  * Skip feature if user specified it manually
1193                                  * on the command line.
1194                                  */
1195                                 if (nvlist_exists(props, propname))
1196                                         continue;
1197
1198                                 ret = add_prop_list(propname,
1199                                     ZFS_FEATURE_ENABLED, &props, B_TRUE);
1200                                 if (ret != 0)
1201                                         goto errout;
1202                         }
1203                 }
1204
1205                 ret = 1;
1206                 if (zpool_create(g_zfs, poolname,
1207                     nvroot, props, fsprops) == 0) {
1208                         zfs_handle_t *pool = zfs_open(g_zfs, poolname,
1209                             ZFS_TYPE_FILESYSTEM);
1210                         if (pool != NULL) {
1211                                 if (zfs_mount(pool, NULL, 0) == 0)
1212                                         ret = zfs_shareall(pool);
1213                                 zfs_close(pool);
1214                         }
1215                 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
1216                         (void) fprintf(stderr, gettext("pool name may have "
1217                             "been omitted\n"));
1218                 }
1219         }
1220
1221 errout:
1222         nvlist_free(nvroot);
1223         nvlist_free(fsprops);
1224         nvlist_free(props);
1225         return (ret);
1226 badusage:
1227         nvlist_free(fsprops);
1228         nvlist_free(props);
1229         usage(B_FALSE);
1230         return (2);
1231 }
1232
1233 /*
1234  * zpool destroy <pool>
1235  *
1236  *      -f      Forcefully unmount any datasets
1237  *
1238  * Destroy the given pool.  Automatically unmounts any datasets in the pool.
1239  */
1240 int
1241 zpool_do_destroy(int argc, char **argv)
1242 {
1243         boolean_t force = B_FALSE;
1244         int c;
1245         char *pool;
1246         zpool_handle_t *zhp;
1247         int ret;
1248
1249         /* check options */
1250         while ((c = getopt(argc, argv, "f")) != -1) {
1251                 switch (c) {
1252                 case 'f':
1253                         force = B_TRUE;
1254                         break;
1255                 case '?':
1256                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1257                             optopt);
1258                         usage(B_FALSE);
1259                 }
1260         }
1261
1262         argc -= optind;
1263         argv += optind;
1264
1265         /* check arguments */
1266         if (argc < 1) {
1267                 (void) fprintf(stderr, gettext("missing pool argument\n"));
1268                 usage(B_FALSE);
1269         }
1270         if (argc > 1) {
1271                 (void) fprintf(stderr, gettext("too many arguments\n"));
1272                 usage(B_FALSE);
1273         }
1274
1275         pool = argv[0];
1276
1277         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1278                 /*
1279                  * As a special case, check for use of '/' in the name, and
1280                  * direct the user to use 'zfs destroy' instead.
1281                  */
1282                 if (strchr(pool, '/') != NULL)
1283                         (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1284                             "destroy a dataset\n"));
1285                 return (1);
1286         }
1287
1288         if (zpool_disable_datasets(zhp, force) != 0) {
1289                 (void) fprintf(stderr, gettext("could not destroy '%s': "
1290                     "could not unmount datasets\n"), zpool_get_name(zhp));
1291                 return (1);
1292         }
1293
1294         /* The history must be logged as part of the export */
1295         log_history = B_FALSE;
1296
1297         ret = (zpool_destroy(zhp, history_str) != 0);
1298
1299         zpool_close(zhp);
1300
1301         return (ret);
1302 }
1303
1304 /*
1305  * zpool export [-f] <pool> ...
1306  *
1307  *      -f      Forcefully unmount datasets
1308  *
1309  * Export the given pools.  By default, the command will attempt to cleanly
1310  * unmount any active datasets within the pool.  If the '-f' flag is specified,
1311  * then the datasets will be forcefully unmounted.
1312  */
1313 int
1314 zpool_do_export(int argc, char **argv)
1315 {
1316         boolean_t force = B_FALSE;
1317         boolean_t hardforce = B_FALSE;
1318         int c;
1319         zpool_handle_t *zhp;
1320         int ret;
1321         int i;
1322
1323         /* check options */
1324         while ((c = getopt(argc, argv, "fF")) != -1) {
1325                 switch (c) {
1326                 case 'f':
1327                         force = B_TRUE;
1328                         break;
1329                 case 'F':
1330                         hardforce = B_TRUE;
1331                         break;
1332                 case '?':
1333                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1334                             optopt);
1335                         usage(B_FALSE);
1336                 }
1337         }
1338
1339         argc -= optind;
1340         argv += optind;
1341
1342         /* check arguments */
1343         if (argc < 1) {
1344                 (void) fprintf(stderr, gettext("missing pool argument\n"));
1345                 usage(B_FALSE);
1346         }
1347
1348         ret = 0;
1349         for (i = 0; i < argc; i++) {
1350                 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1351                         ret = 1;
1352                         continue;
1353                 }
1354
1355                 if (zpool_disable_datasets(zhp, force) != 0) {
1356                         ret = 1;
1357                         zpool_close(zhp);
1358                         continue;
1359                 }
1360
1361                 /* The history must be logged as part of the export */
1362                 log_history = B_FALSE;
1363
1364                 if (hardforce) {
1365                         if (zpool_export_force(zhp, history_str) != 0)
1366                                 ret = 1;
1367                 } else if (zpool_export(zhp, force, history_str) != 0) {
1368                         ret = 1;
1369                 }
1370
1371                 zpool_close(zhp);
1372         }
1373
1374         return (ret);
1375 }
1376
1377 /*
1378  * Given a vdev configuration, determine the maximum width needed for the device
1379  * name column.
1380  */
1381 static int
1382 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
1383 {
1384         char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
1385         nvlist_t **child;
1386         uint_t c, children;
1387         int ret;
1388
1389         if (strlen(name) + depth > max)
1390                 max = strlen(name) + depth;
1391
1392         free(name);
1393
1394         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1395             &child, &children) == 0) {
1396                 for (c = 0; c < children; c++)
1397                         if ((ret = max_width(zhp, child[c], depth + 2,
1398                             max)) > max)
1399                                 max = ret;
1400         }
1401
1402         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1403             &child, &children) == 0) {
1404                 for (c = 0; c < children; c++)
1405                         if ((ret = max_width(zhp, child[c], depth + 2,
1406                             max)) > max)
1407                                 max = ret;
1408         }
1409
1410         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1411             &child, &children) == 0) {
1412                 for (c = 0; c < children; c++)
1413                         if ((ret = max_width(zhp, child[c], depth + 2,
1414                             max)) > max)
1415                                 max = ret;
1416         }
1417
1418
1419         return (max);
1420 }
1421
1422 typedef struct spare_cbdata {
1423         uint64_t        cb_guid;
1424         zpool_handle_t  *cb_zhp;
1425 } spare_cbdata_t;
1426
1427 static boolean_t
1428 find_vdev(nvlist_t *nv, uint64_t search)
1429 {
1430         uint64_t guid;
1431         nvlist_t **child;
1432         uint_t c, children;
1433
1434         if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
1435             search == guid)
1436                 return (B_TRUE);
1437
1438         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1439             &child, &children) == 0) {
1440                 for (c = 0; c < children; c++)
1441                         if (find_vdev(child[c], search))
1442                                 return (B_TRUE);
1443         }
1444
1445         return (B_FALSE);
1446 }
1447
1448 static int
1449 find_spare(zpool_handle_t *zhp, void *data)
1450 {
1451         spare_cbdata_t *cbp = data;
1452         nvlist_t *config, *nvroot;
1453
1454         config = zpool_get_config(zhp, NULL);
1455         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1456             &nvroot) == 0);
1457
1458         if (find_vdev(nvroot, cbp->cb_guid)) {
1459                 cbp->cb_zhp = zhp;
1460                 return (1);
1461         }
1462
1463         zpool_close(zhp);
1464         return (0);
1465 }
1466
1467 /*
1468  * Print out configuration state as requested by status_callback.
1469  */
1470 void
1471 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
1472     int namewidth, int depth, boolean_t isspare)
1473 {
1474         nvlist_t **child;
1475         uint_t c, vsc, children;
1476         pool_scan_stat_t *ps = NULL;
1477         vdev_stat_t *vs;
1478         char rbuf[6], wbuf[6], cbuf[6];
1479         char *vname;
1480         uint64_t notpresent;
1481         uint64_t ashift;
1482         spare_cbdata_t cb;
1483         const char *state;
1484         char *type;
1485
1486         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1487             &child, &children) != 0)
1488                 children = 0;
1489
1490         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1491             (uint64_t **)&vs, &vsc) == 0);
1492
1493         verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1494
1495         if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
1496                 return;
1497
1498         state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1499         if (isspare) {
1500                 /*
1501                  * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1502                  * online drives.
1503                  */
1504                 if (vs->vs_aux == VDEV_AUX_SPARED)
1505                         state = "INUSE";
1506                 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1507                         state = "AVAIL";
1508         }
1509
1510         (void) printf("\t%*s%-*s  %-8s", depth, "", namewidth - depth,
1511             name, state);
1512
1513         if (!isspare) {
1514                 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1515                 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1516                 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1517                 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1518         }
1519
1520         if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
1521             &notpresent) == 0 ||
1522             vs->vs_state <= VDEV_STATE_CANT_OPEN) {
1523                 char *path;
1524                 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0)
1525                         (void) printf("  was %s", path);
1526         } else if (vs->vs_aux != 0) {
1527                 (void) printf("  ");
1528
1529                 switch (vs->vs_aux) {
1530                 case VDEV_AUX_OPEN_FAILED:
1531                         (void) printf(gettext("cannot open"));
1532                         break;
1533
1534                 case VDEV_AUX_BAD_GUID_SUM:
1535                         (void) printf(gettext("missing device"));
1536                         break;
1537
1538                 case VDEV_AUX_NO_REPLICAS:
1539                         (void) printf(gettext("insufficient replicas"));
1540                         break;
1541
1542                 case VDEV_AUX_VERSION_NEWER:
1543                         (void) printf(gettext("newer version"));
1544                         break;
1545
1546                 case VDEV_AUX_UNSUP_FEAT:
1547                         (void) printf(gettext("unsupported feature(s)"));
1548                         break;
1549
1550                 case VDEV_AUX_ASHIFT_TOO_BIG:
1551                         (void) printf(gettext("unsupported minimum blocksize"));
1552                         break;
1553
1554                 case VDEV_AUX_SPARED:
1555                         verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1556                             &cb.cb_guid) == 0);
1557                         if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
1558                                 if (strcmp(zpool_get_name(cb.cb_zhp),
1559                                     zpool_get_name(zhp)) == 0)
1560                                         (void) printf(gettext("currently in "
1561                                             "use"));
1562                                 else
1563                                         (void) printf(gettext("in use by "
1564                                             "pool '%s'"),
1565                                             zpool_get_name(cb.cb_zhp));
1566                                 zpool_close(cb.cb_zhp);
1567                         } else {
1568                                 (void) printf(gettext("currently in use"));
1569                         }
1570                         break;
1571
1572                 case VDEV_AUX_ERR_EXCEEDED:
1573                         (void) printf(gettext("too many errors"));
1574                         break;
1575
1576                 case VDEV_AUX_IO_FAILURE:
1577                         (void) printf(gettext("experienced I/O failures"));
1578                         break;
1579
1580                 case VDEV_AUX_BAD_LOG:
1581                         (void) printf(gettext("bad intent log"));
1582                         break;
1583
1584                 case VDEV_AUX_EXTERNAL:
1585                         (void) printf(gettext("external device fault"));
1586                         break;
1587
1588                 case VDEV_AUX_SPLIT_POOL:
1589                         (void) printf(gettext("split into new pool"));
1590                         break;
1591
1592                 case VDEV_AUX_CHILDREN_OFFLINE:
1593                         (void) printf(gettext("all children offline"));
1594                         break;
1595
1596                 default:
1597                         (void) printf(gettext("corrupted data"));
1598                         break;
1599                 }
1600         } else if (children == 0 && !isspare &&
1601             VDEV_STAT_VALID(vs_physical_ashift, vsc) &&
1602             vs->vs_configured_ashift < vs->vs_physical_ashift) {
1603                 (void) printf(
1604                     gettext("  block size: %dB configured, %dB native"),
1605                     1 << vs->vs_configured_ashift, 1 << vs->vs_physical_ashift);
1606         }
1607
1608         (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1609             (uint64_t **)&ps, &c);
1610
1611         if (ps && ps->pss_state == DSS_SCANNING &&
1612             vs->vs_scan_processed != 0 && children == 0) {
1613                 (void) printf(gettext("  (%s)"),
1614                     (ps->pss_func == POOL_SCAN_RESILVER) ?
1615                     "resilvering" : "repairing");
1616         }
1617
1618         (void) printf("\n");
1619
1620         for (c = 0; c < children; c++) {
1621                 uint64_t islog = B_FALSE, ishole = B_FALSE;
1622
1623                 /* Don't print logs or holes here */
1624                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1625                     &islog);
1626                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1627                     &ishole);
1628                 if (islog || ishole)
1629                         continue;
1630                 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1631                 print_status_config(zhp, vname, child[c],
1632                     namewidth, depth + 2, isspare);
1633                 free(vname);
1634         }
1635 }
1636
1637
1638 /*
1639  * Print the configuration of an exported pool.  Iterate over all vdevs in the
1640  * pool, printing out the name and status for each one.
1641  */
1642 void
1643 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1644 {
1645         nvlist_t **child;
1646         uint_t c, children;
1647         vdev_stat_t *vs;
1648         char *type, *vname;
1649
1650         verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1651         if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
1652             strcmp(type, VDEV_TYPE_HOLE) == 0)
1653                 return;
1654
1655         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1656             (uint64_t **)&vs, &c) == 0);
1657
1658         (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1659         (void) printf("  %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1660
1661         if (vs->vs_aux != 0) {
1662                 (void) printf("  ");
1663
1664                 switch (vs->vs_aux) {
1665                 case VDEV_AUX_OPEN_FAILED:
1666                         (void) printf(gettext("cannot open"));
1667                         break;
1668
1669                 case VDEV_AUX_BAD_GUID_SUM:
1670                         (void) printf(gettext("missing device"));
1671                         break;
1672
1673                 case VDEV_AUX_NO_REPLICAS:
1674                         (void) printf(gettext("insufficient replicas"));
1675                         break;
1676
1677                 case VDEV_AUX_VERSION_NEWER:
1678                         (void) printf(gettext("newer version"));
1679                         break;
1680
1681                 case VDEV_AUX_UNSUP_FEAT:
1682                         (void) printf(gettext("unsupported feature(s)"));
1683                         break;
1684
1685                 case VDEV_AUX_ERR_EXCEEDED:
1686                         (void) printf(gettext("too many errors"));
1687                         break;
1688
1689                 case VDEV_AUX_CHILDREN_OFFLINE:
1690                         (void) printf(gettext("all children offline"));
1691                         break;
1692
1693                 default:
1694                         (void) printf(gettext("corrupted data"));
1695                         break;
1696                 }
1697         }
1698         (void) printf("\n");
1699
1700         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1701             &child, &children) != 0)
1702                 return;
1703
1704         for (c = 0; c < children; c++) {
1705                 uint64_t is_log = B_FALSE;
1706
1707                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1708                     &is_log);
1709                 if (is_log)
1710                         continue;
1711
1712                 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1713                 print_import_config(vname, child[c], namewidth, depth + 2);
1714                 free(vname);
1715         }
1716
1717         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1718             &child, &children) == 0) {
1719                 (void) printf(gettext("\tcache\n"));
1720                 for (c = 0; c < children; c++) {
1721                         vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1722                         (void) printf("\t  %s\n", vname);
1723                         free(vname);
1724                 }
1725         }
1726
1727         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1728             &child, &children) == 0) {
1729                 (void) printf(gettext("\tspares\n"));
1730                 for (c = 0; c < children; c++) {
1731                         vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1732                         (void) printf("\t  %s\n", vname);
1733                         free(vname);
1734                 }
1735         }
1736 }
1737
1738 /*
1739  * Print log vdevs.
1740  * Logs are recorded as top level vdevs in the main pool child array
1741  * but with "is_log" set to 1. We use either print_status_config() or
1742  * print_import_config() to print the top level logs then any log
1743  * children (eg mirrored slogs) are printed recursively - which
1744  * works because only the top level vdev is marked "is_log"
1745  */
1746 static void
1747 print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose)
1748 {
1749         uint_t c, children;
1750         nvlist_t **child;
1751
1752         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1753             &children) != 0)
1754                 return;
1755
1756         (void) printf(gettext("\tlogs\n"));
1757
1758         for (c = 0; c < children; c++) {
1759                 uint64_t is_log = B_FALSE;
1760                 char *name;
1761
1762                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1763                     &is_log);
1764                 if (!is_log)
1765                         continue;
1766                 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1767                 if (verbose)
1768                         print_status_config(zhp, name, child[c], namewidth,
1769                             2, B_FALSE);
1770                 else
1771                         print_import_config(name, child[c], namewidth, 2);
1772                 free(name);
1773         }
1774 }
1775
1776 /*
1777  * Display the status for the given pool.
1778  */
1779 static void
1780 show_import(nvlist_t *config)
1781 {
1782         uint64_t pool_state;
1783         vdev_stat_t *vs;
1784         char *name;
1785         uint64_t guid;
1786         char *msgid;
1787         nvlist_t *nvroot;
1788         int reason;
1789         const char *health;
1790         uint_t vsc;
1791         int namewidth;
1792         char *comment;
1793
1794         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1795             &name) == 0);
1796         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1797             &guid) == 0);
1798         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1799             &pool_state) == 0);
1800         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1801             &nvroot) == 0);
1802
1803         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
1804             (uint64_t **)&vs, &vsc) == 0);
1805         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1806
1807         reason = zpool_import_status(config, &msgid);
1808
1809         (void) printf(gettext("   pool: %s\n"), name);
1810         (void) printf(gettext("     id: %llu\n"), (u_longlong_t)guid);
1811         (void) printf(gettext("  state: %s"), health);
1812         if (pool_state == POOL_STATE_DESTROYED)
1813                 (void) printf(gettext(" (DESTROYED)"));
1814         (void) printf("\n");
1815
1816         switch (reason) {
1817         case ZPOOL_STATUS_MISSING_DEV_R:
1818         case ZPOOL_STATUS_MISSING_DEV_NR:
1819         case ZPOOL_STATUS_BAD_GUID_SUM:
1820                 (void) printf(gettext(" status: One or more devices are "
1821                     "missing from the system.\n"));
1822                 break;
1823
1824         case ZPOOL_STATUS_CORRUPT_LABEL_R:
1825         case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1826                 (void) printf(gettext(" status: One or more devices contains "
1827                     "corrupted data.\n"));
1828                 break;
1829
1830         case ZPOOL_STATUS_CORRUPT_DATA:
1831                 (void) printf(
1832                     gettext(" status: The pool data is corrupted.\n"));
1833                 break;
1834
1835         case ZPOOL_STATUS_OFFLINE_DEV:
1836                 (void) printf(gettext(" status: One or more devices "
1837                     "are offlined.\n"));
1838                 break;
1839
1840         case ZPOOL_STATUS_CORRUPT_POOL:
1841                 (void) printf(gettext(" status: The pool metadata is "
1842                     "corrupted.\n"));
1843                 break;
1844
1845         case ZPOOL_STATUS_VERSION_OLDER:
1846                 (void) printf(gettext(" status: The pool is formatted using a "
1847                     "legacy on-disk version.\n"));
1848                 break;
1849
1850         case ZPOOL_STATUS_VERSION_NEWER:
1851                 (void) printf(gettext(" status: The pool is formatted using an "
1852                     "incompatible version.\n"));
1853                 break;
1854
1855         case ZPOOL_STATUS_FEAT_DISABLED:
1856                 (void) printf(gettext(" status: Some supported features are "
1857                     "not enabled on the pool.\n"));
1858                 break;
1859
1860         case ZPOOL_STATUS_UNSUP_FEAT_READ:
1861                 (void) printf(gettext("status: The pool uses the following "
1862                     "feature(s) not supported on this system:\n"));
1863                 zpool_print_unsup_feat(config);
1864                 break;
1865
1866         case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1867                 (void) printf(gettext("status: The pool can only be accessed "
1868                     "in read-only mode on this system. It\n\tcannot be "
1869                     "accessed in read-write mode because it uses the "
1870                     "following\n\tfeature(s) not supported on this system:\n"));
1871                 zpool_print_unsup_feat(config);
1872                 break;
1873
1874         case ZPOOL_STATUS_HOSTID_MISMATCH:
1875                 (void) printf(gettext(" status: The pool was last accessed by "
1876                     "another system.\n"));
1877                 break;
1878
1879         case ZPOOL_STATUS_FAULTED_DEV_R:
1880         case ZPOOL_STATUS_FAULTED_DEV_NR:
1881                 (void) printf(gettext(" status: One or more devices are "
1882                     "faulted.\n"));
1883                 break;
1884
1885         case ZPOOL_STATUS_BAD_LOG:
1886                 (void) printf(gettext(" status: An intent log record cannot be "
1887                     "read.\n"));
1888                 break;
1889
1890         case ZPOOL_STATUS_RESILVERING:
1891                 (void) printf(gettext(" status: One or more devices were being "
1892                     "resilvered.\n"));
1893                 break;
1894
1895         case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
1896                 (void) printf(gettext("status: One or more devices were "
1897                     "configured to use a non-native block size.\n"
1898                     "\tExpect reduced performance.\n"));
1899                 break;
1900
1901         default:
1902                 /*
1903                  * No other status can be seen when importing pools.
1904                  */
1905                 assert(reason == ZPOOL_STATUS_OK);
1906         }
1907
1908         /*
1909          * Print out an action according to the overall state of the pool.
1910          */
1911         if (vs->vs_state == VDEV_STATE_HEALTHY) {
1912                 if (reason == ZPOOL_STATUS_VERSION_OLDER ||
1913                     reason == ZPOOL_STATUS_FEAT_DISABLED) {
1914                         (void) printf(gettext(" action: The pool can be "
1915                             "imported using its name or numeric identifier, "
1916                             "though\n\tsome features will not be available "
1917                             "without an explicit 'zpool upgrade'.\n"));
1918                 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
1919                         (void) printf(gettext(" action: The pool can be "
1920                             "imported using its name or numeric "
1921                             "identifier and\n\tthe '-f' flag.\n"));
1922                 } else {
1923                         (void) printf(gettext(" action: The pool can be "
1924                             "imported using its name or numeric "
1925                             "identifier.\n"));
1926                 }
1927         } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1928                 (void) printf(gettext(" action: The pool can be imported "
1929                     "despite missing or damaged devices.  The\n\tfault "
1930                     "tolerance of the pool may be compromised if imported.\n"));
1931         } else {
1932                 switch (reason) {
1933                 case ZPOOL_STATUS_VERSION_NEWER:
1934                         (void) printf(gettext(" action: The pool cannot be "
1935                             "imported.  Access the pool on a system running "
1936                             "newer\n\tsoftware, or recreate the pool from "
1937                             "backup.\n"));
1938                         break;
1939                 case ZPOOL_STATUS_UNSUP_FEAT_READ:
1940                         (void) printf(gettext("action: The pool cannot be "
1941                             "imported. Access the pool on a system that "
1942                             "supports\n\tthe required feature(s), or recreate "
1943                             "the pool from backup.\n"));
1944                         break;
1945                 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1946                         (void) printf(gettext("action: The pool cannot be "
1947                             "imported in read-write mode. Import the pool "
1948                             "with\n"
1949                             "\t\"-o readonly=on\", access the pool on a system "
1950                             "that supports the\n\trequired feature(s), or "
1951                             "recreate the pool from backup.\n"));
1952                         break;
1953                 case ZPOOL_STATUS_MISSING_DEV_R:
1954                 case ZPOOL_STATUS_MISSING_DEV_NR:
1955                 case ZPOOL_STATUS_BAD_GUID_SUM:
1956                         (void) printf(gettext(" action: The pool cannot be "
1957                             "imported. Attach the missing\n\tdevices and try "
1958                             "again.\n"));
1959                         break;
1960                 default:
1961                         (void) printf(gettext(" action: The pool cannot be "
1962                             "imported due to damaged devices or data.\n"));
1963                 }
1964         }
1965
1966         /* Print the comment attached to the pool. */
1967         if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
1968                 (void) printf(gettext("comment: %s\n"), comment);
1969
1970         /*
1971          * If the state is "closed" or "can't open", and the aux state
1972          * is "corrupt data":
1973          */
1974         if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1975             (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1976             (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1977                 if (pool_state == POOL_STATE_DESTROYED)
1978                         (void) printf(gettext("\tThe pool was destroyed, "
1979                             "but can be imported using the '-Df' flags.\n"));
1980                 else if (pool_state != POOL_STATE_EXPORTED)
1981                         (void) printf(gettext("\tThe pool may be active on "
1982                             "another system, but can be imported using\n\t"
1983                             "the '-f' flag.\n"));
1984         }
1985
1986         if (msgid != NULL)
1987                 (void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
1988                     msgid);
1989
1990         (void) printf(gettext(" config:\n\n"));
1991
1992         namewidth = max_width(NULL, nvroot, 0, 0);
1993         if (namewidth < 10)
1994                 namewidth = 10;
1995
1996         print_import_config(name, nvroot, namewidth, 0);
1997         if (num_logs(nvroot) > 0)
1998                 print_logs(NULL, nvroot, namewidth, B_FALSE);
1999
2000         if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
2001                 (void) printf(gettext("\n\tAdditional devices are known to "
2002                     "be part of this pool, though their\n\texact "
2003                     "configuration cannot be determined.\n"));
2004         }
2005 }
2006
2007 /*
2008  * Perform the import for the given configuration.  This passes the heavy
2009  * lifting off to zpool_import_props(), and then mounts the datasets contained
2010  * within the pool.
2011  */
2012 static int
2013 do_import(nvlist_t *config, const char *newname, const char *mntopts,
2014     nvlist_t *props, int flags)
2015 {
2016         zpool_handle_t *zhp;
2017         char *name;
2018         uint64_t state;
2019         uint64_t version;
2020
2021         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2022             &name) == 0);
2023
2024         verify(nvlist_lookup_uint64(config,
2025             ZPOOL_CONFIG_POOL_STATE, &state) == 0);
2026         verify(nvlist_lookup_uint64(config,
2027             ZPOOL_CONFIG_VERSION, &version) == 0);
2028         if (!SPA_VERSION_IS_SUPPORTED(version)) {
2029                 (void) fprintf(stderr, gettext("cannot import '%s': pool "
2030                     "is formatted using an unsupported ZFS version\n"), name);
2031                 return (1);
2032         } else if (state != POOL_STATE_EXPORTED &&
2033             !(flags & ZFS_IMPORT_ANY_HOST)) {
2034                 uint64_t hostid;
2035
2036                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
2037                     &hostid) == 0) {
2038                         if ((unsigned long)hostid != gethostid()) {
2039                                 char *hostname;
2040                                 uint64_t timestamp;
2041                                 time_t t;
2042
2043                                 verify(nvlist_lookup_string(config,
2044                                     ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
2045                                 verify(nvlist_lookup_uint64(config,
2046                                     ZPOOL_CONFIG_TIMESTAMP, &timestamp) == 0);
2047                                 t = timestamp;
2048                                 (void) fprintf(stderr, gettext("cannot import "
2049                                     "'%s': pool may be in use from other "
2050                                     "system, it was last accessed by %s "
2051                                     "(hostid: 0x%lx) on %s"), name, hostname,
2052                                     (unsigned long)hostid,
2053                                     asctime(localtime(&t)));
2054                                 (void) fprintf(stderr, gettext("use '-f' to "
2055                                     "import anyway\n"));
2056                                 return (1);
2057                         }
2058                 } else {
2059                         (void) fprintf(stderr, gettext("cannot import '%s': "
2060                             "pool may be in use from other system\n"), name);
2061                         (void) fprintf(stderr, gettext("use '-f' to import "
2062                             "anyway\n"));
2063                         return (1);
2064                 }
2065         }
2066
2067         if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2068                 return (1);
2069
2070         if (newname != NULL)
2071                 name = (char *)newname;
2072
2073         if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2074                 return (1);
2075
2076         if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2077             !(flags & ZFS_IMPORT_ONLY) &&
2078             zpool_enable_datasets(zhp, mntopts, 0) != 0) {
2079                 zpool_close(zhp);
2080                 return (1);
2081         }
2082
2083         zpool_close(zhp);
2084         return (0);
2085 }
2086
2087 /*
2088  * zpool checkpoint <pool>
2089  *       checkpoint --discard <pool>
2090  *
2091  *       -d         Discard the checkpoint from a checkpointed
2092  *       --discard  pool.
2093  *
2094  * Checkpoints the specified pool, by taking a "snapshot" of its
2095  * current state. A pool can only have one checkpoint at a time.
2096  */
2097 int
2098 zpool_do_checkpoint(int argc, char **argv)
2099 {
2100         boolean_t discard;
2101         char *pool;
2102         zpool_handle_t *zhp;
2103         int c, err;
2104
2105         struct option long_options[] = {
2106                 {"discard", no_argument, NULL, 'd'},
2107                 {0, 0, 0, 0}
2108         };
2109
2110         discard = B_FALSE;
2111         while ((c = getopt_long(argc, argv, ":d", long_options, NULL)) != -1) {
2112                 switch (c) {
2113                 case 'd':
2114                         discard = B_TRUE;
2115                         break;
2116                 case '?':
2117                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2118                             optopt);
2119                         usage(B_FALSE);
2120                 }
2121         }
2122
2123         argc -= optind;
2124         argv += optind;
2125
2126         if (argc < 1) {
2127                 (void) fprintf(stderr, gettext("missing pool argument\n"));
2128                 usage(B_FALSE);
2129         }
2130
2131         if (argc > 1) {
2132                 (void) fprintf(stderr, gettext("too many arguments\n"));
2133                 usage(B_FALSE);
2134         }
2135
2136         pool = argv[0];
2137
2138         if ((zhp = zpool_open(g_zfs, pool)) == NULL) {
2139                 /* As a special case, check for use of '/' in the name */
2140                 if (strchr(pool, '/') != NULL)
2141                         (void) fprintf(stderr, gettext("'zpool checkpoint' "
2142                             "doesn't work on datasets. To save the state "
2143                             "of a dataset from a specific point in time "
2144                             "please use 'zfs snapshot'\n"));
2145                 return (1);
2146         }
2147
2148         if (discard)
2149                 err = (zpool_discard_checkpoint(zhp) != 0);
2150         else
2151                 err = (zpool_checkpoint(zhp) != 0);
2152
2153         zpool_close(zhp);
2154
2155         return (err);
2156 }
2157
2158 #define CHECKPOINT_OPT  1024
2159
2160 /*
2161  * zpool import [-d dir] [-D]
2162  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2163  *              [-d dir | -c cachefile] [-f] -a
2164  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2165  *              [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
2166  *
2167  *       -c     Read pool information from a cachefile instead of searching
2168  *              devices.
2169  *
2170  *       -d     Scan in a specific directory, other than /dev/dsk.  More than
2171  *              one directory can be specified using multiple '-d' options.
2172  *
2173  *       -D     Scan for previously destroyed pools or import all or only
2174  *              specified destroyed pools.
2175  *
2176  *       -R     Temporarily import the pool, with all mountpoints relative to
2177  *              the given root.  The pool will remain exported when the machine
2178  *              is rebooted.
2179  *
2180  *       -V     Import even in the presence of faulted vdevs.  This is an
2181  *              intentionally undocumented option for testing purposes, and
2182  *              treats the pool configuration as complete, leaving any bad
2183  *              vdevs in the FAULTED state. In other words, it does verbatim
2184  *              import.
2185  *
2186  *       -f     Force import, even if it appears that the pool is active.
2187  *
2188  *       -F     Attempt rewind if necessary.
2189  *
2190  *       -n     See if rewind would work, but don't actually rewind.
2191  *
2192  *       -N     Import the pool but don't mount datasets.
2193  *
2194  *       -T     Specify a starting txg to use for import. This option is
2195  *              intentionally undocumented option for testing purposes.
2196  *
2197  *       -a     Import all pools found.
2198  *
2199  *       -o     Set property=value and/or temporary mount options (without '=').
2200  *
2201  *       --rewind-to-checkpoint
2202  *              Import the pool and revert back to the checkpoint.
2203  *
2204  * The import command scans for pools to import, and import pools based on pool
2205  * name and GUID.  The pool can also be renamed as part of the import process.
2206  */
2207 int
2208 zpool_do_import(int argc, char **argv)
2209 {
2210         char **searchdirs = NULL;
2211         int nsearch = 0;
2212         int c;
2213         int err = 0;
2214         nvlist_t *pools = NULL;
2215         boolean_t do_all = B_FALSE;
2216         boolean_t do_destroyed = B_FALSE;
2217         char *mntopts = NULL;
2218         nvpair_t *elem;
2219         nvlist_t *config;
2220         uint64_t searchguid = 0;
2221         char *searchname = NULL;
2222         char *propval;
2223         nvlist_t *found_config;
2224         nvlist_t *policy = NULL;
2225         nvlist_t *props = NULL;
2226         boolean_t first;
2227         int flags = ZFS_IMPORT_NORMAL;
2228         uint32_t rewind_policy = ZPOOL_NO_REWIND;
2229         boolean_t dryrun = B_FALSE;
2230         boolean_t do_rewind = B_FALSE;
2231         boolean_t xtreme_rewind = B_FALSE;
2232         uint64_t pool_state, txg = -1ULL;
2233         char *cachefile = NULL;
2234         importargs_t idata = { 0 };
2235         char *endptr;
2236
2237
2238         struct option long_options[] = {
2239                 {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT},
2240                 {0, 0, 0, 0}
2241         };
2242
2243         /* check options */
2244         while ((c = getopt_long(argc, argv, ":aCc:d:DEfFmnNo:rR:T:VX",
2245             long_options, NULL)) != -1) {
2246                 switch (c) {
2247                 case 'a':
2248                         do_all = B_TRUE;
2249                         break;
2250                 case 'c':
2251                         cachefile = optarg;
2252                         break;
2253                 case 'd':
2254                         if (searchdirs == NULL) {
2255                                 searchdirs = safe_malloc(sizeof (char *));
2256                         } else {
2257                                 char **tmp = safe_malloc((nsearch + 1) *
2258                                     sizeof (char *));
2259                                 bcopy(searchdirs, tmp, nsearch *
2260                                     sizeof (char *));
2261                                 free(searchdirs);
2262                                 searchdirs = tmp;
2263                         }
2264                         searchdirs[nsearch++] = optarg;
2265                         break;
2266                 case 'D':
2267                         do_destroyed = B_TRUE;
2268                         break;
2269                 case 'f':
2270                         flags |= ZFS_IMPORT_ANY_HOST;
2271                         break;
2272                 case 'F':
2273                         do_rewind = B_TRUE;
2274                         break;
2275                 case 'm':
2276                         flags |= ZFS_IMPORT_MISSING_LOG;
2277                         break;
2278                 case 'n':
2279                         dryrun = B_TRUE;
2280                         break;
2281                 case 'N':
2282                         flags |= ZFS_IMPORT_ONLY;
2283                         break;
2284                 case 'o':
2285                         if ((propval = strchr(optarg, '=')) != NULL) {
2286                                 *propval = '\0';
2287                                 propval++;
2288                                 if (add_prop_list(optarg, propval,
2289                                     &props, B_TRUE))
2290                                         goto error;
2291                         } else {
2292                                 mntopts = optarg;
2293                         }
2294                         break;
2295                 case 'R':
2296                         if (add_prop_list(zpool_prop_to_name(
2297                             ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2298                                 goto error;
2299                         if (nvlist_lookup_string(props,
2300                             zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
2301                             &propval) == 0)
2302                                 break;
2303                         if (add_prop_list(zpool_prop_to_name(
2304                             ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2305                                 goto error;
2306                         break;
2307                 case 'T':
2308                         errno = 0;
2309                         txg = strtoull(optarg, &endptr, 0);
2310                         if (errno != 0 || *endptr != '\0') {
2311                                 (void) fprintf(stderr,
2312                                     gettext("invalid txg value\n"));
2313                                 usage(B_FALSE);
2314                         }
2315                         rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2316                         break;
2317                 case 'V':
2318                         flags |= ZFS_IMPORT_VERBATIM;
2319                         break;
2320                 case 'X':
2321                         xtreme_rewind = B_TRUE;
2322                         break;
2323                 case CHECKPOINT_OPT:
2324                         flags |= ZFS_IMPORT_CHECKPOINT;
2325                         break;
2326                 case ':':
2327                         (void) fprintf(stderr, gettext("missing argument for "
2328                             "'%c' option\n"), optopt);
2329                         usage(B_FALSE);
2330                         break;
2331                 case '?':
2332                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2333                             optopt);
2334                         usage(B_FALSE);
2335                 }
2336         }
2337
2338         argc -= optind;
2339         argv += optind;
2340
2341         if (cachefile && nsearch != 0) {
2342                 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
2343                 usage(B_FALSE);
2344         }
2345
2346         if ((dryrun || xtreme_rewind) && !do_rewind) {
2347                 (void) fprintf(stderr,
2348                     gettext("-n or -X only meaningful with -F\n"));
2349                 usage(B_FALSE);
2350         }
2351         if (dryrun)
2352                 rewind_policy = ZPOOL_TRY_REWIND;
2353         else if (do_rewind)
2354                 rewind_policy = ZPOOL_DO_REWIND;
2355         if (xtreme_rewind)
2356                 rewind_policy |= ZPOOL_EXTREME_REWIND;
2357
2358         /* In the future, we can capture further policy and include it here */
2359         if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
2360             nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 ||
2361             nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
2362             rewind_policy) != 0)
2363                 goto error;
2364
2365         if (searchdirs == NULL) {
2366                 searchdirs = safe_malloc(sizeof (char *));
2367                 searchdirs[0] = "/dev";
2368                 nsearch = 1;
2369         }
2370
2371         /* check argument count */
2372         if (do_all) {
2373                 if (argc != 0) {
2374                         (void) fprintf(stderr, gettext("too many arguments\n"));
2375                         usage(B_FALSE);
2376                 }
2377         } else {
2378                 if (argc > 2) {
2379                         (void) fprintf(stderr, gettext("too many arguments\n"));
2380                         usage(B_FALSE);
2381                 }
2382
2383                 /*
2384                  * Check for the SYS_CONFIG privilege.  We do this explicitly
2385                  * here because otherwise any attempt to discover pools will
2386                  * silently fail.
2387                  */
2388                 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
2389                         (void) fprintf(stderr, gettext("cannot "
2390                             "discover pools: permission denied\n"));
2391                         free(searchdirs);
2392                         nvlist_free(policy);
2393                         return (1);
2394                 }
2395         }
2396
2397         /*
2398          * Depending on the arguments given, we do one of the following:
2399          *
2400          *      <none>  Iterate through all pools and display information about
2401          *              each one.
2402          *
2403          *      -a      Iterate through all pools and try to import each one.
2404          *
2405          *      <id>    Find the pool that corresponds to the given GUID/pool
2406          *              name and import that one.
2407          *
2408          *      -D      Above options applies only to destroyed pools.
2409          */
2410         if (argc != 0) {
2411                 char *endptr;
2412
2413                 errno = 0;
2414                 searchguid = strtoull(argv[0], &endptr, 10);
2415                 if (errno != 0 || *endptr != '\0') {
2416                         searchname = argv[0];
2417                         searchguid = 0;
2418                 }
2419                 found_config = NULL;
2420
2421                 /*
2422                  * User specified a name or guid.  Ensure it's unique.
2423                  */
2424                 idata.unique = B_TRUE;
2425         }
2426
2427
2428         idata.path = searchdirs;
2429         idata.paths = nsearch;
2430         idata.poolname = searchname;
2431         idata.guid = searchguid;
2432         idata.cachefile = cachefile;
2433         idata.policy = policy;
2434
2435         pools = zpool_search_import(g_zfs, &idata);
2436
2437         if (pools != NULL && idata.exists &&
2438             (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2439                 (void) fprintf(stderr, gettext("cannot import '%s': "
2440                     "a pool with that name already exists\n"),
2441                     argv[0]);
2442                 (void) fprintf(stderr, gettext("use the form '%s "
2443                     "<pool | id> <newpool>' to give it a new name\n"),
2444                     "zpool import");
2445                 err = 1;
2446         } else if (pools == NULL && idata.exists) {
2447                 (void) fprintf(stderr, gettext("cannot import '%s': "
2448                     "a pool with that name is already created/imported,\n"),
2449                     argv[0]);
2450                 (void) fprintf(stderr, gettext("and no additional pools "
2451                     "with that name were found\n"));
2452                 err = 1;
2453         } else if (pools == NULL) {
2454                 if (argc != 0) {
2455                         (void) fprintf(stderr, gettext("cannot import '%s': "
2456                             "no such pool available\n"), argv[0]);
2457                 }
2458                 err = 1;
2459         }
2460
2461         if (err == 1) {
2462                 free(searchdirs);
2463                 nvlist_free(policy);
2464                 return (1);
2465         }
2466
2467         /*
2468          * At this point we have a list of import candidate configs. Even if
2469          * we were searching by pool name or guid, we still need to
2470          * post-process the list to deal with pool state and possible
2471          * duplicate names.
2472          */
2473         err = 0;
2474         elem = NULL;
2475         first = B_TRUE;
2476         while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2477
2478                 verify(nvpair_value_nvlist(elem, &config) == 0);
2479
2480                 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2481                     &pool_state) == 0);
2482                 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2483                         continue;
2484                 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2485                         continue;
2486
2487                 verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY,
2488                     policy) == 0);
2489
2490                 if (argc == 0) {
2491                         if (first)
2492                                 first = B_FALSE;
2493                         else if (!do_all)
2494                                 (void) printf("\n");
2495
2496                         if (do_all) {
2497                                 err |= do_import(config, NULL, mntopts,
2498                                     props, flags);
2499                         } else {
2500                                 show_import(config);
2501                         }
2502                 } else if (searchname != NULL) {
2503                         char *name;
2504
2505                         /*
2506                          * We are searching for a pool based on name.
2507                          */
2508                         verify(nvlist_lookup_string(config,
2509                             ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2510
2511                         if (strcmp(name, searchname) == 0) {
2512                                 if (found_config != NULL) {
2513                                         (void) fprintf(stderr, gettext(
2514                                             "cannot import '%s': more than "
2515                                             "one matching pool\n"), searchname);
2516                                         (void) fprintf(stderr, gettext(
2517                                             "import by numeric ID instead\n"));
2518                                         err = B_TRUE;
2519                                 }
2520                                 found_config = config;
2521                         }
2522                 } else {
2523                         uint64_t guid;
2524
2525                         /*
2526                          * Search for a pool by guid.
2527                          */
2528                         verify(nvlist_lookup_uint64(config,
2529                             ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2530
2531                         if (guid == searchguid)
2532                                 found_config = config;
2533                 }
2534         }
2535
2536         /*
2537          * If we were searching for a specific pool, verify that we found a
2538          * pool, and then do the import.
2539          */
2540         if (argc != 0 && err == 0) {
2541                 if (found_config == NULL) {
2542                         (void) fprintf(stderr, gettext("cannot import '%s': "
2543                             "no such pool available\n"), argv[0]);
2544                         err = B_TRUE;
2545                 } else {
2546                         err |= do_import(found_config, argc == 1 ? NULL :
2547                             argv[1], mntopts, props, flags);
2548                 }
2549         }
2550
2551         /*
2552          * If we were just looking for pools, report an error if none were
2553          * found.
2554          */
2555         if (argc == 0 && first)
2556                 (void) fprintf(stderr,
2557                     gettext("no pools available to import\n"));
2558
2559 error:
2560         nvlist_free(props);
2561         nvlist_free(pools);
2562         nvlist_free(policy);
2563         free(searchdirs);
2564
2565         return (err ? 1 : 0);
2566 }
2567
2568 typedef struct iostat_cbdata {
2569         boolean_t cb_verbose;
2570         int cb_namewidth;
2571         int cb_iteration;
2572         zpool_list_t *cb_list;
2573 } iostat_cbdata_t;
2574
2575 static void
2576 print_iostat_separator(iostat_cbdata_t *cb)
2577 {
2578         int i = 0;
2579
2580         for (i = 0; i < cb->cb_namewidth; i++)
2581                 (void) printf("-");
2582         (void) printf("  -----  -----  -----  -----  -----  -----\n");
2583 }
2584
2585 static void
2586 print_iostat_header(iostat_cbdata_t *cb)
2587 {
2588         (void) printf("%*s     capacity     operations    bandwidth\n",
2589             cb->cb_namewidth, "");
2590         (void) printf("%-*s  alloc   free   read  write   read  write\n",
2591             cb->cb_namewidth, "pool");
2592         print_iostat_separator(cb);
2593 }
2594
2595 /*
2596  * Display a single statistic.
2597  */
2598 static void
2599 print_one_stat(uint64_t value)
2600 {
2601         char buf[64];
2602
2603         zfs_nicenum(value, buf, sizeof (buf));
2604         (void) printf("  %5s", buf);
2605 }
2606
2607 /*
2608  * Print out all the statistics for the given vdev.  This can either be the
2609  * toplevel configuration, or called recursively.  If 'name' is NULL, then this
2610  * is a verbose output, and we don't want to display the toplevel pool stats.
2611  */
2612 void
2613 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2614     nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2615 {
2616         nvlist_t **oldchild, **newchild;
2617         uint_t c, children;
2618         vdev_stat_t *oldvs, *newvs;
2619         vdev_stat_t zerovs = { 0 };
2620         uint64_t tdelta;
2621         double scale;
2622         char *vname;
2623
2624         if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
2625                 return;
2626
2627         if (oldnv != NULL) {
2628                 verify(nvlist_lookup_uint64_array(oldnv,
2629                     ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2630         } else {
2631                 oldvs = &zerovs;
2632         }
2633
2634         verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2635             (uint64_t **)&newvs, &c) == 0);
2636
2637         if (strlen(name) + depth > cb->cb_namewidth)
2638                 (void) printf("%*s%s", depth, "", name);
2639         else
2640                 (void) printf("%*s%s%*s", depth, "", name,
2641                     (int)(cb->cb_namewidth - strlen(name) - depth), "");
2642
2643         tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2644
2645         if (tdelta == 0)
2646                 scale = 1.0;
2647         else
2648                 scale = (double)NANOSEC / tdelta;
2649
2650         /* only toplevel vdevs have capacity stats */
2651         if (newvs->vs_space == 0) {
2652                 (void) printf("      -      -");
2653         } else {
2654                 print_one_stat(newvs->vs_alloc);
2655                 print_one_stat(newvs->vs_space - newvs->vs_alloc);
2656         }
2657
2658         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2659             oldvs->vs_ops[ZIO_TYPE_READ])));
2660
2661         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2662             oldvs->vs_ops[ZIO_TYPE_WRITE])));
2663
2664         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2665             oldvs->vs_bytes[ZIO_TYPE_READ])));
2666
2667         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2668             oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2669
2670         (void) printf("\n");
2671
2672         if (!cb->cb_verbose)
2673                 return;
2674
2675         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2676             &newchild, &children) != 0)
2677                 return;
2678
2679         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2680             &oldchild, &c) != 0)
2681                 return;
2682
2683         for (c = 0; c < children; c++) {
2684                 uint64_t ishole = B_FALSE, islog = B_FALSE;
2685
2686                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2687                     &ishole);
2688
2689                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2690                     &islog);
2691
2692                 if (ishole || islog)
2693                         continue;
2694
2695                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2696                 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2697                     newchild[c], cb, depth + 2);
2698                 free(vname);
2699         }
2700
2701         /*
2702          * Log device section
2703          */
2704
2705         if (num_logs(newnv) > 0) {
2706                 (void) printf("%-*s      -      -      -      -      -      "
2707                     "-\n", cb->cb_namewidth, "logs");
2708
2709                 for (c = 0; c < children; c++) {
2710                         uint64_t islog = B_FALSE;
2711                         (void) nvlist_lookup_uint64(newchild[c],
2712                             ZPOOL_CONFIG_IS_LOG, &islog);
2713
2714                         if (islog) {
2715                                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2716                                     B_FALSE);
2717                                 print_vdev_stats(zhp, vname, oldnv ?
2718                                     oldchild[c] : NULL, newchild[c],
2719                                     cb, depth + 2);
2720                                 free(vname);
2721                         }
2722                 }
2723
2724         }
2725
2726         /*
2727          * Include level 2 ARC devices in iostat output
2728          */
2729         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2730             &newchild, &children) != 0)
2731                 return;
2732
2733         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2734             &oldchild, &c) != 0)
2735                 return;
2736
2737         if (children > 0) {
2738                 (void) printf("%-*s      -      -      -      -      -      "
2739                     "-\n", cb->cb_namewidth, "cache");
2740                 for (c = 0; c < children; c++) {
2741                         vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2742                             B_FALSE);
2743                         print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2744                             newchild[c], cb, depth + 2);
2745                         free(vname);
2746                 }
2747         }
2748 }
2749
2750 static int
2751 refresh_iostat(zpool_handle_t *zhp, void *data)
2752 {
2753         iostat_cbdata_t *cb = data;
2754         boolean_t missing;
2755
2756         /*
2757          * If the pool has disappeared, remove it from the list and continue.
2758          */
2759         if (zpool_refresh_stats(zhp, &missing) != 0)
2760                 return (-1);
2761
2762         if (missing)
2763                 pool_list_remove(cb->cb_list, zhp);
2764
2765         return (0);
2766 }
2767
2768 /*
2769  * Callback to print out the iostats for the given pool.
2770  */
2771 int
2772 print_iostat(zpool_handle_t *zhp, void *data)
2773 {
2774         iostat_cbdata_t *cb = data;
2775         nvlist_t *oldconfig, *newconfig;
2776         nvlist_t *oldnvroot, *newnvroot;
2777
2778         newconfig = zpool_get_config(zhp, &oldconfig);
2779
2780         if (cb->cb_iteration == 1)
2781                 oldconfig = NULL;
2782
2783         verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
2784             &newnvroot) == 0);
2785
2786         if (oldconfig == NULL)
2787                 oldnvroot = NULL;
2788         else
2789                 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
2790                     &oldnvroot) == 0);
2791
2792         /*
2793          * Print out the statistics for the pool.
2794          */
2795         print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
2796
2797         if (cb->cb_verbose)
2798                 print_iostat_separator(cb);
2799
2800         return (0);
2801 }
2802
2803 int
2804 get_namewidth(zpool_handle_t *zhp, void *data)
2805 {
2806         iostat_cbdata_t *cb = data;
2807         nvlist_t *config, *nvroot;
2808
2809         if ((config = zpool_get_config(zhp, NULL)) != NULL) {
2810                 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2811                     &nvroot) == 0);
2812                 if (!cb->cb_verbose)
2813                         cb->cb_namewidth = strlen(zpool_get_name(zhp));
2814                 else
2815                         cb->cb_namewidth = max_width(zhp, nvroot, 0,
2816                             cb->cb_namewidth);
2817         }
2818
2819         /*
2820          * The width must fall into the range [10,38].  The upper limit is the
2821          * maximum we can have and still fit in 80 columns.
2822          */
2823         if (cb->cb_namewidth < 10)
2824                 cb->cb_namewidth = 10;
2825         if (cb->cb_namewidth > 38)
2826                 cb->cb_namewidth = 38;
2827
2828         return (0);
2829 }
2830
2831 /*
2832  * Parse the input string, get the 'interval' and 'count' value if there is one.
2833  */
2834 static void
2835 get_interval_count(int *argcp, char **argv, unsigned long *iv,
2836     unsigned long *cnt)
2837 {
2838         unsigned long interval = 0, count = 0;
2839         int argc = *argcp, errno;
2840
2841         /*
2842          * Determine if the last argument is an integer or a pool name
2843          */
2844         if (argc > 0 && isdigit(argv[argc - 1][0])) {
2845                 char *end;
2846
2847                 errno = 0;
2848                 interval = strtoul(argv[argc - 1], &end, 10);
2849
2850                 if (*end == '\0' && errno == 0) {
2851                         if (interval == 0) {
2852                                 (void) fprintf(stderr, gettext("interval "
2853                                     "cannot be zero\n"));
2854                                 usage(B_FALSE);
2855                         }
2856                         /*
2857                          * Ignore the last parameter
2858                          */
2859                         argc--;
2860                 } else {
2861                         /*
2862                          * If this is not a valid number, just plow on.  The
2863                          * user will get a more informative error message later
2864                          * on.
2865                          */
2866                         interval = 0;
2867                 }
2868         }
2869
2870         /*
2871          * If the last argument is also an integer, then we have both a count
2872          * and an interval.
2873          */
2874         if (argc > 0 && isdigit(argv[argc - 1][0])) {
2875                 char *end;
2876
2877                 errno = 0;
2878                 count = interval;
2879                 interval = strtoul(argv[argc - 1], &end, 10);
2880
2881                 if (*end == '\0' && errno == 0) {
2882                         if (interval == 0) {
2883                                 (void) fprintf(stderr, gettext("interval "
2884                                     "cannot be zero\n"));
2885                                 usage(B_FALSE);
2886                         }
2887
2888                         /*
2889                          * Ignore the last parameter
2890                          */
2891                         argc--;
2892                 } else {
2893                         interval = 0;
2894                 }
2895         }
2896
2897         *iv = interval;
2898         *cnt = count;
2899         *argcp = argc;
2900 }
2901
2902 static void
2903 get_timestamp_arg(char c)
2904 {
2905         if (c == 'u')
2906                 timestamp_fmt = UDATE;
2907         else if (c == 'd')
2908                 timestamp_fmt = DDATE;
2909         else
2910                 usage(B_FALSE);
2911 }
2912
2913 /*
2914  * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
2915  *
2916  *      -v      Display statistics for individual vdevs
2917  *      -T      Display a timestamp in date(1) or Unix format
2918  *
2919  * This command can be tricky because we want to be able to deal with pool
2920  * creation/destruction as well as vdev configuration changes.  The bulk of this
2921  * processing is handled by the pool_list_* routines in zpool_iter.c.  We rely
2922  * on pool_list_update() to detect the addition of new pools.  Configuration
2923  * changes are all handled within libzfs.
2924  */
2925 int
2926 zpool_do_iostat(int argc, char **argv)
2927 {
2928         int c;
2929         int ret;
2930         int npools;
2931         unsigned long interval = 0, count = 0;
2932         zpool_list_t *list;
2933         boolean_t verbose = B_FALSE;
2934         iostat_cbdata_t cb;
2935
2936         /* check options */
2937         while ((c = getopt(argc, argv, "T:v")) != -1) {
2938                 switch (c) {
2939                 case 'T':
2940                         get_timestamp_arg(*optarg);
2941                         break;
2942                 case 'v':
2943                         verbose = B_TRUE;
2944                         break;
2945                 case '?':
2946                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2947                             optopt);
2948                         usage(B_FALSE);
2949                 }
2950         }
2951
2952         argc -= optind;
2953         argv += optind;
2954
2955         get_interval_count(&argc, argv, &interval, &count);
2956
2957         /*
2958          * Construct the list of all interesting pools.
2959          */
2960         ret = 0;
2961         if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
2962                 return (1);
2963
2964         if (pool_list_count(list) == 0 && argc != 0) {
2965                 pool_list_free(list);
2966                 return (1);
2967         }
2968
2969         if (pool_list_count(list) == 0 && interval == 0) {
2970                 pool_list_free(list);
2971                 (void) fprintf(stderr, gettext("no pools available\n"));
2972                 return (1);
2973         }
2974
2975         /*
2976          * Enter the main iostat loop.
2977          */
2978         cb.cb_list = list;
2979         cb.cb_verbose = verbose;
2980         cb.cb_iteration = 0;
2981         cb.cb_namewidth = 0;
2982
2983         for (;;) {
2984                 pool_list_update(list);
2985
2986                 if ((npools = pool_list_count(list)) == 0)
2987                         break;
2988
2989                 /*
2990                  * Refresh all statistics.  This is done as an explicit step
2991                  * before calculating the maximum name width, so that any
2992                  * configuration changes are properly accounted for.
2993                  */
2994                 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
2995
2996                 /*
2997                  * Iterate over all pools to determine the maximum width
2998                  * for the pool / device name column across all pools.
2999                  */
3000                 cb.cb_namewidth = 0;
3001                 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3002
3003                 if (timestamp_fmt != NODATE)
3004                         print_timestamp(timestamp_fmt);
3005
3006                 /*
3007                  * If it's the first time, or verbose mode, print the header.
3008                  */
3009                 if (++cb.cb_iteration == 1 || verbose)
3010                         print_iostat_header(&cb);
3011
3012                 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
3013
3014                 /*
3015                  * If there's more than one pool, and we're not in verbose mode
3016                  * (which prints a separator for us), then print a separator.
3017                  */
3018                 if (npools > 1 && !verbose)
3019                         print_iostat_separator(&cb);
3020
3021                 if (verbose)
3022                         (void) printf("\n");
3023
3024                 /*
3025                  * Flush the output so that redirection to a file isn't buffered
3026                  * indefinitely.
3027                  */
3028                 (void) fflush(stdout);
3029
3030                 if (interval == 0)
3031                         break;
3032
3033                 if (count != 0 && --count == 0)
3034                         break;
3035
3036                 (void) sleep(interval);
3037         }
3038
3039         pool_list_free(list);
3040
3041         return (ret);
3042 }
3043
3044 typedef struct list_cbdata {
3045         boolean_t       cb_verbose;
3046         int             cb_namewidth;
3047         boolean_t       cb_scripted;
3048         zprop_list_t    *cb_proplist;
3049         boolean_t       cb_literal;
3050 } list_cbdata_t;
3051
3052 /*
3053  * Given a list of columns to display, output appropriate headers for each one.
3054  */
3055 static void
3056 print_header(list_cbdata_t *cb)
3057 {
3058         zprop_list_t *pl = cb->cb_proplist;
3059         char headerbuf[ZPOOL_MAXPROPLEN];
3060         const char *header;
3061         boolean_t first = B_TRUE;
3062         boolean_t right_justify;
3063         size_t width = 0;
3064
3065         for (; pl != NULL; pl = pl->pl_next) {
3066                 width = pl->pl_width;
3067                 if (first && cb->cb_verbose) {
3068                         /*
3069                          * Reset the width to accommodate the verbose listing
3070                          * of devices.
3071                          */
3072                         width = cb->cb_namewidth;
3073                 }
3074
3075                 if (!first)
3076                         (void) printf("  ");
3077                 else
3078                         first = B_FALSE;
3079
3080                 right_justify = B_FALSE;
3081                 if (pl->pl_prop != ZPROP_INVAL) {
3082                         header = zpool_prop_column_name(pl->pl_prop);
3083                         right_justify = zpool_prop_align_right(pl->pl_prop);
3084                 } else {
3085                         int i;
3086
3087                         for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
3088                                 headerbuf[i] = toupper(pl->pl_user_prop[i]);
3089                         headerbuf[i] = '\0';
3090                         header = headerbuf;
3091                 }
3092
3093                 if (pl->pl_next == NULL && !right_justify)
3094                         (void) printf("%s", header);
3095                 else if (right_justify)
3096                         (void) printf("%*s", width, header);
3097                 else
3098                         (void) printf("%-*s", width, header);
3099
3100         }
3101
3102         (void) printf("\n");
3103 }
3104
3105 /*
3106  * Given a pool and a list of properties, print out all the properties according
3107  * to the described layout.
3108  */
3109 static void
3110 print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
3111 {
3112         zprop_list_t *pl = cb->cb_proplist;
3113         boolean_t first = B_TRUE;
3114         char property[ZPOOL_MAXPROPLEN];
3115         char *propstr;
3116         boolean_t right_justify;
3117         size_t width;
3118
3119         for (; pl != NULL; pl = pl->pl_next) {
3120
3121                 width = pl->pl_width;
3122                 if (first && cb->cb_verbose) {
3123                         /*
3124                          * Reset the width to accommodate the verbose listing
3125                          * of devices.
3126                          */
3127                         width = cb->cb_namewidth;
3128                 }
3129
3130                 if (!first) {
3131                         if (cb->cb_scripted)
3132                                 (void) printf("\t");
3133                         else
3134                                 (void) printf("  ");
3135                 } else {
3136                         first = B_FALSE;
3137                 }
3138
3139                 right_justify = B_FALSE;
3140                 if (pl->pl_prop != ZPROP_INVAL) {
3141                         if (zpool_get_prop(zhp, pl->pl_prop, property,
3142                             sizeof (property), NULL, cb->cb_literal) != 0)
3143                                 propstr = "-";
3144                         else
3145                                 propstr = property;
3146
3147                         right_justify = zpool_prop_align_right(pl->pl_prop);
3148                 } else if ((zpool_prop_feature(pl->pl_user_prop) ||
3149                     zpool_prop_unsupported(pl->pl_user_prop)) &&
3150                     zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
3151                     sizeof (property)) == 0) {
3152                         propstr = property;
3153                 } else {
3154                         propstr = "-";
3155                 }
3156
3157
3158                 /*
3159                  * If this is being called in scripted mode, or if this is the
3160                  * last column and it is left-justified, don't include a width
3161                  * format specifier.
3162                  */
3163                 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
3164                         (void) printf("%s", propstr);
3165                 else if (right_justify)
3166                         (void) printf("%*s", width, propstr);
3167                 else
3168                         (void) printf("%-*s", width, propstr);
3169         }
3170
3171         (void) printf("\n");
3172 }
3173
3174 static void
3175 print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
3176     boolean_t valid)
3177 {
3178         char propval[64];
3179         boolean_t fixed;
3180         size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
3181
3182         switch (prop) {
3183         case ZPOOL_PROP_EXPANDSZ:
3184         case ZPOOL_PROP_CHECKPOINT:
3185                 if (value == 0)
3186                         (void) strlcpy(propval, "-", sizeof (propval));
3187                 else
3188                         zfs_nicenum(value, propval, sizeof (propval));
3189                 break;
3190         case ZPOOL_PROP_FRAGMENTATION:
3191                 if (value == ZFS_FRAG_INVALID) {
3192                         (void) strlcpy(propval, "-", sizeof (propval));
3193                 } else {
3194                         (void) snprintf(propval, sizeof (propval), "%llu%%",
3195                             value);
3196                 }
3197                 break;
3198         case ZPOOL_PROP_CAPACITY:
3199                 (void) snprintf(propval, sizeof (propval), "%llu%%", value);
3200                 break;
3201         default:
3202                 zfs_nicenum(value, propval, sizeof (propval));
3203         }
3204
3205         if (!valid)
3206                 (void) strlcpy(propval, "-", sizeof (propval));
3207
3208         if (scripted)
3209                 (void) printf("\t%s", propval);
3210         else
3211                 (void) printf("  %*s", width, propval);
3212 }
3213
3214 void
3215 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
3216     list_cbdata_t *cb, int depth)
3217 {
3218         nvlist_t **child;
3219         vdev_stat_t *vs;
3220         uint_t c, children;
3221         char *vname;
3222         boolean_t scripted = cb->cb_scripted;
3223         uint64_t islog = B_FALSE;
3224         boolean_t haslog = B_FALSE;
3225         char *dashes = "%-*s      -      -      -         -      -      -\n";
3226
3227         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3228             (uint64_t **)&vs, &c) == 0);
3229
3230         if (name != NULL) {
3231                 boolean_t toplevel = (vs->vs_space != 0);
3232                 uint64_t cap;
3233
3234                 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
3235                         return;
3236
3237                 if (scripted)
3238                         (void) printf("\t%s", name);
3239                 else if (strlen(name) + depth > cb->cb_namewidth)
3240                         (void) printf("%*s%s", depth, "", name);
3241                 else
3242                         (void) printf("%*s%s%*s", depth, "", name,
3243                             (int)(cb->cb_namewidth - strlen(name) - depth), "");
3244
3245                 /*
3246                  * Print the properties for the individual vdevs. Some
3247                  * properties are only applicable to toplevel vdevs. The
3248                  * 'toplevel' boolean value is passed to the print_one_column()
3249                  * to indicate that the value is valid.
3250                  */
3251                 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
3252                     toplevel);
3253                 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
3254                     toplevel);
3255                 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
3256                     scripted, toplevel);
3257                 print_one_column(ZPOOL_PROP_CHECKPOINT,
3258                     vs->vs_checkpoint_space, scripted, toplevel);
3259                 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
3260                     B_TRUE);
3261                 print_one_column(ZPOOL_PROP_FRAGMENTATION,
3262                     vs->vs_fragmentation, scripted,
3263                     (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel));
3264                 cap = (vs->vs_space == 0) ? 0 :
3265                     (vs->vs_alloc * 100 / vs->vs_space);
3266                 print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel);
3267                 (void) printf("\n");
3268         }
3269
3270         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
3271             &child, &children) != 0)
3272                 return;
3273
3274         for (c = 0; c < children; c++) {
3275                 uint64_t ishole = B_FALSE;
3276
3277                 if (nvlist_lookup_uint64(child[c],
3278                     ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
3279                         continue;
3280
3281                 if (nvlist_lookup_uint64(child[c],
3282                     ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) {
3283                         haslog = B_TRUE;
3284                         continue;
3285                 }
3286
3287                 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3288                 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3289                 free(vname);
3290         }
3291
3292         if (haslog == B_TRUE) {
3293                 /* LINTED E_SEC_PRINTF_VAR_FMT */
3294                 (void) printf(dashes, cb->cb_namewidth, "log");
3295                 for (c = 0; c < children; c++) {
3296                         if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
3297                             &islog) != 0 || !islog)
3298                                 continue;
3299                         vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3300                         print_list_stats(zhp, vname, child[c], cb, depth + 2);
3301                         free(vname);
3302                 }
3303         }
3304
3305         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
3306             &child, &children) == 0 && children > 0) {
3307                 /* LINTED E_SEC_PRINTF_VAR_FMT */
3308                 (void) printf(dashes, cb->cb_namewidth, "cache");
3309                 for (c = 0; c < children; c++) {
3310                         vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3311                         print_list_stats(zhp, vname, child[c], cb, depth + 2);
3312                         free(vname);
3313                 }
3314         }
3315
3316         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
3317             &children) == 0 && children > 0) {
3318                 /* LINTED E_SEC_PRINTF_VAR_FMT */
3319                 (void) printf(dashes, cb->cb_namewidth, "spare");
3320                 for (c = 0; c < children; c++) {
3321                         vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3322                         print_list_stats(zhp, vname, child[c], cb, depth + 2);
3323                         free(vname);
3324                 }
3325         }
3326 }
3327
3328
3329 /*
3330  * Generic callback function to list a pool.
3331  */
3332 int
3333 list_callback(zpool_handle_t *zhp, void *data)
3334 {
3335         list_cbdata_t *cbp = data;
3336         nvlist_t *config;
3337         nvlist_t *nvroot;
3338
3339         config = zpool_get_config(zhp, NULL);
3340
3341         print_pool(zhp, cbp);
3342         if (!cbp->cb_verbose)
3343                 return (0);
3344
3345         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3346             &nvroot) == 0);
3347         print_list_stats(zhp, NULL, nvroot, cbp, 0);
3348
3349         return (0);
3350 }
3351
3352 /*
3353  * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3354  *
3355  *      -H      Scripted mode.  Don't display headers, and separate properties
3356  *              by a single tab.
3357  *      -o      List of properties to display.  Defaults to
3358  *              "name,size,allocated,free,expandsize,fragmentation,capacity,"
3359  *              "dedupratio,health,altroot"
3360  *      -p      Diplay values in parsable (exact) format.
3361  *      -T      Display a timestamp in date(1) or Unix format
3362  *
3363  * List all pools in the system, whether or not they're healthy.  Output space
3364  * statistics for each one, as well as health status summary.
3365  */
3366 int
3367 zpool_do_list(int argc, char **argv)
3368 {
3369         int c;
3370         int ret;
3371         list_cbdata_t cb = { 0 };
3372         static char default_props[] =
3373             "name,size,allocated,free,checkpoint,expandsize,fragmentation,"
3374             "capacity,dedupratio,health,altroot";
3375         char *props = default_props;
3376         unsigned long interval = 0, count = 0;
3377         zpool_list_t *list;
3378         boolean_t first = B_TRUE;
3379
3380         /* check options */
3381         while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
3382                 switch (c) {
3383                 case 'H':
3384                         cb.cb_scripted = B_TRUE;
3385                         break;
3386                 case 'o':
3387                         props = optarg;
3388                         break;
3389                 case 'p':
3390                         cb.cb_literal = B_TRUE;
3391                         break;
3392                 case 'T':
3393                         get_timestamp_arg(*optarg);
3394                         break;
3395                 case 'v':
3396                         cb.cb_verbose = B_TRUE;
3397                         break;
3398                 case ':':
3399                         (void) fprintf(stderr, gettext("missing argument for "
3400                             "'%c' option\n"), optopt);
3401                         usage(B_FALSE);
3402                         break;
3403                 case '?':
3404                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3405                             optopt);
3406                         usage(B_FALSE);
3407                 }
3408         }
3409
3410         argc -= optind;
3411         argv += optind;
3412
3413         get_interval_count(&argc, argv, &interval, &count);
3414
3415         if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
3416                 usage(B_FALSE);
3417
3418         for (;;) {
3419                 if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
3420                     &ret)) == NULL)
3421                         return (1);
3422
3423                 if (pool_list_count(list) == 0)
3424                         break;
3425
3426                 cb.cb_namewidth = 0;
3427                 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3428
3429                 if (timestamp_fmt != NODATE)
3430                         print_timestamp(timestamp_fmt);
3431
3432                 if (!cb.cb_scripted && (first || cb.cb_verbose)) {
3433                         print_header(&cb);
3434                         first = B_FALSE;
3435                 }
3436                 ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
3437
3438                 if (interval == 0)
3439                         break;
3440
3441                 if (count != 0 && --count == 0)
3442                         break;
3443
3444                 pool_list_free(list);
3445                 (void) sleep(interval);
3446         }
3447
3448         if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
3449                 (void) printf(gettext("no pools available\n"));
3450                 ret = 0;
3451         }
3452
3453         pool_list_free(list);
3454         zprop_free_list(cb.cb_proplist);
3455         return (ret);
3456 }
3457
3458 static int
3459 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
3460 {
3461         boolean_t force = B_FALSE;
3462         int c;
3463         nvlist_t *nvroot;
3464         char *poolname, *old_disk, *new_disk;
3465         zpool_handle_t *zhp;
3466         zpool_boot_label_t boot_type;
3467         uint64_t boot_size;
3468         int ret;
3469
3470         /* check options */
3471         while ((c = getopt(argc, argv, "f")) != -1) {
3472                 switch (c) {
3473                 case 'f':
3474                         force = B_TRUE;
3475                         break;
3476                 case '?':
3477                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3478                             optopt);
3479                         usage(B_FALSE);
3480                 }
3481         }
3482
3483         argc -= optind;
3484         argv += optind;
3485
3486         /* get pool name and check number of arguments */
3487         if (argc < 1) {
3488                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3489                 usage(B_FALSE);
3490         }
3491
3492         poolname = argv[0];
3493
3494         if (argc < 2) {
3495                 (void) fprintf(stderr,
3496                     gettext("missing <device> specification\n"));
3497                 usage(B_FALSE);
3498         }
3499
3500         old_disk = argv[1];
3501
3502         if (argc < 3) {
3503                 if (!replacing) {
3504                         (void) fprintf(stderr,
3505                             gettext("missing <new_device> specification\n"));
3506                         usage(B_FALSE);
3507                 }
3508                 new_disk = old_disk;
3509                 argc -= 1;
3510                 argv += 1;
3511         } else {
3512                 new_disk = argv[2];
3513                 argc -= 2;
3514                 argv += 2;
3515         }
3516
3517         if (argc > 1) {
3518                 (void) fprintf(stderr, gettext("too many arguments\n"));
3519                 usage(B_FALSE);
3520         }
3521
3522         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3523                 return (1);
3524
3525         if (zpool_get_config(zhp, NULL) == NULL) {
3526                 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
3527                     poolname);
3528                 zpool_close(zhp);
3529                 return (1);
3530         }
3531
3532         if (zpool_is_bootable(zhp))
3533                 boot_type = ZPOOL_COPY_BOOT_LABEL;
3534         else
3535                 boot_type = ZPOOL_NO_BOOT_LABEL;
3536
3537         boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
3538         nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
3539             boot_type, boot_size, argc, argv);
3540         if (nvroot == NULL) {
3541                 zpool_close(zhp);
3542                 return (1);
3543         }
3544
3545         ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
3546
3547         nvlist_free(nvroot);
3548         zpool_close(zhp);
3549
3550         return (ret);
3551 }
3552
3553 /*
3554  * zpool replace [-f] <pool> <device> <new_device>
3555  *
3556  *      -f      Force attach, even if <new_device> appears to be in use.
3557  *
3558  * Replace <device> with <new_device>.
3559  */
3560 /* ARGSUSED */
3561 int
3562 zpool_do_replace(int argc, char **argv)
3563 {
3564         return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
3565 }
3566
3567 /*
3568  * zpool attach [-f] <pool> <device> <new_device>
3569  *
3570  *      -f      Force attach, even if <new_device> appears to be in use.
3571  *
3572  * Attach <new_device> to the mirror containing <device>.  If <device> is not
3573  * part of a mirror, then <device> will be transformed into a mirror of
3574  * <device> and <new_device>.  In either case, <new_device> will begin life
3575  * with a DTL of [0, now], and will immediately begin to resilver itself.
3576  */
3577 int
3578 zpool_do_attach(int argc, char **argv)
3579 {
3580         return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
3581 }
3582
3583 /*
3584  * zpool detach [-f] <pool> <device>
3585  *
3586  *      -f      Force detach of <device>, even if DTLs argue against it
3587  *              (not supported yet)
3588  *
3589  * Detach a device from a mirror.  The operation will be refused if <device>
3590  * is the last device in the mirror, or if the DTLs indicate that this device
3591  * has the only valid copy of some data.
3592  */
3593 /* ARGSUSED */
3594 int
3595 zpool_do_detach(int argc, char **argv)
3596 {
3597         int c;
3598         char *poolname, *path;
3599         zpool_handle_t *zhp;
3600         int ret;
3601
3602         /* check options */
3603         while ((c = getopt(argc, argv, "f")) != -1) {
3604                 switch (c) {
3605                 case 'f':
3606                 case '?':
3607                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3608                             optopt);
3609                         usage(B_FALSE);
3610                 }
3611         }
3612
3613         argc -= optind;
3614         argv += optind;
3615
3616         /* get pool name and check number of arguments */
3617         if (argc < 1) {
3618                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3619                 usage(B_FALSE);
3620         }
3621
3622         if (argc < 2) {
3623                 (void) fprintf(stderr,
3624                     gettext("missing <device> specification\n"));
3625                 usage(B_FALSE);
3626         }
3627
3628         poolname = argv[0];
3629         path = argv[1];
3630
3631         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3632                 return (1);
3633
3634         ret = zpool_vdev_detach(zhp, path);
3635
3636         zpool_close(zhp);
3637
3638         return (ret);
3639 }
3640
3641 /*
3642  * zpool split [-n] [-o prop=val] ...
3643  *              [-o mntopt] ...
3644  *              [-R altroot] <pool> <newpool> [<device> ...]
3645  *
3646  *      -n      Do not split the pool, but display the resulting layout if
3647  *              it were to be split.
3648  *      -o      Set property=value, or set mount options.
3649  *      -R      Mount the split-off pool under an alternate root.
3650  *
3651  * Splits the named pool and gives it the new pool name.  Devices to be split
3652  * off may be listed, provided that no more than one device is specified
3653  * per top-level vdev mirror.  The newly split pool is left in an exported
3654  * state unless -R is specified.
3655  *
3656  * Restrictions: the top-level of the pool pool must only be made up of
3657  * mirrors; all devices in the pool must be healthy; no device may be
3658  * undergoing a resilvering operation.
3659  */
3660 int
3661 zpool_do_split(int argc, char **argv)
3662 {
3663         char *srcpool, *newpool, *propval;
3664         char *mntopts = NULL;
3665         splitflags_t flags;
3666         int c, ret = 0;
3667         zpool_handle_t *zhp;
3668         nvlist_t *config, *props = NULL;
3669
3670         flags.dryrun = B_FALSE;
3671         flags.import = B_FALSE;
3672
3673         /* check options */
3674         while ((c = getopt(argc, argv, ":R:no:")) != -1) {
3675                 switch (c) {
3676                 case 'R':
3677                         flags.import = B_TRUE;
3678                         if (add_prop_list(
3679                             zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
3680                             &props, B_TRUE) != 0) {
3681                                 nvlist_free(props);
3682                                 usage(B_FALSE);
3683                         }
3684                         break;
3685                 case 'n':
3686                         flags.dryrun = B_TRUE;
3687                         break;
3688                 case 'o':
3689                         if ((propval = strchr(optarg, '=')) != NULL) {
3690                                 *propval = '\0';
3691                                 propval++;
3692                                 if (add_prop_list(optarg, propval,
3693                                     &props, B_TRUE) != 0) {
3694                                         nvlist_free(props);
3695                                         usage(B_FALSE);
3696                                 }
3697                         } else {
3698                                 mntopts = optarg;
3699                         }
3700                         break;
3701                 case ':':
3702                         (void) fprintf(stderr, gettext("missing argument for "
3703                             "'%c' option\n"), optopt);
3704                         usage(B_FALSE);
3705                         break;
3706                 case '?':
3707                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3708                             optopt);
3709                         usage(B_FALSE);
3710                         break;
3711                 }
3712         }
3713
3714         if (!flags.import && mntopts != NULL) {
3715                 (void) fprintf(stderr, gettext("setting mntopts is only "
3716                     "valid when importing the pool\n"));
3717                 usage(B_FALSE);
3718         }
3719
3720         argc -= optind;
3721         argv += optind;
3722
3723         if (argc < 1) {
3724                 (void) fprintf(stderr, gettext("Missing pool name\n"));
3725                 usage(B_FALSE);
3726         }
3727         if (argc < 2) {
3728                 (void) fprintf(stderr, gettext("Missing new pool name\n"));
3729                 usage(B_FALSE);
3730         }
3731
3732         srcpool = argv[0];
3733         newpool = argv[1];
3734
3735         argc -= 2;
3736         argv += 2;
3737
3738         if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
3739                 return (1);
3740
3741         config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
3742         if (config == NULL) {
3743                 ret = 1;
3744         } else {
3745                 if (flags.dryrun) {
3746                         (void) printf(gettext("would create '%s' with the "
3747                             "following layout:\n\n"), newpool);
3748                         print_vdev_tree(NULL, newpool, config, 0, B_FALSE);
3749                 }
3750                 nvlist_free(config);
3751         }
3752
3753         zpool_close(zhp);
3754
3755         if (ret != 0 || flags.dryrun || !flags.import)
3756                 return (ret);
3757
3758         /*
3759          * The split was successful. Now we need to open the new
3760          * pool and import it.
3761          */
3762         if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
3763                 return (1);
3764         if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
3765             zpool_enable_datasets(zhp, mntopts, 0) != 0) {
3766                 ret = 1;
3767                 (void) fprintf(stderr, gettext("Split was successful, but "
3768                     "the datasets could not all be mounted\n"));
3769                 (void) fprintf(stderr, gettext("Try doing '%s' with a "
3770                     "different altroot\n"), "zpool import");
3771         }
3772         zpool_close(zhp);
3773
3774         return (ret);
3775 }
3776
3777
3778
3779 /*
3780  * zpool online <pool> <device> ...
3781  */
3782 int
3783 zpool_do_online(int argc, char **argv)
3784 {
3785         int c, i;
3786         char *poolname;
3787         zpool_handle_t *zhp;
3788         int ret = 0;
3789         vdev_state_t newstate;
3790         int flags = 0;
3791
3792         /* check options */
3793         while ((c = getopt(argc, argv, "et")) != -1) {
3794                 switch (c) {
3795                 case 'e':
3796                         flags |= ZFS_ONLINE_EXPAND;
3797                         break;
3798                 case 't':
3799                 case '?':
3800                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3801                             optopt);
3802                         usage(B_FALSE);
3803                 }
3804         }
3805
3806         argc -= optind;
3807         argv += optind;
3808
3809         /* get pool name and check number of arguments */
3810         if (argc < 1) {
3811                 (void) fprintf(stderr, gettext("missing pool name\n"));
3812                 usage(B_FALSE);
3813         }
3814         if (argc < 2) {
3815                 (void) fprintf(stderr, gettext("missing device name\n"));
3816                 usage(B_FALSE);
3817         }
3818
3819         poolname = argv[0];
3820
3821         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3822                 return (1);
3823
3824         for (i = 1; i < argc; i++) {
3825                 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
3826                         if (newstate != VDEV_STATE_HEALTHY) {
3827                                 (void) printf(gettext("warning: device '%s' "
3828                                     "onlined, but remains in faulted state\n"),
3829                                     argv[i]);
3830                                 if (newstate == VDEV_STATE_FAULTED)
3831                                         (void) printf(gettext("use 'zpool "
3832                                             "clear' to restore a faulted "
3833                                             "device\n"));
3834                                 else
3835                                         (void) printf(gettext("use 'zpool "
3836                                             "replace' to replace devices "
3837                                             "that are no longer present\n"));
3838                         }
3839                 } else {
3840                         ret = 1;
3841                 }
3842         }
3843
3844         zpool_close(zhp);
3845
3846         return (ret);
3847 }
3848
3849 /*
3850  * zpool offline [-ft] <pool> <device> ...
3851  *
3852  *      -f      Force the device into the offline state, even if doing
3853  *              so would appear to compromise pool availability.
3854  *              (not supported yet)
3855  *
3856  *      -t      Only take the device off-line temporarily.  The offline
3857  *              state will not be persistent across reboots.
3858  */
3859 /* ARGSUSED */
3860 int
3861 zpool_do_offline(int argc, char **argv)
3862 {
3863         int c, i;
3864         char *poolname;
3865         zpool_handle_t *zhp;
3866         int ret = 0;
3867         boolean_t istmp = B_FALSE;
3868
3869         /* check options */
3870         while ((c = getopt(argc, argv, "ft")) != -1) {
3871                 switch (c) {
3872                 case 't':
3873                         istmp = B_TRUE;
3874                         break;
3875                 case 'f':
3876                 case '?':
3877                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3878                             optopt);
3879                         usage(B_FALSE);
3880                 }
3881         }
3882
3883         argc -= optind;
3884         argv += optind;
3885
3886         /* get pool name and check number of arguments */
3887         if (argc < 1) {
3888                 (void) fprintf(stderr, gettext("missing pool name\n"));
3889                 usage(B_FALSE);
3890         }
3891         if (argc < 2) {
3892                 (void) fprintf(stderr, gettext("missing device name\n"));
3893                 usage(B_FALSE);
3894         }
3895
3896         poolname = argv[0];
3897
3898         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3899                 return (1);
3900
3901         for (i = 1; i < argc; i++) {
3902                 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
3903                         ret = 1;
3904         }
3905
3906         zpool_close(zhp);
3907
3908         return (ret);
3909 }
3910
3911 /*
3912  * zpool clear <pool> [device]
3913  *
3914  * Clear all errors associated with a pool or a particular device.
3915  */
3916 int
3917 zpool_do_clear(int argc, char **argv)
3918 {
3919         int c;
3920         int ret = 0;
3921         boolean_t dryrun = B_FALSE;
3922         boolean_t do_rewind = B_FALSE;
3923         boolean_t xtreme_rewind = B_FALSE;
3924         uint32_t rewind_policy = ZPOOL_NO_REWIND;
3925         nvlist_t *policy = NULL;
3926         zpool_handle_t *zhp;
3927         char *pool, *device;
3928
3929         /* check options */
3930         while ((c = getopt(argc, argv, "FnX")) != -1) {
3931                 switch (c) {
3932                 case 'F':
3933                         do_rewind = B_TRUE;
3934                         break;
3935                 case 'n':
3936                         dryrun = B_TRUE;
3937                         break;
3938                 case 'X':
3939                         xtreme_rewind = B_TRUE;
3940                         break;
3941                 case '?':
3942                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3943                             optopt);
3944                         usage(B_FALSE);
3945                 }
3946         }
3947
3948         argc -= optind;
3949         argv += optind;
3950
3951         if (argc < 1) {
3952                 (void) fprintf(stderr, gettext("missing pool name\n"));
3953                 usage(B_FALSE);
3954         }
3955
3956         if (argc > 2) {
3957                 (void) fprintf(stderr, gettext("too many arguments\n"));
3958                 usage(B_FALSE);
3959         }
3960
3961         if ((dryrun || xtreme_rewind) && !do_rewind) {
3962                 (void) fprintf(stderr,
3963                     gettext("-n or -X only meaningful with -F\n"));
3964                 usage(B_FALSE);
3965         }
3966         if (dryrun)
3967                 rewind_policy = ZPOOL_TRY_REWIND;
3968         else if (do_rewind)
3969                 rewind_policy = ZPOOL_DO_REWIND;
3970         if (xtreme_rewind)
3971                 rewind_policy |= ZPOOL_EXTREME_REWIND;
3972
3973         /* In future, further rewind policy choices can be passed along here */
3974         if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
3975             nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
3976             rewind_policy) != 0) {
3977                 return (1);
3978         }
3979
3980         pool = argv[0];
3981         device = argc == 2 ? argv[1] : NULL;
3982
3983         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
3984                 nvlist_free(policy);
3985                 return (1);
3986         }
3987
3988         if (zpool_clear(zhp, device, policy) != 0)
3989                 ret = 1;
3990
3991         zpool_close(zhp);
3992
3993         nvlist_free(policy);
3994
3995         return (ret);
3996 }
3997
3998 /*
3999  * zpool reguid <pool>
4000  */
4001 int
4002 zpool_do_reguid(int argc, char **argv)
4003 {
4004         int c;
4005         char *poolname;
4006         zpool_handle_t *zhp;
4007         int ret = 0;
4008
4009         /* check options */
4010         while ((c = getopt(argc, argv, "")) != -1) {
4011                 switch (c) {
4012                 case '?':
4013                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4014                             optopt);
4015                         usage(B_FALSE);
4016                 }
4017         }
4018
4019         argc -= optind;
4020         argv += optind;
4021
4022         /* get pool name and check number of arguments */
4023         if (argc < 1) {
4024                 (void) fprintf(stderr, gettext("missing pool name\n"));
4025                 usage(B_FALSE);
4026         }
4027
4028         if (argc > 1) {
4029                 (void) fprintf(stderr, gettext("too many arguments\n"));
4030                 usage(B_FALSE);
4031         }
4032
4033         poolname = argv[0];
4034         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
4035                 return (1);
4036
4037         ret = zpool_reguid(zhp);
4038
4039         zpool_close(zhp);
4040         return (ret);
4041 }
4042
4043
4044 /*
4045  * zpool reopen <pool>
4046  *
4047  * Reopen the pool so that the kernel can update the sizes of all vdevs.
4048  */
4049 int
4050 zpool_do_reopen(int argc, char **argv)
4051 {
4052         int c;
4053         int ret = 0;
4054         zpool_handle_t *zhp;
4055         char *pool;
4056
4057         /* check options */
4058         while ((c = getopt(argc, argv, "")) != -1) {
4059                 switch (c) {
4060                 case '?':
4061                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4062                             optopt);
4063                         usage(B_FALSE);
4064                 }
4065         }
4066
4067         argc--;
4068         argv++;
4069
4070         if (argc < 1) {
4071                 (void) fprintf(stderr, gettext("missing pool name\n"));
4072                 usage(B_FALSE);
4073         }
4074
4075         if (argc > 1) {
4076                 (void) fprintf(stderr, gettext("too many arguments\n"));
4077                 usage(B_FALSE);
4078         }
4079
4080         pool = argv[0];
4081         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
4082                 return (1);
4083
4084         ret = zpool_reopen(zhp);
4085         zpool_close(zhp);
4086         return (ret);
4087 }
4088
4089 typedef struct scrub_cbdata {
4090         int     cb_type;
4091         int     cb_argc;
4092         char    **cb_argv;
4093         pool_scrub_cmd_t cb_scrub_cmd;
4094 } scrub_cbdata_t;
4095
4096 static boolean_t
4097 zpool_has_checkpoint(zpool_handle_t *zhp)
4098 {
4099         nvlist_t *config, *nvroot;
4100
4101         config = zpool_get_config(zhp, NULL);
4102
4103         if (config != NULL) {
4104                 pool_checkpoint_stat_t *pcs = NULL;
4105                 uint_t c;
4106
4107                 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4108                 (void) nvlist_lookup_uint64_array(nvroot,
4109                     ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
4110
4111                 if (pcs == NULL || pcs->pcs_state == CS_NONE)
4112                         return (B_FALSE);
4113
4114                 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS ||
4115                     pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
4116                 return (B_TRUE);
4117         }
4118
4119         return (B_FALSE);
4120 }
4121
4122 int
4123 scrub_callback(zpool_handle_t *zhp, void *data)
4124 {
4125         scrub_cbdata_t *cb = data;
4126         int err;
4127
4128         /*
4129          * Ignore faulted pools.
4130          */
4131         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4132                 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
4133                     "currently unavailable\n"), zpool_get_name(zhp));
4134                 return (1);
4135         }
4136
4137         err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
4138
4139         if (err == 0 && zpool_has_checkpoint(zhp) &&
4140             cb->cb_type == POOL_SCAN_SCRUB) {
4141                 (void) printf(gettext("warning: will not scrub state that "
4142                     "belongs to the checkpoint of pool '%s'\n"),
4143                     zpool_get_name(zhp));
4144         }
4145
4146         return (err != 0);
4147 }
4148
4149 /*
4150  * zpool scrub [-s | -p] <pool> ...
4151  *
4152  *      -s      Stop.  Stops any in-progress scrub.
4153  *      -p      Pause. Pause in-progress scrub.
4154  */
4155 int
4156 zpool_do_scrub(int argc, char **argv)
4157 {
4158         int c;
4159         scrub_cbdata_t cb;
4160
4161         cb.cb_type = POOL_SCAN_SCRUB;
4162         cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
4163
4164         /* check options */
4165         while ((c = getopt(argc, argv, "sp")) != -1) {
4166                 switch (c) {
4167                 case 's':
4168                         cb.cb_type = POOL_SCAN_NONE;
4169                         break;
4170                 case 'p':
4171                         cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
4172                         break;
4173                 case '?':
4174                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4175                             optopt);
4176                         usage(B_FALSE);
4177                 }
4178         }
4179
4180         if (cb.cb_type == POOL_SCAN_NONE &&
4181             cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
4182                 (void) fprintf(stderr, gettext("invalid option combination: "
4183                     "-s and -p are mutually exclusive\n"));
4184                 usage(B_FALSE);
4185         }
4186
4187         cb.cb_argc = argc;
4188         cb.cb_argv = argv;
4189         argc -= optind;
4190         argv += optind;
4191
4192         if (argc < 1) {
4193                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4194                 usage(B_FALSE);
4195         }
4196
4197         return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
4198 }
4199
4200 typedef struct status_cbdata {
4201         int             cb_count;
4202         boolean_t       cb_allpools;
4203         boolean_t       cb_verbose;
4204         boolean_t       cb_explain;
4205         boolean_t       cb_first;
4206         boolean_t       cb_dedup_stats;
4207 } status_cbdata_t;
4208
4209 /*
4210  * Print out detailed scrub status.
4211  */
4212 static void
4213 print_scan_status(pool_scan_stat_t *ps)
4214 {
4215         time_t start, end, pause;
4216         uint64_t elapsed, mins_left, hours_left;
4217         uint64_t pass_exam, examined, total;
4218         uint_t rate;
4219         double fraction_done;
4220         char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4221
4222         (void) printf(gettext("  scan: "));
4223
4224         /* If there's never been a scan, there's not much to say. */
4225         if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
4226             ps->pss_func >= POOL_SCAN_FUNCS) {
4227                 (void) printf(gettext("none requested\n"));
4228                 return;
4229         }
4230
4231         start = ps->pss_start_time;
4232         end = ps->pss_end_time;
4233         pause = ps->pss_pass_scrub_pause;
4234         zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
4235
4236         assert(ps->pss_func == POOL_SCAN_SCRUB ||
4237             ps->pss_func == POOL_SCAN_RESILVER);
4238         /*
4239          * Scan is finished or canceled.
4240          */
4241         if (ps->pss_state == DSS_FINISHED) {
4242                 uint64_t minutes_taken = (end - start) / 60;
4243                 char *fmt = NULL;
4244
4245                 if (ps->pss_func == POOL_SCAN_SCRUB) {
4246                         fmt = gettext("scrub repaired %s in %lluh%um with "
4247                             "%llu errors on %s");
4248                 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4249                         fmt = gettext("resilvered %s in %lluh%um with "
4250                             "%llu errors on %s");
4251                 }
4252                 /* LINTED */
4253                 (void) printf(fmt, processed_buf,
4254                     (u_longlong_t)(minutes_taken / 60),
4255                     (uint_t)(minutes_taken % 60),
4256                     (u_longlong_t)ps->pss_errors,
4257                     ctime((time_t *)&end));
4258                 return;
4259         } else if (ps->pss_state == DSS_CANCELED) {
4260                 if (ps->pss_func == POOL_SCAN_SCRUB) {
4261                         (void) printf(gettext("scrub canceled on %s"),
4262                             ctime(&end));
4263                 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4264                         (void) printf(gettext("resilver canceled on %s"),
4265                             ctime(&end));
4266                 }
4267                 return;
4268         }
4269
4270         assert(ps->pss_state == DSS_SCANNING);
4271
4272         /*
4273          * Scan is in progress.
4274          */
4275         if (ps->pss_func == POOL_SCAN_SCRUB) {
4276                 if (pause == 0) {
4277                         (void) printf(gettext("scrub in progress since %s"),
4278                             ctime(&start));
4279                 } else {
4280                         char buf[32];
4281                         struct tm *p = localtime(&pause);
4282                         (void) strftime(buf, sizeof (buf), "%a %b %e %T %Y", p);
4283                         (void) printf(gettext("scrub paused since %s\n"), buf);
4284                         (void) printf(gettext("\tscrub started on   %s"),
4285                             ctime(&start));
4286                 }
4287         } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4288                 (void) printf(gettext("resilver in progress since %s"),
4289                     ctime(&start));
4290         }
4291
4292         examined = ps->pss_examined ? ps->pss_examined : 1;
4293         total = ps->pss_to_examine;
4294         fraction_done = (double)examined / total;
4295
4296         /* elapsed time for this pass */
4297         elapsed = time(NULL) - ps->pss_pass_start;
4298         elapsed -= ps->pss_pass_scrub_spent_paused;
4299         elapsed = elapsed ? elapsed : 1;
4300         pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1;
4301         rate = pass_exam / elapsed;
4302         rate = rate ? rate : 1;
4303         mins_left = ((total - examined) / rate) / 60;
4304         hours_left = mins_left / 60;
4305
4306         zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
4307         zfs_nicenum(total, total_buf, sizeof (total_buf));
4308
4309         /*
4310          * do not print estimated time if hours_left is more than 30 days
4311          * or we have a paused scrub
4312          */
4313         if (pause == 0) {
4314                 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4315                 (void) printf(gettext("\t%s scanned out of %s at %s/s"),
4316                     examined_buf, total_buf, rate_buf);
4317                 if (hours_left < (30 * 24)) {
4318                         (void) printf(gettext(", %lluh%um to go\n"),
4319                             (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4320                 } else {
4321                         (void) printf(gettext(
4322                             ", (scan is slow, no estimated time)\n"));
4323                 }
4324         } else {
4325                 (void) printf(gettext("\t%s scanned out of %s\n"),
4326                     examined_buf, total_buf);
4327         }
4328
4329         if (ps->pss_func == POOL_SCAN_RESILVER) {
4330                 (void) printf(gettext("        %s resilvered, %.2f%% done\n"),
4331                     processed_buf, 100 * fraction_done);
4332         } else if (ps->pss_func == POOL_SCAN_SCRUB) {
4333                 (void) printf(gettext("        %s repaired, %.2f%% done\n"),
4334                     processed_buf, 100 * fraction_done);
4335         }
4336 }
4337
4338 /*
4339  * As we don't scrub checkpointed blocks, we want to warn the
4340  * user that we skipped scanning some blocks if a checkpoint exists
4341  * or existed at any time during the scan.
4342  */
4343 static void
4344 print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs)
4345 {
4346         if (ps == NULL || pcs == NULL)
4347                 return;
4348
4349         if (pcs->pcs_state == CS_NONE ||
4350             pcs->pcs_state == CS_CHECKPOINT_DISCARDING)
4351                 return;
4352
4353         assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS);
4354
4355         if (ps->pss_state == DSS_NONE)
4356                 return;
4357
4358         if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) &&
4359             ps->pss_end_time < pcs->pcs_start_time)
4360                 return;
4361
4362         if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) {
4363                 (void) printf(gettext("    scan warning: skipped blocks "
4364                     "that are only referenced by the checkpoint.\n"));
4365         } else {
4366                 assert(ps->pss_state == DSS_SCANNING);
4367                 (void) printf(gettext("    scan warning: skipping blocks "
4368                     "that are only referenced by the checkpoint.\n"));
4369         }
4370 }
4371
4372 /*
4373  * Print out detailed removal status.
4374  */
4375 static void
4376 print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
4377 {
4378         char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4379         time_t start, end;
4380         nvlist_t *config, *nvroot;
4381         nvlist_t **child;
4382         uint_t children;
4383         char *vdev_name;
4384
4385         if (prs == NULL || prs->prs_state == DSS_NONE)
4386                 return;
4387
4388         /*
4389          * Determine name of vdev.
4390          */
4391         config = zpool_get_config(zhp, NULL);
4392         nvroot = fnvlist_lookup_nvlist(config,
4393             ZPOOL_CONFIG_VDEV_TREE);
4394         verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4395             &child, &children) == 0);
4396         assert(prs->prs_removing_vdev < children);
4397         vdev_name = zpool_vdev_name(g_zfs, zhp,
4398             child[prs->prs_removing_vdev], B_TRUE);
4399
4400         (void) printf(gettext("remove: "));
4401
4402         start = prs->prs_start_time;
4403         end = prs->prs_end_time;
4404         zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
4405
4406         /*
4407          * Removal is finished or canceled.
4408          */
4409         if (prs->prs_state == DSS_FINISHED) {
4410                 uint64_t minutes_taken = (end - start) / 60;
4411
4412                 (void) printf(gettext("Removal of vdev %llu copied %s "
4413                     "in %lluh%um, completed on %s"),
4414                     (longlong_t)prs->prs_removing_vdev,
4415                     copied_buf,
4416                     (u_longlong_t)(minutes_taken / 60),
4417                     (uint_t)(minutes_taken % 60),
4418                     ctime((time_t *)&end));
4419         } else if (prs->prs_state == DSS_CANCELED) {
4420                 (void) printf(gettext("Removal of %s canceled on %s"),
4421                     vdev_name, ctime(&end));
4422         } else {
4423                 uint64_t copied, total, elapsed, mins_left, hours_left;
4424                 double fraction_done;
4425                 uint_t rate;
4426
4427                 assert(prs->prs_state == DSS_SCANNING);
4428
4429                 /*
4430                  * Removal is in progress.
4431                  */
4432                 (void) printf(gettext(
4433                     "Evacuation of %s in progress since %s"),
4434                     vdev_name, ctime(&start));
4435
4436                 copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
4437                 total = prs->prs_to_copy;
4438                 fraction_done = (double)copied / total;
4439
4440                 /* elapsed time for this pass */
4441                 elapsed = time(NULL) - prs->prs_start_time;
4442                 elapsed = elapsed > 0 ? elapsed : 1;
4443                 rate = copied / elapsed;
4444                 rate = rate > 0 ? rate : 1;
4445                 mins_left = ((total - copied) / rate) / 60;
4446                 hours_left = mins_left / 60;
4447
4448                 zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
4449                 zfs_nicenum(total, total_buf, sizeof (total_buf));
4450                 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4451
4452                 /*
4453                  * do not print estimated time if hours_left is more than
4454                  * 30 days
4455                  */
4456                 (void) printf(gettext("    %s copied out of %s at %s/s, "
4457                     "%.2f%% done"),
4458                     examined_buf, total_buf, rate_buf, 100 * fraction_done);
4459                 if (hours_left < (30 * 24)) {
4460                         (void) printf(gettext(", %lluh%um to go\n"),
4461                             (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4462                 } else {
4463                         (void) printf(gettext(
4464                             ", (copy is slow, no estimated time)\n"));
4465                 }
4466         }
4467
4468         if (prs->prs_mapping_memory > 0) {
4469                 char mem_buf[7];
4470                 zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
4471                 (void) printf(gettext("    %s memory used for "
4472                     "removed device mappings\n"),
4473                     mem_buf);
4474         }
4475 }
4476
4477 static void
4478 print_checkpoint_status(pool_checkpoint_stat_t *pcs)
4479 {
4480         time_t start;
4481         char space_buf[7];
4482
4483         if (pcs == NULL || pcs->pcs_state == CS_NONE)
4484                 return;
4485
4486         (void) printf(gettext("checkpoint: "));
4487
4488         start = pcs->pcs_start_time;
4489         zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf));
4490
4491         if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) {
4492                 char *date = ctime(&start);
4493
4494                 /*
4495                  * ctime() adds a newline at the end of the generated
4496                  * string, thus the weird format specifier and the
4497                  * strlen() call used to chop it off from the output.
4498                  */
4499                 (void) printf(gettext("created %.*s, consumes %s\n"),
4500                     strlen(date) - 1, date, space_buf);
4501                 return;
4502         }
4503
4504         assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
4505
4506         (void) printf(gettext("discarding, %s remaining.\n"),
4507             space_buf);
4508 }
4509
4510 static void
4511 print_error_log(zpool_handle_t *zhp)
4512 {
4513         nvlist_t *nverrlist = NULL;
4514         nvpair_t *elem;
4515         char *pathname;
4516         size_t len = MAXPATHLEN * 2;
4517
4518         if (zpool_get_errlog(zhp, &nverrlist) != 0) {
4519                 (void) printf("errors: List of errors unavailable "
4520                     "(insufficient privileges)\n");
4521                 return;
4522         }
4523
4524         (void) printf("errors: Permanent errors have been "
4525             "detected in the following files:\n\n");
4526
4527         pathname = safe_malloc(len);
4528         elem = NULL;
4529         while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
4530                 nvlist_t *nv;
4531                 uint64_t dsobj, obj;
4532
4533                 verify(nvpair_value_nvlist(elem, &nv) == 0);
4534                 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
4535                     &dsobj) == 0);
4536                 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
4537                     &obj) == 0);
4538                 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
4539                 (void) printf("%7s %s\n", "", pathname);
4540         }
4541         free(pathname);
4542         nvlist_free(nverrlist);
4543 }
4544
4545 static void
4546 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
4547     int namewidth)
4548 {
4549         uint_t i;
4550         char *name;
4551
4552         if (nspares == 0)
4553                 return;
4554
4555         (void) printf(gettext("\tspares\n"));
4556
4557         for (i = 0; i < nspares; i++) {
4558                 name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE);
4559                 print_status_config(zhp, name, spares[i],
4560                     namewidth, 2, B_TRUE);
4561                 free(name);
4562         }
4563 }
4564
4565 static void
4566 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
4567     int namewidth)
4568 {
4569         uint_t i;
4570         char *name;
4571
4572         if (nl2cache == 0)
4573                 return;
4574
4575         (void) printf(gettext("\tcache\n"));
4576
4577         for (i = 0; i < nl2cache; i++) {
4578                 name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE);
4579                 print_status_config(zhp, name, l2cache[i],
4580                     namewidth, 2, B_FALSE);
4581                 free(name);
4582         }
4583 }
4584
4585 static void
4586 print_dedup_stats(nvlist_t *config)
4587 {
4588         ddt_histogram_t *ddh;
4589         ddt_stat_t *dds;
4590         ddt_object_t *ddo;
4591         uint_t c;
4592
4593         /*
4594          * If the pool was faulted then we may not have been able to
4595          * obtain the config. Otherwise, if we have anything in the dedup
4596          * table continue processing the stats.
4597          */
4598         if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
4599             (uint64_t **)&ddo, &c) != 0)
4600                 return;
4601
4602         (void) printf("\n");
4603         (void) printf(gettext(" dedup: "));
4604         if (ddo->ddo_count == 0) {
4605                 (void) printf(gettext("no DDT entries\n"));
4606                 return;
4607         }
4608
4609         (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
4610             (u_longlong_t)ddo->ddo_count,
4611             (u_longlong_t)ddo->ddo_dspace,
4612             (u_longlong_t)ddo->ddo_mspace);
4613
4614         verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
4615             (uint64_t **)&dds, &c) == 0);
4616         verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
4617             (uint64_t **)&ddh, &c) == 0);
4618         zpool_dump_ddt(dds, ddh);
4619 }
4620
4621 /*
4622  * Display a summary of pool status.  Displays a summary such as:
4623  *
4624  *        pool: tank
4625  *      status: DEGRADED
4626  *      reason: One or more devices ...
4627  *         see: http://illumos.org/msg/ZFS-xxxx-01
4628  *      config:
4629  *              mirror          DEGRADED
4630  *                c1t0d0        OK
4631  *                c2t0d0        UNAVAIL
4632  *
4633  * When given the '-v' option, we print out the complete config.  If the '-e'
4634  * option is specified, then we print out error rate information as well.
4635  */
4636 int
4637 status_callback(zpool_handle_t *zhp, void *data)
4638 {
4639         status_cbdata_t *cbp = data;
4640         nvlist_t *config, *nvroot;
4641         char *msgid;
4642         int reason;
4643         const char *health;
4644         uint_t c;
4645         vdev_stat_t *vs;
4646
4647         config = zpool_get_config(zhp, NULL);
4648         reason = zpool_get_status(zhp, &msgid);
4649
4650         cbp->cb_count++;
4651
4652         /*
4653          * If we were given 'zpool status -x', only report those pools with
4654          * problems.
4655          */
4656         if (cbp->cb_explain &&
4657             (reason == ZPOOL_STATUS_OK ||
4658             reason == ZPOOL_STATUS_VERSION_OLDER ||
4659             reason == ZPOOL_STATUS_NON_NATIVE_ASHIFT ||
4660             reason == ZPOOL_STATUS_FEAT_DISABLED)) {
4661                 if (!cbp->cb_allpools) {
4662                         (void) printf(gettext("pool '%s' is healthy\n"),
4663                             zpool_get_name(zhp));
4664                         if (cbp->cb_first)
4665                                 cbp->cb_first = B_FALSE;
4666                 }
4667                 return (0);
4668         }
4669
4670         if (cbp->cb_first)
4671                 cbp->cb_first = B_FALSE;
4672         else
4673                 (void) printf("\n");
4674
4675         nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4676         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
4677             (uint64_t **)&vs, &c) == 0);
4678         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
4679
4680         (void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
4681         (void) printf(gettext(" state: %s\n"), health);
4682
4683         switch (reason) {
4684         case ZPOOL_STATUS_MISSING_DEV_R:
4685                 (void) printf(gettext("status: One or more devices could not "
4686                     "be opened.  Sufficient replicas exist for\n\tthe pool to "
4687                     "continue functioning in a degraded state.\n"));
4688                 (void) printf(gettext("action: Attach the missing device and "
4689                     "online it using 'zpool online'.\n"));
4690                 break;
4691
4692         case ZPOOL_STATUS_MISSING_DEV_NR:
4693                 (void) printf(gettext("status: One or more devices could not "
4694                     "be opened.  There are insufficient\n\treplicas for the "
4695                     "pool to continue functioning.\n"));
4696                 (void) printf(gettext("action: Attach the missing device and "
4697                     "online it using 'zpool online'.\n"));
4698                 break;
4699
4700         case ZPOOL_STATUS_CORRUPT_LABEL_R:
4701                 (void) printf(gettext("status: One or more devices could not "
4702                     "be used because the label is missing or\n\tinvalid.  "
4703                     "Sufficient replicas exist for the pool to continue\n\t"
4704                     "functioning in a degraded state.\n"));
4705                 (void) printf(gettext("action: Replace the device using "
4706                     "'zpool replace'.\n"));
4707                 break;
4708
4709         case ZPOOL_STATUS_CORRUPT_LABEL_NR:
4710                 (void) printf(gettext("status: One or more devices could not "
4711                     "be used because the label is missing \n\tor invalid.  "
4712                     "There are insufficient replicas for the pool to "
4713                     "continue\n\tfunctioning.\n"));
4714                 zpool_explain_recover(zpool_get_handle(zhp),
4715                     zpool_get_name(zhp), reason, config);
4716                 break;
4717
4718         case ZPOOL_STATUS_FAILING_DEV:
4719                 (void) printf(gettext("status: One or more devices has "
4720                     "experienced an unrecoverable error.  An\n\tattempt was "
4721                     "made to correct the error.  Applications are "
4722                     "unaffected.\n"));
4723                 (void) printf(gettext("action: Determine if the device needs "
4724                     "to be replaced, and clear the errors\n\tusing "
4725                     "'zpool clear' or replace the device with 'zpool "
4726                     "replace'.\n"));
4727                 break;
4728
4729         case ZPOOL_STATUS_OFFLINE_DEV:
4730                 (void) printf(gettext("status: One or more devices has "
4731                     "been taken offline by the administrator.\n\tSufficient "
4732                     "replicas exist for the pool to continue functioning in "
4733                     "a\n\tdegraded state.\n"));
4734                 (void) printf(gettext("action: Online the device using "
4735                     "'zpool online' or replace the device with\n\t'zpool "
4736                     "replace'.\n"));
4737                 break;
4738
4739         case ZPOOL_STATUS_REMOVED_DEV:
4740                 (void) printf(gettext("status: One or more devices has "
4741                     "been removed by the administrator.\n\tSufficient "
4742                     "replicas exist for the pool to continue functioning in "
4743                     "a\n\tdegraded state.\n"));
4744                 (void) printf(gettext("action: Online the device using "
4745                     "'zpool online' or replace the device with\n\t'zpool "
4746                     "replace'.\n"));
4747                 break;
4748
4749         case ZPOOL_STATUS_RESILVERING:
4750                 (void) printf(gettext("status: One or more devices is "
4751                     "currently being resilvered.  The pool will\n\tcontinue "
4752                     "to function, possibly in a degraded state.\n"));
4753                 (void) printf(gettext("action: Wait for the resilver to "
4754                     "complete.\n"));
4755                 break;
4756
4757         case ZPOOL_STATUS_CORRUPT_DATA:
4758                 (void) printf(gettext("status: One or more devices has "
4759                     "experienced an error resulting in data\n\tcorruption.  "
4760                     "Applications may be affected.\n"));
4761                 (void) printf(gettext("action: Restore the file in question "
4762                     "if possible.  Otherwise restore the\n\tentire pool from "
4763                     "backup.\n"));
4764                 break;
4765
4766         case ZPOOL_STATUS_CORRUPT_POOL:
4767                 (void) printf(gettext("status: The pool metadata is corrupted "
4768                     "and the pool cannot be opened.\n"));
4769                 zpool_explain_recover(zpool_get_handle(zhp),
4770                     zpool_get_name(zhp), reason, config);
4771                 break;
4772
4773         case ZPOOL_STATUS_VERSION_OLDER:
4774                 (void) printf(gettext("status: The pool is formatted using a "
4775                     "legacy on-disk format.  The pool can\n\tstill be used, "
4776                     "but some features are unavailable.\n"));
4777                 (void) printf(gettext("action: Upgrade the pool using 'zpool "
4778                     "upgrade'.  Once this is done, the\n\tpool will no longer "
4779                     "be accessible on software that does not support feature\n"
4780                     "\tflags.\n"));
4781                 break;
4782
4783         case ZPOOL_STATUS_VERSION_NEWER:
4784                 (void) printf(gettext("status: The pool has been upgraded to a "
4785                     "newer, incompatible on-disk version.\n\tThe pool cannot "
4786                     "be accessed on this system.\n"));
4787                 (void) printf(gettext("action: Access the pool from a system "
4788                     "running more recent software, or\n\trestore the pool from "
4789                     "backup.\n"));
4790                 break;
4791
4792         case ZPOOL_STATUS_FEAT_DISABLED:
4793                 (void) printf(gettext("status: Some supported features are not "
4794                     "enabled on the pool. The pool can\n\tstill be used, but "
4795                     "some features are unavailable.\n"));
4796                 (void) printf(gettext("action: Enable all features using "
4797                     "'zpool upgrade'. Once this is done,\n\tthe pool may no "
4798                     "longer be accessible by software that does not support\n\t"
4799                     "the features. See zpool-features(7) for details.\n"));
4800                 break;
4801
4802         case ZPOOL_STATUS_UNSUP_FEAT_READ:
4803                 (void) printf(gettext("status: The pool cannot be accessed on "
4804                     "this system because it uses the\n\tfollowing feature(s) "
4805                     "not supported on this system:\n"));
4806                 zpool_print_unsup_feat(config);
4807                 (void) printf("\n");
4808                 (void) printf(gettext("action: Access the pool from a system "
4809                     "that supports the required feature(s),\n\tor restore the "
4810                     "pool from backup.\n"));
4811                 break;
4812
4813         case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
4814                 (void) printf(gettext("status: The pool can only be accessed "
4815                     "in read-only mode on this system. It\n\tcannot be "
4816                     "accessed in read-write mode because it uses the "
4817                     "following\n\tfeature(s) not supported on this system:\n"));
4818                 zpool_print_unsup_feat(config);
4819                 (void) printf("\n");
4820                 (void) printf(gettext("action: The pool cannot be accessed in "
4821                     "read-write mode. Import the pool with\n"
4822                     "\t\"-o readonly=on\", access the pool from a system that "
4823                     "supports the\n\trequired feature(s), or restore the "
4824                     "pool from backup.\n"));
4825                 break;
4826
4827         case ZPOOL_STATUS_FAULTED_DEV_R:
4828                 (void) printf(gettext("status: One or more devices are "
4829                     "faulted in response to persistent errors.\n\tSufficient "
4830                     "replicas exist for the pool to continue functioning "
4831                     "in a\n\tdegraded state.\n"));
4832                 (void) printf(gettext("action: Replace the faulted device, "
4833                     "or use 'zpool clear' to mark the device\n\trepaired.\n"));
4834                 break;
4835
4836         case ZPOOL_STATUS_FAULTED_DEV_NR:
4837                 (void) printf(gettext("status: One or more devices are "
4838                     "faulted in response to persistent errors.  There are "
4839                     "insufficient replicas for the pool to\n\tcontinue "
4840                     "functioning.\n"));
4841                 (void) printf(gettext("action: Destroy and re-create the pool "
4842                     "from a backup source.  Manually marking the device\n"
4843                     "\trepaired using 'zpool clear' may allow some data "
4844                     "to be recovered.\n"));
4845                 break;
4846
4847         case ZPOOL_STATUS_IO_FAILURE_WAIT:
4848         case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
4849                 (void) printf(gettext("status: One or more devices are "
4850                     "faulted in response to IO failures.\n"));
4851                 (void) printf(gettext("action: Make sure the affected devices "
4852                     "are connected, then run 'zpool clear'.\n"));
4853                 break;
4854
4855         case ZPOOL_STATUS_BAD_LOG:
4856                 (void) printf(gettext("status: An intent log record "
4857                     "could not be read.\n"
4858                     "\tWaiting for adminstrator intervention to fix the "
4859                     "faulted pool.\n"));
4860                 (void) printf(gettext("action: Either restore the affected "
4861                     "device(s) and run 'zpool online',\n"
4862                     "\tor ignore the intent log records by running "
4863                     "'zpool clear'.\n"));
4864                 break;
4865
4866         case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
4867                 (void) printf(gettext("status: One or more devices are "
4868                     "configured to use a non-native block size.\n"
4869                     "\tExpect reduced performance.\n"));
4870                 (void) printf(gettext("action: Replace affected devices with "
4871                     "devices that support the\n\tconfigured block size, or "
4872                     "migrate data to a properly configured\n\tpool.\n"));
4873                 break;
4874
4875         default:
4876                 /*
4877                  * The remaining errors can't actually be generated, yet.
4878                  */
4879                 assert(reason == ZPOOL_STATUS_OK);
4880         }
4881
4882         if (msgid != NULL)
4883                 (void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
4884                     msgid);
4885
4886         if (config != NULL) {
4887                 int namewidth;
4888                 uint64_t nerr;
4889                 nvlist_t **spares, **l2cache;
4890                 uint_t nspares, nl2cache;
4891                 pool_checkpoint_stat_t *pcs = NULL;
4892                 pool_scan_stat_t *ps = NULL;
4893                 pool_removal_stat_t *prs = NULL;
4894
4895                 (void) nvlist_lookup_uint64_array(nvroot,
4896                     ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
4897                 (void) nvlist_lookup_uint64_array(nvroot,
4898                     ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4899                 (void) nvlist_lookup_uint64_array(nvroot,
4900                     ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
4901
4902                 print_scan_status(ps);
4903                 print_checkpoint_scan_warning(ps, pcs);
4904                 print_removal_status(zhp, prs);
4905                 print_checkpoint_status(pcs);
4906
4907                 namewidth = max_width(zhp, nvroot, 0, 0);
4908                 if (namewidth < 10)
4909                         namewidth = 10;
4910
4911                 (void) printf(gettext("config:\n\n"));
4912                 (void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
4913                     "NAME", "STATE", "READ", "WRITE", "CKSUM");
4914                 print_status_config(zhp, zpool_get_name(zhp), nvroot,
4915                     namewidth, 0, B_FALSE);
4916
4917                 if (num_logs(nvroot) > 0)
4918                         print_logs(zhp, nvroot, namewidth, B_TRUE);
4919                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
4920                     &l2cache, &nl2cache) == 0)
4921                         print_l2cache(zhp, l2cache, nl2cache, namewidth);
4922
4923                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
4924                     &spares, &nspares) == 0)
4925                         print_spares(zhp, spares, nspares, namewidth);
4926
4927                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
4928                     &nerr) == 0) {
4929                         nvlist_t *nverrlist = NULL;
4930
4931                         /*
4932                          * If the approximate error count is small, get a
4933                          * precise count by fetching the entire log and
4934                          * uniquifying the results.
4935                          */
4936                         if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
4937                             zpool_get_errlog(zhp, &nverrlist) == 0) {
4938                                 nvpair_t *elem;
4939
4940                                 elem = NULL;
4941                                 nerr = 0;
4942                                 while ((elem = nvlist_next_nvpair(nverrlist,
4943                                     elem)) != NULL) {
4944                                         nerr++;
4945                                 }
4946                         }
4947                         nvlist_free(nverrlist);
4948
4949                         (void) printf("\n");
4950
4951                         if (nerr == 0)
4952                                 (void) printf(gettext("errors: No known data "
4953                                     "errors\n"));
4954                         else if (!cbp->cb_verbose)
4955                                 (void) printf(gettext("errors: %llu data "
4956                                     "errors, use '-v' for a list\n"),
4957                                     (u_longlong_t)nerr);
4958                         else
4959                                 print_error_log(zhp);
4960                 }
4961
4962                 if (cbp->cb_dedup_stats)
4963                         print_dedup_stats(config);
4964         } else {
4965                 (void) printf(gettext("config: The configuration cannot be "
4966                     "determined.\n"));
4967         }
4968
4969         return (0);
4970 }
4971
4972 /*
4973  * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
4974  *
4975  *      -v      Display complete error logs
4976  *      -x      Display only pools with potential problems
4977  *      -D      Display dedup status (undocumented)
4978  *      -T      Display a timestamp in date(1) or Unix format
4979  *
4980  * Describes the health status of all pools or some subset.
4981  */
4982 int
4983 zpool_do_status(int argc, char **argv)
4984 {
4985         int c;
4986         int ret;
4987         unsigned long interval = 0, count = 0;
4988         status_cbdata_t cb = { 0 };
4989
4990         /* check options */
4991         while ((c = getopt(argc, argv, "vxDT:")) != -1) {
4992                 switch (c) {
4993                 case 'v':
4994                         cb.cb_verbose = B_TRUE;
4995                         break;
4996                 case 'x':
4997                         cb.cb_explain = B_TRUE;
4998                         break;
4999                 case 'D':
5000                         cb.cb_dedup_stats = B_TRUE;
5001                         break;
5002                 case 'T':
5003                         get_timestamp_arg(*optarg);
5004                         break;
5005                 case '?':
5006                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5007                             optopt);
5008                         usage(B_FALSE);
5009                 }
5010         }
5011
5012         argc -= optind;
5013         argv += optind;
5014
5015         get_interval_count(&argc, argv, &interval, &count);
5016
5017         if (argc == 0)
5018                 cb.cb_allpools = B_TRUE;
5019
5020         cb.cb_first = B_TRUE;
5021
5022         for (;;) {
5023                 if (timestamp_fmt != NODATE)
5024                         print_timestamp(timestamp_fmt);
5025
5026                 ret = for_each_pool(argc, argv, B_TRUE, NULL,
5027                     status_callback, &cb);
5028
5029                 if (argc == 0 && cb.cb_count == 0)
5030                         (void) printf(gettext("no pools available\n"));
5031                 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
5032                         (void) printf(gettext("all pools are healthy\n"));
5033
5034                 if (ret != 0)
5035                         return (ret);
5036
5037                 if (interval == 0)
5038                         break;
5039
5040                 if (count != 0 && --count == 0)
5041                         break;
5042
5043                 (void) sleep(interval);
5044         }
5045
5046         return (0);
5047 }
5048
5049 typedef struct upgrade_cbdata {
5050         boolean_t       cb_first;
5051         boolean_t       cb_unavail;
5052         char            cb_poolname[ZFS_MAX_DATASET_NAME_LEN];
5053         int             cb_argc;
5054         uint64_t        cb_version;
5055         char            **cb_argv;
5056 } upgrade_cbdata_t;
5057
5058 #ifdef __FreeBSD__
5059 static int
5060 is_root_pool(zpool_handle_t *zhp)
5061 {
5062         static struct statfs sfs;
5063         static char *poolname = NULL;
5064         static boolean_t stated = B_FALSE;
5065         char *slash;
5066
5067         if (!stated) {
5068                 stated = B_TRUE;
5069                 if (statfs("/", &sfs) == -1) {
5070                         (void) fprintf(stderr,
5071                             "Unable to stat root file system: %s.\n",
5072                             strerror(errno));
5073                         return (0);
5074                 }
5075                 if (strcmp(sfs.f_fstypename, "zfs") != 0)
5076                         return (0);
5077                 poolname = sfs.f_mntfromname;
5078                 if ((slash = strchr(poolname, '/')) != NULL)
5079                         *slash = '\0';
5080         }
5081         return (poolname != NULL && strcmp(poolname, zpool_get_name(zhp)) == 0);
5082 }
5083
5084 static void
5085 root_pool_upgrade_check(zpool_handle_t *zhp, char *poolname, int size)
5086 {
5087
5088         if (poolname[0] == '\0' && is_root_pool(zhp))
5089                 (void) strlcpy(poolname, zpool_get_name(zhp), size);
5090 }
5091 #endif  /* FreeBSD */
5092
5093 static int
5094 upgrade_version(zpool_handle_t *zhp, uint64_t version)
5095 {
5096         int ret;
5097         nvlist_t *config;
5098         uint64_t oldversion;
5099
5100         config = zpool_get_config(zhp, NULL);
5101         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5102             &oldversion) == 0);
5103
5104         assert(SPA_VERSION_IS_SUPPORTED(oldversion));
5105         assert(oldversion < version);
5106
5107         ret = zpool_upgrade(zhp, version);
5108         if (ret != 0)
5109                 return (ret);
5110
5111         if (version >= SPA_VERSION_FEATURES) {
5112                 (void) printf(gettext("Successfully upgraded "
5113                     "'%s' from version %llu to feature flags.\n"),
5114                     zpool_get_name(zhp), oldversion);
5115         } else {
5116                 (void) printf(gettext("Successfully upgraded "
5117                     "'%s' from version %llu to version %llu.\n"),
5118                     zpool_get_name(zhp), oldversion, version);
5119         }
5120
5121         return (0);
5122 }
5123
5124 static int
5125 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
5126 {
5127         int i, ret, count;
5128         boolean_t firstff = B_TRUE;
5129         nvlist_t *enabled = zpool_get_features(zhp);
5130
5131         count = 0;
5132         for (i = 0; i < SPA_FEATURES; i++) {
5133                 const char *fname = spa_feature_table[i].fi_uname;
5134                 const char *fguid = spa_feature_table[i].fi_guid;
5135                 if (!nvlist_exists(enabled, fguid)) {
5136                         char *propname;
5137                         verify(-1 != asprintf(&propname, "feature@%s", fname));
5138                         ret = zpool_set_prop(zhp, propname,
5139                             ZFS_FEATURE_ENABLED);
5140                         if (ret != 0) {
5141                                 free(propname);
5142                                 return (ret);
5143                         }
5144                         count++;
5145
5146                         if (firstff) {
5147                                 (void) printf(gettext("Enabled the "
5148                                     "following features on '%s':\n"),
5149                                     zpool_get_name(zhp));
5150                                 firstff = B_FALSE;
5151                         }
5152                         (void) printf(gettext("  %s\n"), fname);
5153                         free(propname);
5154                 }
5155         }
5156
5157         if (countp != NULL)
5158                 *countp = count;
5159         return (0);
5160 }
5161
5162 static int
5163 upgrade_cb(zpool_handle_t *zhp, void *arg)
5164 {
5165         upgrade_cbdata_t *cbp = arg;
5166         nvlist_t *config;
5167         uint64_t version;
5168         boolean_t printnl = B_FALSE;
5169         int ret;
5170
5171         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5172                 (void) fprintf(stderr, gettext("cannot upgrade '%s': pool is "
5173                     "currently unavailable.\n\n"), zpool_get_name(zhp));
5174                 cbp->cb_unavail = B_TRUE;
5175                 /* Allow iteration to continue. */
5176                 return (0);
5177         }
5178
5179         config = zpool_get_config(zhp, NULL);
5180         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5181             &version) == 0);
5182
5183         assert(SPA_VERSION_IS_SUPPORTED(version));
5184
5185         if (version < cbp->cb_version) {
5186                 cbp->cb_first = B_FALSE;
5187                 ret = upgrade_version(zhp, cbp->cb_version);
5188                 if (ret != 0)
5189                         return (ret);
5190 #ifdef __FreeBSD__
5191                 root_pool_upgrade_check(zhp, cbp->cb_poolname,
5192                     sizeof(cbp->cb_poolname));
5193 #endif  /* __FreeBSD__ */
5194                 printnl = B_TRUE;
5195
5196 #ifdef illumos
5197                 /*
5198                  * If they did "zpool upgrade -a", then we could
5199                  * be doing ioctls to different pools.  We need
5200                  * to log this history once to each pool, and bypass
5201                  * the normal history logging that happens in main().
5202                  */
5203                 (void) zpool_log_history(g_zfs, history_str);
5204                 log_history = B_FALSE;
5205 #endif
5206         }
5207
5208         if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5209                 int count;
5210                 ret = upgrade_enable_all(zhp, &count);
5211                 if (ret != 0)
5212                         return (ret);
5213
5214                 if (count > 0) {
5215                         cbp->cb_first = B_FALSE;
5216                         printnl = B_TRUE;
5217 #ifdef __FreeBSD__
5218                         root_pool_upgrade_check(zhp, cbp->cb_poolname,
5219                             sizeof(cbp->cb_poolname));
5220 #endif  /* __FreeBSD__ */
5221                         /*
5222                          * If they did "zpool upgrade -a", then we could
5223                          * be doing ioctls to different pools.  We need
5224                          * to log this history once to each pool, and bypass
5225                          * the normal history logging that happens in main().
5226                          */
5227                         (void) zpool_log_history(g_zfs, history_str);
5228                         log_history = B_FALSE;
5229                 }
5230         }
5231
5232         if (printnl) {
5233                 (void) printf(gettext("\n"));
5234         }
5235
5236         return (0);
5237 }
5238
5239 static int
5240 upgrade_list_unavail(zpool_handle_t *zhp, void *arg)
5241 {
5242         upgrade_cbdata_t *cbp = arg;
5243
5244         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5245                 if (cbp->cb_first) {
5246                         (void) fprintf(stderr, gettext("The following pools "
5247                             "are unavailable and cannot be upgraded as this "
5248                             "time.\n\n"));
5249                         (void) fprintf(stderr, gettext("POOL\n"));
5250                         (void) fprintf(stderr, gettext("------------\n"));
5251                         cbp->cb_first = B_FALSE;
5252                 }
5253                 (void) printf(gettext("%s\n"), zpool_get_name(zhp));
5254                 cbp->cb_unavail = B_TRUE;
5255         }
5256         return (0);
5257 }
5258
5259 static int
5260 upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
5261 {
5262         upgrade_cbdata_t *cbp = arg;
5263         nvlist_t *config;
5264         uint64_t version;
5265
5266         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5267                 /*
5268                  * This will have been reported by upgrade_list_unavail so
5269                  * just allow iteration to continue.
5270                  */
5271                 cbp->cb_unavail = B_TRUE;
5272                 return (0);
5273         }
5274
5275         config = zpool_get_config(zhp, NULL);
5276         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5277             &version) == 0);
5278
5279         assert(SPA_VERSION_IS_SUPPORTED(version));
5280
5281         if (version < SPA_VERSION_FEATURES) {
5282                 if (cbp->cb_first) {
5283                         (void) printf(gettext("The following pools are "
5284                             "formatted with legacy version numbers and can\n"
5285                             "be upgraded to use feature flags.  After "
5286                             "being upgraded, these pools\nwill no "
5287                             "longer be accessible by software that does not "
5288                             "support feature\nflags.\n\n"));
5289                         (void) printf(gettext("VER  POOL\n"));
5290                         (void) printf(gettext("---  ------------\n"));
5291                         cbp->cb_first = B_FALSE;
5292                 }
5293
5294                 (void) printf("%2llu   %s\n", (u_longlong_t)version,
5295                     zpool_get_name(zhp));
5296         }
5297
5298         return (0);
5299 }
5300
5301 static int
5302 upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
5303 {
5304         upgrade_cbdata_t *cbp = arg;
5305         nvlist_t *config;
5306         uint64_t version;
5307
5308         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5309                 /*
5310                  * This will have been reported by upgrade_list_unavail so
5311                  * just allow iteration to continue.
5312                  */
5313                 cbp->cb_unavail = B_TRUE;
5314                 return (0);
5315         }
5316
5317         config = zpool_get_config(zhp, NULL);
5318         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5319             &version) == 0);
5320
5321         if (version >= SPA_VERSION_FEATURES) {
5322                 int i;
5323                 boolean_t poolfirst = B_TRUE;
5324                 nvlist_t *enabled = zpool_get_features(zhp);
5325
5326                 for (i = 0; i < SPA_FEATURES; i++) {
5327                         const char *fguid = spa_feature_table[i].fi_guid;
5328                         const char *fname = spa_feature_table[i].fi_uname;
5329                         if (!nvlist_exists(enabled, fguid)) {
5330                                 if (cbp->cb_first) {
5331                                         (void) printf(gettext("\nSome "
5332                                             "supported features are not "
5333                                             "enabled on the following pools. "
5334                                             "Once a\nfeature is enabled the "
5335                                             "pool may become incompatible with "
5336                                             "software\nthat does not support "
5337                                             "the feature. See "
5338                                             "zpool-features(7) for "
5339                                             "details.\n\n"));
5340                                         (void) printf(gettext("POOL  "
5341                                             "FEATURE\n"));
5342                                         (void) printf(gettext("------"
5343                                             "---------\n"));
5344                                         cbp->cb_first = B_FALSE;
5345                                 }
5346
5347                                 if (poolfirst) {
5348                                         (void) printf(gettext("%s\n"),
5349                                             zpool_get_name(zhp));
5350                                         poolfirst = B_FALSE;
5351                                 }
5352
5353                                 (void) printf(gettext("      %s\n"), fname);
5354                         }
5355                 }
5356         }
5357
5358         return (0);
5359 }
5360
5361 /* ARGSUSED */
5362 static int
5363 upgrade_one(zpool_handle_t *zhp, void *data)
5364 {
5365         boolean_t printnl = B_FALSE;
5366         upgrade_cbdata_t *cbp = data;
5367         uint64_t cur_version;
5368         int ret;
5369
5370         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5371                 (void) fprintf(stderr, gettext("cannot upgrade '%s': pool is "
5372                     "is currently unavailable.\n\n"), zpool_get_name(zhp));
5373                 cbp->cb_unavail = B_TRUE;
5374                 return (1);
5375         }
5376
5377         if (strcmp("log", zpool_get_name(zhp)) == 0) {
5378                 (void) printf(gettext("'log' is now a reserved word\n"
5379                     "Pool 'log' must be renamed using export and import"
5380                     " to upgrade.\n\n"));
5381                 return (1);
5382         }
5383
5384         cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
5385         if (cur_version > cbp->cb_version) {
5386                 (void) printf(gettext("Pool '%s' is already formatted "
5387                     "using more current version '%llu'.\n\n"),
5388                     zpool_get_name(zhp), cur_version);
5389                 return (0);
5390         }
5391
5392         if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
5393                 (void) printf(gettext("Pool '%s' is already formatted "
5394                     "using version %llu.\n\n"), zpool_get_name(zhp),
5395                     cbp->cb_version);
5396                 return (0);
5397         }
5398
5399         if (cur_version != cbp->cb_version) {
5400                 printnl = B_TRUE;
5401                 ret = upgrade_version(zhp, cbp->cb_version);
5402                 if (ret != 0)
5403                         return (ret);
5404 #ifdef __FreeBSD__
5405                 root_pool_upgrade_check(zhp, cbp->cb_poolname,
5406                     sizeof(cbp->cb_poolname));
5407 #endif  /* __FreeBSD__ */
5408         }
5409
5410         if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5411                 int count = 0;
5412                 ret = upgrade_enable_all(zhp, &count);
5413                 if (ret != 0)
5414                         return (ret);
5415
5416                 if (count != 0) {
5417                         printnl = B_TRUE;
5418 #ifdef __FreeBSD__
5419                         root_pool_upgrade_check(zhp, cbp->cb_poolname,
5420                             sizeof(cbp->cb_poolname));
5421 #endif  /* __FreeBSD __*/
5422                 } else if (cur_version == SPA_VERSION) {
5423                         (void) printf(gettext("Pool '%s' already has all "
5424                             "supported features enabled.\n\n"),
5425                             zpool_get_name(zhp));
5426                 }
5427         }
5428
5429         if (printnl) {
5430                 (void) printf(gettext("\n"));
5431         }
5432
5433         return (0);
5434 }
5435
5436 /*
5437  * zpool upgrade
5438  * zpool upgrade -v
5439  * zpool upgrade [-V version] <-a | pool ...>
5440  *
5441  * With no arguments, display downrev'd ZFS pool available for upgrade.
5442  * Individual pools can be upgraded by specifying the pool, and '-a' will
5443  * upgrade all pools.
5444  */
5445 int
5446 zpool_do_upgrade(int argc, char **argv)
5447 {
5448         int c;
5449         upgrade_cbdata_t cb = { 0 };
5450         int ret = 0;
5451         boolean_t showversions = B_FALSE;
5452         boolean_t upgradeall = B_FALSE;
5453         char *end;
5454
5455
5456         /* check options */
5457         while ((c = getopt(argc, argv, ":avV:")) != -1) {
5458                 switch (c) {
5459                 case 'a':
5460                         upgradeall = B_TRUE;
5461                         break;
5462                 case 'v':
5463                         showversions = B_TRUE;
5464                         break;
5465                 case 'V':
5466                         cb.cb_version = strtoll(optarg, &end, 10);
5467                         if (*end != '\0' ||
5468                             !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
5469                                 (void) fprintf(stderr,
5470                                     gettext("invalid version '%s'\n"), optarg);
5471                                 usage(B_FALSE);
5472                         }
5473                         break;
5474                 case ':':
5475                         (void) fprintf(stderr, gettext("missing argument for "
5476                             "'%c' option\n"), optopt);
5477                         usage(B_FALSE);
5478                         break;
5479                 case '?':
5480                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5481                             optopt);
5482                         usage(B_FALSE);
5483                 }
5484         }
5485
5486         cb.cb_argc = argc;
5487         cb.cb_argv = argv;
5488         argc -= optind;
5489         argv += optind;
5490
5491         if (cb.cb_version == 0) {
5492                 cb.cb_version = SPA_VERSION;
5493         } else if (!upgradeall && argc == 0) {
5494                 (void) fprintf(stderr, gettext("-V option is "
5495                     "incompatible with other arguments\n"));
5496                 usage(B_FALSE);
5497         }
5498
5499         if (showversions) {
5500                 if (upgradeall || argc != 0) {
5501                         (void) fprintf(stderr, gettext("-v option is "
5502                             "incompatible with other arguments\n"));
5503                         usage(B_FALSE);
5504                 }
5505         } else if (upgradeall) {
5506                 if (argc != 0) {
5507                         (void) fprintf(stderr, gettext("-a option should not "
5508                             "be used along with a pool name\n"));
5509                         usage(B_FALSE);
5510                 }
5511         }
5512
5513         (void) printf(gettext("This system supports ZFS pool feature "
5514             "flags.\n\n"));
5515         if (showversions) {
5516                 int i;
5517
5518                 (void) printf(gettext("The following features are "
5519                     "supported:\n\n"));
5520                 (void) printf(gettext("FEAT DESCRIPTION\n"));
5521                 (void) printf("----------------------------------------------"
5522                     "---------------\n");
5523                 for (i = 0; i < SPA_FEATURES; i++) {
5524                         zfeature_info_t *fi = &spa_feature_table[i];
5525                         const char *ro =
5526                             (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
5527                             " (read-only compatible)" : "";
5528
5529                         (void) printf("%-37s%s\n", fi->fi_uname, ro);
5530                         (void) printf("     %s\n", fi->fi_desc);
5531                 }
5532                 (void) printf("\n");
5533
5534                 (void) printf(gettext("The following legacy versions are also "
5535                     "supported:\n\n"));
5536                 (void) printf(gettext("VER  DESCRIPTION\n"));
5537                 (void) printf("---  -----------------------------------------"
5538                     "---------------\n");
5539                 (void) printf(gettext(" 1   Initial ZFS version\n"));
5540                 (void) printf(gettext(" 2   Ditto blocks "
5541                     "(replicated metadata)\n"));
5542                 (void) printf(gettext(" 3   Hot spares and double parity "
5543                     "RAID-Z\n"));
5544                 (void) printf(gettext(" 4   zpool history\n"));
5545                 (void) printf(gettext(" 5   Compression using the gzip "
5546                     "algorithm\n"));
5547                 (void) printf(gettext(" 6   bootfs pool property\n"));
5548                 (void) printf(gettext(" 7   Separate intent log devices\n"));
5549                 (void) printf(gettext(" 8   Delegated administration\n"));
5550                 (void) printf(gettext(" 9   refquota and refreservation "
5551                     "properties\n"));
5552                 (void) printf(gettext(" 10  Cache devices\n"));
5553                 (void) printf(gettext(" 11  Improved scrub performance\n"));
5554                 (void) printf(gettext(" 12  Snapshot properties\n"));
5555                 (void) printf(gettext(" 13  snapused property\n"));
5556                 (void) printf(gettext(" 14  passthrough-x aclinherit\n"));
5557                 (void) printf(gettext(" 15  user/group space accounting\n"));
5558                 (void) printf(gettext(" 16  stmf property support\n"));
5559                 (void) printf(gettext(" 17  Triple-parity RAID-Z\n"));
5560                 (void) printf(gettext(" 18  Snapshot user holds\n"));
5561                 (void) printf(gettext(" 19  Log device removal\n"));
5562                 (void) printf(gettext(" 20  Compression using zle "
5563                     "(zero-length encoding)\n"));
5564                 (void) printf(gettext(" 21  Deduplication\n"));
5565                 (void) printf(gettext(" 22  Received properties\n"));
5566                 (void) printf(gettext(" 23  Slim ZIL\n"));
5567                 (void) printf(gettext(" 24  System attributes\n"));
5568                 (void) printf(gettext(" 25  Improved scrub stats\n"));
5569                 (void) printf(gettext(" 26  Improved snapshot deletion "
5570                     "performance\n"));
5571                 (void) printf(gettext(" 27  Improved snapshot creation "
5572                     "performance\n"));
5573                 (void) printf(gettext(" 28  Multiple vdev replacements\n"));
5574                 (void) printf(gettext("\nFor more information on a particular "
5575                     "version, including supported releases,\n"));
5576                 (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
5577         } else if (argc == 0 && upgradeall) {
5578                 cb.cb_first = B_TRUE;
5579                 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
5580                 if (ret == 0 && cb.cb_first) {
5581                         if (cb.cb_version == SPA_VERSION) {
5582                                 (void) printf(gettext("All %spools are already "
5583                                     "formatted using feature flags.\n\n"),
5584                                     cb.cb_unavail ? gettext("available ") : "");
5585                                 (void) printf(gettext("Every %sfeature flags "
5586                                     "pool already has all supported features "
5587                                     "enabled.\n"),
5588                                     cb.cb_unavail ? gettext("available ") : "");
5589                         } else {
5590                                 (void) printf(gettext("All pools are already "
5591                                     "formatted with version %llu or higher.\n"),
5592                                     cb.cb_version);
5593                         }
5594                 }
5595         } else if (argc == 0) {
5596                 cb.cb_first = B_TRUE;
5597                 ret = zpool_iter(g_zfs, upgrade_list_unavail, &cb);
5598                 assert(ret == 0);
5599
5600                 if (!cb.cb_first) {
5601                         (void) fprintf(stderr, "\n");
5602                 }
5603
5604                 cb.cb_first = B_TRUE;
5605                 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
5606                 assert(ret == 0);
5607
5608                 if (cb.cb_first) {
5609                         (void) printf(gettext("All %spools are formatted using "
5610                             "feature flags.\n\n"), cb.cb_unavail ?
5611                             gettext("available ") : "");
5612                 } else {
5613                         (void) printf(gettext("\nUse 'zpool upgrade -v' "
5614                             "for a list of available legacy versions.\n"));
5615                 }
5616
5617                 cb.cb_first = B_TRUE;
5618                 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
5619                 assert(ret == 0);
5620
5621                 if (cb.cb_first) {
5622                         (void) printf(gettext("Every %sfeature flags pool has "
5623                             "all supported features enabled.\n"),
5624                             cb.cb_unavail ? gettext("available ") : "");
5625                 } else {
5626                         (void) printf(gettext("\n"));
5627                 }
5628         } else {
5629                 ret = for_each_pool(argc, argv, B_TRUE, NULL,
5630                     upgrade_one, &cb);
5631         }
5632
5633         if (cb.cb_poolname[0] != '\0') {
5634                 (void) printf(
5635                     "If you boot from pool '%s', don't forget to update boot code.\n"
5636                     "Assuming you use GPT partitioning and da0 is your boot disk\n"
5637                     "the following command will do it:\n"
5638                     "\n"
5639                     "\tgpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0\n\n",
5640                     cb.cb_poolname);
5641         }
5642
5643         return (ret);
5644 }
5645
5646 typedef struct hist_cbdata {
5647         boolean_t first;
5648         boolean_t longfmt;
5649         boolean_t internal;
5650 } hist_cbdata_t;
5651
5652 /*
5653  * Print out the command history for a specific pool.
5654  */
5655 static int
5656 get_history_one(zpool_handle_t *zhp, void *data)
5657 {
5658         nvlist_t *nvhis;
5659         nvlist_t **records;
5660         uint_t numrecords;
5661         int ret, i;
5662         hist_cbdata_t *cb = (hist_cbdata_t *)data;
5663
5664         cb->first = B_FALSE;
5665
5666         (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
5667
5668         if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
5669                 return (ret);
5670
5671         verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
5672             &records, &numrecords) == 0);
5673         for (i = 0; i < numrecords; i++) {
5674                 nvlist_t *rec = records[i];
5675                 char tbuf[30] = "";
5676
5677                 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
5678                         time_t tsec;
5679                         struct tm t;
5680
5681                         tsec = fnvlist_lookup_uint64(records[i],
5682                             ZPOOL_HIST_TIME);
5683                         (void) localtime_r(&tsec, &t);
5684                         (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
5685                 }
5686
5687                 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
5688                         (void) printf("%s %s", tbuf,
5689                             fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
5690                 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
5691                         int ievent =
5692                             fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
5693                         if (!cb->internal)
5694                                 continue;
5695                         if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
5696                                 (void) printf("%s unrecognized record:\n",
5697                                     tbuf);
5698                                 dump_nvlist(rec, 4);
5699                                 continue;
5700                         }
5701                         (void) printf("%s [internal %s txg:%lld] %s", tbuf,
5702                             zfs_history_event_names[ievent],
5703                             fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5704                             fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
5705                 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
5706                         if (!cb->internal)
5707                                 continue;
5708                         (void) printf("%s [txg:%lld] %s", tbuf,
5709                             fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5710                             fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
5711                         if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
5712                                 (void) printf(" %s (%llu)",
5713                                     fnvlist_lookup_string(rec,
5714                                     ZPOOL_HIST_DSNAME),
5715                                     fnvlist_lookup_uint64(rec,
5716                                     ZPOOL_HIST_DSID));
5717                         }
5718                         (void) printf(" %s", fnvlist_lookup_string(rec,
5719                             ZPOOL_HIST_INT_STR));
5720                 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
5721                         if (!cb->internal)
5722                                 continue;
5723                         (void) printf("%s ioctl %s\n", tbuf,
5724                             fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
5725                         if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
5726                                 (void) printf("    input:\n");
5727                                 dump_nvlist(fnvlist_lookup_nvlist(rec,
5728                                     ZPOOL_HIST_INPUT_NVL), 8);
5729                         }
5730                         if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
5731                                 (void) printf("    output:\n");
5732                                 dump_nvlist(fnvlist_lookup_nvlist(rec,
5733                                     ZPOOL_HIST_OUTPUT_NVL), 8);
5734                         }
5735                         if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
5736                                 (void) printf("    errno: %lld\n",
5737                                     fnvlist_lookup_int64(rec,
5738                                     ZPOOL_HIST_ERRNO));
5739                         }
5740                 } else {
5741                         if (!cb->internal)
5742                                 continue;
5743                         (void) printf("%s unrecognized record:\n", tbuf);
5744                         dump_nvlist(rec, 4);
5745                 }
5746
5747                 if (!cb->longfmt) {
5748                         (void) printf("\n");
5749                         continue;
5750                 }
5751                 (void) printf(" [");
5752                 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
5753                         uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
5754                         struct passwd *pwd = getpwuid(who);
5755                         (void) printf("user %d ", (int)who);
5756                         if (pwd != NULL)
5757                                 (void) printf("(%s) ", pwd->pw_name);
5758                 }
5759                 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
5760                         (void) printf("on %s",
5761                             fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
5762                 }
5763                 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
5764                         (void) printf(":%s",
5765                             fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
5766                 }
5767                 (void) printf("]");
5768                 (void) printf("\n");
5769         }
5770         (void) printf("\n");
5771         nvlist_free(nvhis);
5772
5773         return (ret);
5774 }
5775
5776 /*
5777  * zpool history <pool>
5778  *
5779  * Displays the history of commands that modified pools.
5780  */
5781 int
5782 zpool_do_history(int argc, char **argv)
5783 {
5784         hist_cbdata_t cbdata = { 0 };
5785         int ret;
5786         int c;
5787
5788         cbdata.first = B_TRUE;
5789         /* check options */
5790         while ((c = getopt(argc, argv, "li")) != -1) {
5791                 switch (c) {
5792                 case 'l':
5793                         cbdata.longfmt = B_TRUE;
5794                         break;
5795                 case 'i':
5796                         cbdata.internal = B_TRUE;
5797                         break;
5798                 case '?':
5799                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5800                             optopt);
5801                         usage(B_FALSE);
5802                 }
5803         }
5804         argc -= optind;
5805         argv += optind;
5806
5807         ret = for_each_pool(argc, argv, B_FALSE,  NULL, get_history_one,
5808             &cbdata);
5809
5810         if (argc == 0 && cbdata.first == B_TRUE) {
5811                 (void) printf(gettext("no pools available\n"));
5812                 return (0);
5813         }
5814
5815         return (ret);
5816 }
5817
5818 static int
5819 get_callback(zpool_handle_t *zhp, void *data)
5820 {
5821         zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
5822         char value[MAXNAMELEN];
5823         zprop_source_t srctype;
5824         zprop_list_t *pl;
5825
5826         for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
5827
5828                 /*
5829                  * Skip the special fake placeholder. This will also skip
5830                  * over the name property when 'all' is specified.
5831                  */
5832                 if (pl->pl_prop == ZPOOL_PROP_NAME &&
5833                     pl == cbp->cb_proplist)
5834                         continue;
5835
5836                 if (pl->pl_prop == ZPROP_INVAL &&
5837                     (zpool_prop_feature(pl->pl_user_prop) ||
5838                     zpool_prop_unsupported(pl->pl_user_prop))) {
5839                         srctype = ZPROP_SRC_LOCAL;
5840
5841                         if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
5842                             value, sizeof (value)) == 0) {
5843                                 zprop_print_one_property(zpool_get_name(zhp),
5844                                     cbp, pl->pl_user_prop, value, srctype,
5845                                     NULL, NULL);
5846                         }
5847                 } else {
5848                         if (zpool_get_prop(zhp, pl->pl_prop, value,
5849                             sizeof (value), &srctype, cbp->cb_literal) != 0)
5850                                 continue;
5851
5852                         zprop_print_one_property(zpool_get_name(zhp), cbp,
5853                             zpool_prop_to_name(pl->pl_prop), value, srctype,
5854                             NULL, NULL);
5855                 }
5856         }
5857         return (0);
5858 }
5859
5860 /*
5861  * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
5862  *
5863  *      -H      Scripted mode.  Don't display headers, and separate properties
5864  *              by a single tab.
5865  *      -o      List of columns to display.  Defaults to
5866  *              "name,property,value,source".
5867  *      -p      Diplay values in parsable (exact) format.
5868  *
5869  * Get properties of pools in the system. Output space statistics
5870  * for each one as well as other attributes.
5871  */
5872 int
5873 zpool_do_get(int argc, char **argv)
5874 {
5875         zprop_get_cbdata_t cb = { 0 };
5876         zprop_list_t fake_name = { 0 };
5877         int ret;
5878         int c, i;
5879         char *value;
5880
5881         cb.cb_first = B_TRUE;
5882
5883         /*
5884          * Set up default columns and sources.
5885          */
5886         cb.cb_sources = ZPROP_SRC_ALL;
5887         cb.cb_columns[0] = GET_COL_NAME;
5888         cb.cb_columns[1] = GET_COL_PROPERTY;
5889         cb.cb_columns[2] = GET_COL_VALUE;
5890         cb.cb_columns[3] = GET_COL_SOURCE;
5891         cb.cb_type = ZFS_TYPE_POOL;
5892
5893         /* check options */
5894         while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
5895                 switch (c) {
5896                 case 'p':
5897                         cb.cb_literal = B_TRUE;
5898                         break;
5899                 case 'H':
5900                         cb.cb_scripted = B_TRUE;
5901                         break;
5902                 case 'o':
5903                         bzero(&cb.cb_columns, sizeof (cb.cb_columns));
5904                         i = 0;
5905                         while (*optarg != '\0') {
5906                                 static char *col_subopts[] =
5907                                 { "name", "property", "value", "source",
5908                                 "all", NULL };
5909
5910                                 if (i == ZFS_GET_NCOLS) {
5911                                         (void) fprintf(stderr, gettext("too "
5912                                         "many fields given to -o "
5913                                         "option\n"));
5914                                         usage(B_FALSE);
5915                                 }
5916
5917                                 switch (getsubopt(&optarg, col_subopts,
5918                                     &value)) {
5919                                 case 0:
5920                                         cb.cb_columns[i++] = GET_COL_NAME;
5921                                         break;
5922                                 case 1:
5923                                         cb.cb_columns[i++] = GET_COL_PROPERTY;
5924                                         break;
5925                                 case 2:
5926                                         cb.cb_columns[i++] = GET_COL_VALUE;
5927                                         break;
5928                                 case 3:
5929                                         cb.cb_columns[i++] = GET_COL_SOURCE;
5930                                         break;
5931                                 case 4:
5932                                         if (i > 0) {
5933                                                 (void) fprintf(stderr,
5934                                                     gettext("\"all\" conflicts "
5935                                                     "with specific fields "
5936                                                     "given to -o option\n"));
5937                                                 usage(B_FALSE);
5938                                         }
5939                                         cb.cb_columns[0] = GET_COL_NAME;
5940                                         cb.cb_columns[1] = GET_COL_PROPERTY;
5941                                         cb.cb_columns[2] = GET_COL_VALUE;
5942                                         cb.cb_columns[3] = GET_COL_SOURCE;
5943                                         i = ZFS_GET_NCOLS;
5944                                         break;
5945                                 default:
5946                                         (void) fprintf(stderr,
5947                                             gettext("invalid column name "
5948                                             "'%s'\n"), suboptarg);
5949                                         usage(B_FALSE);
5950                                 }
5951                         }
5952                         break;
5953                 case '?':
5954                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5955                             optopt);
5956                         usage(B_FALSE);
5957                 }
5958         }
5959
5960         argc -= optind;
5961         argv += optind;
5962
5963         if (argc < 1) {
5964                 (void) fprintf(stderr, gettext("missing property "
5965                     "argument\n"));
5966                 usage(B_FALSE);
5967         }
5968
5969         if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
5970             ZFS_TYPE_POOL) != 0)
5971                 usage(B_FALSE);
5972
5973         argc--;
5974         argv++;
5975
5976         if (cb.cb_proplist != NULL) {
5977                 fake_name.pl_prop = ZPOOL_PROP_NAME;
5978                 fake_name.pl_width = strlen(gettext("NAME"));
5979                 fake_name.pl_next = cb.cb_proplist;
5980                 cb.cb_proplist = &fake_name;
5981         }
5982
5983         ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
5984             get_callback, &cb);
5985
5986         if (cb.cb_proplist == &fake_name)
5987                 zprop_free_list(fake_name.pl_next);
5988         else
5989                 zprop_free_list(cb.cb_proplist);
5990
5991         return (ret);
5992 }
5993
5994 typedef struct set_cbdata {
5995         char *cb_propname;
5996         char *cb_value;
5997         boolean_t cb_any_successful;
5998 } set_cbdata_t;
5999
6000 int
6001 set_callback(zpool_handle_t *zhp, void *data)
6002 {
6003         int error;
6004         set_cbdata_t *cb = (set_cbdata_t *)data;
6005
6006         error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
6007
6008         if (!error)
6009                 cb->cb_any_successful = B_TRUE;
6010
6011         return (error);
6012 }
6013
6014 int
6015 zpool_do_set(int argc, char **argv)
6016 {
6017         set_cbdata_t cb = { 0 };
6018         int error;
6019
6020         if (argc > 1 && argv[1][0] == '-') {
6021                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6022                     argv[1][1]);
6023                 usage(B_FALSE);
6024         }
6025
6026         if (argc < 2) {
6027                 (void) fprintf(stderr, gettext("missing property=value "
6028                     "argument\n"));
6029                 usage(B_FALSE);
6030         }
6031
6032         if (argc < 3) {
6033                 (void) fprintf(stderr, gettext("missing pool name\n"));
6034                 usage(B_FALSE);
6035         }
6036
6037         if (argc > 3) {
6038                 (void) fprintf(stderr, gettext("too many pool names\n"));
6039                 usage(B_FALSE);
6040         }
6041
6042         cb.cb_propname = argv[1];
6043         cb.cb_value = strchr(cb.cb_propname, '=');
6044         if (cb.cb_value == NULL) {
6045                 (void) fprintf(stderr, gettext("missing value in "
6046                     "property=value argument\n"));
6047                 usage(B_FALSE);
6048         }
6049
6050         *(cb.cb_value) = '\0';
6051         cb.cb_value++;
6052
6053         error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
6054             set_callback, &cb);
6055
6056         return (error);
6057 }
6058
6059 static int
6060 find_command_idx(char *command, int *idx)
6061 {
6062         int i;
6063
6064         for (i = 0; i < NCOMMAND; i++) {
6065                 if (command_table[i].name == NULL)
6066                         continue;
6067
6068                 if (strcmp(command, command_table[i].name) == 0) {
6069                         *idx = i;
6070                         return (0);
6071                 }
6072         }
6073         return (1);
6074 }
6075
6076 int
6077 main(int argc, char **argv)
6078 {
6079         int ret = 0;
6080         int i;
6081         char *cmdname;
6082
6083         (void) setlocale(LC_ALL, "");
6084         (void) textdomain(TEXT_DOMAIN);
6085
6086         if ((g_zfs = libzfs_init()) == NULL) {
6087                 (void) fprintf(stderr, gettext("internal error: failed to "
6088                     "initialize ZFS library\n"));
6089                 return (1);
6090         }
6091
6092         libzfs_print_on_error(g_zfs, B_TRUE);
6093
6094         opterr = 0;
6095
6096         /*
6097          * Make sure the user has specified some command.
6098          */
6099         if (argc < 2) {
6100                 (void) fprintf(stderr, gettext("missing command\n"));
6101                 usage(B_FALSE);
6102         }
6103
6104         cmdname = argv[1];
6105
6106         /*
6107          * Special case '-?'
6108          */
6109         if (strcmp(cmdname, "-?") == 0)
6110                 usage(B_TRUE);
6111
6112         zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
6113
6114         /*
6115          * Run the appropriate command.
6116          */
6117         if (find_command_idx(cmdname, &i) == 0) {
6118                 current_command = &command_table[i];
6119                 ret = command_table[i].func(argc - 1, argv + 1);
6120         } else if (strchr(cmdname, '=')) {
6121                 verify(find_command_idx("set", &i) == 0);
6122                 current_command = &command_table[i];
6123                 ret = command_table[i].func(argc, argv);
6124         } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
6125                 /*
6126                  * 'freeze' is a vile debugging abomination, so we treat
6127                  * it as such.
6128                  */
6129                 zfs_cmd_t zc = { 0 };
6130                 (void) strlcpy(zc.zc_name, argv[2], sizeof (zc.zc_name));
6131                 return (!!zfs_ioctl(g_zfs, ZFS_IOC_POOL_FREEZE, &zc));
6132         } else {
6133                 (void) fprintf(stderr, gettext("unrecognized "
6134                     "command '%s'\n"), cmdname);
6135                 usage(B_FALSE);
6136         }
6137
6138         if (ret == 0 && log_history)
6139                 (void) zpool_log_history(g_zfs, history_str);
6140
6141         libzfs_fini(g_zfs);
6142
6143         /*
6144          * The 'ZFS_ABORT' environment variable causes us to dump core on exit
6145          * for the purposes of running ::findleaks.
6146          */
6147         if (getenv("ZFS_ABORT") != NULL) {
6148                 (void) printf("dumping core by request\n");
6149                 abort();
6150         }
6151
6152         return (ret);
6153 }