]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
MFV r331695, 331700: 9166 zfs storage pool checkpoint
[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_REWIND_REQUEST_TXG, txg) != 0 ||
2361             nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
2362                 goto error;
2363
2364         if (searchdirs == NULL) {
2365                 searchdirs = safe_malloc(sizeof (char *));
2366                 searchdirs[0] = "/dev";
2367                 nsearch = 1;
2368         }
2369
2370         /* check argument count */
2371         if (do_all) {
2372                 if (argc != 0) {
2373                         (void) fprintf(stderr, gettext("too many arguments\n"));
2374                         usage(B_FALSE);
2375                 }
2376         } else {
2377                 if (argc > 2) {
2378                         (void) fprintf(stderr, gettext("too many arguments\n"));
2379                         usage(B_FALSE);
2380                 }
2381
2382                 /*
2383                  * Check for the SYS_CONFIG privilege.  We do this explicitly
2384                  * here because otherwise any attempt to discover pools will
2385                  * silently fail.
2386                  */
2387                 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
2388                         (void) fprintf(stderr, gettext("cannot "
2389                             "discover pools: permission denied\n"));
2390                         free(searchdirs);
2391                         nvlist_free(policy);
2392                         return (1);
2393                 }
2394         }
2395
2396         /*
2397          * Depending on the arguments given, we do one of the following:
2398          *
2399          *      <none>  Iterate through all pools and display information about
2400          *              each one.
2401          *
2402          *      -a      Iterate through all pools and try to import each one.
2403          *
2404          *      <id>    Find the pool that corresponds to the given GUID/pool
2405          *              name and import that one.
2406          *
2407          *      -D      Above options applies only to destroyed pools.
2408          */
2409         if (argc != 0) {
2410                 char *endptr;
2411
2412                 errno = 0;
2413                 searchguid = strtoull(argv[0], &endptr, 10);
2414                 if (errno != 0 || *endptr != '\0') {
2415                         searchname = argv[0];
2416                         searchguid = 0;
2417                 }
2418                 found_config = NULL;
2419
2420                 /*
2421                  * User specified a name or guid.  Ensure it's unique.
2422                  */
2423                 idata.unique = B_TRUE;
2424         }
2425
2426
2427         idata.path = searchdirs;
2428         idata.paths = nsearch;
2429         idata.poolname = searchname;
2430         idata.guid = searchguid;
2431         idata.cachefile = cachefile;
2432         idata.policy = policy;
2433
2434         pools = zpool_search_import(g_zfs, &idata);
2435
2436         if (pools != NULL && idata.exists &&
2437             (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2438                 (void) fprintf(stderr, gettext("cannot import '%s': "
2439                     "a pool with that name already exists\n"),
2440                     argv[0]);
2441                 (void) fprintf(stderr, gettext("use the form '%s "
2442                     "<pool | id> <newpool>' to give it a new name\n"),
2443                     "zpool import");
2444                 err = 1;
2445         } else if (pools == NULL && idata.exists) {
2446                 (void) fprintf(stderr, gettext("cannot import '%s': "
2447                     "a pool with that name is already created/imported,\n"),
2448                     argv[0]);
2449                 (void) fprintf(stderr, gettext("and no additional pools "
2450                     "with that name were found\n"));
2451                 err = 1;
2452         } else if (pools == NULL) {
2453                 if (argc != 0) {
2454                         (void) fprintf(stderr, gettext("cannot import '%s': "
2455                             "no such pool available\n"), argv[0]);
2456                 }
2457                 err = 1;
2458         }
2459
2460         if (err == 1) {
2461                 free(searchdirs);
2462                 nvlist_free(policy);
2463                 return (1);
2464         }
2465
2466         /*
2467          * At this point we have a list of import candidate configs. Even if
2468          * we were searching by pool name or guid, we still need to
2469          * post-process the list to deal with pool state and possible
2470          * duplicate names.
2471          */
2472         err = 0;
2473         elem = NULL;
2474         first = B_TRUE;
2475         while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2476
2477                 verify(nvpair_value_nvlist(elem, &config) == 0);
2478
2479                 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2480                     &pool_state) == 0);
2481                 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2482                         continue;
2483                 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2484                         continue;
2485
2486                 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
2487                     policy) == 0);
2488
2489                 if (argc == 0) {
2490                         if (first)
2491                                 first = B_FALSE;
2492                         else if (!do_all)
2493                                 (void) printf("\n");
2494
2495                         if (do_all) {
2496                                 err |= do_import(config, NULL, mntopts,
2497                                     props, flags);
2498                         } else {
2499                                 show_import(config);
2500                         }
2501                 } else if (searchname != NULL) {
2502                         char *name;
2503
2504                         /*
2505                          * We are searching for a pool based on name.
2506                          */
2507                         verify(nvlist_lookup_string(config,
2508                             ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2509
2510                         if (strcmp(name, searchname) == 0) {
2511                                 if (found_config != NULL) {
2512                                         (void) fprintf(stderr, gettext(
2513                                             "cannot import '%s': more than "
2514                                             "one matching pool\n"), searchname);
2515                                         (void) fprintf(stderr, gettext(
2516                                             "import by numeric ID instead\n"));
2517                                         err = B_TRUE;
2518                                 }
2519                                 found_config = config;
2520                         }
2521                 } else {
2522                         uint64_t guid;
2523
2524                         /*
2525                          * Search for a pool by guid.
2526                          */
2527                         verify(nvlist_lookup_uint64(config,
2528                             ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2529
2530                         if (guid == searchguid)
2531                                 found_config = config;
2532                 }
2533         }
2534
2535         /*
2536          * If we were searching for a specific pool, verify that we found a
2537          * pool, and then do the import.
2538          */
2539         if (argc != 0 && err == 0) {
2540                 if (found_config == NULL) {
2541                         (void) fprintf(stderr, gettext("cannot import '%s': "
2542                             "no such pool available\n"), argv[0]);
2543                         err = B_TRUE;
2544                 } else {
2545                         err |= do_import(found_config, argc == 1 ? NULL :
2546                             argv[1], mntopts, props, flags);
2547                 }
2548         }
2549
2550         /*
2551          * If we were just looking for pools, report an error if none were
2552          * found.
2553          */
2554         if (argc == 0 && first)
2555                 (void) fprintf(stderr,
2556                     gettext("no pools available to import\n"));
2557
2558 error:
2559         nvlist_free(props);
2560         nvlist_free(pools);
2561         nvlist_free(policy);
2562         free(searchdirs);
2563
2564         return (err ? 1 : 0);
2565 }
2566
2567 typedef struct iostat_cbdata {
2568         boolean_t cb_verbose;
2569         int cb_namewidth;
2570         int cb_iteration;
2571         zpool_list_t *cb_list;
2572 } iostat_cbdata_t;
2573
2574 static void
2575 print_iostat_separator(iostat_cbdata_t *cb)
2576 {
2577         int i = 0;
2578
2579         for (i = 0; i < cb->cb_namewidth; i++)
2580                 (void) printf("-");
2581         (void) printf("  -----  -----  -----  -----  -----  -----\n");
2582 }
2583
2584 static void
2585 print_iostat_header(iostat_cbdata_t *cb)
2586 {
2587         (void) printf("%*s     capacity     operations    bandwidth\n",
2588             cb->cb_namewidth, "");
2589         (void) printf("%-*s  alloc   free   read  write   read  write\n",
2590             cb->cb_namewidth, "pool");
2591         print_iostat_separator(cb);
2592 }
2593
2594 /*
2595  * Display a single statistic.
2596  */
2597 static void
2598 print_one_stat(uint64_t value)
2599 {
2600         char buf[64];
2601
2602         zfs_nicenum(value, buf, sizeof (buf));
2603         (void) printf("  %5s", buf);
2604 }
2605
2606 /*
2607  * Print out all the statistics for the given vdev.  This can either be the
2608  * toplevel configuration, or called recursively.  If 'name' is NULL, then this
2609  * is a verbose output, and we don't want to display the toplevel pool stats.
2610  */
2611 void
2612 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2613     nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2614 {
2615         nvlist_t **oldchild, **newchild;
2616         uint_t c, children;
2617         vdev_stat_t *oldvs, *newvs;
2618         vdev_stat_t zerovs = { 0 };
2619         uint64_t tdelta;
2620         double scale;
2621         char *vname;
2622
2623         if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
2624                 return;
2625
2626         if (oldnv != NULL) {
2627                 verify(nvlist_lookup_uint64_array(oldnv,
2628                     ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2629         } else {
2630                 oldvs = &zerovs;
2631         }
2632
2633         verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2634             (uint64_t **)&newvs, &c) == 0);
2635
2636         if (strlen(name) + depth > cb->cb_namewidth)
2637                 (void) printf("%*s%s", depth, "", name);
2638         else
2639                 (void) printf("%*s%s%*s", depth, "", name,
2640                     (int)(cb->cb_namewidth - strlen(name) - depth), "");
2641
2642         tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2643
2644         if (tdelta == 0)
2645                 scale = 1.0;
2646         else
2647                 scale = (double)NANOSEC / tdelta;
2648
2649         /* only toplevel vdevs have capacity stats */
2650         if (newvs->vs_space == 0) {
2651                 (void) printf("      -      -");
2652         } else {
2653                 print_one_stat(newvs->vs_alloc);
2654                 print_one_stat(newvs->vs_space - newvs->vs_alloc);
2655         }
2656
2657         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2658             oldvs->vs_ops[ZIO_TYPE_READ])));
2659
2660         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2661             oldvs->vs_ops[ZIO_TYPE_WRITE])));
2662
2663         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2664             oldvs->vs_bytes[ZIO_TYPE_READ])));
2665
2666         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2667             oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2668
2669         (void) printf("\n");
2670
2671         if (!cb->cb_verbose)
2672                 return;
2673
2674         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2675             &newchild, &children) != 0)
2676                 return;
2677
2678         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2679             &oldchild, &c) != 0)
2680                 return;
2681
2682         for (c = 0; c < children; c++) {
2683                 uint64_t ishole = B_FALSE, islog = B_FALSE;
2684
2685                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2686                     &ishole);
2687
2688                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2689                     &islog);
2690
2691                 if (ishole || islog)
2692                         continue;
2693
2694                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2695                 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2696                     newchild[c], cb, depth + 2);
2697                 free(vname);
2698         }
2699
2700         /*
2701          * Log device section
2702          */
2703
2704         if (num_logs(newnv) > 0) {
2705                 (void) printf("%-*s      -      -      -      -      -      "
2706                     "-\n", cb->cb_namewidth, "logs");
2707
2708                 for (c = 0; c < children; c++) {
2709                         uint64_t islog = B_FALSE;
2710                         (void) nvlist_lookup_uint64(newchild[c],
2711                             ZPOOL_CONFIG_IS_LOG, &islog);
2712
2713                         if (islog) {
2714                                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2715                                     B_FALSE);
2716                                 print_vdev_stats(zhp, vname, oldnv ?
2717                                     oldchild[c] : NULL, newchild[c],
2718                                     cb, depth + 2);
2719                                 free(vname);
2720                         }
2721                 }
2722
2723         }
2724
2725         /*
2726          * Include level 2 ARC devices in iostat output
2727          */
2728         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2729             &newchild, &children) != 0)
2730                 return;
2731
2732         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2733             &oldchild, &c) != 0)
2734                 return;
2735
2736         if (children > 0) {
2737                 (void) printf("%-*s      -      -      -      -      -      "
2738                     "-\n", cb->cb_namewidth, "cache");
2739                 for (c = 0; c < children; c++) {
2740                         vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2741                             B_FALSE);
2742                         print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2743                             newchild[c], cb, depth + 2);
2744                         free(vname);
2745                 }
2746         }
2747 }
2748
2749 static int
2750 refresh_iostat(zpool_handle_t *zhp, void *data)
2751 {
2752         iostat_cbdata_t *cb = data;
2753         boolean_t missing;
2754
2755         /*
2756          * If the pool has disappeared, remove it from the list and continue.
2757          */
2758         if (zpool_refresh_stats(zhp, &missing) != 0)
2759                 return (-1);
2760
2761         if (missing)
2762                 pool_list_remove(cb->cb_list, zhp);
2763
2764         return (0);
2765 }
2766
2767 /*
2768  * Callback to print out the iostats for the given pool.
2769  */
2770 int
2771 print_iostat(zpool_handle_t *zhp, void *data)
2772 {
2773         iostat_cbdata_t *cb = data;
2774         nvlist_t *oldconfig, *newconfig;
2775         nvlist_t *oldnvroot, *newnvroot;
2776
2777         newconfig = zpool_get_config(zhp, &oldconfig);
2778
2779         if (cb->cb_iteration == 1)
2780                 oldconfig = NULL;
2781
2782         verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
2783             &newnvroot) == 0);
2784
2785         if (oldconfig == NULL)
2786                 oldnvroot = NULL;
2787         else
2788                 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
2789                     &oldnvroot) == 0);
2790
2791         /*
2792          * Print out the statistics for the pool.
2793          */
2794         print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
2795
2796         if (cb->cb_verbose)
2797                 print_iostat_separator(cb);
2798
2799         return (0);
2800 }
2801
2802 int
2803 get_namewidth(zpool_handle_t *zhp, void *data)
2804 {
2805         iostat_cbdata_t *cb = data;
2806         nvlist_t *config, *nvroot;
2807
2808         if ((config = zpool_get_config(zhp, NULL)) != NULL) {
2809                 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2810                     &nvroot) == 0);
2811                 if (!cb->cb_verbose)
2812                         cb->cb_namewidth = strlen(zpool_get_name(zhp));
2813                 else
2814                         cb->cb_namewidth = max_width(zhp, nvroot, 0,
2815                             cb->cb_namewidth);
2816         }
2817
2818         /*
2819          * The width must fall into the range [10,38].  The upper limit is the
2820          * maximum we can have and still fit in 80 columns.
2821          */
2822         if (cb->cb_namewidth < 10)
2823                 cb->cb_namewidth = 10;
2824         if (cb->cb_namewidth > 38)
2825                 cb->cb_namewidth = 38;
2826
2827         return (0);
2828 }
2829
2830 /*
2831  * Parse the input string, get the 'interval' and 'count' value if there is one.
2832  */
2833 static void
2834 get_interval_count(int *argcp, char **argv, unsigned long *iv,
2835     unsigned long *cnt)
2836 {
2837         unsigned long interval = 0, count = 0;
2838         int argc = *argcp, errno;
2839
2840         /*
2841          * Determine if the last argument is an integer or a pool name
2842          */
2843         if (argc > 0 && isdigit(argv[argc - 1][0])) {
2844                 char *end;
2845
2846                 errno = 0;
2847                 interval = strtoul(argv[argc - 1], &end, 10);
2848
2849                 if (*end == '\0' && errno == 0) {
2850                         if (interval == 0) {
2851                                 (void) fprintf(stderr, gettext("interval "
2852                                     "cannot be zero\n"));
2853                                 usage(B_FALSE);
2854                         }
2855                         /*
2856                          * Ignore the last parameter
2857                          */
2858                         argc--;
2859                 } else {
2860                         /*
2861                          * If this is not a valid number, just plow on.  The
2862                          * user will get a more informative error message later
2863                          * on.
2864                          */
2865                         interval = 0;
2866                 }
2867         }
2868
2869         /*
2870          * If the last argument is also an integer, then we have both a count
2871          * and an interval.
2872          */
2873         if (argc > 0 && isdigit(argv[argc - 1][0])) {
2874                 char *end;
2875
2876                 errno = 0;
2877                 count = interval;
2878                 interval = strtoul(argv[argc - 1], &end, 10);
2879
2880                 if (*end == '\0' && errno == 0) {
2881                         if (interval == 0) {
2882                                 (void) fprintf(stderr, gettext("interval "
2883                                     "cannot be zero\n"));
2884                                 usage(B_FALSE);
2885                         }
2886
2887                         /*
2888                          * Ignore the last parameter
2889                          */
2890                         argc--;
2891                 } else {
2892                         interval = 0;
2893                 }
2894         }
2895
2896         *iv = interval;
2897         *cnt = count;
2898         *argcp = argc;
2899 }
2900
2901 static void
2902 get_timestamp_arg(char c)
2903 {
2904         if (c == 'u')
2905                 timestamp_fmt = UDATE;
2906         else if (c == 'd')
2907                 timestamp_fmt = DDATE;
2908         else
2909                 usage(B_FALSE);
2910 }
2911
2912 /*
2913  * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
2914  *
2915  *      -v      Display statistics for individual vdevs
2916  *      -T      Display a timestamp in date(1) or Unix format
2917  *
2918  * This command can be tricky because we want to be able to deal with pool
2919  * creation/destruction as well as vdev configuration changes.  The bulk of this
2920  * processing is handled by the pool_list_* routines in zpool_iter.c.  We rely
2921  * on pool_list_update() to detect the addition of new pools.  Configuration
2922  * changes are all handled within libzfs.
2923  */
2924 int
2925 zpool_do_iostat(int argc, char **argv)
2926 {
2927         int c;
2928         int ret;
2929         int npools;
2930         unsigned long interval = 0, count = 0;
2931         zpool_list_t *list;
2932         boolean_t verbose = B_FALSE;
2933         iostat_cbdata_t cb;
2934
2935         /* check options */
2936         while ((c = getopt(argc, argv, "T:v")) != -1) {
2937                 switch (c) {
2938                 case 'T':
2939                         get_timestamp_arg(*optarg);
2940                         break;
2941                 case 'v':
2942                         verbose = B_TRUE;
2943                         break;
2944                 case '?':
2945                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2946                             optopt);
2947                         usage(B_FALSE);
2948                 }
2949         }
2950
2951         argc -= optind;
2952         argv += optind;
2953
2954         get_interval_count(&argc, argv, &interval, &count);
2955
2956         /*
2957          * Construct the list of all interesting pools.
2958          */
2959         ret = 0;
2960         if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
2961                 return (1);
2962
2963         if (pool_list_count(list) == 0 && argc != 0) {
2964                 pool_list_free(list);
2965                 return (1);
2966         }
2967
2968         if (pool_list_count(list) == 0 && interval == 0) {
2969                 pool_list_free(list);
2970                 (void) fprintf(stderr, gettext("no pools available\n"));
2971                 return (1);
2972         }
2973
2974         /*
2975          * Enter the main iostat loop.
2976          */
2977         cb.cb_list = list;
2978         cb.cb_verbose = verbose;
2979         cb.cb_iteration = 0;
2980         cb.cb_namewidth = 0;
2981
2982         for (;;) {
2983                 pool_list_update(list);
2984
2985                 if ((npools = pool_list_count(list)) == 0)
2986                         break;
2987
2988                 /*
2989                  * Refresh all statistics.  This is done as an explicit step
2990                  * before calculating the maximum name width, so that any
2991                  * configuration changes are properly accounted for.
2992                  */
2993                 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
2994
2995                 /*
2996                  * Iterate over all pools to determine the maximum width
2997                  * for the pool / device name column across all pools.
2998                  */
2999                 cb.cb_namewidth = 0;
3000                 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3001
3002                 if (timestamp_fmt != NODATE)
3003                         print_timestamp(timestamp_fmt);
3004
3005                 /*
3006                  * If it's the first time, or verbose mode, print the header.
3007                  */
3008                 if (++cb.cb_iteration == 1 || verbose)
3009                         print_iostat_header(&cb);
3010
3011                 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
3012
3013                 /*
3014                  * If there's more than one pool, and we're not in verbose mode
3015                  * (which prints a separator for us), then print a separator.
3016                  */
3017                 if (npools > 1 && !verbose)
3018                         print_iostat_separator(&cb);
3019
3020                 if (verbose)
3021                         (void) printf("\n");
3022
3023                 /*
3024                  * Flush the output so that redirection to a file isn't buffered
3025                  * indefinitely.
3026                  */
3027                 (void) fflush(stdout);
3028
3029                 if (interval == 0)
3030                         break;
3031
3032                 if (count != 0 && --count == 0)
3033                         break;
3034
3035                 (void) sleep(interval);
3036         }
3037
3038         pool_list_free(list);
3039
3040         return (ret);
3041 }
3042
3043 typedef struct list_cbdata {
3044         boolean_t       cb_verbose;
3045         int             cb_namewidth;
3046         boolean_t       cb_scripted;
3047         zprop_list_t    *cb_proplist;
3048         boolean_t       cb_literal;
3049 } list_cbdata_t;
3050
3051 /*
3052  * Given a list of columns to display, output appropriate headers for each one.
3053  */
3054 static void
3055 print_header(list_cbdata_t *cb)
3056 {
3057         zprop_list_t *pl = cb->cb_proplist;
3058         char headerbuf[ZPOOL_MAXPROPLEN];
3059         const char *header;
3060         boolean_t first = B_TRUE;
3061         boolean_t right_justify;
3062         size_t width = 0;
3063
3064         for (; pl != NULL; pl = pl->pl_next) {
3065                 width = pl->pl_width;
3066                 if (first && cb->cb_verbose) {
3067                         /*
3068                          * Reset the width to accommodate the verbose listing
3069                          * of devices.
3070                          */
3071                         width = cb->cb_namewidth;
3072                 }
3073
3074                 if (!first)
3075                         (void) printf("  ");
3076                 else
3077                         first = B_FALSE;
3078
3079                 right_justify = B_FALSE;
3080                 if (pl->pl_prop != ZPROP_INVAL) {
3081                         header = zpool_prop_column_name(pl->pl_prop);
3082                         right_justify = zpool_prop_align_right(pl->pl_prop);
3083                 } else {
3084                         int i;
3085
3086                         for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
3087                                 headerbuf[i] = toupper(pl->pl_user_prop[i]);
3088                         headerbuf[i] = '\0';
3089                         header = headerbuf;
3090                 }
3091
3092                 if (pl->pl_next == NULL && !right_justify)
3093                         (void) printf("%s", header);
3094                 else if (right_justify)
3095                         (void) printf("%*s", width, header);
3096                 else
3097                         (void) printf("%-*s", width, header);
3098
3099         }
3100
3101         (void) printf("\n");
3102 }
3103
3104 /*
3105  * Given a pool and a list of properties, print out all the properties according
3106  * to the described layout.
3107  */
3108 static void
3109 print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
3110 {
3111         zprop_list_t *pl = cb->cb_proplist;
3112         boolean_t first = B_TRUE;
3113         char property[ZPOOL_MAXPROPLEN];
3114         char *propstr;
3115         boolean_t right_justify;
3116         size_t width;
3117
3118         for (; pl != NULL; pl = pl->pl_next) {
3119
3120                 width = pl->pl_width;
3121                 if (first && cb->cb_verbose) {
3122                         /*
3123                          * Reset the width to accommodate the verbose listing
3124                          * of devices.
3125                          */
3126                         width = cb->cb_namewidth;
3127                 }
3128
3129                 if (!first) {
3130                         if (cb->cb_scripted)
3131                                 (void) printf("\t");
3132                         else
3133                                 (void) printf("  ");
3134                 } else {
3135                         first = B_FALSE;
3136                 }
3137
3138                 right_justify = B_FALSE;
3139                 if (pl->pl_prop != ZPROP_INVAL) {
3140                         if (zpool_get_prop(zhp, pl->pl_prop, property,
3141                             sizeof (property), NULL, cb->cb_literal) != 0)
3142                                 propstr = "-";
3143                         else
3144                                 propstr = property;
3145
3146                         right_justify = zpool_prop_align_right(pl->pl_prop);
3147                 } else if ((zpool_prop_feature(pl->pl_user_prop) ||
3148                     zpool_prop_unsupported(pl->pl_user_prop)) &&
3149                     zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
3150                     sizeof (property)) == 0) {
3151                         propstr = property;
3152                 } else {
3153                         propstr = "-";
3154                 }
3155
3156
3157                 /*
3158                  * If this is being called in scripted mode, or if this is the
3159                  * last column and it is left-justified, don't include a width
3160                  * format specifier.
3161                  */
3162                 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
3163                         (void) printf("%s", propstr);
3164                 else if (right_justify)
3165                         (void) printf("%*s", width, propstr);
3166                 else
3167                         (void) printf("%-*s", width, propstr);
3168         }
3169
3170         (void) printf("\n");
3171 }
3172
3173 static void
3174 print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
3175     boolean_t valid)
3176 {
3177         char propval[64];
3178         boolean_t fixed;
3179         size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
3180
3181         switch (prop) {
3182         case ZPOOL_PROP_EXPANDSZ:
3183         case ZPOOL_PROP_CHECKPOINT:
3184                 if (value == 0)
3185                         (void) strlcpy(propval, "-", sizeof (propval));
3186                 else
3187                         zfs_nicenum(value, propval, sizeof (propval));
3188                 break;
3189         case ZPOOL_PROP_FRAGMENTATION:
3190                 if (value == ZFS_FRAG_INVALID) {
3191                         (void) strlcpy(propval, "-", sizeof (propval));
3192                 } else {
3193                         (void) snprintf(propval, sizeof (propval), "%llu%%",
3194                             value);
3195                 }
3196                 break;
3197         case ZPOOL_PROP_CAPACITY:
3198                 (void) snprintf(propval, sizeof (propval), "%llu%%", value);
3199                 break;
3200         default:
3201                 zfs_nicenum(value, propval, sizeof (propval));
3202         }
3203
3204         if (!valid)
3205                 (void) strlcpy(propval, "-", sizeof (propval));
3206
3207         if (scripted)
3208                 (void) printf("\t%s", propval);
3209         else
3210                 (void) printf("  %*s", width, propval);
3211 }
3212
3213 void
3214 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
3215     list_cbdata_t *cb, int depth)
3216 {
3217         nvlist_t **child;
3218         vdev_stat_t *vs;
3219         uint_t c, children;
3220         char *vname;
3221         boolean_t scripted = cb->cb_scripted;
3222         uint64_t islog = B_FALSE;
3223         boolean_t haslog = B_FALSE;
3224         char *dashes = "%-*s      -      -      -         -      -      -\n";
3225
3226         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3227             (uint64_t **)&vs, &c) == 0);
3228
3229         if (name != NULL) {
3230                 boolean_t toplevel = (vs->vs_space != 0);
3231                 uint64_t cap;
3232
3233                 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
3234                         return;
3235
3236                 if (scripted)
3237                         (void) printf("\t%s", name);
3238                 else if (strlen(name) + depth > cb->cb_namewidth)
3239                         (void) printf("%*s%s", depth, "", name);
3240                 else
3241                         (void) printf("%*s%s%*s", depth, "", name,
3242                             (int)(cb->cb_namewidth - strlen(name) - depth), "");
3243
3244                 /*
3245                  * Print the properties for the individual vdevs. Some
3246                  * properties are only applicable to toplevel vdevs. The
3247                  * 'toplevel' boolean value is passed to the print_one_column()
3248                  * to indicate that the value is valid.
3249                  */
3250                 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
3251                     toplevel);
3252                 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
3253                     toplevel);
3254                 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
3255                     scripted, toplevel);
3256                 print_one_column(ZPOOL_PROP_CHECKPOINT,
3257                     vs->vs_checkpoint_space, scripted, toplevel);
3258                 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
3259                     B_TRUE);
3260                 print_one_column(ZPOOL_PROP_FRAGMENTATION,
3261                     vs->vs_fragmentation, scripted,
3262                     (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel));
3263                 cap = (vs->vs_space == 0) ? 0 :
3264                     (vs->vs_alloc * 100 / vs->vs_space);
3265                 print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel);
3266                 (void) printf("\n");
3267         }
3268
3269         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
3270             &child, &children) != 0)
3271                 return;
3272
3273         for (c = 0; c < children; c++) {
3274                 uint64_t ishole = B_FALSE;
3275
3276                 if (nvlist_lookup_uint64(child[c],
3277                     ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
3278                         continue;
3279
3280                 if (nvlist_lookup_uint64(child[c],
3281                     ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) {
3282                         haslog = B_TRUE;
3283                         continue;
3284                 }
3285
3286                 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3287                 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3288                 free(vname);
3289         }
3290
3291         if (haslog == B_TRUE) {
3292                 /* LINTED E_SEC_PRINTF_VAR_FMT */
3293                 (void) printf(dashes, cb->cb_namewidth, "log");
3294                 for (c = 0; c < children; c++) {
3295                         if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
3296                             &islog) != 0 || !islog)
3297                                 continue;
3298                         vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3299                         print_list_stats(zhp, vname, child[c], cb, depth + 2);
3300                         free(vname);
3301                 }
3302         }
3303
3304         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
3305             &child, &children) == 0 && children > 0) {
3306                 /* LINTED E_SEC_PRINTF_VAR_FMT */
3307                 (void) printf(dashes, cb->cb_namewidth, "cache");
3308                 for (c = 0; c < children; c++) {
3309                         vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3310                         print_list_stats(zhp, vname, child[c], cb, depth + 2);
3311                         free(vname);
3312                 }
3313         }
3314
3315         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
3316             &children) == 0 && children > 0) {
3317                 /* LINTED E_SEC_PRINTF_VAR_FMT */
3318                 (void) printf(dashes, cb->cb_namewidth, "spare");
3319                 for (c = 0; c < children; c++) {
3320                         vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3321                         print_list_stats(zhp, vname, child[c], cb, depth + 2);
3322                         free(vname);
3323                 }
3324         }
3325 }
3326
3327
3328 /*
3329  * Generic callback function to list a pool.
3330  */
3331 int
3332 list_callback(zpool_handle_t *zhp, void *data)
3333 {
3334         list_cbdata_t *cbp = data;
3335         nvlist_t *config;
3336         nvlist_t *nvroot;
3337
3338         config = zpool_get_config(zhp, NULL);
3339
3340         print_pool(zhp, cbp);
3341         if (!cbp->cb_verbose)
3342                 return (0);
3343
3344         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3345             &nvroot) == 0);
3346         print_list_stats(zhp, NULL, nvroot, cbp, 0);
3347
3348         return (0);
3349 }
3350
3351 /*
3352  * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3353  *
3354  *      -H      Scripted mode.  Don't display headers, and separate properties
3355  *              by a single tab.
3356  *      -o      List of properties to display.  Defaults to
3357  *              "name,size,allocated,free,expandsize,fragmentation,capacity,"
3358  *              "dedupratio,health,altroot"
3359  *      -p      Diplay values in parsable (exact) format.
3360  *      -T      Display a timestamp in date(1) or Unix format
3361  *
3362  * List all pools in the system, whether or not they're healthy.  Output space
3363  * statistics for each one, as well as health status summary.
3364  */
3365 int
3366 zpool_do_list(int argc, char **argv)
3367 {
3368         int c;
3369         int ret;
3370         list_cbdata_t cb = { 0 };
3371         static char default_props[] =
3372             "name,size,allocated,free,checkpoint,expandsize,fragmentation,"
3373             "capacity,dedupratio,health,altroot";
3374         char *props = default_props;
3375         unsigned long interval = 0, count = 0;
3376         zpool_list_t *list;
3377         boolean_t first = B_TRUE;
3378
3379         /* check options */
3380         while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
3381                 switch (c) {
3382                 case 'H':
3383                         cb.cb_scripted = B_TRUE;
3384                         break;
3385                 case 'o':
3386                         props = optarg;
3387                         break;
3388                 case 'p':
3389                         cb.cb_literal = B_TRUE;
3390                         break;
3391                 case 'T':
3392                         get_timestamp_arg(*optarg);
3393                         break;
3394                 case 'v':
3395                         cb.cb_verbose = B_TRUE;
3396                         break;
3397                 case ':':
3398                         (void) fprintf(stderr, gettext("missing argument for "
3399                             "'%c' option\n"), optopt);
3400                         usage(B_FALSE);
3401                         break;
3402                 case '?':
3403                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3404                             optopt);
3405                         usage(B_FALSE);
3406                 }
3407         }
3408
3409         argc -= optind;
3410         argv += optind;
3411
3412         get_interval_count(&argc, argv, &interval, &count);
3413
3414         if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
3415                 usage(B_FALSE);
3416
3417         for (;;) {
3418                 if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
3419                     &ret)) == NULL)
3420                         return (1);
3421
3422                 if (pool_list_count(list) == 0)
3423                         break;
3424
3425                 cb.cb_namewidth = 0;
3426                 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3427
3428                 if (timestamp_fmt != NODATE)
3429                         print_timestamp(timestamp_fmt);
3430
3431                 if (!cb.cb_scripted && (first || cb.cb_verbose)) {
3432                         print_header(&cb);
3433                         first = B_FALSE;
3434                 }
3435                 ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
3436
3437                 if (interval == 0)
3438                         break;
3439
3440                 if (count != 0 && --count == 0)
3441                         break;
3442
3443                 pool_list_free(list);
3444                 (void) sleep(interval);
3445         }
3446
3447         if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
3448                 (void) printf(gettext("no pools available\n"));
3449                 ret = 0;
3450         }
3451
3452         pool_list_free(list);
3453         zprop_free_list(cb.cb_proplist);
3454         return (ret);
3455 }
3456
3457 static int
3458 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
3459 {
3460         boolean_t force = B_FALSE;
3461         int c;
3462         nvlist_t *nvroot;
3463         char *poolname, *old_disk, *new_disk;
3464         zpool_handle_t *zhp;
3465         zpool_boot_label_t boot_type;
3466         uint64_t boot_size;
3467         int ret;
3468
3469         /* check options */
3470         while ((c = getopt(argc, argv, "f")) != -1) {
3471                 switch (c) {
3472                 case 'f':
3473                         force = B_TRUE;
3474                         break;
3475                 case '?':
3476                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3477                             optopt);
3478                         usage(B_FALSE);
3479                 }
3480         }
3481
3482         argc -= optind;
3483         argv += optind;
3484
3485         /* get pool name and check number of arguments */
3486         if (argc < 1) {
3487                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3488                 usage(B_FALSE);
3489         }
3490
3491         poolname = argv[0];
3492
3493         if (argc < 2) {
3494                 (void) fprintf(stderr,
3495                     gettext("missing <device> specification\n"));
3496                 usage(B_FALSE);
3497         }
3498
3499         old_disk = argv[1];
3500
3501         if (argc < 3) {
3502                 if (!replacing) {
3503                         (void) fprintf(stderr,
3504                             gettext("missing <new_device> specification\n"));
3505                         usage(B_FALSE);
3506                 }
3507                 new_disk = old_disk;
3508                 argc -= 1;
3509                 argv += 1;
3510         } else {
3511                 new_disk = argv[2];
3512                 argc -= 2;
3513                 argv += 2;
3514         }
3515
3516         if (argc > 1) {
3517                 (void) fprintf(stderr, gettext("too many arguments\n"));
3518                 usage(B_FALSE);
3519         }
3520
3521         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3522                 return (1);
3523
3524         if (zpool_get_config(zhp, NULL) == NULL) {
3525                 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
3526                     poolname);
3527                 zpool_close(zhp);
3528                 return (1);
3529         }
3530
3531         if (zpool_is_bootable(zhp))
3532                 boot_type = ZPOOL_COPY_BOOT_LABEL;
3533         else
3534                 boot_type = ZPOOL_NO_BOOT_LABEL;
3535
3536         boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
3537         nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
3538             boot_type, boot_size, argc, argv);
3539         if (nvroot == NULL) {
3540                 zpool_close(zhp);
3541                 return (1);
3542         }
3543
3544         ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
3545
3546         nvlist_free(nvroot);
3547         zpool_close(zhp);
3548
3549         return (ret);
3550 }
3551
3552 /*
3553  * zpool replace [-f] <pool> <device> <new_device>
3554  *
3555  *      -f      Force attach, even if <new_device> appears to be in use.
3556  *
3557  * Replace <device> with <new_device>.
3558  */
3559 /* ARGSUSED */
3560 int
3561 zpool_do_replace(int argc, char **argv)
3562 {
3563         return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
3564 }
3565
3566 /*
3567  * zpool attach [-f] <pool> <device> <new_device>
3568  *
3569  *      -f      Force attach, even if <new_device> appears to be in use.
3570  *
3571  * Attach <new_device> to the mirror containing <device>.  If <device> is not
3572  * part of a mirror, then <device> will be transformed into a mirror of
3573  * <device> and <new_device>.  In either case, <new_device> will begin life
3574  * with a DTL of [0, now], and will immediately begin to resilver itself.
3575  */
3576 int
3577 zpool_do_attach(int argc, char **argv)
3578 {
3579         return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
3580 }
3581
3582 /*
3583  * zpool detach [-f] <pool> <device>
3584  *
3585  *      -f      Force detach of <device>, even if DTLs argue against it
3586  *              (not supported yet)
3587  *
3588  * Detach a device from a mirror.  The operation will be refused if <device>
3589  * is the last device in the mirror, or if the DTLs indicate that this device
3590  * has the only valid copy of some data.
3591  */
3592 /* ARGSUSED */
3593 int
3594 zpool_do_detach(int argc, char **argv)
3595 {
3596         int c;
3597         char *poolname, *path;
3598         zpool_handle_t *zhp;
3599         int ret;
3600
3601         /* check options */
3602         while ((c = getopt(argc, argv, "f")) != -1) {
3603                 switch (c) {
3604                 case 'f':
3605                 case '?':
3606                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3607                             optopt);
3608                         usage(B_FALSE);
3609                 }
3610         }
3611
3612         argc -= optind;
3613         argv += optind;
3614
3615         /* get pool name and check number of arguments */
3616         if (argc < 1) {
3617                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3618                 usage(B_FALSE);
3619         }
3620
3621         if (argc < 2) {
3622                 (void) fprintf(stderr,
3623                     gettext("missing <device> specification\n"));
3624                 usage(B_FALSE);
3625         }
3626
3627         poolname = argv[0];
3628         path = argv[1];
3629
3630         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3631                 return (1);
3632
3633         ret = zpool_vdev_detach(zhp, path);
3634
3635         zpool_close(zhp);
3636
3637         return (ret);
3638 }
3639
3640 /*
3641  * zpool split [-n] [-o prop=val] ...
3642  *              [-o mntopt] ...
3643  *              [-R altroot] <pool> <newpool> [<device> ...]
3644  *
3645  *      -n      Do not split the pool, but display the resulting layout if
3646  *              it were to be split.
3647  *      -o      Set property=value, or set mount options.
3648  *      -R      Mount the split-off pool under an alternate root.
3649  *
3650  * Splits the named pool and gives it the new pool name.  Devices to be split
3651  * off may be listed, provided that no more than one device is specified
3652  * per top-level vdev mirror.  The newly split pool is left in an exported
3653  * state unless -R is specified.
3654  *
3655  * Restrictions: the top-level of the pool pool must only be made up of
3656  * mirrors; all devices in the pool must be healthy; no device may be
3657  * undergoing a resilvering operation.
3658  */
3659 int
3660 zpool_do_split(int argc, char **argv)
3661 {
3662         char *srcpool, *newpool, *propval;
3663         char *mntopts = NULL;
3664         splitflags_t flags;
3665         int c, ret = 0;
3666         zpool_handle_t *zhp;
3667         nvlist_t *config, *props = NULL;
3668
3669         flags.dryrun = B_FALSE;
3670         flags.import = B_FALSE;
3671
3672         /* check options */
3673         while ((c = getopt(argc, argv, ":R:no:")) != -1) {
3674                 switch (c) {
3675                 case 'R':
3676                         flags.import = B_TRUE;
3677                         if (add_prop_list(
3678                             zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
3679                             &props, B_TRUE) != 0) {
3680                                 nvlist_free(props);
3681                                 usage(B_FALSE);
3682                         }
3683                         break;
3684                 case 'n':
3685                         flags.dryrun = B_TRUE;
3686                         break;
3687                 case 'o':
3688                         if ((propval = strchr(optarg, '=')) != NULL) {
3689                                 *propval = '\0';
3690                                 propval++;
3691                                 if (add_prop_list(optarg, propval,
3692                                     &props, B_TRUE) != 0) {
3693                                         nvlist_free(props);
3694                                         usage(B_FALSE);
3695                                 }
3696                         } else {
3697                                 mntopts = optarg;
3698                         }
3699                         break;
3700                 case ':':
3701                         (void) fprintf(stderr, gettext("missing argument for "
3702                             "'%c' option\n"), optopt);
3703                         usage(B_FALSE);
3704                         break;
3705                 case '?':
3706                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3707                             optopt);
3708                         usage(B_FALSE);
3709                         break;
3710                 }
3711         }
3712
3713         if (!flags.import && mntopts != NULL) {
3714                 (void) fprintf(stderr, gettext("setting mntopts is only "
3715                     "valid when importing the pool\n"));
3716                 usage(B_FALSE);
3717         }
3718
3719         argc -= optind;
3720         argv += optind;
3721
3722         if (argc < 1) {
3723                 (void) fprintf(stderr, gettext("Missing pool name\n"));
3724                 usage(B_FALSE);
3725         }
3726         if (argc < 2) {
3727                 (void) fprintf(stderr, gettext("Missing new pool name\n"));
3728                 usage(B_FALSE);
3729         }
3730
3731         srcpool = argv[0];
3732         newpool = argv[1];
3733
3734         argc -= 2;
3735         argv += 2;
3736
3737         if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
3738                 return (1);
3739
3740         config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
3741         if (config == NULL) {
3742                 ret = 1;
3743         } else {
3744                 if (flags.dryrun) {
3745                         (void) printf(gettext("would create '%s' with the "
3746                             "following layout:\n\n"), newpool);
3747                         print_vdev_tree(NULL, newpool, config, 0, B_FALSE);
3748                 }
3749                 nvlist_free(config);
3750         }
3751
3752         zpool_close(zhp);
3753
3754         if (ret != 0 || flags.dryrun || !flags.import)
3755                 return (ret);
3756
3757         /*
3758          * The split was successful. Now we need to open the new
3759          * pool and import it.
3760          */
3761         if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
3762                 return (1);
3763         if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
3764             zpool_enable_datasets(zhp, mntopts, 0) != 0) {
3765                 ret = 1;
3766                 (void) fprintf(stderr, gettext("Split was successful, but "
3767                     "the datasets could not all be mounted\n"));
3768                 (void) fprintf(stderr, gettext("Try doing '%s' with a "
3769                     "different altroot\n"), "zpool import");
3770         }
3771         zpool_close(zhp);
3772
3773         return (ret);
3774 }
3775
3776
3777
3778 /*
3779  * zpool online <pool> <device> ...
3780  */
3781 int
3782 zpool_do_online(int argc, char **argv)
3783 {
3784         int c, i;
3785         char *poolname;
3786         zpool_handle_t *zhp;
3787         int ret = 0;
3788         vdev_state_t newstate;
3789         int flags = 0;
3790
3791         /* check options */
3792         while ((c = getopt(argc, argv, "et")) != -1) {
3793                 switch (c) {
3794                 case 'e':
3795                         flags |= ZFS_ONLINE_EXPAND;
3796                         break;
3797                 case 't':
3798                 case '?':
3799                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3800                             optopt);
3801                         usage(B_FALSE);
3802                 }
3803         }
3804
3805         argc -= optind;
3806         argv += optind;
3807
3808         /* get pool name and check number of arguments */
3809         if (argc < 1) {
3810                 (void) fprintf(stderr, gettext("missing pool name\n"));
3811                 usage(B_FALSE);
3812         }
3813         if (argc < 2) {
3814                 (void) fprintf(stderr, gettext("missing device name\n"));
3815                 usage(B_FALSE);
3816         }
3817
3818         poolname = argv[0];
3819
3820         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3821                 return (1);
3822
3823         for (i = 1; i < argc; i++) {
3824                 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
3825                         if (newstate != VDEV_STATE_HEALTHY) {
3826                                 (void) printf(gettext("warning: device '%s' "
3827                                     "onlined, but remains in faulted state\n"),
3828                                     argv[i]);
3829                                 if (newstate == VDEV_STATE_FAULTED)
3830                                         (void) printf(gettext("use 'zpool "
3831                                             "clear' to restore a faulted "
3832                                             "device\n"));
3833                                 else
3834                                         (void) printf(gettext("use 'zpool "
3835                                             "replace' to replace devices "
3836                                             "that are no longer present\n"));
3837                         }
3838                 } else {
3839                         ret = 1;
3840                 }
3841         }
3842
3843         zpool_close(zhp);
3844
3845         return (ret);
3846 }
3847
3848 /*
3849  * zpool offline [-ft] <pool> <device> ...
3850  *
3851  *      -f      Force the device into the offline state, even if doing
3852  *              so would appear to compromise pool availability.
3853  *              (not supported yet)
3854  *
3855  *      -t      Only take the device off-line temporarily.  The offline
3856  *              state will not be persistent across reboots.
3857  */
3858 /* ARGSUSED */
3859 int
3860 zpool_do_offline(int argc, char **argv)
3861 {
3862         int c, i;
3863         char *poolname;
3864         zpool_handle_t *zhp;
3865         int ret = 0;
3866         boolean_t istmp = B_FALSE;
3867
3868         /* check options */
3869         while ((c = getopt(argc, argv, "ft")) != -1) {
3870                 switch (c) {
3871                 case 't':
3872                         istmp = B_TRUE;
3873                         break;
3874                 case 'f':
3875                 case '?':
3876                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3877                             optopt);
3878                         usage(B_FALSE);
3879                 }
3880         }
3881
3882         argc -= optind;
3883         argv += optind;
3884
3885         /* get pool name and check number of arguments */
3886         if (argc < 1) {
3887                 (void) fprintf(stderr, gettext("missing pool name\n"));
3888                 usage(B_FALSE);
3889         }
3890         if (argc < 2) {
3891                 (void) fprintf(stderr, gettext("missing device name\n"));
3892                 usage(B_FALSE);
3893         }
3894
3895         poolname = argv[0];
3896
3897         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3898                 return (1);
3899
3900         for (i = 1; i < argc; i++) {
3901                 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
3902                         ret = 1;
3903         }
3904
3905         zpool_close(zhp);
3906
3907         return (ret);
3908 }
3909
3910 /*
3911  * zpool clear <pool> [device]
3912  *
3913  * Clear all errors associated with a pool or a particular device.
3914  */
3915 int
3916 zpool_do_clear(int argc, char **argv)
3917 {
3918         int c;
3919         int ret = 0;
3920         boolean_t dryrun = B_FALSE;
3921         boolean_t do_rewind = B_FALSE;
3922         boolean_t xtreme_rewind = B_FALSE;
3923         uint32_t rewind_policy = ZPOOL_NO_REWIND;
3924         nvlist_t *policy = NULL;
3925         zpool_handle_t *zhp;
3926         char *pool, *device;
3927
3928         /* check options */
3929         while ((c = getopt(argc, argv, "FnX")) != -1) {
3930                 switch (c) {
3931                 case 'F':
3932                         do_rewind = B_TRUE;
3933                         break;
3934                 case 'n':
3935                         dryrun = B_TRUE;
3936                         break;
3937                 case 'X':
3938                         xtreme_rewind = B_TRUE;
3939                         break;
3940                 case '?':
3941                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3942                             optopt);
3943                         usage(B_FALSE);
3944                 }
3945         }
3946
3947         argc -= optind;
3948         argv += optind;
3949
3950         if (argc < 1) {
3951                 (void) fprintf(stderr, gettext("missing pool name\n"));
3952                 usage(B_FALSE);
3953         }
3954
3955         if (argc > 2) {
3956                 (void) fprintf(stderr, gettext("too many arguments\n"));
3957                 usage(B_FALSE);
3958         }
3959
3960         if ((dryrun || xtreme_rewind) && !do_rewind) {
3961                 (void) fprintf(stderr,
3962                     gettext("-n or -X only meaningful with -F\n"));
3963                 usage(B_FALSE);
3964         }
3965         if (dryrun)
3966                 rewind_policy = ZPOOL_TRY_REWIND;
3967         else if (do_rewind)
3968                 rewind_policy = ZPOOL_DO_REWIND;
3969         if (xtreme_rewind)
3970                 rewind_policy |= ZPOOL_EXTREME_REWIND;
3971
3972         /* In future, further rewind policy choices can be passed along here */
3973         if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
3974             nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
3975                 return (1);
3976
3977         pool = argv[0];
3978         device = argc == 2 ? argv[1] : NULL;
3979
3980         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
3981                 nvlist_free(policy);
3982                 return (1);
3983         }
3984
3985         if (zpool_clear(zhp, device, policy) != 0)
3986                 ret = 1;
3987
3988         zpool_close(zhp);
3989
3990         nvlist_free(policy);
3991
3992         return (ret);
3993 }
3994
3995 /*
3996  * zpool reguid <pool>
3997  */
3998 int
3999 zpool_do_reguid(int argc, char **argv)
4000 {
4001         int c;
4002         char *poolname;
4003         zpool_handle_t *zhp;
4004         int ret = 0;
4005
4006         /* check options */
4007         while ((c = getopt(argc, argv, "")) != -1) {
4008                 switch (c) {
4009                 case '?':
4010                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4011                             optopt);
4012                         usage(B_FALSE);
4013                 }
4014         }
4015
4016         argc -= optind;
4017         argv += optind;
4018
4019         /* get pool name and check number of arguments */
4020         if (argc < 1) {
4021                 (void) fprintf(stderr, gettext("missing pool name\n"));
4022                 usage(B_FALSE);
4023         }
4024
4025         if (argc > 1) {
4026                 (void) fprintf(stderr, gettext("too many arguments\n"));
4027                 usage(B_FALSE);
4028         }
4029
4030         poolname = argv[0];
4031         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
4032                 return (1);
4033
4034         ret = zpool_reguid(zhp);
4035
4036         zpool_close(zhp);
4037         return (ret);
4038 }
4039
4040
4041 /*
4042  * zpool reopen <pool>
4043  *
4044  * Reopen the pool so that the kernel can update the sizes of all vdevs.
4045  */
4046 int
4047 zpool_do_reopen(int argc, char **argv)
4048 {
4049         int c;
4050         int ret = 0;
4051         zpool_handle_t *zhp;
4052         char *pool;
4053
4054         /* check options */
4055         while ((c = getopt(argc, argv, "")) != -1) {
4056                 switch (c) {
4057                 case '?':
4058                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4059                             optopt);
4060                         usage(B_FALSE);
4061                 }
4062         }
4063
4064         argc--;
4065         argv++;
4066
4067         if (argc < 1) {
4068                 (void) fprintf(stderr, gettext("missing pool name\n"));
4069                 usage(B_FALSE);
4070         }
4071
4072         if (argc > 1) {
4073                 (void) fprintf(stderr, gettext("too many arguments\n"));
4074                 usage(B_FALSE);
4075         }
4076
4077         pool = argv[0];
4078         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
4079                 return (1);
4080
4081         ret = zpool_reopen(zhp);
4082         zpool_close(zhp);
4083         return (ret);
4084 }
4085
4086 typedef struct scrub_cbdata {
4087         int     cb_type;
4088         int     cb_argc;
4089         char    **cb_argv;
4090         pool_scrub_cmd_t cb_scrub_cmd;
4091 } scrub_cbdata_t;
4092
4093 static boolean_t
4094 zpool_has_checkpoint(zpool_handle_t *zhp)
4095 {
4096         nvlist_t *config, *nvroot;
4097
4098         config = zpool_get_config(zhp, NULL);
4099
4100         if (config != NULL) {
4101                 pool_checkpoint_stat_t *pcs = NULL;
4102                 uint_t c;
4103
4104                 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4105                 (void) nvlist_lookup_uint64_array(nvroot,
4106                     ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
4107
4108                 if (pcs == NULL || pcs->pcs_state == CS_NONE)
4109                         return (B_FALSE);
4110
4111                 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS ||
4112                     pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
4113                 return (B_TRUE);
4114         }
4115
4116         return (B_FALSE);
4117 }
4118
4119 int
4120 scrub_callback(zpool_handle_t *zhp, void *data)
4121 {
4122         scrub_cbdata_t *cb = data;
4123         int err;
4124
4125         /*
4126          * Ignore faulted pools.
4127          */
4128         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4129                 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
4130                     "currently unavailable\n"), zpool_get_name(zhp));
4131                 return (1);
4132         }
4133
4134         err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
4135
4136         if (err == 0 && zpool_has_checkpoint(zhp) &&
4137             cb->cb_type == POOL_SCAN_SCRUB) {
4138                 (void) printf(gettext("warning: will not scrub state that "
4139                     "belongs to the checkpoint of pool '%s'\n"),
4140                     zpool_get_name(zhp));
4141         }
4142
4143         return (err != 0);
4144 }
4145
4146 /*
4147  * zpool scrub [-s | -p] <pool> ...
4148  *
4149  *      -s      Stop.  Stops any in-progress scrub.
4150  *      -p      Pause. Pause in-progress scrub.
4151  */
4152 int
4153 zpool_do_scrub(int argc, char **argv)
4154 {
4155         int c;
4156         scrub_cbdata_t cb;
4157
4158         cb.cb_type = POOL_SCAN_SCRUB;
4159         cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
4160
4161         /* check options */
4162         while ((c = getopt(argc, argv, "sp")) != -1) {
4163                 switch (c) {
4164                 case 's':
4165                         cb.cb_type = POOL_SCAN_NONE;
4166                         break;
4167                 case 'p':
4168                         cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
4169                         break;
4170                 case '?':
4171                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4172                             optopt);
4173                         usage(B_FALSE);
4174                 }
4175         }
4176
4177         if (cb.cb_type == POOL_SCAN_NONE &&
4178             cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
4179                 (void) fprintf(stderr, gettext("invalid option combination: "
4180                     "-s and -p are mutually exclusive\n"));
4181                 usage(B_FALSE);
4182         }
4183
4184         cb.cb_argc = argc;
4185         cb.cb_argv = argv;
4186         argc -= optind;
4187         argv += optind;
4188
4189         if (argc < 1) {
4190                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4191                 usage(B_FALSE);
4192         }
4193
4194         return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
4195 }
4196
4197 typedef struct status_cbdata {
4198         int             cb_count;
4199         boolean_t       cb_allpools;
4200         boolean_t       cb_verbose;
4201         boolean_t       cb_explain;
4202         boolean_t       cb_first;
4203         boolean_t       cb_dedup_stats;
4204 } status_cbdata_t;
4205
4206 /*
4207  * Print out detailed scrub status.
4208  */
4209 static void
4210 print_scan_status(pool_scan_stat_t *ps)
4211 {
4212         time_t start, end, pause;
4213         uint64_t elapsed, mins_left, hours_left;
4214         uint64_t pass_exam, examined, total;
4215         uint_t rate;
4216         double fraction_done;
4217         char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4218
4219         (void) printf(gettext("  scan: "));
4220
4221         /* If there's never been a scan, there's not much to say. */
4222         if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
4223             ps->pss_func >= POOL_SCAN_FUNCS) {
4224                 (void) printf(gettext("none requested\n"));
4225                 return;
4226         }
4227
4228         start = ps->pss_start_time;
4229         end = ps->pss_end_time;
4230         pause = ps->pss_pass_scrub_pause;
4231         zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
4232
4233         assert(ps->pss_func == POOL_SCAN_SCRUB ||
4234             ps->pss_func == POOL_SCAN_RESILVER);
4235         /*
4236          * Scan is finished or canceled.
4237          */
4238         if (ps->pss_state == DSS_FINISHED) {
4239                 uint64_t minutes_taken = (end - start) / 60;
4240                 char *fmt = NULL;
4241
4242                 if (ps->pss_func == POOL_SCAN_SCRUB) {
4243                         fmt = gettext("scrub repaired %s in %lluh%um with "
4244                             "%llu errors on %s");
4245                 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4246                         fmt = gettext("resilvered %s in %lluh%um with "
4247                             "%llu errors on %s");
4248                 }
4249                 /* LINTED */
4250                 (void) printf(fmt, processed_buf,
4251                     (u_longlong_t)(minutes_taken / 60),
4252                     (uint_t)(minutes_taken % 60),
4253                     (u_longlong_t)ps->pss_errors,
4254                     ctime((time_t *)&end));
4255                 return;
4256         } else if (ps->pss_state == DSS_CANCELED) {
4257                 if (ps->pss_func == POOL_SCAN_SCRUB) {
4258                         (void) printf(gettext("scrub canceled on %s"),
4259                             ctime(&end));
4260                 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4261                         (void) printf(gettext("resilver canceled on %s"),
4262                             ctime(&end));
4263                 }
4264                 return;
4265         }
4266
4267         assert(ps->pss_state == DSS_SCANNING);
4268
4269         /*
4270          * Scan is in progress.
4271          */
4272         if (ps->pss_func == POOL_SCAN_SCRUB) {
4273                 if (pause == 0) {
4274                         (void) printf(gettext("scrub in progress since %s"),
4275                             ctime(&start));
4276                 } else {
4277                         char buf[32];
4278                         struct tm *p = localtime(&pause);
4279                         (void) strftime(buf, sizeof (buf), "%a %b %e %T %Y", p);
4280                         (void) printf(gettext("scrub paused since %s\n"), buf);
4281                         (void) printf(gettext("\tscrub started on   %s"),
4282                             ctime(&start));
4283                 }
4284         } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4285                 (void) printf(gettext("resilver in progress since %s"),
4286                     ctime(&start));
4287         }
4288
4289         examined = ps->pss_examined ? ps->pss_examined : 1;
4290         total = ps->pss_to_examine;
4291         fraction_done = (double)examined / total;
4292
4293         /* elapsed time for this pass */
4294         elapsed = time(NULL) - ps->pss_pass_start;
4295         elapsed -= ps->pss_pass_scrub_spent_paused;
4296         elapsed = elapsed ? elapsed : 1;
4297         pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1;
4298         rate = pass_exam / elapsed;
4299         rate = rate ? rate : 1;
4300         mins_left = ((total - examined) / rate) / 60;
4301         hours_left = mins_left / 60;
4302
4303         zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
4304         zfs_nicenum(total, total_buf, sizeof (total_buf));
4305
4306         /*
4307          * do not print estimated time if hours_left is more than 30 days
4308          * or we have a paused scrub
4309          */
4310         if (pause == 0) {
4311                 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4312                 (void) printf(gettext("\t%s scanned out of %s at %s/s"),
4313                     examined_buf, total_buf, rate_buf);
4314                 if (hours_left < (30 * 24)) {
4315                         (void) printf(gettext(", %lluh%um to go\n"),
4316                             (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4317                 } else {
4318                         (void) printf(gettext(
4319                             ", (scan is slow, no estimated time)\n"));
4320                 }
4321         } else {
4322                 (void) printf(gettext("\t%s scanned out of %s\n"),
4323                     examined_buf, total_buf);
4324         }
4325
4326         if (ps->pss_func == POOL_SCAN_RESILVER) {
4327                 (void) printf(gettext("        %s resilvered, %.2f%% done\n"),
4328                     processed_buf, 100 * fraction_done);
4329         } else if (ps->pss_func == POOL_SCAN_SCRUB) {
4330                 (void) printf(gettext("        %s repaired, %.2f%% done\n"),
4331                     processed_buf, 100 * fraction_done);
4332         }
4333 }
4334
4335 /*
4336  * As we don't scrub checkpointed blocks, we want to warn the
4337  * user that we skipped scanning some blocks if a checkpoint exists
4338  * or existed at any time during the scan.
4339  */
4340 static void
4341 print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs)
4342 {
4343         if (ps == NULL || pcs == NULL)
4344                 return;
4345
4346         if (pcs->pcs_state == CS_NONE ||
4347             pcs->pcs_state == CS_CHECKPOINT_DISCARDING)
4348                 return;
4349
4350         assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS);
4351
4352         if (ps->pss_state == DSS_NONE)
4353                 return;
4354
4355         if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) &&
4356             ps->pss_end_time < pcs->pcs_start_time)
4357                 return;
4358
4359         if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) {
4360                 (void) printf(gettext("    scan warning: skipped blocks "
4361                     "that are only referenced by the checkpoint.\n"));
4362         } else {
4363                 assert(ps->pss_state == DSS_SCANNING);
4364                 (void) printf(gettext("    scan warning: skipping blocks "
4365                     "that are only referenced by the checkpoint.\n"));
4366         }
4367 }
4368
4369 /*
4370  * Print out detailed removal status.
4371  */
4372 static void
4373 print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
4374 {
4375         char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4376         time_t start, end;
4377         nvlist_t *config, *nvroot;
4378         nvlist_t **child;
4379         uint_t children;
4380         char *vdev_name;
4381
4382         if (prs == NULL || prs->prs_state == DSS_NONE)
4383                 return;
4384
4385         /*
4386          * Determine name of vdev.
4387          */
4388         config = zpool_get_config(zhp, NULL);
4389         nvroot = fnvlist_lookup_nvlist(config,
4390             ZPOOL_CONFIG_VDEV_TREE);
4391         verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4392             &child, &children) == 0);
4393         assert(prs->prs_removing_vdev < children);
4394         vdev_name = zpool_vdev_name(g_zfs, zhp,
4395             child[prs->prs_removing_vdev], B_TRUE);
4396
4397         (void) printf(gettext("remove: "));
4398
4399         start = prs->prs_start_time;
4400         end = prs->prs_end_time;
4401         zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
4402
4403         /*
4404          * Removal is finished or canceled.
4405          */
4406         if (prs->prs_state == DSS_FINISHED) {
4407                 uint64_t minutes_taken = (end - start) / 60;
4408
4409                 (void) printf(gettext("Removal of vdev %llu copied %s "
4410                     "in %lluh%um, completed on %s"),
4411                     (longlong_t)prs->prs_removing_vdev,
4412                     copied_buf,
4413                     (u_longlong_t)(minutes_taken / 60),
4414                     (uint_t)(minutes_taken % 60),
4415                     ctime((time_t *)&end));
4416         } else if (prs->prs_state == DSS_CANCELED) {
4417                 (void) printf(gettext("Removal of %s canceled on %s"),
4418                     vdev_name, ctime(&end));
4419         } else {
4420                 uint64_t copied, total, elapsed, mins_left, hours_left;
4421                 double fraction_done;
4422                 uint_t rate;
4423
4424                 assert(prs->prs_state == DSS_SCANNING);
4425
4426                 /*
4427                  * Removal is in progress.
4428                  */
4429                 (void) printf(gettext(
4430                     "Evacuation of %s in progress since %s"),
4431                     vdev_name, ctime(&start));
4432
4433                 copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
4434                 total = prs->prs_to_copy;
4435                 fraction_done = (double)copied / total;
4436
4437                 /* elapsed time for this pass */
4438                 elapsed = time(NULL) - prs->prs_start_time;
4439                 elapsed = elapsed > 0 ? elapsed : 1;
4440                 rate = copied / elapsed;
4441                 rate = rate > 0 ? rate : 1;
4442                 mins_left = ((total - copied) / rate) / 60;
4443                 hours_left = mins_left / 60;
4444
4445                 zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
4446                 zfs_nicenum(total, total_buf, sizeof (total_buf));
4447                 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4448
4449                 /*
4450                  * do not print estimated time if hours_left is more than
4451                  * 30 days
4452                  */
4453                 (void) printf(gettext("    %s copied out of %s at %s/s, "
4454                     "%.2f%% done"),
4455                     examined_buf, total_buf, rate_buf, 100 * fraction_done);
4456                 if (hours_left < (30 * 24)) {
4457                         (void) printf(gettext(", %lluh%um to go\n"),
4458                             (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4459                 } else {
4460                         (void) printf(gettext(
4461                             ", (copy is slow, no estimated time)\n"));
4462                 }
4463         }
4464
4465         if (prs->prs_mapping_memory > 0) {
4466                 char mem_buf[7];
4467                 zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
4468                 (void) printf(gettext("    %s memory used for "
4469                     "removed device mappings\n"),
4470                     mem_buf);
4471         }
4472 }
4473
4474 static void
4475 print_checkpoint_status(pool_checkpoint_stat_t *pcs)
4476 {
4477         time_t start;
4478         char space_buf[7];
4479
4480         if (pcs == NULL || pcs->pcs_state == CS_NONE)
4481                 return;
4482
4483         (void) printf(gettext("checkpoint: "));
4484
4485         start = pcs->pcs_start_time;
4486         zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf));
4487
4488         if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) {
4489                 char *date = ctime(&start);
4490
4491                 /*
4492                  * ctime() adds a newline at the end of the generated
4493                  * string, thus the weird format specifier and the
4494                  * strlen() call used to chop it off from the output.
4495                  */
4496                 (void) printf(gettext("created %.*s, consumes %s\n"),
4497                     strlen(date) - 1, date, space_buf);
4498                 return;
4499         }
4500
4501         assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
4502
4503         (void) printf(gettext("discarding, %s remaining.\n"),
4504             space_buf);
4505 }
4506
4507 static void
4508 print_error_log(zpool_handle_t *zhp)
4509 {
4510         nvlist_t *nverrlist = NULL;
4511         nvpair_t *elem;
4512         char *pathname;
4513         size_t len = MAXPATHLEN * 2;
4514
4515         if (zpool_get_errlog(zhp, &nverrlist) != 0) {
4516                 (void) printf("errors: List of errors unavailable "
4517                     "(insufficient privileges)\n");
4518                 return;
4519         }
4520
4521         (void) printf("errors: Permanent errors have been "
4522             "detected in the following files:\n\n");
4523
4524         pathname = safe_malloc(len);
4525         elem = NULL;
4526         while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
4527                 nvlist_t *nv;
4528                 uint64_t dsobj, obj;
4529
4530                 verify(nvpair_value_nvlist(elem, &nv) == 0);
4531                 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
4532                     &dsobj) == 0);
4533                 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
4534                     &obj) == 0);
4535                 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
4536                 (void) printf("%7s %s\n", "", pathname);
4537         }
4538         free(pathname);
4539         nvlist_free(nverrlist);
4540 }
4541
4542 static void
4543 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
4544     int namewidth)
4545 {
4546         uint_t i;
4547         char *name;
4548
4549         if (nspares == 0)
4550                 return;
4551
4552         (void) printf(gettext("\tspares\n"));
4553
4554         for (i = 0; i < nspares; i++) {
4555                 name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE);
4556                 print_status_config(zhp, name, spares[i],
4557                     namewidth, 2, B_TRUE);
4558                 free(name);
4559         }
4560 }
4561
4562 static void
4563 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
4564     int namewidth)
4565 {
4566         uint_t i;
4567         char *name;
4568
4569         if (nl2cache == 0)
4570                 return;
4571
4572         (void) printf(gettext("\tcache\n"));
4573
4574         for (i = 0; i < nl2cache; i++) {
4575                 name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE);
4576                 print_status_config(zhp, name, l2cache[i],
4577                     namewidth, 2, B_FALSE);
4578                 free(name);
4579         }
4580 }
4581
4582 static void
4583 print_dedup_stats(nvlist_t *config)
4584 {
4585         ddt_histogram_t *ddh;
4586         ddt_stat_t *dds;
4587         ddt_object_t *ddo;
4588         uint_t c;
4589
4590         /*
4591          * If the pool was faulted then we may not have been able to
4592          * obtain the config. Otherwise, if we have anything in the dedup
4593          * table continue processing the stats.
4594          */
4595         if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
4596             (uint64_t **)&ddo, &c) != 0)
4597                 return;
4598
4599         (void) printf("\n");
4600         (void) printf(gettext(" dedup: "));
4601         if (ddo->ddo_count == 0) {
4602                 (void) printf(gettext("no DDT entries\n"));
4603                 return;
4604         }
4605
4606         (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
4607             (u_longlong_t)ddo->ddo_count,
4608             (u_longlong_t)ddo->ddo_dspace,
4609             (u_longlong_t)ddo->ddo_mspace);
4610
4611         verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
4612             (uint64_t **)&dds, &c) == 0);
4613         verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
4614             (uint64_t **)&ddh, &c) == 0);
4615         zpool_dump_ddt(dds, ddh);
4616 }
4617
4618 /*
4619  * Display a summary of pool status.  Displays a summary such as:
4620  *
4621  *        pool: tank
4622  *      status: DEGRADED
4623  *      reason: One or more devices ...
4624  *         see: http://illumos.org/msg/ZFS-xxxx-01
4625  *      config:
4626  *              mirror          DEGRADED
4627  *                c1t0d0        OK
4628  *                c2t0d0        UNAVAIL
4629  *
4630  * When given the '-v' option, we print out the complete config.  If the '-e'
4631  * option is specified, then we print out error rate information as well.
4632  */
4633 int
4634 status_callback(zpool_handle_t *zhp, void *data)
4635 {
4636         status_cbdata_t *cbp = data;
4637         nvlist_t *config, *nvroot;
4638         char *msgid;
4639         int reason;
4640         const char *health;
4641         uint_t c;
4642         vdev_stat_t *vs;
4643
4644         config = zpool_get_config(zhp, NULL);
4645         reason = zpool_get_status(zhp, &msgid);
4646
4647         cbp->cb_count++;
4648
4649         /*
4650          * If we were given 'zpool status -x', only report those pools with
4651          * problems.
4652          */
4653         if (cbp->cb_explain &&
4654             (reason == ZPOOL_STATUS_OK ||
4655             reason == ZPOOL_STATUS_VERSION_OLDER ||
4656             reason == ZPOOL_STATUS_NON_NATIVE_ASHIFT ||
4657             reason == ZPOOL_STATUS_FEAT_DISABLED)) {
4658                 if (!cbp->cb_allpools) {
4659                         (void) printf(gettext("pool '%s' is healthy\n"),
4660                             zpool_get_name(zhp));
4661                         if (cbp->cb_first)
4662                                 cbp->cb_first = B_FALSE;
4663                 }
4664                 return (0);
4665         }
4666
4667         if (cbp->cb_first)
4668                 cbp->cb_first = B_FALSE;
4669         else
4670                 (void) printf("\n");
4671
4672         nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4673         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
4674             (uint64_t **)&vs, &c) == 0);
4675         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
4676
4677         (void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
4678         (void) printf(gettext(" state: %s\n"), health);
4679
4680         switch (reason) {
4681         case ZPOOL_STATUS_MISSING_DEV_R:
4682                 (void) printf(gettext("status: One or more devices could not "
4683                     "be opened.  Sufficient replicas exist for\n\tthe pool to "
4684                     "continue functioning in a degraded state.\n"));
4685                 (void) printf(gettext("action: Attach the missing device and "
4686                     "online it using 'zpool online'.\n"));
4687                 break;
4688
4689         case ZPOOL_STATUS_MISSING_DEV_NR:
4690                 (void) printf(gettext("status: One or more devices could not "
4691                     "be opened.  There are insufficient\n\treplicas for the "
4692                     "pool to continue functioning.\n"));
4693                 (void) printf(gettext("action: Attach the missing device and "
4694                     "online it using 'zpool online'.\n"));
4695                 break;
4696
4697         case ZPOOL_STATUS_CORRUPT_LABEL_R:
4698                 (void) printf(gettext("status: One or more devices could not "
4699                     "be used because the label is missing or\n\tinvalid.  "
4700                     "Sufficient replicas exist for the pool to continue\n\t"
4701                     "functioning in a degraded state.\n"));
4702                 (void) printf(gettext("action: Replace the device using "
4703                     "'zpool replace'.\n"));
4704                 break;
4705
4706         case ZPOOL_STATUS_CORRUPT_LABEL_NR:
4707                 (void) printf(gettext("status: One or more devices could not "
4708                     "be used because the label is missing \n\tor invalid.  "
4709                     "There are insufficient replicas for the pool to "
4710                     "continue\n\tfunctioning.\n"));
4711                 zpool_explain_recover(zpool_get_handle(zhp),
4712                     zpool_get_name(zhp), reason, config);
4713                 break;
4714
4715         case ZPOOL_STATUS_FAILING_DEV:
4716                 (void) printf(gettext("status: One or more devices has "
4717                     "experienced an unrecoverable error.  An\n\tattempt was "
4718                     "made to correct the error.  Applications are "
4719                     "unaffected.\n"));
4720                 (void) printf(gettext("action: Determine if the device needs "
4721                     "to be replaced, and clear the errors\n\tusing "
4722                     "'zpool clear' or replace the device with 'zpool "
4723                     "replace'.\n"));
4724                 break;
4725
4726         case ZPOOL_STATUS_OFFLINE_DEV:
4727                 (void) printf(gettext("status: One or more devices has "
4728                     "been taken offline by the administrator.\n\tSufficient "
4729                     "replicas exist for the pool to continue functioning in "
4730                     "a\n\tdegraded state.\n"));
4731                 (void) printf(gettext("action: Online the device using "
4732                     "'zpool online' or replace the device with\n\t'zpool "
4733                     "replace'.\n"));
4734                 break;
4735
4736         case ZPOOL_STATUS_REMOVED_DEV:
4737                 (void) printf(gettext("status: One or more devices has "
4738                     "been removed by the administrator.\n\tSufficient "
4739                     "replicas exist for the pool to continue functioning in "
4740                     "a\n\tdegraded state.\n"));
4741                 (void) printf(gettext("action: Online the device using "
4742                     "'zpool online' or replace the device with\n\t'zpool "
4743                     "replace'.\n"));
4744                 break;
4745
4746         case ZPOOL_STATUS_RESILVERING:
4747                 (void) printf(gettext("status: One or more devices is "
4748                     "currently being resilvered.  The pool will\n\tcontinue "
4749                     "to function, possibly in a degraded state.\n"));
4750                 (void) printf(gettext("action: Wait for the resilver to "
4751                     "complete.\n"));
4752                 break;
4753
4754         case ZPOOL_STATUS_CORRUPT_DATA:
4755                 (void) printf(gettext("status: One or more devices has "
4756                     "experienced an error resulting in data\n\tcorruption.  "
4757                     "Applications may be affected.\n"));
4758                 (void) printf(gettext("action: Restore the file in question "
4759                     "if possible.  Otherwise restore the\n\tentire pool from "
4760                     "backup.\n"));
4761                 break;
4762
4763         case ZPOOL_STATUS_CORRUPT_POOL:
4764                 (void) printf(gettext("status: The pool metadata is corrupted "
4765                     "and the pool cannot be opened.\n"));
4766                 zpool_explain_recover(zpool_get_handle(zhp),
4767                     zpool_get_name(zhp), reason, config);
4768                 break;
4769
4770         case ZPOOL_STATUS_VERSION_OLDER:
4771                 (void) printf(gettext("status: The pool is formatted using a "
4772                     "legacy on-disk format.  The pool can\n\tstill be used, "
4773                     "but some features are unavailable.\n"));
4774                 (void) printf(gettext("action: Upgrade the pool using 'zpool "
4775                     "upgrade'.  Once this is done, the\n\tpool will no longer "
4776                     "be accessible on software that does not support feature\n"
4777                     "\tflags.\n"));
4778                 break;
4779
4780         case ZPOOL_STATUS_VERSION_NEWER:
4781                 (void) printf(gettext("status: The pool has been upgraded to a "
4782                     "newer, incompatible on-disk version.\n\tThe pool cannot "
4783                     "be accessed on this system.\n"));
4784                 (void) printf(gettext("action: Access the pool from a system "
4785                     "running more recent software, or\n\trestore the pool from "
4786                     "backup.\n"));
4787                 break;
4788
4789         case ZPOOL_STATUS_FEAT_DISABLED:
4790                 (void) printf(gettext("status: Some supported features are not "
4791                     "enabled on the pool. The pool can\n\tstill be used, but "
4792                     "some features are unavailable.\n"));
4793                 (void) printf(gettext("action: Enable all features using "
4794                     "'zpool upgrade'. Once this is done,\n\tthe pool may no "
4795                     "longer be accessible by software that does not support\n\t"
4796                     "the features. See zpool-features(7) for details.\n"));
4797                 break;
4798
4799         case ZPOOL_STATUS_UNSUP_FEAT_READ:
4800                 (void) printf(gettext("status: The pool cannot be accessed on "
4801                     "this system because it uses the\n\tfollowing feature(s) "
4802                     "not supported on this system:\n"));
4803                 zpool_print_unsup_feat(config);
4804                 (void) printf("\n");
4805                 (void) printf(gettext("action: Access the pool from a system "
4806                     "that supports the required feature(s),\n\tor restore the "
4807                     "pool from backup.\n"));
4808                 break;
4809
4810         case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
4811                 (void) printf(gettext("status: The pool can only be accessed "
4812                     "in read-only mode on this system. It\n\tcannot be "
4813                     "accessed in read-write mode because it uses the "
4814                     "following\n\tfeature(s) not supported on this system:\n"));
4815                 zpool_print_unsup_feat(config);
4816                 (void) printf("\n");
4817                 (void) printf(gettext("action: The pool cannot be accessed in "
4818                     "read-write mode. Import the pool with\n"
4819                     "\t\"-o readonly=on\", access the pool from a system that "
4820                     "supports the\n\trequired feature(s), or restore the "
4821                     "pool from backup.\n"));
4822                 break;
4823
4824         case ZPOOL_STATUS_FAULTED_DEV_R:
4825                 (void) printf(gettext("status: One or more devices are "
4826                     "faulted in response to persistent errors.\n\tSufficient "
4827                     "replicas exist for the pool to continue functioning "
4828                     "in a\n\tdegraded state.\n"));
4829                 (void) printf(gettext("action: Replace the faulted device, "
4830                     "or use 'zpool clear' to mark the device\n\trepaired.\n"));
4831                 break;
4832
4833         case ZPOOL_STATUS_FAULTED_DEV_NR:
4834                 (void) printf(gettext("status: One or more devices are "
4835                     "faulted in response to persistent errors.  There are "
4836                     "insufficient replicas for the pool to\n\tcontinue "
4837                     "functioning.\n"));
4838                 (void) printf(gettext("action: Destroy and re-create the pool "
4839                     "from a backup source.  Manually marking the device\n"
4840                     "\trepaired using 'zpool clear' may allow some data "
4841                     "to be recovered.\n"));
4842                 break;
4843
4844         case ZPOOL_STATUS_IO_FAILURE_WAIT:
4845         case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
4846                 (void) printf(gettext("status: One or more devices are "
4847                     "faulted in response to IO failures.\n"));
4848                 (void) printf(gettext("action: Make sure the affected devices "
4849                     "are connected, then run 'zpool clear'.\n"));
4850                 break;
4851
4852         case ZPOOL_STATUS_BAD_LOG:
4853                 (void) printf(gettext("status: An intent log record "
4854                     "could not be read.\n"
4855                     "\tWaiting for adminstrator intervention to fix the "
4856                     "faulted pool.\n"));
4857                 (void) printf(gettext("action: Either restore the affected "
4858                     "device(s) and run 'zpool online',\n"
4859                     "\tor ignore the intent log records by running "
4860                     "'zpool clear'.\n"));
4861                 break;
4862
4863         case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
4864                 (void) printf(gettext("status: One or more devices are "
4865                     "configured to use a non-native block size.\n"
4866                     "\tExpect reduced performance.\n"));
4867                 (void) printf(gettext("action: Replace affected devices with "
4868                     "devices that support the\n\tconfigured block size, or "
4869                     "migrate data to a properly configured\n\tpool.\n"));
4870                 break;
4871
4872         default:
4873                 /*
4874                  * The remaining errors can't actually be generated, yet.
4875                  */
4876                 assert(reason == ZPOOL_STATUS_OK);
4877         }
4878
4879         if (msgid != NULL)
4880                 (void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
4881                     msgid);
4882
4883         if (config != NULL) {
4884                 int namewidth;
4885                 uint64_t nerr;
4886                 nvlist_t **spares, **l2cache;
4887                 uint_t nspares, nl2cache;
4888                 pool_checkpoint_stat_t *pcs = NULL;
4889                 pool_scan_stat_t *ps = NULL;
4890                 pool_removal_stat_t *prs = NULL;
4891
4892                 (void) nvlist_lookup_uint64_array(nvroot,
4893                     ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
4894                 (void) nvlist_lookup_uint64_array(nvroot,
4895                     ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4896                 (void) nvlist_lookup_uint64_array(nvroot,
4897                     ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
4898
4899                 print_scan_status(ps);
4900                 print_checkpoint_scan_warning(ps, pcs);
4901                 print_removal_status(zhp, prs);
4902                 print_checkpoint_status(pcs);
4903
4904                 namewidth = max_width(zhp, nvroot, 0, 0);
4905                 if (namewidth < 10)
4906                         namewidth = 10;
4907
4908                 (void) printf(gettext("config:\n\n"));
4909                 (void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
4910                     "NAME", "STATE", "READ", "WRITE", "CKSUM");
4911                 print_status_config(zhp, zpool_get_name(zhp), nvroot,
4912                     namewidth, 0, B_FALSE);
4913
4914                 if (num_logs(nvroot) > 0)
4915                         print_logs(zhp, nvroot, namewidth, B_TRUE);
4916                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
4917                     &l2cache, &nl2cache) == 0)
4918                         print_l2cache(zhp, l2cache, nl2cache, namewidth);
4919
4920                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
4921                     &spares, &nspares) == 0)
4922                         print_spares(zhp, spares, nspares, namewidth);
4923
4924                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
4925                     &nerr) == 0) {
4926                         nvlist_t *nverrlist = NULL;
4927
4928                         /*
4929                          * If the approximate error count is small, get a
4930                          * precise count by fetching the entire log and
4931                          * uniquifying the results.
4932                          */
4933                         if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
4934                             zpool_get_errlog(zhp, &nverrlist) == 0) {
4935                                 nvpair_t *elem;
4936
4937                                 elem = NULL;
4938                                 nerr = 0;
4939                                 while ((elem = nvlist_next_nvpair(nverrlist,
4940                                     elem)) != NULL) {
4941                                         nerr++;
4942                                 }
4943                         }
4944                         nvlist_free(nverrlist);
4945
4946                         (void) printf("\n");
4947
4948                         if (nerr == 0)
4949                                 (void) printf(gettext("errors: No known data "
4950                                     "errors\n"));
4951                         else if (!cbp->cb_verbose)
4952                                 (void) printf(gettext("errors: %llu data "
4953                                     "errors, use '-v' for a list\n"),
4954                                     (u_longlong_t)nerr);
4955                         else
4956                                 print_error_log(zhp);
4957                 }
4958
4959                 if (cbp->cb_dedup_stats)
4960                         print_dedup_stats(config);
4961         } else {
4962                 (void) printf(gettext("config: The configuration cannot be "
4963                     "determined.\n"));
4964         }
4965
4966         return (0);
4967 }
4968
4969 /*
4970  * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
4971  *
4972  *      -v      Display complete error logs
4973  *      -x      Display only pools with potential problems
4974  *      -D      Display dedup status (undocumented)
4975  *      -T      Display a timestamp in date(1) or Unix format
4976  *
4977  * Describes the health status of all pools or some subset.
4978  */
4979 int
4980 zpool_do_status(int argc, char **argv)
4981 {
4982         int c;
4983         int ret;
4984         unsigned long interval = 0, count = 0;
4985         status_cbdata_t cb = { 0 };
4986
4987         /* check options */
4988         while ((c = getopt(argc, argv, "vxDT:")) != -1) {
4989                 switch (c) {
4990                 case 'v':
4991                         cb.cb_verbose = B_TRUE;
4992                         break;
4993                 case 'x':
4994                         cb.cb_explain = B_TRUE;
4995                         break;
4996                 case 'D':
4997                         cb.cb_dedup_stats = B_TRUE;
4998                         break;
4999                 case 'T':
5000                         get_timestamp_arg(*optarg);
5001                         break;
5002                 case '?':
5003                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5004                             optopt);
5005                         usage(B_FALSE);
5006                 }
5007         }
5008
5009         argc -= optind;
5010         argv += optind;
5011
5012         get_interval_count(&argc, argv, &interval, &count);
5013
5014         if (argc == 0)
5015                 cb.cb_allpools = B_TRUE;
5016
5017         cb.cb_first = B_TRUE;
5018
5019         for (;;) {
5020                 if (timestamp_fmt != NODATE)
5021                         print_timestamp(timestamp_fmt);
5022
5023                 ret = for_each_pool(argc, argv, B_TRUE, NULL,
5024                     status_callback, &cb);
5025
5026                 if (argc == 0 && cb.cb_count == 0)
5027                         (void) printf(gettext("no pools available\n"));
5028                 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
5029                         (void) printf(gettext("all pools are healthy\n"));
5030
5031                 if (ret != 0)
5032                         return (ret);
5033
5034                 if (interval == 0)
5035                         break;
5036
5037                 if (count != 0 && --count == 0)
5038                         break;
5039
5040                 (void) sleep(interval);
5041         }
5042
5043         return (0);
5044 }
5045
5046 typedef struct upgrade_cbdata {
5047         boolean_t       cb_first;
5048         boolean_t       cb_unavail;
5049         char            cb_poolname[ZFS_MAX_DATASET_NAME_LEN];
5050         int             cb_argc;
5051         uint64_t        cb_version;
5052         char            **cb_argv;
5053 } upgrade_cbdata_t;
5054
5055 #ifdef __FreeBSD__
5056 static int
5057 is_root_pool(zpool_handle_t *zhp)
5058 {
5059         static struct statfs sfs;
5060         static char *poolname = NULL;
5061         static boolean_t stated = B_FALSE;
5062         char *slash;
5063
5064         if (!stated) {
5065                 stated = B_TRUE;
5066                 if (statfs("/", &sfs) == -1) {
5067                         (void) fprintf(stderr,
5068                             "Unable to stat root file system: %s.\n",
5069                             strerror(errno));
5070                         return (0);
5071                 }
5072                 if (strcmp(sfs.f_fstypename, "zfs") != 0)
5073                         return (0);
5074                 poolname = sfs.f_mntfromname;
5075                 if ((slash = strchr(poolname, '/')) != NULL)
5076                         *slash = '\0';
5077         }
5078         return (poolname != NULL && strcmp(poolname, zpool_get_name(zhp)) == 0);
5079 }
5080
5081 static void
5082 root_pool_upgrade_check(zpool_handle_t *zhp, char *poolname, int size)
5083 {
5084
5085         if (poolname[0] == '\0' && is_root_pool(zhp))
5086                 (void) strlcpy(poolname, zpool_get_name(zhp), size);
5087 }
5088 #endif  /* FreeBSD */
5089
5090 static int
5091 upgrade_version(zpool_handle_t *zhp, uint64_t version)
5092 {
5093         int ret;
5094         nvlist_t *config;
5095         uint64_t oldversion;
5096
5097         config = zpool_get_config(zhp, NULL);
5098         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5099             &oldversion) == 0);
5100
5101         assert(SPA_VERSION_IS_SUPPORTED(oldversion));
5102         assert(oldversion < version);
5103
5104         ret = zpool_upgrade(zhp, version);
5105         if (ret != 0)
5106                 return (ret);
5107
5108         if (version >= SPA_VERSION_FEATURES) {
5109                 (void) printf(gettext("Successfully upgraded "
5110                     "'%s' from version %llu to feature flags.\n"),
5111                     zpool_get_name(zhp), oldversion);
5112         } else {
5113                 (void) printf(gettext("Successfully upgraded "
5114                     "'%s' from version %llu to version %llu.\n"),
5115                     zpool_get_name(zhp), oldversion, version);
5116         }
5117
5118         return (0);
5119 }
5120
5121 static int
5122 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
5123 {
5124         int i, ret, count;
5125         boolean_t firstff = B_TRUE;
5126         nvlist_t *enabled = zpool_get_features(zhp);
5127
5128         count = 0;
5129         for (i = 0; i < SPA_FEATURES; i++) {
5130                 const char *fname = spa_feature_table[i].fi_uname;
5131                 const char *fguid = spa_feature_table[i].fi_guid;
5132                 if (!nvlist_exists(enabled, fguid)) {
5133                         char *propname;
5134                         verify(-1 != asprintf(&propname, "feature@%s", fname));
5135                         ret = zpool_set_prop(zhp, propname,
5136                             ZFS_FEATURE_ENABLED);
5137                         if (ret != 0) {
5138                                 free(propname);
5139                                 return (ret);
5140                         }
5141                         count++;
5142
5143                         if (firstff) {
5144                                 (void) printf(gettext("Enabled the "
5145                                     "following features on '%s':\n"),
5146                                     zpool_get_name(zhp));
5147                                 firstff = B_FALSE;
5148                         }
5149                         (void) printf(gettext("  %s\n"), fname);
5150                         free(propname);
5151                 }
5152         }
5153
5154         if (countp != NULL)
5155                 *countp = count;
5156         return (0);
5157 }
5158
5159 static int
5160 upgrade_cb(zpool_handle_t *zhp, void *arg)
5161 {
5162         upgrade_cbdata_t *cbp = arg;
5163         nvlist_t *config;
5164         uint64_t version;
5165         boolean_t printnl = B_FALSE;
5166         int ret;
5167
5168         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5169                 (void) fprintf(stderr, gettext("cannot upgrade '%s': pool is "
5170                     "currently unavailable.\n\n"), zpool_get_name(zhp));
5171                 cbp->cb_unavail = B_TRUE;
5172                 /* Allow iteration to continue. */
5173                 return (0);
5174         }
5175
5176         config = zpool_get_config(zhp, NULL);
5177         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5178             &version) == 0);
5179
5180         assert(SPA_VERSION_IS_SUPPORTED(version));
5181
5182         if (version < cbp->cb_version) {
5183                 cbp->cb_first = B_FALSE;
5184                 ret = upgrade_version(zhp, cbp->cb_version);
5185                 if (ret != 0)
5186                         return (ret);
5187 #ifdef __FreeBSD__
5188                 root_pool_upgrade_check(zhp, cbp->cb_poolname,
5189                     sizeof(cbp->cb_poolname));
5190 #endif  /* __FreeBSD__ */
5191                 printnl = B_TRUE;
5192
5193 #ifdef illumos
5194                 /*
5195                  * If they did "zpool upgrade -a", then we could
5196                  * be doing ioctls to different pools.  We need
5197                  * to log this history once to each pool, and bypass
5198                  * the normal history logging that happens in main().
5199                  */
5200                 (void) zpool_log_history(g_zfs, history_str);
5201                 log_history = B_FALSE;
5202 #endif
5203         }
5204
5205         if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5206                 int count;
5207                 ret = upgrade_enable_all(zhp, &count);
5208                 if (ret != 0)
5209                         return (ret);
5210
5211                 if (count > 0) {
5212                         cbp->cb_first = B_FALSE;
5213                         printnl = B_TRUE;
5214 #ifdef __FreeBSD__
5215                         root_pool_upgrade_check(zhp, cbp->cb_poolname,
5216                             sizeof(cbp->cb_poolname));
5217 #endif  /* __FreeBSD__ */
5218                         /*
5219                          * If they did "zpool upgrade -a", then we could
5220                          * be doing ioctls to different pools.  We need
5221                          * to log this history once to each pool, and bypass
5222                          * the normal history logging that happens in main().
5223                          */
5224                         (void) zpool_log_history(g_zfs, history_str);
5225                         log_history = B_FALSE;
5226                 }
5227         }
5228
5229         if (printnl) {
5230                 (void) printf(gettext("\n"));
5231         }
5232
5233         return (0);
5234 }
5235
5236 static int
5237 upgrade_list_unavail(zpool_handle_t *zhp, void *arg)
5238 {
5239         upgrade_cbdata_t *cbp = arg;
5240
5241         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5242                 if (cbp->cb_first) {
5243                         (void) fprintf(stderr, gettext("The following pools "
5244                             "are unavailable and cannot be upgraded as this "
5245                             "time.\n\n"));
5246                         (void) fprintf(stderr, gettext("POOL\n"));
5247                         (void) fprintf(stderr, gettext("------------\n"));
5248                         cbp->cb_first = B_FALSE;
5249                 }
5250                 (void) printf(gettext("%s\n"), zpool_get_name(zhp));
5251                 cbp->cb_unavail = B_TRUE;
5252         }
5253         return (0);
5254 }
5255
5256 static int
5257 upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
5258 {
5259         upgrade_cbdata_t *cbp = arg;
5260         nvlist_t *config;
5261         uint64_t version;
5262
5263         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5264                 /*
5265                  * This will have been reported by upgrade_list_unavail so
5266                  * just allow iteration to continue.
5267                  */
5268                 cbp->cb_unavail = B_TRUE;
5269                 return (0);
5270         }
5271
5272         config = zpool_get_config(zhp, NULL);
5273         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5274             &version) == 0);
5275
5276         assert(SPA_VERSION_IS_SUPPORTED(version));
5277
5278         if (version < SPA_VERSION_FEATURES) {
5279                 if (cbp->cb_first) {
5280                         (void) printf(gettext("The following pools are "
5281                             "formatted with legacy version numbers and can\n"
5282                             "be upgraded to use feature flags.  After "
5283                             "being upgraded, these pools\nwill no "
5284                             "longer be accessible by software that does not "
5285                             "support feature\nflags.\n\n"));
5286                         (void) printf(gettext("VER  POOL\n"));
5287                         (void) printf(gettext("---  ------------\n"));
5288                         cbp->cb_first = B_FALSE;
5289                 }
5290
5291                 (void) printf("%2llu   %s\n", (u_longlong_t)version,
5292                     zpool_get_name(zhp));
5293         }
5294
5295         return (0);
5296 }
5297
5298 static int
5299 upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
5300 {
5301         upgrade_cbdata_t *cbp = arg;
5302         nvlist_t *config;
5303         uint64_t version;
5304
5305         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5306                 /*
5307                  * This will have been reported by upgrade_list_unavail so
5308                  * just allow iteration to continue.
5309                  */
5310                 cbp->cb_unavail = B_TRUE;
5311                 return (0);
5312         }
5313
5314         config = zpool_get_config(zhp, NULL);
5315         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5316             &version) == 0);
5317
5318         if (version >= SPA_VERSION_FEATURES) {
5319                 int i;
5320                 boolean_t poolfirst = B_TRUE;
5321                 nvlist_t *enabled = zpool_get_features(zhp);
5322
5323                 for (i = 0; i < SPA_FEATURES; i++) {
5324                         const char *fguid = spa_feature_table[i].fi_guid;
5325                         const char *fname = spa_feature_table[i].fi_uname;
5326                         if (!nvlist_exists(enabled, fguid)) {
5327                                 if (cbp->cb_first) {
5328                                         (void) printf(gettext("\nSome "
5329                                             "supported features are not "
5330                                             "enabled on the following pools. "
5331                                             "Once a\nfeature is enabled the "
5332                                             "pool may become incompatible with "
5333                                             "software\nthat does not support "
5334                                             "the feature. See "
5335                                             "zpool-features(7) for "
5336                                             "details.\n\n"));
5337                                         (void) printf(gettext("POOL  "
5338                                             "FEATURE\n"));
5339                                         (void) printf(gettext("------"
5340                                             "---------\n"));
5341                                         cbp->cb_first = B_FALSE;
5342                                 }
5343
5344                                 if (poolfirst) {
5345                                         (void) printf(gettext("%s\n"),
5346                                             zpool_get_name(zhp));
5347                                         poolfirst = B_FALSE;
5348                                 }
5349
5350                                 (void) printf(gettext("      %s\n"), fname);
5351                         }
5352                 }
5353         }
5354
5355         return (0);
5356 }
5357
5358 /* ARGSUSED */
5359 static int
5360 upgrade_one(zpool_handle_t *zhp, void *data)
5361 {
5362         boolean_t printnl = B_FALSE;
5363         upgrade_cbdata_t *cbp = data;
5364         uint64_t cur_version;
5365         int ret;
5366
5367         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5368                 (void) fprintf(stderr, gettext("cannot upgrade '%s': pool is "
5369                     "is currently unavailable.\n\n"), zpool_get_name(zhp));
5370                 cbp->cb_unavail = B_TRUE;
5371                 return (1);
5372         }
5373
5374         if (strcmp("log", zpool_get_name(zhp)) == 0) {
5375                 (void) printf(gettext("'log' is now a reserved word\n"
5376                     "Pool 'log' must be renamed using export and import"
5377                     " to upgrade.\n\n"));
5378                 return (1);
5379         }
5380
5381         cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
5382         if (cur_version > cbp->cb_version) {
5383                 (void) printf(gettext("Pool '%s' is already formatted "
5384                     "using more current version '%llu'.\n\n"),
5385                     zpool_get_name(zhp), cur_version);
5386                 return (0);
5387         }
5388
5389         if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
5390                 (void) printf(gettext("Pool '%s' is already formatted "
5391                     "using version %llu.\n\n"), zpool_get_name(zhp),
5392                     cbp->cb_version);
5393                 return (0);
5394         }
5395
5396         if (cur_version != cbp->cb_version) {
5397                 printnl = B_TRUE;
5398                 ret = upgrade_version(zhp, cbp->cb_version);
5399                 if (ret != 0)
5400                         return (ret);
5401 #ifdef __FreeBSD__
5402                 root_pool_upgrade_check(zhp, cbp->cb_poolname,
5403                     sizeof(cbp->cb_poolname));
5404 #endif  /* __FreeBSD__ */
5405         }
5406
5407         if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5408                 int count = 0;
5409                 ret = upgrade_enable_all(zhp, &count);
5410                 if (ret != 0)
5411                         return (ret);
5412
5413                 if (count != 0) {
5414                         printnl = B_TRUE;
5415 #ifdef __FreeBSD__
5416                         root_pool_upgrade_check(zhp, cbp->cb_poolname,
5417                             sizeof(cbp->cb_poolname));
5418 #endif  /* __FreeBSD __*/
5419                 } else if (cur_version == SPA_VERSION) {
5420                         (void) printf(gettext("Pool '%s' already has all "
5421                             "supported features enabled.\n\n"),
5422                             zpool_get_name(zhp));
5423                 }
5424         }
5425
5426         if (printnl) {
5427                 (void) printf(gettext("\n"));
5428         }
5429
5430         return (0);
5431 }
5432
5433 /*
5434  * zpool upgrade
5435  * zpool upgrade -v
5436  * zpool upgrade [-V version] <-a | pool ...>
5437  *
5438  * With no arguments, display downrev'd ZFS pool available for upgrade.
5439  * Individual pools can be upgraded by specifying the pool, and '-a' will
5440  * upgrade all pools.
5441  */
5442 int
5443 zpool_do_upgrade(int argc, char **argv)
5444 {
5445         int c;
5446         upgrade_cbdata_t cb = { 0 };
5447         int ret = 0;
5448         boolean_t showversions = B_FALSE;
5449         boolean_t upgradeall = B_FALSE;
5450         char *end;
5451
5452
5453         /* check options */
5454         while ((c = getopt(argc, argv, ":avV:")) != -1) {
5455                 switch (c) {
5456                 case 'a':
5457                         upgradeall = B_TRUE;
5458                         break;
5459                 case 'v':
5460                         showversions = B_TRUE;
5461                         break;
5462                 case 'V':
5463                         cb.cb_version = strtoll(optarg, &end, 10);
5464                         if (*end != '\0' ||
5465                             !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
5466                                 (void) fprintf(stderr,
5467                                     gettext("invalid version '%s'\n"), optarg);
5468                                 usage(B_FALSE);
5469                         }
5470                         break;
5471                 case ':':
5472                         (void) fprintf(stderr, gettext("missing argument for "
5473                             "'%c' option\n"), optopt);
5474                         usage(B_FALSE);
5475                         break;
5476                 case '?':
5477                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5478                             optopt);
5479                         usage(B_FALSE);
5480                 }
5481         }
5482
5483         cb.cb_argc = argc;
5484         cb.cb_argv = argv;
5485         argc -= optind;
5486         argv += optind;
5487
5488         if (cb.cb_version == 0) {
5489                 cb.cb_version = SPA_VERSION;
5490         } else if (!upgradeall && argc == 0) {
5491                 (void) fprintf(stderr, gettext("-V option is "
5492                     "incompatible with other arguments\n"));
5493                 usage(B_FALSE);
5494         }
5495
5496         if (showversions) {
5497                 if (upgradeall || argc != 0) {
5498                         (void) fprintf(stderr, gettext("-v option is "
5499                             "incompatible with other arguments\n"));
5500                         usage(B_FALSE);
5501                 }
5502         } else if (upgradeall) {
5503                 if (argc != 0) {
5504                         (void) fprintf(stderr, gettext("-a option should not "
5505                             "be used along with a pool name\n"));
5506                         usage(B_FALSE);
5507                 }
5508         }
5509
5510         (void) printf(gettext("This system supports ZFS pool feature "
5511             "flags.\n\n"));
5512         if (showversions) {
5513                 int i;
5514
5515                 (void) printf(gettext("The following features are "
5516                     "supported:\n\n"));
5517                 (void) printf(gettext("FEAT DESCRIPTION\n"));
5518                 (void) printf("----------------------------------------------"
5519                     "---------------\n");
5520                 for (i = 0; i < SPA_FEATURES; i++) {
5521                         zfeature_info_t *fi = &spa_feature_table[i];
5522                         const char *ro =
5523                             (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
5524                             " (read-only compatible)" : "";
5525
5526                         (void) printf("%-37s%s\n", fi->fi_uname, ro);
5527                         (void) printf("     %s\n", fi->fi_desc);
5528                 }
5529                 (void) printf("\n");
5530
5531                 (void) printf(gettext("The following legacy versions are also "
5532                     "supported:\n\n"));
5533                 (void) printf(gettext("VER  DESCRIPTION\n"));
5534                 (void) printf("---  -----------------------------------------"
5535                     "---------------\n");
5536                 (void) printf(gettext(" 1   Initial ZFS version\n"));
5537                 (void) printf(gettext(" 2   Ditto blocks "
5538                     "(replicated metadata)\n"));
5539                 (void) printf(gettext(" 3   Hot spares and double parity "
5540                     "RAID-Z\n"));
5541                 (void) printf(gettext(" 4   zpool history\n"));
5542                 (void) printf(gettext(" 5   Compression using the gzip "
5543                     "algorithm\n"));
5544                 (void) printf(gettext(" 6   bootfs pool property\n"));
5545                 (void) printf(gettext(" 7   Separate intent log devices\n"));
5546                 (void) printf(gettext(" 8   Delegated administration\n"));
5547                 (void) printf(gettext(" 9   refquota and refreservation "
5548                     "properties\n"));
5549                 (void) printf(gettext(" 10  Cache devices\n"));
5550                 (void) printf(gettext(" 11  Improved scrub performance\n"));
5551                 (void) printf(gettext(" 12  Snapshot properties\n"));
5552                 (void) printf(gettext(" 13  snapused property\n"));
5553                 (void) printf(gettext(" 14  passthrough-x aclinherit\n"));
5554                 (void) printf(gettext(" 15  user/group space accounting\n"));
5555                 (void) printf(gettext(" 16  stmf property support\n"));
5556                 (void) printf(gettext(" 17  Triple-parity RAID-Z\n"));
5557                 (void) printf(gettext(" 18  Snapshot user holds\n"));
5558                 (void) printf(gettext(" 19  Log device removal\n"));
5559                 (void) printf(gettext(" 20  Compression using zle "
5560                     "(zero-length encoding)\n"));
5561                 (void) printf(gettext(" 21  Deduplication\n"));
5562                 (void) printf(gettext(" 22  Received properties\n"));
5563                 (void) printf(gettext(" 23  Slim ZIL\n"));
5564                 (void) printf(gettext(" 24  System attributes\n"));
5565                 (void) printf(gettext(" 25  Improved scrub stats\n"));
5566                 (void) printf(gettext(" 26  Improved snapshot deletion "
5567                     "performance\n"));
5568                 (void) printf(gettext(" 27  Improved snapshot creation "
5569                     "performance\n"));
5570                 (void) printf(gettext(" 28  Multiple vdev replacements\n"));
5571                 (void) printf(gettext("\nFor more information on a particular "
5572                     "version, including supported releases,\n"));
5573                 (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
5574         } else if (argc == 0 && upgradeall) {
5575                 cb.cb_first = B_TRUE;
5576                 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
5577                 if (ret == 0 && cb.cb_first) {
5578                         if (cb.cb_version == SPA_VERSION) {
5579                                 (void) printf(gettext("All %spools are already "
5580                                     "formatted using feature flags.\n\n"),
5581                                     cb.cb_unavail ? gettext("available ") : "");
5582                                 (void) printf(gettext("Every %sfeature flags "
5583                                     "pool already has all supported features "
5584                                     "enabled.\n"),
5585                                     cb.cb_unavail ? gettext("available ") : "");
5586                         } else {
5587                                 (void) printf(gettext("All pools are already "
5588                                     "formatted with version %llu or higher.\n"),
5589                                     cb.cb_version);
5590                         }
5591                 }
5592         } else if (argc == 0) {
5593                 cb.cb_first = B_TRUE;
5594                 ret = zpool_iter(g_zfs, upgrade_list_unavail, &cb);
5595                 assert(ret == 0);
5596
5597                 if (!cb.cb_first) {
5598                         (void) fprintf(stderr, "\n");
5599                 }
5600
5601                 cb.cb_first = B_TRUE;
5602                 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
5603                 assert(ret == 0);
5604
5605                 if (cb.cb_first) {
5606                         (void) printf(gettext("All %spools are formatted using "
5607                             "feature flags.\n\n"), cb.cb_unavail ?
5608                             gettext("available ") : "");
5609                 } else {
5610                         (void) printf(gettext("\nUse 'zpool upgrade -v' "
5611                             "for a list of available legacy versions.\n"));
5612                 }
5613
5614                 cb.cb_first = B_TRUE;
5615                 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
5616                 assert(ret == 0);
5617
5618                 if (cb.cb_first) {
5619                         (void) printf(gettext("Every %sfeature flags pool has "
5620                             "all supported features enabled.\n"),
5621                             cb.cb_unavail ? gettext("available ") : "");
5622                 } else {
5623                         (void) printf(gettext("\n"));
5624                 }
5625         } else {
5626                 ret = for_each_pool(argc, argv, B_TRUE, NULL,
5627                     upgrade_one, &cb);
5628         }
5629
5630         if (cb.cb_poolname[0] != '\0') {
5631                 (void) printf(
5632                     "If you boot from pool '%s', don't forget to update boot code.\n"
5633                     "Assuming you use GPT partitioning and da0 is your boot disk\n"
5634                     "the following command will do it:\n"
5635                     "\n"
5636                     "\tgpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0\n\n",
5637                     cb.cb_poolname);
5638         }
5639
5640         return (ret);
5641 }
5642
5643 typedef struct hist_cbdata {
5644         boolean_t first;
5645         boolean_t longfmt;
5646         boolean_t internal;
5647 } hist_cbdata_t;
5648
5649 /*
5650  * Print out the command history for a specific pool.
5651  */
5652 static int
5653 get_history_one(zpool_handle_t *zhp, void *data)
5654 {
5655         nvlist_t *nvhis;
5656         nvlist_t **records;
5657         uint_t numrecords;
5658         int ret, i;
5659         hist_cbdata_t *cb = (hist_cbdata_t *)data;
5660
5661         cb->first = B_FALSE;
5662
5663         (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
5664
5665         if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
5666                 return (ret);
5667
5668         verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
5669             &records, &numrecords) == 0);
5670         for (i = 0; i < numrecords; i++) {
5671                 nvlist_t *rec = records[i];
5672                 char tbuf[30] = "";
5673
5674                 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
5675                         time_t tsec;
5676                         struct tm t;
5677
5678                         tsec = fnvlist_lookup_uint64(records[i],
5679                             ZPOOL_HIST_TIME);
5680                         (void) localtime_r(&tsec, &t);
5681                         (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
5682                 }
5683
5684                 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
5685                         (void) printf("%s %s", tbuf,
5686                             fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
5687                 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
5688                         int ievent =
5689                             fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
5690                         if (!cb->internal)
5691                                 continue;
5692                         if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
5693                                 (void) printf("%s unrecognized record:\n",
5694                                     tbuf);
5695                                 dump_nvlist(rec, 4);
5696                                 continue;
5697                         }
5698                         (void) printf("%s [internal %s txg:%lld] %s", tbuf,
5699                             zfs_history_event_names[ievent],
5700                             fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5701                             fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
5702                 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
5703                         if (!cb->internal)
5704                                 continue;
5705                         (void) printf("%s [txg:%lld] %s", tbuf,
5706                             fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5707                             fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
5708                         if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
5709                                 (void) printf(" %s (%llu)",
5710                                     fnvlist_lookup_string(rec,
5711                                     ZPOOL_HIST_DSNAME),
5712                                     fnvlist_lookup_uint64(rec,
5713                                     ZPOOL_HIST_DSID));
5714                         }
5715                         (void) printf(" %s", fnvlist_lookup_string(rec,
5716                             ZPOOL_HIST_INT_STR));
5717                 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
5718                         if (!cb->internal)
5719                                 continue;
5720                         (void) printf("%s ioctl %s\n", tbuf,
5721                             fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
5722                         if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
5723                                 (void) printf("    input:\n");
5724                                 dump_nvlist(fnvlist_lookup_nvlist(rec,
5725                                     ZPOOL_HIST_INPUT_NVL), 8);
5726                         }
5727                         if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
5728                                 (void) printf("    output:\n");
5729                                 dump_nvlist(fnvlist_lookup_nvlist(rec,
5730                                     ZPOOL_HIST_OUTPUT_NVL), 8);
5731                         }
5732                         if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
5733                                 (void) printf("    errno: %lld\n",
5734                                     fnvlist_lookup_int64(rec,
5735                                     ZPOOL_HIST_ERRNO));
5736                         }
5737                 } else {
5738                         if (!cb->internal)
5739                                 continue;
5740                         (void) printf("%s unrecognized record:\n", tbuf);
5741                         dump_nvlist(rec, 4);
5742                 }
5743
5744                 if (!cb->longfmt) {
5745                         (void) printf("\n");
5746                         continue;
5747                 }
5748                 (void) printf(" [");
5749                 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
5750                         uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
5751                         struct passwd *pwd = getpwuid(who);
5752                         (void) printf("user %d ", (int)who);
5753                         if (pwd != NULL)
5754                                 (void) printf("(%s) ", pwd->pw_name);
5755                 }
5756                 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
5757                         (void) printf("on %s",
5758                             fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
5759                 }
5760                 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
5761                         (void) printf(":%s",
5762                             fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
5763                 }
5764                 (void) printf("]");
5765                 (void) printf("\n");
5766         }
5767         (void) printf("\n");
5768         nvlist_free(nvhis);
5769
5770         return (ret);
5771 }
5772
5773 /*
5774  * zpool history <pool>
5775  *
5776  * Displays the history of commands that modified pools.
5777  */
5778 int
5779 zpool_do_history(int argc, char **argv)
5780 {
5781         hist_cbdata_t cbdata = { 0 };
5782         int ret;
5783         int c;
5784
5785         cbdata.first = B_TRUE;
5786         /* check options */
5787         while ((c = getopt(argc, argv, "li")) != -1) {
5788                 switch (c) {
5789                 case 'l':
5790                         cbdata.longfmt = B_TRUE;
5791                         break;
5792                 case 'i':
5793                         cbdata.internal = B_TRUE;
5794                         break;
5795                 case '?':
5796                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5797                             optopt);
5798                         usage(B_FALSE);
5799                 }
5800         }
5801         argc -= optind;
5802         argv += optind;
5803
5804         ret = for_each_pool(argc, argv, B_FALSE,  NULL, get_history_one,
5805             &cbdata);
5806
5807         if (argc == 0 && cbdata.first == B_TRUE) {
5808                 (void) printf(gettext("no pools available\n"));
5809                 return (0);
5810         }
5811
5812         return (ret);
5813 }
5814
5815 static int
5816 get_callback(zpool_handle_t *zhp, void *data)
5817 {
5818         zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
5819         char value[MAXNAMELEN];
5820         zprop_source_t srctype;
5821         zprop_list_t *pl;
5822
5823         for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
5824
5825                 /*
5826                  * Skip the special fake placeholder. This will also skip
5827                  * over the name property when 'all' is specified.
5828                  */
5829                 if (pl->pl_prop == ZPOOL_PROP_NAME &&
5830                     pl == cbp->cb_proplist)
5831                         continue;
5832
5833                 if (pl->pl_prop == ZPROP_INVAL &&
5834                     (zpool_prop_feature(pl->pl_user_prop) ||
5835                     zpool_prop_unsupported(pl->pl_user_prop))) {
5836                         srctype = ZPROP_SRC_LOCAL;
5837
5838                         if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
5839                             value, sizeof (value)) == 0) {
5840                                 zprop_print_one_property(zpool_get_name(zhp),
5841                                     cbp, pl->pl_user_prop, value, srctype,
5842                                     NULL, NULL);
5843                         }
5844                 } else {
5845                         if (zpool_get_prop(zhp, pl->pl_prop, value,
5846                             sizeof (value), &srctype, cbp->cb_literal) != 0)
5847                                 continue;
5848
5849                         zprop_print_one_property(zpool_get_name(zhp), cbp,
5850                             zpool_prop_to_name(pl->pl_prop), value, srctype,
5851                             NULL, NULL);
5852                 }
5853         }
5854         return (0);
5855 }
5856
5857 /*
5858  * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
5859  *
5860  *      -H      Scripted mode.  Don't display headers, and separate properties
5861  *              by a single tab.
5862  *      -o      List of columns to display.  Defaults to
5863  *              "name,property,value,source".
5864  *      -p      Diplay values in parsable (exact) format.
5865  *
5866  * Get properties of pools in the system. Output space statistics
5867  * for each one as well as other attributes.
5868  */
5869 int
5870 zpool_do_get(int argc, char **argv)
5871 {
5872         zprop_get_cbdata_t cb = { 0 };
5873         zprop_list_t fake_name = { 0 };
5874         int ret;
5875         int c, i;
5876         char *value;
5877
5878         cb.cb_first = B_TRUE;
5879
5880         /*
5881          * Set up default columns and sources.
5882          */
5883         cb.cb_sources = ZPROP_SRC_ALL;
5884         cb.cb_columns[0] = GET_COL_NAME;
5885         cb.cb_columns[1] = GET_COL_PROPERTY;
5886         cb.cb_columns[2] = GET_COL_VALUE;
5887         cb.cb_columns[3] = GET_COL_SOURCE;
5888         cb.cb_type = ZFS_TYPE_POOL;
5889
5890         /* check options */
5891         while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
5892                 switch (c) {
5893                 case 'p':
5894                         cb.cb_literal = B_TRUE;
5895                         break;
5896                 case 'H':
5897                         cb.cb_scripted = B_TRUE;
5898                         break;
5899                 case 'o':
5900                         bzero(&cb.cb_columns, sizeof (cb.cb_columns));
5901                         i = 0;
5902                         while (*optarg != '\0') {
5903                                 static char *col_subopts[] =
5904                                 { "name", "property", "value", "source",
5905                                 "all", NULL };
5906
5907                                 if (i == ZFS_GET_NCOLS) {
5908                                         (void) fprintf(stderr, gettext("too "
5909                                         "many fields given to -o "
5910                                         "option\n"));
5911                                         usage(B_FALSE);
5912                                 }
5913
5914                                 switch (getsubopt(&optarg, col_subopts,
5915                                     &value)) {
5916                                 case 0:
5917                                         cb.cb_columns[i++] = GET_COL_NAME;
5918                                         break;
5919                                 case 1:
5920                                         cb.cb_columns[i++] = GET_COL_PROPERTY;
5921                                         break;
5922                                 case 2:
5923                                         cb.cb_columns[i++] = GET_COL_VALUE;
5924                                         break;
5925                                 case 3:
5926                                         cb.cb_columns[i++] = GET_COL_SOURCE;
5927                                         break;
5928                                 case 4:
5929                                         if (i > 0) {
5930                                                 (void) fprintf(stderr,
5931                                                     gettext("\"all\" conflicts "
5932                                                     "with specific fields "
5933                                                     "given to -o option\n"));
5934                                                 usage(B_FALSE);
5935                                         }
5936                                         cb.cb_columns[0] = GET_COL_NAME;
5937                                         cb.cb_columns[1] = GET_COL_PROPERTY;
5938                                         cb.cb_columns[2] = GET_COL_VALUE;
5939                                         cb.cb_columns[3] = GET_COL_SOURCE;
5940                                         i = ZFS_GET_NCOLS;
5941                                         break;
5942                                 default:
5943                                         (void) fprintf(stderr,
5944                                             gettext("invalid column name "
5945                                             "'%s'\n"), suboptarg);
5946                                         usage(B_FALSE);
5947                                 }
5948                         }
5949                         break;
5950                 case '?':
5951                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5952                             optopt);
5953                         usage(B_FALSE);
5954                 }
5955         }
5956
5957         argc -= optind;
5958         argv += optind;
5959
5960         if (argc < 1) {
5961                 (void) fprintf(stderr, gettext("missing property "
5962                     "argument\n"));
5963                 usage(B_FALSE);
5964         }
5965
5966         if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
5967             ZFS_TYPE_POOL) != 0)
5968                 usage(B_FALSE);
5969
5970         argc--;
5971         argv++;
5972
5973         if (cb.cb_proplist != NULL) {
5974                 fake_name.pl_prop = ZPOOL_PROP_NAME;
5975                 fake_name.pl_width = strlen(gettext("NAME"));
5976                 fake_name.pl_next = cb.cb_proplist;
5977                 cb.cb_proplist = &fake_name;
5978         }
5979
5980         ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
5981             get_callback, &cb);
5982
5983         if (cb.cb_proplist == &fake_name)
5984                 zprop_free_list(fake_name.pl_next);
5985         else
5986                 zprop_free_list(cb.cb_proplist);
5987
5988         return (ret);
5989 }
5990
5991 typedef struct set_cbdata {
5992         char *cb_propname;
5993         char *cb_value;
5994         boolean_t cb_any_successful;
5995 } set_cbdata_t;
5996
5997 int
5998 set_callback(zpool_handle_t *zhp, void *data)
5999 {
6000         int error;
6001         set_cbdata_t *cb = (set_cbdata_t *)data;
6002
6003         error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
6004
6005         if (!error)
6006                 cb->cb_any_successful = B_TRUE;
6007
6008         return (error);
6009 }
6010
6011 int
6012 zpool_do_set(int argc, char **argv)
6013 {
6014         set_cbdata_t cb = { 0 };
6015         int error;
6016
6017         if (argc > 1 && argv[1][0] == '-') {
6018                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6019                     argv[1][1]);
6020                 usage(B_FALSE);
6021         }
6022
6023         if (argc < 2) {
6024                 (void) fprintf(stderr, gettext("missing property=value "
6025                     "argument\n"));
6026                 usage(B_FALSE);
6027         }
6028
6029         if (argc < 3) {
6030                 (void) fprintf(stderr, gettext("missing pool name\n"));
6031                 usage(B_FALSE);
6032         }
6033
6034         if (argc > 3) {
6035                 (void) fprintf(stderr, gettext("too many pool names\n"));
6036                 usage(B_FALSE);
6037         }
6038
6039         cb.cb_propname = argv[1];
6040         cb.cb_value = strchr(cb.cb_propname, '=');
6041         if (cb.cb_value == NULL) {
6042                 (void) fprintf(stderr, gettext("missing value in "
6043                     "property=value argument\n"));
6044                 usage(B_FALSE);
6045         }
6046
6047         *(cb.cb_value) = '\0';
6048         cb.cb_value++;
6049
6050         error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
6051             set_callback, &cb);
6052
6053         return (error);
6054 }
6055
6056 static int
6057 find_command_idx(char *command, int *idx)
6058 {
6059         int i;
6060
6061         for (i = 0; i < NCOMMAND; i++) {
6062                 if (command_table[i].name == NULL)
6063                         continue;
6064
6065                 if (strcmp(command, command_table[i].name) == 0) {
6066                         *idx = i;
6067                         return (0);
6068                 }
6069         }
6070         return (1);
6071 }
6072
6073 int
6074 main(int argc, char **argv)
6075 {
6076         int ret = 0;
6077         int i;
6078         char *cmdname;
6079
6080         (void) setlocale(LC_ALL, "");
6081         (void) textdomain(TEXT_DOMAIN);
6082
6083         if ((g_zfs = libzfs_init()) == NULL) {
6084                 (void) fprintf(stderr, gettext("internal error: failed to "
6085                     "initialize ZFS library\n"));
6086                 return (1);
6087         }
6088
6089         libzfs_print_on_error(g_zfs, B_TRUE);
6090
6091         opterr = 0;
6092
6093         /*
6094          * Make sure the user has specified some command.
6095          */
6096         if (argc < 2) {
6097                 (void) fprintf(stderr, gettext("missing command\n"));
6098                 usage(B_FALSE);
6099         }
6100
6101         cmdname = argv[1];
6102
6103         /*
6104          * Special case '-?'
6105          */
6106         if (strcmp(cmdname, "-?") == 0)
6107                 usage(B_TRUE);
6108
6109         zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
6110
6111         /*
6112          * Run the appropriate command.
6113          */
6114         if (find_command_idx(cmdname, &i) == 0) {
6115                 current_command = &command_table[i];
6116                 ret = command_table[i].func(argc - 1, argv + 1);
6117         } else if (strchr(cmdname, '=')) {
6118                 verify(find_command_idx("set", &i) == 0);
6119                 current_command = &command_table[i];
6120                 ret = command_table[i].func(argc, argv);
6121         } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
6122                 /*
6123                  * 'freeze' is a vile debugging abomination, so we treat
6124                  * it as such.
6125                  */
6126                 zfs_cmd_t zc = { 0 };
6127                 (void) strlcpy(zc.zc_name, argv[2], sizeof (zc.zc_name));
6128                 return (!!zfs_ioctl(g_zfs, ZFS_IOC_POOL_FREEZE, &zc));
6129         } else {
6130                 (void) fprintf(stderr, gettext("unrecognized "
6131                     "command '%s'\n"), cmdname);
6132                 usage(B_FALSE);
6133         }
6134
6135         if (ret == 0 && log_history)
6136                 (void) zpool_log_history(g_zfs, history_str);
6137
6138         libzfs_fini(g_zfs);
6139
6140         /*
6141          * The 'ZFS_ABORT' environment variable causes us to dump core on exit
6142          * for the purposes of running ::findleaks.
6143          */
6144         if (getenv("ZFS_ABORT") != NULL) {
6145                 (void) printf("dumping core by request\n");
6146                 abort();
6147         }
6148
6149         return (ret);
6150 }