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