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