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 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #include <assert.h>
  28 #include <ctype.h>
  29 #include <dirent.h>
  30 #include <errno.h>
  31 #include <fcntl.h>
  32 #include <libgen.h>
  33 #include <libintl.h>
  34 #include <libuutil.h>
  35 #include <locale.h>
  36 #include <stdio.h>
  37 #include <stdlib.h>
  38 #include <string.h>
  39 #include <strings.h>
  40 #include <unistd.h>
  41 #include <priv.h>
  42 #include <pwd.h>
  43 #include <zone.h>
  44 #include <sys/fs/zfs.h>
  45 
  46 #include <sys/stat.h>
  47 
  48 #include <libzfs.h>
  49 
  50 #include "zpool_util.h"
  51 #include "zfs_comutil.h"
  52 
  53 static int zpool_do_create(int, char **);
  54 static int zpool_do_destroy(int, char **);
  55 
  56 static int zpool_do_add(int, char **);
  57 static int zpool_do_remove(int, char **);
  58 
  59 static int zpool_do_list(int, char **);
  60 static int zpool_do_iostat(int, char **);
  61 static int zpool_do_status(int, char **);
  62 
  63 static int zpool_do_online(int, char **);
  64 static int zpool_do_offline(int, char **);
  65 static int zpool_do_clear(int, char **);
  66 
  67 static int zpool_do_attach(int, char **);
  68 static int zpool_do_detach(int, char **);
  69 static int zpool_do_replace(int, char **);
  70 
  71 static int zpool_do_scrub(int, char **);
  72 
  73 static int zpool_do_import(int, char **);
  74 static int zpool_do_export(int, char **);
  75 
  76 static int zpool_do_upgrade(int, char **);
  77 
  78 static int zpool_do_history(int, char **);
  79 
  80 static int zpool_do_get(int, char **);
  81 static int zpool_do_set(int, char **);
  82 
  83 static int zpool_do_key(int, char **);
  84 
  85 /*
  86  * These libumem hooks provide a reasonable set of defaults for the allocator's
  87  * debugging facilities.
  88  */
  89 
  90 #ifdef DEBUG
  91 const char *
  92 _umem_debug_init(void)
  93 {
  94         return ("default,verbose"); /* $UMEM_DEBUG setting */
  95 }
  96 
  97 const char *
  98 _umem_logging_init(void)
  99 {
 100         return ("fail,contents"); /* $UMEM_LOGGING setting */
 101 }
 102 #endif
 103 
 104 typedef enum {
 105         HELP_ADD,
 106         HELP_ATTACH,
 107         HELP_CLEAR,
 108         HELP_CREATE,
 109         HELP_DESTROY,
 110         HELP_DETACH,
 111         HELP_EXPORT,
 112         HELP_HISTORY,
 113         HELP_IMPORT,
 114         HELP_IOSTAT,
 115         HELP_LIST,
 116         HELP_OFFLINE,
 117         HELP_ONLINE,
 118         HELP_REPLACE,
 119         HELP_REMOVE,
 120         HELP_SCRUB,
 121         HELP_STATUS,
 122         HELP_UPGRADE,
 123         HELP_GET,
 124         HELP_SET,
 125         HELP_KEY
 126 } zpool_help_t;
 127 
 128 
 129 typedef struct zpool_command {
 130         const char      *name;
 131         int             (*func)(int, char **);
 132         zpool_help_t    usage;
 133 } zpool_command_t;
 134 
 135 /*
 136  * Master command table.  Each ZFS command has a name, associated function, and
 137  * usage message.  The usage messages need to be internationalized, so we have
 138  * to have a function to return the usage message based on a command index.
 139  *
 140  * These commands are organized according to how they are displayed in the usage
 141  * message.  An empty command (one with a NULL name) indicates an empty line in
 142  * the generic usage message.
 143  */
 144 static zpool_command_t command_table[] = {
 145         { "create",     zpool_do_create,        HELP_CREATE             },
 146         { "destroy",    zpool_do_destroy,       HELP_DESTROY            },
 147         { NULL },
 148         { "add",        zpool_do_add,           HELP_ADD                },
 149         { "remove",     zpool_do_remove,        HELP_REMOVE             },
 150         { NULL },
 151         { "list",       zpool_do_list,          HELP_LIST               },
 152         { "iostat",     zpool_do_iostat,        HELP_IOSTAT             },
 153         { "status",     zpool_do_status,        HELP_STATUS             },
 154         { NULL },
 155         { "online",     zpool_do_online,        HELP_ONLINE             },
 156         { "offline",    zpool_do_offline,       HELP_OFFLINE            },
 157         { "clear",      zpool_do_clear,         HELP_CLEAR              },
 158         { NULL },
 159         { "attach",     zpool_do_attach,        HELP_ATTACH             },
 160         { "detach",     zpool_do_detach,        HELP_DETACH             },
 161         { "replace",    zpool_do_replace,       HELP_REPLACE            },
 162         { NULL },
 163         { "scrub",      zpool_do_scrub,         HELP_SCRUB              },
 164         { NULL },
 165         { "import",     zpool_do_import,        HELP_IMPORT             },
 166         { "export",     zpool_do_export,        HELP_EXPORT             },
 167         { "upgrade",    zpool_do_upgrade,       HELP_UPGRADE            },
 168         { NULL },
 169         { "history",    zpool_do_history,       HELP_HISTORY            },
 170         { "get",        zpool_do_get,           HELP_GET                },
 171         { "set",        zpool_do_set,           HELP_SET                },
 172         { NULL },
 173         { "key",        zpool_do_key,           HELP_KEY                },
 174 };
 175 
 176 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 177 
 178 zpool_command_t *current_command;
 179 static char history_str[HIS_MAX_RECORD_LEN];
 180 
 181 static const char *
 182 get_usage(zpool_help_t idx) {
 183         switch (idx) {
 184         case HELP_ADD:
 185                 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
 186         case HELP_ATTACH:
 187                 return (gettext("\tattach [-f] <pool> <device> "
 188                     "<new-device>\n"));
 189         case HELP_CLEAR:
 190                 return (gettext("\tclear <pool> [device]\n"));
 191         case HELP_CREATE:
 192                 return (gettext("\tcreate [-fn] [-o property=value] ... \n"
 193                     "\t    [-O file-system-property=value] ... \n"
 194                     "\t    [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
 195         case HELP_DESTROY:
 196                 return (gettext("\tdestroy [-f] <pool>\n"));
 197         case HELP_DETACH:
 198                 return (gettext("\tdetach <pool> <device>\n"));
 199         case HELP_EXPORT:
 200                 return (gettext("\texport [-f] <pool> ...\n"));
 201         case HELP_HISTORY:
 202                 return (gettext("\thistory [-il] [<pool>] ...\n"));
 203         case HELP_IMPORT:
 204                 return (gettext("\timport [-d dir] [-D]\n"
 205                     "\timport [-o mntopts] [-o property=value] ... \n"
 206                     "\t    [-d dir | -c cachefile] [-D] [-f] [-R root] -a\n"
 207                     "\timport [-o mntopts] [-o property=value] ... \n"
 208                     "\t    [-d dir | -c cachefile] [-D] [-f] [-R root] "
 209                     "<pool | id> [newpool]\n"));
 210         case HELP_IOSTAT:
 211                 return (gettext("\tiostat [-v] [pool] ... [interval "
 212                     "[count]]\n"));
 213         case HELP_LIST:
 214                 return (gettext("\tlist [-H] [-o property[,...]] "
 215                     "[pool] ...\n"));
 216         case HELP_OFFLINE:
 217                 return (gettext("\toffline [-t] <pool> <device> ...\n"));
 218         case HELP_ONLINE:
 219                 return (gettext("\tonline <pool> <device> ...\n"));
 220         case HELP_REPLACE:
 221                 return (gettext("\treplace [-f] <pool> <device> "
 222                     "[new-device]\n"));
 223         case HELP_REMOVE:
 224                 return (gettext("\tremove <pool> <device> ...\n"));
 225         case HELP_SCRUB:
 226                 return (gettext("\tscrub [-s] <pool> ...\n"));
 227         case HELP_STATUS:
 228                 return (gettext("\tstatus [-vx] [pool] ...\n"));
 229         case HELP_UPGRADE:
 230                 return (gettext("\tupgrade\n"
 231                     "\tupgrade -v\n"
 232                     "\tupgrade [-V version] <-a | pool ...>\n"));
 233         case HELP_GET:
 234                 return (gettext("\tget <\"all\" | property[,...]> "
 235                     "<pool> ...\n"));
 236         case HELP_SET:
 237                 return (gettext("\tset <property=value> <pool> \n"));
 238         case HELP_KEY:
 239                 return (gettext("\tkey <-l | -u | -c [ -o <property=value>]> "
 240                     "<-a | pool>\n"));
 241         }
 242 
 243         abort();
 244         /* NOTREACHED */
 245 }
 246 
 247 
 248 /*
 249  * Callback routine that will print out a pool property value.
 250  */
 251 static int
 252 print_prop_cb(int prop, void *cb)
 253 {
 254         FILE *fp = cb;
 255 
 256         (void) fprintf(fp, "\t%-13s  ", zpool_prop_to_name(prop));
 257 
 258         if (zpool_prop_readonly(prop))
 259                 (void) fprintf(fp, "  NO   ");
 260         else
 261                 (void) fprintf(fp, " YES    ");
 262 
 263         if (zpool_prop_values(prop) == NULL)
 264                 (void) fprintf(fp, "-\n");
 265         else
 266                 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
 267 
 268         return (ZPROP_CONT);
 269 }
 270 
 271 /*
 272  * Display usage message.  If we're inside a command, display only the usage for
 273  * that command.  Otherwise, iterate over the entire command table and display
 274  * a complete usage message.
 275  */
 276 void
 277 usage(boolean_t requested)
 278 {
 279         FILE *fp = requested ? stdout : stderr;
 280 
 281         if (current_command == NULL) {
 282                 int i;
 283 
 284                 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
 285                 (void) fprintf(fp,
 286                     gettext("where 'command' is one of the following:\n\n"));
 287 
 288                 for (i = 0; i < NCOMMAND; i++) {
 289                         if (command_table[i].name == NULL)
 290                                 (void) fprintf(fp, "\n");
 291                         else
 292                                 (void) fprintf(fp, "%s",
 293                                     get_usage(command_table[i].usage));
 294                 }
 295         } else {
 296                 (void) fprintf(fp, gettext("usage:\n"));
 297                 (void) fprintf(fp, "%s", get_usage(current_command->usage));
 298         }
 299 
 300         if (current_command != NULL &&
 301             ((strcmp(current_command->name, "set") == 0) ||
 302             (strcmp(current_command->name, "get") == 0) ||
 303             (strcmp(current_command->name, "list") == 0))) {
 304 
 305                 (void) fprintf(fp,
 306                     gettext("\nthe following properties are supported:\n"));
 307 
 308                 (void) fprintf(fp, "\n\t%-13s  %s  %s\n\n",
 309                     "PROPERTY", "EDIT", "VALUES");
 310 
 311                 /* Iterate over all properties */
 312                 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
 313                     ZFS_TYPE_POOL);
 314         }
 315 
 316         /*
 317          * See comments at end of main().
 318          */
 319         if (getenv("ZFS_ABORT") != NULL) {
 320                 (void) printf("dumping core by request\n");
 321                 abort();
 322         }
 323 
 324         exit(requested ? 0 : 2);
 325 }
 326 
 327 void
 328 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
 329     boolean_t print_logs)
 330 {
 331         nvlist_t **child;
 332         uint_t c, children;
 333         char *vname;
 334 
 335         if (name != NULL)
 336                 (void) printf("\t%*s%s\n", indent, "", name);
 337 
 338         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
 339             &child, &children) != 0)
 340                 return;
 341 
 342         for (c = 0; c < children; c++) {
 343                 uint64_t is_log = B_FALSE;
 344 
 345                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
 346                     &is_log);
 347                 if ((is_log && !print_logs) || (!is_log && print_logs))
 348                         continue;
 349 
 350                 vname = zpool_vdev_name(g_zfs, zhp, child[c]);
 351                 print_vdev_tree(zhp, vname, child[c], indent + 2,
 352                     B_FALSE);
 353                 free(vname);
 354         }
 355 }
 356 
 357 /*
 358  * Add a property pair (name, string-value) into a property nvlist.
 359  */
 360 static int
 361 add_prop_list(const char *propname, char *propval, nvlist_t **props,
 362     boolean_t poolprop)
 363 {
 364         zpool_prop_t prop = ZPROP_INVAL;
 365         zfs_prop_t fprop;
 366         nvlist_t *proplist;
 367         const char *normnm;
 368         char *strval;
 369 
 370         if (*props == NULL &&
 371             nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
 372                 (void) fprintf(stderr,
 373                     gettext("internal error: out of memory\n"));
 374                 return (1);
 375         }
 376 
 377         proplist = *props;
 378 
 379         if (poolprop) {
 380                 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
 381                         (void) fprintf(stderr, gettext("property '%s' is "
 382                             "not a valid pool property\n"), propname);
 383                         return (2);
 384                 }
 385                 normnm = zpool_prop_to_name(prop);
 386         } else {
 387                 if ((fprop = zfs_name_to_prop(propname)) == ZPROP_INVAL) {
 388                         (void) fprintf(stderr, gettext("property '%s' is "
 389                             "not a valid file system property\n"), propname);
 390                         return (2);
 391                 }
 392                 normnm = zfs_prop_to_name(fprop);
 393         }
 394 
 395         if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
 396             prop != ZPOOL_PROP_CACHEFILE) {
 397                 (void) fprintf(stderr, gettext("property '%s' "
 398                     "specified multiple times\n"), propname);
 399                 return (2);
 400         }
 401 
 402         if (nvlist_add_string(proplist, normnm, propval) != 0) {
 403                 (void) fprintf(stderr, gettext("internal "
 404                     "error: out of memory\n"));
 405                 return (1);
 406         }
 407 
 408         return (0);
 409 }
 410 
 411 /*
 412  * zpool add [-fn] <pool> <vdev> ...
 413  *
 414  *      -f      Force addition of devices, even if they appear in use
 415  *      -n      Do not add the devices, but display the resulting layout if
 416  *              they were to be added.
 417  *
 418  * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
 419  * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
 420  * libzfs.
 421  */
 422 int
 423 zpool_do_add(int argc, char **argv)
 424 {
 425         boolean_t force = B_FALSE;
 426         boolean_t dryrun = B_FALSE;
 427         int c;
 428         nvlist_t *nvroot;
 429         char *poolname;
 430         int ret;
 431         zpool_handle_t *zhp;
 432         nvlist_t *config;
 433 
 434         /* check options */
 435         while ((c = getopt(argc, argv, "fn")) != -1) {
 436                 switch (c) {
 437                 case 'f':
 438                         force = B_TRUE;
 439                         break;
 440                 case 'n':
 441                         dryrun = B_TRUE;
 442                         break;
 443                 case '?':
 444                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
 445                             optopt);
 446                         usage(B_FALSE);
 447                 }
 448         }
 449 
 450         argc -= optind;
 451         argv += optind;
 452 
 453         /* get pool name and check number of arguments */
 454         if (argc < 1) {
 455                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
 456                 usage(B_FALSE);
 457         }
 458         if (argc < 2) {
 459                 (void) fprintf(stderr, gettext("missing vdev specification\n"));
 460                 usage(B_FALSE);
 461         }
 462 
 463         poolname = argv[0];
 464 
 465         argc--;
 466         argv++;
 467 
 468         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
 469                 return (1);
 470 
 471         if ((config = zpool_get_config(zhp, NULL)) == NULL) {
 472                 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
 473                     poolname);
 474                 zpool_close(zhp);
 475                 return (1);
 476         }
 477 
 478         /* pass off to get_vdev_spec for processing */
 479         nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
 480             argc, argv);
 481         if (nvroot == NULL) {
 482                 zpool_close(zhp);
 483                 return (1);
 484         }
 485 
 486         if (dryrun) {
 487                 nvlist_t *poolnvroot;
 488 
 489                 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
 490                     &poolnvroot) == 0);
 491 
 492                 (void) printf(gettext("would update '%s' to the following "
 493                     "configuration:\n"), zpool_get_name(zhp));
 494 
 495                 /* print original main pool and new tree */
 496                 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
 497                 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
 498 
 499                 /* Do the same for the logs */
 500                 if (num_logs(poolnvroot) > 0) {
 501                         print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
 502                         print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
 503                 } else if (num_logs(nvroot) > 0) {
 504                         print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
 505                 }
 506 
 507                 ret = 0;
 508         } else {
 509                 ret = (zpool_add(zhp, nvroot) != 0);
 510         }
 511 
 512         nvlist_free(nvroot);
 513         zpool_close(zhp);
 514 
 515         return (ret);
 516 }
 517 
 518 /*
 519  * zpool remove <pool> <vdev> ...
 520  *
 521  * Removes the given vdev from the pool.  Currently, this only supports removing
 522  * spares and cache devices from the pool.  Eventually, we'll want to support
 523  * removing leaf vdevs (as an alias for 'detach') as well as toplevel vdevs.
 524  */
 525 int
 526 zpool_do_remove(int argc, char **argv)
 527 {
 528         char *poolname;
 529         int i, ret = 0;
 530         zpool_handle_t *zhp;
 531 
 532         argc--;
 533         argv++;
 534 
 535         /* get pool name and check number of arguments */
 536         if (argc < 1) {
 537                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
 538                 usage(B_FALSE);
 539         }
 540         if (argc < 2) {
 541                 (void) fprintf(stderr, gettext("missing device\n"));
 542                 usage(B_FALSE);
 543         }
 544 
 545         poolname = argv[0];
 546 
 547         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
 548                 return (1);
 549 
 550         for (i = 1; i < argc; i++) {
 551                 if (zpool_vdev_remove(zhp, argv[i]) != 0)
 552                         ret = 1;
 553         }
 554 
 555         return (ret);
 556 }
 557 
 558 /*
 559  * zpool create [-fn] [-o property=value] ...
 560  *              [-O file-system-property=value] ...
 561  *              [-R root] [-m mountpoint] <pool> <dev> ...
 562  *
 563  *      -f      Force creation, even if devices appear in use
 564  *      -n      Do not create the pool, but display the resulting layout if it
 565  *              were to be created.
 566  *      -R      Create a pool under an alternate root
 567  *      -m      Set default mountpoint for the root dataset.  By default it's
 568  *              '/<pool>'
 569  *      -o      Set property=value.
 570  *      -O      Set fsproperty=value in the pool's root file system
 571  *
 572  * Creates the named pool according to the given vdev specification.  The
 573  * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c.  Once
 574  * we get the nvlist back from get_vdev_spec(), we either print out the contents
 575  * (if '-n' was specified), or pass it to libzfs to do the creation.
 576  */
 577 int
 578 zpool_do_create(int argc, char **argv)
 579 {
 580         boolean_t force = B_FALSE;
 581         boolean_t dryrun = B_FALSE;
 582         int c;
 583         nvlist_t *nvroot = NULL;
 584         char *poolname;
 585         int ret = 1;
 586         char *altroot = NULL;
 587         char *mountpoint = NULL;
 588         nvlist_t *fsprops = NULL;
 589         nvlist_t *props = NULL;
 590         char *propval;
 591 
 592         /* check options */
 593         while ((c = getopt(argc, argv, ":fnR:m:o:O:")) != -1) {
 594                 switch (c) {
 595                 case 'f':
 596                         force = B_TRUE;
 597                         break;
 598                 case 'n':
 599                         dryrun = B_TRUE;
 600                         break;
 601                 case 'R':
 602                         altroot = optarg;
 603                         if (add_prop_list(zpool_prop_to_name(
 604                             ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
 605                                 goto errout;
 606                         if (nvlist_lookup_string(props,
 607                             zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
 608                             &propval) == 0)
 609                                 break;
 610                         if (add_prop_list(zpool_prop_to_name(
 611                             ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
 612                                 goto errout;
 613                         break;
 614                 case 'm':
 615                         mountpoint = optarg;
 616                         break;
 617                 case 'o':
 618                         if ((propval = strchr(optarg, '=')) == NULL) {
 619                                 (void) fprintf(stderr, gettext("missing "
 620                                     "'=' for -o option\n"));
 621                                 goto errout;
 622                         }
 623                         *propval = '\0';
 624                         propval++;
 625 
 626                         if (add_prop_list(optarg, propval, &props, B_TRUE))
 627                                 goto errout;
 628                         break;
 629                 case 'O':
 630                         if ((propval = strchr(optarg, '=')) == NULL) {
 631                                 (void) fprintf(stderr, gettext("missing "
 632                                     "'=' for -O option\n"));
 633                                 goto errout;
 634                         }
 635                         *propval = '\0';
 636                         propval++;
 637 
 638                         if (add_prop_list(optarg, propval, &fsprops, B_FALSE))
 639                                 goto errout;
 640                         break;
 641                 case ':':
 642                         (void) fprintf(stderr, gettext("missing argument for "
 643                             "'%c' option\n"), optopt);
 644                         goto badusage;
 645                 case '?':
 646                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
 647                             optopt);
 648                         goto badusage;
 649                 }
 650         }
 651 
 652         argc -= optind;
 653         argv += optind;
 654 
 655         /* get pool name and check number of arguments */
 656         if (argc < 1) {
 657                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
 658                 goto badusage;
 659         }
 660         if (argc < 2) {
 661                 (void) fprintf(stderr, gettext("missing vdev specification\n"));
 662                 goto badusage;
 663         }
 664 
 665         poolname = argv[0];
 666 
 667         /*
 668          * As a special case, check for use of '/' in the name, and direct the
 669          * user to use 'zfs create' instead.
 670          */
 671         if (strchr(poolname, '/') != NULL) {
 672                 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
 673                     "character '/' in pool name\n"), poolname);
 674                 (void) fprintf(stderr, gettext("use 'zfs create' to "
 675                     "create a dataset\n"));
 676                 goto errout;
 677         }
 678 
 679         /* pass off to get_vdev_spec for bulk processing */
 680         nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
 681             argc - 1, argv + 1);
 682         if (nvroot == NULL)
 683                 goto errout;
 684 
 685         /* make_root_vdev() allows 0 toplevel children if there are spares */
 686         if (!zfs_allocatable_devs(nvroot)) {
 687                 (void) fprintf(stderr, gettext("invalid vdev "
 688                     "specification: at least one toplevel vdev must be "
 689                     "specified\n"));
 690                 goto errout;
 691         }
 692 
 693 
 694         if (altroot != NULL && altroot[0] != '/') {
 695                 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
 696                     "must be an absolute path\n"), altroot);
 697                 goto errout;
 698         }
 699 
 700         /*
 701          * Check the validity of the mountpoint and direct the user to use the
 702          * '-m' mountpoint option if it looks like its in use.
 703          */
 704         if (mountpoint == NULL ||
 705             (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
 706             strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
 707                 char buf[MAXPATHLEN];
 708                 DIR *dirp;
 709 
 710                 if (mountpoint && mountpoint[0] != '/') {
 711                         (void) fprintf(stderr, gettext("invalid mountpoint "
 712                             "'%s': must be an absolute path, 'legacy', or "
 713                             "'none'\n"), mountpoint);
 714                         goto errout;
 715                 }
 716 
 717                 if (mountpoint == NULL) {
 718                         if (altroot != NULL)
 719                                 (void) snprintf(buf, sizeof (buf), "%s/%s",
 720                                     altroot, poolname);
 721                         else
 722                                 (void) snprintf(buf, sizeof (buf), "/%s",
 723                                     poolname);
 724                 } else {
 725                         if (altroot != NULL)
 726                                 (void) snprintf(buf, sizeof (buf), "%s%s",
 727                                     altroot, mountpoint);
 728                         else
 729                                 (void) snprintf(buf, sizeof (buf), "%s",
 730                                     mountpoint);
 731                 }
 732 
 733                 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
 734                         (void) fprintf(stderr, gettext("mountpoint '%s' : "
 735                             "%s\n"), buf, strerror(errno));
 736                         (void) fprintf(stderr, gettext("use '-m' "
 737                             "option to provide a different default\n"));
 738                         goto errout;
 739                 } else if (dirp) {
 740                         int count = 0;
 741 
 742                         while (count < 3 && readdir(dirp) != NULL)
 743                                 count++;
 744                         (void) closedir(dirp);
 745 
 746                         if (count > 2) {
 747                                 (void) fprintf(stderr, gettext("mountpoint "
 748                                     "'%s' exists and is not empty\n"), buf);
 749                                 (void) fprintf(stderr, gettext("use '-m' "
 750                                     "option to provide a "
 751                                     "different default\n"));
 752                                 goto errout;
 753                         }
 754                 }
 755         }
 756 
 757         if (dryrun) {
 758                 /*
 759                  * For a dry run invocation, print out a basic message and run
 760                  * through all the vdevs in the list and print out in an
 761                  * appropriate hierarchy.
 762                  */
 763                 (void) printf(gettext("would create '%s' with the "
 764                     "following layout:\n\n"), poolname);
 765 
 766                 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
 767                 if (num_logs(nvroot) > 0)
 768                         print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
 769 
 770                 ret = 0;
 771         } else {
 772                 /*
 773                  * Hand off to libzfs.
 774                  */
 775                 if (zpool_create(g_zfs, poolname,
 776                     nvroot, props, fsprops) == 0) {
 777                         zfs_handle_t *pool = zfs_open(g_zfs, poolname,
 778                             ZFS_TYPE_FILESYSTEM);
 779                         if (pool != NULL) {
 780                                 if (mountpoint != NULL)
 781                                         verify(zfs_prop_set(pool,
 782                                             zfs_prop_to_name(
 783                                             ZFS_PROP_MOUNTPOINT),
 784                                             mountpoint) == 0);
 785                                 if (zfs_mount(pool, NULL, 0) == 0)
 786                                         ret = zfs_shareall(pool);
 787                                 zfs_close(pool);
 788                         }
 789                 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
 790                         (void) fprintf(stderr, gettext("pool name may have "
 791                             "been omitted\n"));
 792                 }
 793         }
 794 
 795 errout:
 796         nvlist_free(nvroot);
 797         nvlist_free(fsprops);
 798         nvlist_free(props);
 799         return (ret);
 800 badusage:
 801         nvlist_free(fsprops);
 802         nvlist_free(props);
 803         usage(B_FALSE);
 804         return (2);
 805 }
 806 
 807 /*
 808  * zpool destroy <pool>
 809  *
 810  *      -f      Forcefully unmount any datasets
 811  *
 812  * Destroy the given pool.  Automatically unmounts any datasets in the pool.
 813  */
 814 int
 815 zpool_do_destroy(int argc, char **argv)
 816 {
 817         boolean_t force = B_FALSE;
 818         boolean_t encrypted_only = B_FALSE;
 819         int c;
 820         char *pool;
 821         zpool_handle_t *zhp;
 822         int ret;
 823 
 824         /* check options */
 825         while ((c = getopt(argc, argv, "f")) != -1) {
 826                 switch (c) {
 827                 case 'f':
 828                         force = B_TRUE;
 829                         break;
 830                 case '?':
 831                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
 832                             optopt);
 833                         usage(B_FALSE);
 834                 }
 835         }
 836 
 837         argc -= optind;
 838         argv += optind;
 839 
 840         /* check arguments */
 841         if (argc < 1) {
 842                 (void) fprintf(stderr, gettext("missing pool argument\n"));
 843                 usage(B_FALSE);
 844         }
 845         if (argc > 1) {
 846                 (void) fprintf(stderr, gettext("too many arguments\n"));
 847                 usage(B_FALSE);
 848         }
 849 
 850         pool = argv[0];
 851 
 852         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
 853                 /*
 854                  * As a special case, check for use of '/' in the name, and
 855                  * direct the user to use 'zfs destroy' instead.
 856                  */
 857                 if (strchr(pool, '/') != NULL)
 858                         (void) fprintf(stderr, gettext("use 'zfs destroy' to "
 859                             "destroy a dataset\n"));
 860                 return (1);
 861         }
 862 
 863         if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) {
 864                 (void) fprintf(stderr, gettext("could not destroy '%s': "
 865                     "could not unmount datasets\n"), zpool_get_name(zhp));
 866                 return (1);
 867         }
 868 
 869         ret = (zpool_destroy(zhp) != 0);
 870 
 871         zpool_close(zhp);
 872 
 873         return (ret);
 874 }
 875 
 876 /*
 877  * zpool export [-f] <pool> ...
 878  *
 879  *      -f      Forcefully unmount datasets
 880  *
 881  * Export the given pools.  By default, the command will attempt to cleanly
 882  * unmount any active datasets within the pool.  If the '-f' flag is specified,
 883  * then the datasets will be forcefully unmounted.
 884  */
 885 int
 886 zpool_do_export(int argc, char **argv)
 887 {
 888         boolean_t force = B_FALSE;
 889         boolean_t hardforce = B_FALSE;
 890         boolean_t encrypted_only = B_FALSE;
 891         int c;
 892         zpool_handle_t *zhp;
 893         int ret;
 894         int i;
 895 
 896         /* check options */
 897         while ((c = getopt(argc, argv, "fF")) != -1) {
 898                 switch (c) {
 899                 case 'f':
 900                         force = B_TRUE;
 901                         break;
 902                 case 'F':
 903                         hardforce = B_TRUE;
 904                         break;
 905                 case '?':
 906                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
 907                             optopt);
 908                         usage(B_FALSE);
 909                 }
 910         }
 911 
 912         argc -= optind;
 913         argv += optind;
 914 
 915         /* check arguments */
 916         if (argc < 1) {
 917                 (void) fprintf(stderr, gettext("missing pool argument\n"));
 918                 usage(B_FALSE);
 919         }
 920 
 921         ret = 0;
 922         for (i = 0; i < argc; i++) {
 923                 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
 924                         ret = 1;
 925                         continue;
 926                 }
 927 
 928                 if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) {
 929                         ret = 1;
 930                         zpool_close(zhp);
 931                         continue;
 932                 }
 933 
 934                 if (hardforce) {
 935                         if (zpool_export_force(zhp) != 0)
 936                                 ret = 1;
 937                 } else if (zpool_export(zhp, force) != 0) {
 938                         ret = 1;
 939                 }
 940 
 941                 zpool_close(zhp);
 942         }
 943 
 944         return (ret);
 945 }
 946 
 947 /*
 948  * Given a vdev configuration, determine the maximum width needed for the device
 949  * name column.
 950  */
 951 static int
 952 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
 953 {
 954         char *name = zpool_vdev_name(g_zfs, zhp, nv);
 955         nvlist_t **child;
 956         uint_t c, children;
 957         int ret;
 958 
 959         if (strlen(name) + depth > max)
 960                 max = strlen(name) + depth;
 961 
 962         free(name);
 963 
 964         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
 965             &child, &children) == 0) {
 966                 for (c = 0; c < children; c++)
 967                         if ((ret = max_width(zhp, child[c], depth + 2,
 968                             max)) > max)
 969                                 max = ret;
 970         }
 971 
 972         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
 973             &child, &children) == 0) {
 974                 for (c = 0; c < children; c++)
 975                         if ((ret = max_width(zhp, child[c], depth + 2,
 976                             max)) > max)
 977                                 max = ret;
 978         }
 979 
 980         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
 981             &child, &children) == 0) {
 982                 for (c = 0; c < children; c++)
 983                         if ((ret = max_width(zhp, child[c], depth + 2,
 984                             max)) > max)
 985                                 max = ret;
 986         }
 987 
 988 
 989         return (max);
 990 }
 991 
 992 
 993 /*
 994  * Print the configuration of an exported pool.  Iterate over all vdevs in the
 995  * pool, printing out the name and status for each one.
 996  */
 997 void
 998 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth,
 999     boolean_t print_logs)
1000 {
1001         nvlist_t **child;
1002         uint_t c, children;
1003         vdev_stat_t *vs;
1004         char *type, *vname;
1005 
1006         verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1007         if (strcmp(type, VDEV_TYPE_MISSING) == 0)
1008                 return;
1009 
1010         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
1011             (uint64_t **)&vs, &c) == 0);
1012 
1013         (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1014         (void) printf("  %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1015 
1016         if (vs->vs_aux != 0) {
1017                 (void) printf("  ");
1018 
1019                 switch (vs->vs_aux) {
1020                 case VDEV_AUX_OPEN_FAILED:
1021                         (void) printf(gettext("cannot open"));
1022                         break;
1023 
1024                 case VDEV_AUX_BAD_GUID_SUM:
1025                         (void) printf(gettext("missing device"));
1026                         break;
1027 
1028                 case VDEV_AUX_NO_REPLICAS:
1029                         (void) printf(gettext("insufficient replicas"));
1030                         break;
1031 
1032                 case VDEV_AUX_VERSION_NEWER:
1033                         (void) printf(gettext("newer version"));
1034                         break;
1035 
1036                 case VDEV_AUX_ERR_EXCEEDED:
1037                         (void) printf(gettext("too many errors"));
1038                         break;
1039 
1040                 default:
1041                         (void) printf(gettext("corrupted data"));
1042                         break;
1043                 }
1044         }
1045         (void) printf("\n");
1046 
1047         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1048             &child, &children) != 0)
1049                 return;
1050 
1051         for (c = 0; c < children; c++) {
1052                 uint64_t is_log = B_FALSE;
1053 
1054                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1055                     &is_log);
1056                 if ((is_log && !print_logs) || (!is_log && print_logs))
1057                         continue;
1058 
1059                 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1060                 print_import_config(vname, child[c],
1061                     namewidth, depth + 2, B_FALSE);
1062                 free(vname);
1063         }
1064 
1065         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1066             &child, &children) == 0) {
1067                 (void) printf(gettext("\tcache\n"));
1068                 for (c = 0; c < children; c++) {
1069                         vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1070                         (void) printf("\t  %s\n", vname);
1071                         free(vname);
1072                 }
1073         }
1074 
1075         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1076             &child, &children) == 0) {
1077                 (void) printf(gettext("\tspares\n"));
1078                 for (c = 0; c < children; c++) {
1079                         vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1080                         (void) printf("\t  %s\n", vname);
1081                         free(vname);
1082                 }
1083         }
1084 }
1085 
1086 /*
1087  * Display the status for the given pool.
1088  */
1089 static void
1090 show_import(nvlist_t *config)
1091 {
1092         uint64_t pool_state;
1093         vdev_stat_t *vs;
1094         char *name;
1095         uint64_t guid;
1096         char *msgid;
1097         nvlist_t *nvroot;
1098         int reason;
1099         const char *health;
1100         uint_t vsc;
1101         int namewidth;
1102 
1103         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1104             &name) == 0);
1105         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1106             &guid) == 0);
1107         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1108             &pool_state) == 0);
1109         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1110             &nvroot) == 0);
1111 
1112         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
1113             (uint64_t **)&vs, &vsc) == 0);
1114         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1115 
1116         reason = zpool_import_status(config, &msgid);
1117 
1118         (void) printf(gettext("  pool: %s\n"), name);
1119         (void) printf(gettext("    id: %llu\n"), (u_longlong_t)guid);
1120         (void) printf(gettext(" state: %s"), health);
1121         if (pool_state == POOL_STATE_DESTROYED)
1122                 (void) printf(gettext(" (DESTROYED)"));
1123         (void) printf("\n");
1124 
1125         switch (reason) {
1126         case ZPOOL_STATUS_MISSING_DEV_R:
1127         case ZPOOL_STATUS_MISSING_DEV_NR:
1128         case ZPOOL_STATUS_BAD_GUID_SUM:
1129                 (void) printf(gettext("status: One or more devices are missing "
1130                     "from the system.\n"));
1131                 break;
1132 
1133         case ZPOOL_STATUS_CORRUPT_LABEL_R:
1134         case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1135                 (void) printf(gettext("status: One or more devices contains "
1136                     "corrupted data.\n"));
1137                 break;
1138 
1139         case ZPOOL_STATUS_CORRUPT_DATA:
1140                 (void) printf(gettext("status: The pool data is corrupted.\n"));
1141                 break;
1142 
1143         case ZPOOL_STATUS_OFFLINE_DEV:
1144                 (void) printf(gettext("status: One or more devices "
1145                     "are offlined.\n"));
1146                 break;
1147 
1148         case ZPOOL_STATUS_CORRUPT_POOL:
1149                 (void) printf(gettext("status: The pool metadata is "
1150                     "corrupted.\n"));
1151                 break;
1152 
1153         case ZPOOL_STATUS_VERSION_OLDER:
1154                 (void) printf(gettext("status: The pool is formatted using an "
1155                     "older on-disk version.\n"));
1156                 break;
1157 
1158         case ZPOOL_STATUS_VERSION_NEWER:
1159                 (void) printf(gettext("status: The pool is formatted using an "
1160                     "incompatible version.\n"));
1161                 break;
1162 
1163         case ZPOOL_STATUS_HOSTID_MISMATCH:
1164                 (void) printf(gettext("status: The pool was last accessed by "
1165                     "another system.\n"));
1166                 break;
1167 
1168         case ZPOOL_STATUS_FAULTED_DEV_R:
1169         case ZPOOL_STATUS_FAULTED_DEV_NR:
1170                 (void) printf(gettext("status: One or more devices are "
1171                     "faulted.\n"));
1172                 break;
1173 
1174         case ZPOOL_STATUS_BAD_LOG:
1175                 (void) printf(gettext("status: An intent log record cannot be "
1176                     "read.\n"));
1177                 break;
1178 
1179         default:
1180                 /*
1181                  * No other status can be seen when importing pools.
1182                  */
1183                 assert(reason == ZPOOL_STATUS_OK);
1184         }
1185 
1186         /*
1187          * Print out an action according to the overall state of the pool.
1188          */
1189         if (vs->vs_state == VDEV_STATE_HEALTHY) {
1190                 if (reason == ZPOOL_STATUS_VERSION_OLDER)
1191                         (void) printf(gettext("action: The pool can be "
1192                             "imported using its name or numeric identifier, "
1193                             "though\n\tsome features will not be available "
1194                             "without an explicit 'zpool upgrade'.\n"));
1195                 else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH)
1196                         (void) printf(gettext("action: The pool can be "
1197                             "imported using its name or numeric "
1198                             "identifier and\n\tthe '-f' flag.\n"));
1199                 else
1200                         (void) printf(gettext("action: The pool can be "
1201                             "imported using its name or numeric "
1202                             "identifier.\n"));
1203         } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1204                 (void) printf(gettext("action: The pool can be imported "
1205                     "despite missing or damaged devices.  The\n\tfault "
1206                     "tolerance of the pool may be compromised if imported.\n"));
1207         } else {
1208                 switch (reason) {
1209                 case ZPOOL_STATUS_VERSION_NEWER:
1210                         (void) printf(gettext("action: The pool cannot be "
1211                             "imported.  Access the pool on a system running "
1212                             "newer\n\tsoftware, or recreate the pool from "
1213                             "backup.\n"));
1214                         break;
1215                 case ZPOOL_STATUS_MISSING_DEV_R:
1216                 case ZPOOL_STATUS_MISSING_DEV_NR:
1217                 case ZPOOL_STATUS_BAD_GUID_SUM:
1218                         (void) printf(gettext("action: The pool cannot be "
1219                             "imported. Attach the missing\n\tdevices and try "
1220                             "again.\n"));
1221                         break;
1222                 default:
1223                         (void) printf(gettext("action: The pool cannot be "
1224                             "imported due to damaged devices or data.\n"));
1225                 }
1226         }
1227 
1228         /*
1229          * If the state is "closed" or "can't open", and the aux state
1230          * is "corrupt data":
1231          */
1232         if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1233             (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1234             (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1235                 if (pool_state == POOL_STATE_DESTROYED)
1236                         (void) printf(gettext("\tThe pool was destroyed, "
1237                             "but can be imported using the '-Df' flags.\n"));
1238                 else if (pool_state != POOL_STATE_EXPORTED)
1239                         (void) printf(gettext("\tThe pool may be active on "
1240                             "another system, but can be imported using\n\t"
1241                             "the '-f' flag.\n"));
1242         }
1243 
1244         if (msgid != NULL)
1245                 (void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
1246                     msgid);
1247 
1248         (void) printf(gettext("config:\n\n"));
1249 
1250         namewidth = max_width(NULL, nvroot, 0, 0);
1251         if (namewidth < 10)
1252                 namewidth = 10;
1253 
1254         print_import_config(name, nvroot, namewidth, 0, B_FALSE);
1255         if (num_logs(nvroot) > 0) {
1256                 (void) printf(gettext("\tlogs\n"));
1257                 print_import_config(name, nvroot, namewidth, 0, B_TRUE);
1258         }
1259 
1260         if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1261                 (void) printf(gettext("\n\tAdditional devices are known to "
1262                     "be part of this pool, though their\n\texact "
1263                     "configuration cannot be determined.\n"));
1264         }
1265 }
1266 
1267 /*
1268  * Perform the import for the given configuration.  This passes the heavy
1269  * lifting off to zpool_import_props(), and then mounts the datasets contained
1270  * within the pool.
1271  */
1272 static int
1273 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1274     int force, nvlist_t *props, boolean_t allowfaulted)
1275 {
1276         boolean_t encrypted_only = B_FALSE;
1277         zpool_handle_t *zhp;
1278         char *name;
1279         uint64_t state;
1280         uint64_t version;
1281         int error = 0;
1282 
1283         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1284             &name) == 0);
1285 
1286         verify(nvlist_lookup_uint64(config,
1287             ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1288         verify(nvlist_lookup_uint64(config,
1289             ZPOOL_CONFIG_VERSION, &version) == 0);
1290         if (version > SPA_VERSION) {
1291                 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1292                     "is formatted using a newer ZFS version\n"), name);
1293                 return (1);
1294         } else if (state != POOL_STATE_EXPORTED && !force) {
1295                 uint64_t hostid;
1296 
1297                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
1298                     &hostid) == 0) {
1299                         if ((unsigned long)hostid != gethostid()) {
1300                                 char *hostname;
1301                                 uint64_t timestamp;
1302                                 time_t t;
1303 
1304                                 verify(nvlist_lookup_string(config,
1305                                     ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
1306                                 verify(nvlist_lookup_uint64(config,
1307                                     ZPOOL_CONFIG_TIMESTAMP, &timestamp) == 0);
1308                                 t = timestamp;
1309                                 (void) fprintf(stderr, gettext("cannot import "
1310                                     "'%s': pool may be in use from other "
1311                                     "system, it was last accessed by %s "
1312                                     "(hostid: 0x%lx) on %s"), name, hostname,
1313                                     (unsigned long)hostid,
1314                                     asctime(localtime(&t)));
1315                                 (void) fprintf(stderr, gettext("use '-f' to "
1316                                     "import anyway\n"));
1317                                 return (1);
1318                         }
1319                 } else {
1320                         (void) fprintf(stderr, gettext("cannot import '%s': "
1321                             "pool may be in use from other system\n"), name);
1322                         (void) fprintf(stderr, gettext("use '-f' to import "
1323                             "anyway\n"));
1324                         return (1);
1325                 }
1326         }
1327 
1328         if (zpool_import_props(g_zfs, config, newname, props,
1329             allowfaulted) != 0)
1330                 return (1);
1331 
1332         if (newname != NULL)
1333                 name = (char *)newname;
1334 
1335         verify((zhp = zpool_open_canfail(g_zfs, name)) != NULL);
1336 
1337         /*
1338          * Attempt to load the crypto keys before mounting up the datasets
1339          * Note that depending on the value of the keysource property
1340          * this could cause us to go interactive.
1341          * We don't mind if this falls though and continue to enable what
1342          * datasets we can if it does.
1343          *
1344          * Use zpool_load_key() and tell it we are doing an import rather than
1345          * zpool_cmd_key_load().
1346          *
1347          * We then attempt enable all datasets not just the encrypted ones.
1348          */
1349 
1350         error = zpool_load_key(zhp, B_TRUE);
1351         if (error != 0 && error != ENOTSUP) {
1352                 libzfs_handle_t *zpool_hdl = zpool_get_handle(zhp);
1353                 (void) fprintf(stderr, gettext(
1354                     "%s.\nEncrypted datasets with keyscope=pool "
1355                     "will not be mounted.\n"),
1356                     libzfs_error_description(zpool_hdl));
1357         }
1358 
1359         if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
1360             zpool_enable_datasets(zhp, mntopts, 0, encrypted_only) != 0) {
1361                 zpool_close(zhp);
1362                 return (1);
1363         }
1364 
1365         zpool_close(zhp);
1366         return (0);
1367 }
1368 
1369 /*
1370  * zpool import [-d dir] [-D]
1371  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1372  *              [-d dir | -c cachefile] [-f] -a
1373  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1374  *              [-d dir | -c cachefile] [-f] <pool | id> [newpool]
1375  *
1376  *       -c     Read pool information from a cachefile instead of searching
1377  *              devices.
1378  *
1379  *       -d     Scan in a specific directory, other than /dev/dsk.  More than
1380  *              one directory can be specified using multiple '-d' options.
1381  *
1382  *       -D     Scan for previously destroyed pools or import all or only
1383  *              specified destroyed pools.
1384  *
1385  *       -R     Temporarily import the pool, with all mountpoints relative to
1386  *              the given root.  The pool will remain exported when the machine
1387  *              is rebooted.
1388  *
1389  *       -f     Force import, even if it appears that the pool is active.
1390  *
1391  *       -F     Import even in the presence of faulted vdevs.  This is an
1392  *              intentionally undocumented option for testing purposes, and
1393  *              treats the pool configuration as complete, leaving any bad
1394  *              vdevs in the FAULTED state.
1395  *
1396  *       -a     Import all pools found.
1397  *
1398  *       -o     Set property=value and/or temporary mount options (without '=').
1399  *
1400  * The import command scans for pools to import, and import pools based on pool
1401  * name and GUID.  The pool can also be renamed as part of the import process.
1402  */
1403 int
1404 zpool_do_import(int argc, char **argv)
1405 {
1406         char **searchdirs = NULL;
1407         int nsearch = 0;
1408         int c;
1409         int err;
1410         nvlist_t *pools = NULL;
1411         boolean_t do_all = B_FALSE;
1412         boolean_t do_destroyed = B_FALSE;
1413         char *mntopts = NULL;
1414         boolean_t do_force = B_FALSE;
1415         nvpair_t *elem;
1416         nvlist_t *config;
1417         uint64_t searchguid = 0;
1418         char *searchname = NULL;
1419         char *propval;
1420         nvlist_t *found_config;
1421         nvlist_t *props = NULL;
1422         boolean_t first;
1423         boolean_t allow_faulted = B_FALSE;
1424         uint64_t pool_state;
1425         char *cachefile = NULL;
1426 
1427         /* check options */
1428         while ((c = getopt(argc, argv, ":ac:d:DfFo:p:R:")) != -1) {
1429                 switch (c) {
1430                 case 'a':
1431                         do_all = B_TRUE;
1432                         break;
1433                 case 'c':
1434                         cachefile = optarg;
1435                         break;
1436                 case 'd':
1437                         if (searchdirs == NULL) {
1438                                 searchdirs = safe_malloc(sizeof (char *));
1439                         } else {
1440                                 char **tmp = safe_malloc((nsearch + 1) *
1441                                     sizeof (char *));
1442                                 bcopy(searchdirs, tmp, nsearch *
1443                                     sizeof (char *));
1444                                 free(searchdirs);
1445                                 searchdirs = tmp;
1446                         }
1447                         searchdirs[nsearch++] = optarg;
1448                         break;
1449                 case 'D':
1450                         do_destroyed = B_TRUE;
1451                         break;
1452                 case 'f':
1453                         do_force = B_TRUE;
1454                         break;
1455                 case 'F':
1456                         allow_faulted = B_TRUE;
1457                         break;
1458                 case 'o':
1459                         if ((propval = strchr(optarg, '=')) != NULL) {
1460                                 *propval = '\0';
1461                                 propval++;
1462                                 if (add_prop_list(optarg, propval,
1463                                     &props, B_TRUE))
1464                                         goto error;
1465                         } else {
1466                                 mntopts = optarg;
1467                         }
1468                         break;
1469                 case 'R':
1470                         if (add_prop_list(zpool_prop_to_name(
1471                             ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
1472                                 goto error;
1473                         if (nvlist_lookup_string(props,
1474                             zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
1475                             &propval) == 0)
1476                                 break;
1477                         if (add_prop_list(zpool_prop_to_name(
1478                             ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1479                                 goto error;
1480                         break;
1481                 case ':':
1482                         (void) fprintf(stderr, gettext("missing argument for "
1483                             "'%c' option\n"), optopt);
1484                         usage(B_FALSE);
1485                         break;
1486                 case '?':
1487                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1488                             optopt);
1489                         usage(B_FALSE);
1490                 }
1491         }
1492 
1493         argc -= optind;
1494         argv += optind;
1495 
1496         if (cachefile && nsearch != 0) {
1497                 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
1498                 usage(B_FALSE);
1499         }
1500 
1501         if (searchdirs == NULL) {
1502                 searchdirs = safe_malloc(sizeof (char *));
1503                 searchdirs[0] = "/dev/dsk";
1504                 nsearch = 1;
1505         }
1506 
1507         /* check argument count */
1508         if (do_all) {
1509                 if (argc != 0) {
1510                         (void) fprintf(stderr, gettext("too many arguments\n"));
1511                         usage(B_FALSE);
1512                 }
1513         } else {
1514                 if (argc > 2) {
1515                         (void) fprintf(stderr, gettext("too many arguments\n"));
1516                         usage(B_FALSE);
1517                 }
1518 
1519                 /*
1520                  * Check for the SYS_CONFIG privilege.  We do this explicitly
1521                  * here because otherwise any attempt to discover pools will
1522                  * silently fail.
1523                  */
1524                 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
1525                         (void) fprintf(stderr, gettext("cannot "
1526                             "discover pools: permission denied\n"));
1527                         free(searchdirs);
1528                         return (1);
1529                 }
1530         }
1531 
1532         /*
1533          * Depending on the arguments given, we do one of the following:
1534          *
1535          *      <none>    Iterate through all pools and display information about
1536          *              each one.
1537          *
1538          *      -a      Iterate through all pools and try to import each one.
1539          *
1540          *      <id>      Find the pool that corresponds to the given GUID/pool
1541          *              name and import that one.
1542          *
1543          *      -D      Above options applies only to destroyed pools.
1544          */
1545         if (argc != 0) {
1546                 char *endptr;
1547 
1548                 errno = 0;
1549                 searchguid = strtoull(argv[0], &endptr, 10);
1550                 if (errno != 0 || *endptr != '\0')
1551                         searchname = argv[0];
1552                 found_config = NULL;
1553         }
1554 
1555         if (cachefile) {
1556                 pools = zpool_find_import_cached(g_zfs, cachefile, searchname,
1557                     searchguid);
1558         } else if (searchname != NULL) {
1559                 pools = zpool_find_import_byname(g_zfs, nsearch, searchdirs,
1560                     searchname);
1561         } else {
1562                 /*
1563                  * It's OK to search by guid even if searchguid is 0.
1564                  */
1565                 pools = zpool_find_import_byguid(g_zfs, nsearch, searchdirs,
1566                     searchguid);
1567         }
1568 
1569         if (pools == NULL) {
1570                 if (argc != 0) {
1571                         (void) fprintf(stderr, gettext("cannot import '%s': "
1572                             "no such pool available\n"), argv[0]);
1573                 }
1574                 free(searchdirs);
1575                 return (1);
1576         }
1577 
1578         /*
1579          * At this point we have a list of import candidate configs. Even if
1580          * we were searching by pool name or guid, we still need to
1581          * post-process the list to deal with pool state and possible
1582          * duplicate names.
1583          */
1584         err = 0;
1585         elem = NULL;
1586         first = B_TRUE;
1587         while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
1588 
1589                 verify(nvpair_value_nvlist(elem, &config) == 0);
1590 
1591                 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1592                     &pool_state) == 0);
1593                 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
1594                         continue;
1595                 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
1596                         continue;
1597 
1598                 if (argc == 0) {
1599                         if (first)
1600                                 first = B_FALSE;
1601                         else if (!do_all)
1602                                 (void) printf("\n");
1603 
1604                         if (do_all)
1605                                 err |= do_import(config, NULL, mntopts,
1606                                     do_force, props, allow_faulted);
1607                         else
1608                                 show_import(config);
1609                 } else if (searchname != NULL) {
1610                         char *name;
1611 
1612                         /*
1613                          * We are searching for a pool based on name.
1614                          */
1615                         verify(nvlist_lookup_string(config,
1616                             ZPOOL_CONFIG_POOL_NAME, &name) == 0);
1617 
1618                         if (strcmp(name, searchname) == 0) {
1619                                 if (found_config != NULL) {
1620                                         (void) fprintf(stderr, gettext(
1621                                             "cannot import '%s': more than "
1622                                             "one matching pool\n"), searchname);
1623                                         (void) fprintf(stderr, gettext(
1624                                             "import by numeric ID instead\n"));
1625                                         err = B_TRUE;
1626                                 }
1627                                 found_config = config;
1628                         }
1629                 } else {
1630                         uint64_t guid;
1631 
1632                         /*
1633                          * Search for a pool by guid.
1634                          */
1635                         verify(nvlist_lookup_uint64(config,
1636                             ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
1637 
1638                         if (guid == searchguid)
1639                                 found_config = config;
1640                 }
1641         }
1642 
1643         /*
1644          * If we were searching for a specific pool, verify that we found a
1645          * pool, and then do the import.
1646          */
1647         if (argc != 0 && err == 0) {
1648                 if (found_config == NULL) {
1649                         (void) fprintf(stderr, gettext("cannot import '%s': "
1650                             "no such pool available\n"), argv[0]);
1651                         err = B_TRUE;
1652                 } else {
1653                         err |= do_import(found_config, argc == 1 ? NULL :
1654                             argv[1], mntopts, do_force, props, allow_faulted);
1655                 }
1656         }
1657 
1658         /*
1659          * If we were just looking for pools, report an error if none were
1660          * found.
1661          */
1662         if (argc == 0 && first)
1663                 (void) fprintf(stderr,
1664                     gettext("no pools available to import\n"));
1665 
1666 error:
1667         nvlist_free(props);
1668         nvlist_free(pools);
1669         free(searchdirs);
1670 
1671         return (err ? 1 : 0);
1672 }
1673 
1674 typedef struct iostat_cbdata {
1675         zpool_list_t *cb_list;
1676         int cb_verbose;
1677         int cb_iteration;
1678         int cb_namewidth;
1679 } iostat_cbdata_t;
1680 
1681 static void
1682 print_iostat_separator(iostat_cbdata_t *cb)
1683 {
1684         int i = 0;
1685 
1686         for (i = 0; i < cb->cb_namewidth; i++)
1687                 (void) printf("-");
1688         (void) printf("  -----  -----  -----  -----  -----  -----\n");
1689 }
1690 
1691 static void
1692 print_iostat_header(iostat_cbdata_t *cb)
1693 {
1694         (void) printf("%*s     capacity     operations    bandwidth\n",
1695             cb->cb_namewidth, "");
1696         (void) printf("%-*s   used  avail   read  write   read  write\n",
1697             cb->cb_namewidth, "pool");
1698         print_iostat_separator(cb);
1699 }
1700 
1701 /*
1702  * Display a single statistic.
1703  */
1704 static void
1705 print_one_stat(uint64_t value)
1706 {
1707         char buf[64];
1708 
1709         zfs_nicenum(value, buf, sizeof (buf));
1710         (void) printf("  %5s", buf);
1711 }
1712 
1713 /*
1714  * Print out all the statistics for the given vdev.  This can either be the
1715  * toplevel configuration, or called recursively.  If 'name' is NULL, then this
1716  * is a verbose output, and we don't want to display the toplevel pool stats.
1717  */
1718 void
1719 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
1720     nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
1721 {
1722         nvlist_t **oldchild, **newchild;
1723         uint_t c, children;
1724         vdev_stat_t *oldvs, *newvs;
1725         vdev_stat_t zerovs = { 0 };
1726         uint64_t tdelta;
1727         double scale;
1728         char *vname;
1729 
1730         if (oldnv != NULL) {
1731                 verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS,
1732                     (uint64_t **)&oldvs, &c) == 0);
1733         } else {
1734                 oldvs = &zerovs;
1735         }
1736 
1737         verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS,
1738             (uint64_t **)&newvs, &c) == 0);
1739 
1740         if (strlen(name) + depth > cb->cb_namewidth)
1741                 (void) printf("%*s%s", depth, "", name);
1742         else
1743                 (void) printf("%*s%s%*s", depth, "", name,
1744                     (int)(cb->cb_namewidth - strlen(name) - depth), "");
1745 
1746         tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
1747 
1748         if (tdelta == 0)
1749                 scale = 1.0;
1750         else
1751                 scale = (double)NANOSEC / tdelta;
1752 
1753         /* only toplevel vdevs have capacity stats */
1754         if (newvs->vs_space == 0) {
1755                 (void) printf("      -      -");
1756         } else {
1757                 print_one_stat(newvs->vs_alloc);
1758                 print_one_stat(newvs->vs_space - newvs->vs_alloc);
1759         }
1760 
1761         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
1762             oldvs->vs_ops[ZIO_TYPE_READ])));
1763 
1764         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
1765             oldvs->vs_ops[ZIO_TYPE_WRITE])));
1766 
1767         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
1768             oldvs->vs_bytes[ZIO_TYPE_READ])));
1769 
1770         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
1771             oldvs->vs_bytes[ZIO_TYPE_WRITE])));
1772 
1773         (void) printf("\n");
1774 
1775         if (!cb->cb_verbose)
1776                 return;
1777 
1778         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
1779             &newchild, &children) != 0)
1780                 return;
1781 
1782         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
1783             &oldchild, &c) != 0)
1784                 return;
1785 
1786         for (c = 0; c < children; c++) {
1787                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1788                 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1789                     newchild[c], cb, depth + 2);
1790                 free(vname);
1791         }
1792 
1793         /*
1794          * Include level 2 ARC devices in iostat output
1795          */
1796         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
1797             &newchild, &children) != 0)
1798                 return;
1799 
1800         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
1801             &oldchild, &c) != 0)
1802                 return;
1803 
1804         if (children > 0) {
1805                 (void) printf("%-*s      -      -      -      -      -      "
1806                     "-\n", cb->cb_namewidth, "cache");
1807                 for (c = 0; c < children; c++) {
1808                         vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1809                         print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1810                             newchild[c], cb, depth + 2);
1811                         free(vname);
1812                 }
1813         }
1814 }
1815 
1816 static int
1817 refresh_iostat(zpool_handle_t *zhp, void *data)
1818 {
1819         iostat_cbdata_t *cb = data;
1820         boolean_t missing;
1821 
1822         /*
1823          * If the pool has disappeared, remove it from the list and continue.
1824          */
1825         if (zpool_refresh_stats(zhp, &missing) != 0)
1826                 return (-1);
1827 
1828         if (missing)
1829                 pool_list_remove(cb->cb_list, zhp);
1830 
1831         return (0);
1832 }
1833 
1834 /*
1835  * Callback to print out the iostats for the given pool.
1836  */
1837 int
1838 print_iostat(zpool_handle_t *zhp, void *data)
1839 {
1840         iostat_cbdata_t *cb = data;
1841         nvlist_t *oldconfig, *newconfig;
1842         nvlist_t *oldnvroot, *newnvroot;
1843 
1844         newconfig = zpool_get_config(zhp, &oldconfig);
1845 
1846         if (cb->cb_iteration == 1)
1847                 oldconfig = NULL;
1848 
1849         verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
1850             &newnvroot) == 0);
1851 
1852         if (oldconfig == NULL)
1853                 oldnvroot = NULL;
1854         else
1855                 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
1856                     &oldnvroot) == 0);
1857 
1858         /*
1859          * Print out the statistics for the pool.
1860          */
1861         print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
1862 
1863         if (cb->cb_verbose)
1864                 print_iostat_separator(cb);
1865 
1866         return (0);
1867 }
1868 
1869 int
1870 get_namewidth(zpool_handle_t *zhp, void *data)
1871 {
1872         iostat_cbdata_t *cb = data;
1873         nvlist_t *config, *nvroot;
1874 
1875         if ((config = zpool_get_config(zhp, NULL)) != NULL) {
1876                 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1877                     &nvroot) == 0);
1878                 if (!cb->cb_verbose)
1879                         cb->cb_namewidth = strlen(zpool_get_name(zhp));
1880                 else
1881                         cb->cb_namewidth = max_width(zhp, nvroot, 0, 0);
1882         }
1883 
1884         /*
1885          * The width must fall into the range [10,38].  The upper limit is the
1886          * maximum we can have and still fit in 80 columns.
1887          */
1888         if (cb->cb_namewidth < 10)
1889                 cb->cb_namewidth = 10;
1890         if (cb->cb_namewidth > 38)
1891                 cb->cb_namewidth = 38;
1892 
1893         return (0);
1894 }
1895 
1896 /*
1897  * zpool iostat [-v] [pool] ... [interval [count]]
1898  *
1899  *      -v      Display statistics for individual vdevs
1900  *
1901  * This command can be tricky because we want to be able to deal with pool
1902  * creation/destruction as well as vdev configuration changes.  The bulk of this
1903  * processing is handled by the pool_list_* routines in zpool_iter.c.  We rely
1904  * on pool_list_update() to detect the addition of new pools.  Configuration
1905  * changes are all handled within libzfs.
1906  */
1907 int
1908 zpool_do_iostat(int argc, char **argv)
1909 {
1910         int c;
1911         int ret;
1912         int npools;
1913         unsigned long interval = 0, count = 0;
1914         zpool_list_t *list;
1915         boolean_t verbose = B_FALSE;
1916         iostat_cbdata_t cb;
1917 
1918         /* check options */
1919         while ((c = getopt(argc, argv, "v")) != -1) {
1920                 switch (c) {
1921                 case 'v':
1922                         verbose = B_TRUE;
1923                         break;
1924                 case '?':
1925                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1926                             optopt);
1927                         usage(B_FALSE);
1928                 }
1929         }
1930 
1931         argc -= optind;
1932         argv += optind;
1933 
1934         /*
1935          * Determine if the last argument is an integer or a pool name
1936          */
1937         if (argc > 0 && isdigit(argv[argc - 1][0])) {
1938                 char *end;
1939 
1940                 errno = 0;
1941                 interval = strtoul(argv[argc - 1], &end, 10);
1942 
1943                 if (*end == '\0' && errno == 0) {
1944                         if (interval == 0) {
1945                                 (void) fprintf(stderr, gettext("interval "
1946                                     "cannot be zero\n"));
1947                                 usage(B_FALSE);
1948                         }
1949 
1950                         /*
1951                          * Ignore the last parameter
1952                          */
1953                         argc--;
1954                 } else {
1955                         /*
1956                          * If this is not a valid number, just plow on.  The
1957                          * user will get a more informative error message later
1958                          * on.
1959                          */
1960                         interval = 0;
1961                 }
1962         }
1963 
1964         /*
1965          * If the last argument is also an integer, then we have both a count
1966          * and an integer.
1967          */
1968         if (argc > 0 && isdigit(argv[argc - 1][0])) {
1969                 char *end;
1970 
1971                 errno = 0;
1972                 count = interval;
1973                 interval = strtoul(argv[argc - 1], &end, 10);
1974 
1975                 if (*end == '\0' && errno == 0) {
1976                         if (interval == 0) {
1977                                 (void) fprintf(stderr, gettext("interval "
1978                                     "cannot be zero\n"));
1979                                 usage(B_FALSE);
1980                         }
1981 
1982                         /*
1983                          * Ignore the last parameter
1984                          */
1985                         argc--;
1986                 } else {
1987                         interval = 0;
1988                 }
1989         }
1990 
1991         /*
1992          * Construct the list of all interesting pools.
1993          */
1994         ret = 0;
1995         if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
1996                 return (1);
1997 
1998         if (pool_list_count(list) == 0 && argc != 0) {
1999                 pool_list_free(list);
2000                 return (1);
2001         }
2002 
2003         if (pool_list_count(list) == 0 && interval == 0) {
2004                 pool_list_free(list);
2005                 (void) fprintf(stderr, gettext("no pools available\n"));
2006                 return (1);
2007         }
2008 
2009         /*
2010          * Enter the main iostat loop.
2011          */
2012         cb.cb_list = list;
2013         cb.cb_verbose = verbose;
2014         cb.cb_iteration = 0;
2015         cb.cb_namewidth = 0;
2016 
2017         for (;;) {
2018                 pool_list_update(list);
2019 
2020                 if ((npools = pool_list_count(list)) == 0)
2021                         break;
2022 
2023                 /*
2024                  * Refresh all statistics.  This is done as an explicit step
2025                  * before calculating the maximum name width, so that any
2026                  * configuration changes are properly accounted for.
2027                  */
2028                 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
2029 
2030                 /*
2031                  * Iterate over all pools to determine the maximum width
2032                  * for the pool / device name column across all pools.
2033                  */
2034                 cb.cb_namewidth = 0;
2035                 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2036 
2037                 /*
2038                  * If it's the first time, or verbose mode, print the header.
2039                  */
2040                 if (++cb.cb_iteration == 1 || verbose)
2041                         print_iostat_header(&cb);
2042 
2043                 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
2044 
2045                 /*
2046                  * If there's more than one pool, and we're not in verbose mode
2047                  * (which prints a separator for us), then print a separator.
2048                  */
2049                 if (npools > 1 && !verbose)
2050                         print_iostat_separator(&cb);
2051 
2052                 if (verbose)
2053                         (void) printf("\n");
2054 
2055                 /*
2056                  * Flush the output so that redirection to a file isn't buffered
2057                  * indefinitely.
2058                  */
2059                 (void) fflush(stdout);
2060 
2061                 if (interval == 0)
2062                         break;
2063 
2064                 if (count != 0 && --count == 0)
2065                         break;
2066 
2067                 (void) sleep(interval);
2068         }
2069 
2070         pool_list_free(list);
2071 
2072         return (ret);
2073 }
2074 
2075 typedef struct list_cbdata {
2076         boolean_t       cb_scripted;
2077         boolean_t       cb_first;
2078         zprop_list_t    *cb_proplist;
2079 } list_cbdata_t;
2080 
2081 /*
2082  * Given a list of columns to display, output appropriate headers for each one.
2083  */
2084 static void
2085 print_header(zprop_list_t *pl)
2086 {
2087         const char *header;
2088         boolean_t first = B_TRUE;
2089         boolean_t right_justify;
2090 
2091         for (; pl != NULL; pl = pl->pl_next) {
2092                 if (pl->pl_prop == ZPROP_INVAL)
2093                         continue;
2094 
2095                 if (!first)
2096                         (void) printf("  ");
2097                 else
2098                         first = B_FALSE;
2099 
2100                 header = zpool_prop_column_name(pl->pl_prop);
2101                 right_justify = zpool_prop_align_right(pl->pl_prop);
2102 
2103                 if (pl->pl_next == NULL && !right_justify)
2104                         (void) printf("%s", header);
2105                 else if (right_justify)
2106                         (void) printf("%*s", pl->pl_width, header);
2107                 else
2108                         (void) printf("%-*s", pl->pl_width, header);
2109         }
2110 
2111         (void) printf("\n");
2112 }
2113 
2114 /*
2115  * Given a pool and a list of properties, print out all the properties according
2116  * to the described layout.
2117  */
2118 static void
2119 print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
2120 {
2121         boolean_t first = B_TRUE;
2122         char property[ZPOOL_MAXPROPLEN];
2123         char *propstr;
2124         boolean_t right_justify;
2125         int width;
2126 
2127         for (; pl != NULL; pl = pl->pl_next) {
2128                 if (!first) {
2129                         if (scripted)
2130                                 (void) printf("\t");
2131                         else
2132                                 (void) printf("  ");
2133                 } else {
2134                         first = B_FALSE;
2135                 }
2136 
2137                 right_justify = B_FALSE;
2138                 if (pl->pl_prop != ZPROP_INVAL) {
2139                         if (zpool_get_prop(zhp, pl->pl_prop, property,
2140                             sizeof (property), NULL) != 0)
2141                                 propstr = "-";
2142                         else
2143                                 propstr = property;
2144 
2145                         right_justify = zpool_prop_align_right(pl->pl_prop);
2146                 } else {
2147                         propstr = "-";
2148                 }
2149 
2150                 width = pl->pl_width;
2151 
2152                 /*
2153                  * If this is being called in scripted mode, or if this is the
2154                  * last column and it is left-justified, don't include a width
2155                  * format specifier.
2156                  */
2157                 if (scripted || (pl->pl_next == NULL && !right_justify))
2158                         (void) printf("%s", propstr);
2159                 else if (right_justify)
2160                         (void) printf("%*s", width, propstr);
2161                 else
2162                         (void) printf("%-*s", width, propstr);
2163         }
2164 
2165         (void) printf("\n");
2166 }
2167 
2168 /*
2169  * Generic callback function to list a pool.
2170  */
2171 int
2172 list_callback(zpool_handle_t *zhp, void *data)
2173 {
2174         list_cbdata_t *cbp = data;
2175 
2176         if (cbp->cb_first) {
2177                 if (!cbp->cb_scripted)
2178                         print_header(cbp->cb_proplist);
2179                 cbp->cb_first = B_FALSE;
2180         }
2181 
2182         print_pool(zhp, cbp->cb_proplist, cbp->cb_scripted);
2183 
2184         return (0);
2185 }
2186 
2187 /*
2188  * zpool list [-H] [-o prop[,prop]*] [pool] ...
2189  *
2190  *      -H      Scripted mode.  Don't display headers, and separate properties
2191  *              by a single tab.
2192  *      -o      List of properties to display.  Defaults to
2193  *              "name,size,used,available,capacity,health,altroot"
2194  *
2195  * List all pools in the system, whether or not they're healthy.  Output space
2196  * statistics for each one, as well as health status summary.
2197  */
2198 int
2199 zpool_do_list(int argc, char **argv)
2200 {
2201         int c;
2202         int ret;
2203         list_cbdata_t cb = { 0 };
2204         static char default_props[] =
2205             "name,size,used,available,capacity,health,altroot";
2206         char *props = default_props;
2207 
2208         /* check options */
2209         while ((c = getopt(argc, argv, ":Ho:")) != -1) {
2210                 switch (c) {
2211                 case 'H':
2212                         cb.cb_scripted = B_TRUE;
2213                         break;
2214                 case 'o':
2215                         props = optarg;
2216                         break;
2217                 case ':':
2218                         (void) fprintf(stderr, gettext("missing argument for "
2219                             "'%c' option\n"), optopt);
2220                         usage(B_FALSE);
2221                         break;
2222                 case '?':
2223                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2224                             optopt);
2225                         usage(B_FALSE);
2226                 }
2227         }
2228 
2229         argc -= optind;
2230         argv += optind;
2231 
2232         if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
2233                 usage(B_FALSE);
2234 
2235         cb.cb_first = B_TRUE;
2236 
2237         ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
2238             list_callback, &cb);
2239 
2240         zprop_free_list(cb.cb_proplist);
2241 
2242         if (argc == 0 && cb.cb_first && !cb.cb_scripted) {
2243                 (void) printf(gettext("no pools available\n"));
2244                 return (0);
2245         }
2246 
2247         return (ret);
2248 }
2249 
2250 static nvlist_t *
2251 zpool_get_vdev_by_name(nvlist_t *nv, char *name)
2252 {
2253         nvlist_t **child;
2254         uint_t c, children;
2255         nvlist_t *match;
2256         char *path;
2257 
2258         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2259             &child, &children) != 0) {
2260                 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2261                 if (strncmp(name, "/dev/dsk/", 9) == 0)
2262                         name += 9;
2263                 if (strncmp(path, "/dev/dsk/", 9) == 0)
2264                         path += 9;
2265                 if (strcmp(name, path) == 0)
2266                         return (nv);
2267                 return (NULL);
2268         }
2269 
2270         for (c = 0; c < children; c++)
2271                 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL)
2272                         return (match);
2273 
2274         return (NULL);
2275 }
2276 
2277 static int
2278 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
2279 {
2280         boolean_t force = B_FALSE;
2281         int c;
2282         nvlist_t *nvroot;
2283         char *poolname, *old_disk, *new_disk;
2284         zpool_handle_t *zhp;
2285         int ret;
2286 
2287         /* check options */
2288         while ((c = getopt(argc, argv, "f")) != -1) {
2289                 switch (c) {
2290                 case 'f':
2291                         force = B_TRUE;
2292                         break;
2293                 case '?':
2294                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2295                             optopt);
2296                         usage(B_FALSE);
2297                 }
2298         }
2299 
2300         argc -= optind;
2301         argv += optind;
2302 
2303         /* get pool name and check number of arguments */
2304         if (argc < 1) {
2305                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2306                 usage(B_FALSE);
2307         }
2308 
2309         poolname = argv[0];
2310 
2311         if (argc < 2) {
2312                 (void) fprintf(stderr,
2313                     gettext("missing <device> specification\n"));
2314                 usage(B_FALSE);
2315         }
2316 
2317         old_disk = argv[1];
2318 
2319         if (argc < 3) {
2320                 if (!replacing) {
2321                         (void) fprintf(stderr,
2322                             gettext("missing <new_device> specification\n"));
2323                         usage(B_FALSE);
2324                 }
2325                 new_disk = old_disk;
2326                 argc -= 1;
2327                 argv += 1;
2328         } else {
2329                 new_disk = argv[2];
2330                 argc -= 2;
2331                 argv += 2;
2332         }
2333 
2334         if (argc > 1) {
2335                 (void) fprintf(stderr, gettext("too many arguments\n"));
2336                 usage(B_FALSE);
2337         }
2338 
2339         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2340                 return (1);
2341 
2342         if (zpool_get_config(zhp, NULL) == NULL) {
2343                 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
2344                     poolname);
2345                 zpool_close(zhp);
2346                 return (1);
2347         }
2348 
2349         nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
2350             argc, argv);
2351         if (nvroot == NULL) {
2352                 zpool_close(zhp);
2353                 return (1);
2354         }
2355 
2356         ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
2357 
2358         nvlist_free(nvroot);
2359         zpool_close(zhp);
2360 
2361         return (ret);
2362 }
2363 
2364 /*
2365  * zpool replace [-f] <pool> <device> <new_device>
2366  *
2367  *      -f      Force attach, even if <new_device> appears to be in use.
2368  *
2369  * Replace <device> with <new_device>.
2370  */
2371 /* ARGSUSED */
2372 int
2373 zpool_do_replace(int argc, char **argv)
2374 {
2375         return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
2376 }
2377 
2378 /*
2379  * zpool attach [-f] <pool> <device> <new_device>
2380  *
2381  *      -f      Force attach, even if <new_device> appears to be in use.
2382  *
2383  * Attach <new_device> to the mirror containing <device>.  If <device> is not
2384  * part of a mirror, then <device> will be transformed into a mirror of
2385  * <device> and <new_device>.  In either case, <new_device> will begin life
2386  * with a DTL of [0, now], and will immediately begin to resilver itself.
2387  */
2388 int
2389 zpool_do_attach(int argc, char **argv)
2390 {
2391         return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
2392 }
2393 
2394 /*
2395  * zpool detach [-f] <pool> <device>
2396  *
2397  *      -f      Force detach of <device>, even if DTLs argue against it
2398  *              (not supported yet)
2399  *
2400  * Detach a device from a mirror.  The operation will be refused if <device>
2401  * is the last device in the mirror, or if the DTLs indicate that this device
2402  * has the only valid copy of some data.
2403  */
2404 /* ARGSUSED */
2405 int
2406 zpool_do_detach(int argc, char **argv)
2407 {
2408         int c;
2409         char *poolname, *path;
2410         zpool_handle_t *zhp;
2411         int ret;
2412 
2413         /* check options */
2414         while ((c = getopt(argc, argv, "f")) != -1) {
2415                 switch (c) {
2416                 case 'f':
2417                 case '?':
2418                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2419                             optopt);
2420                         usage(B_FALSE);
2421                 }
2422         }
2423 
2424         argc -= optind;
2425         argv += optind;
2426 
2427         /* get pool name and check number of arguments */
2428         if (argc < 1) {
2429                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2430                 usage(B_FALSE);
2431         }
2432 
2433         if (argc < 2) {
2434                 (void) fprintf(stderr,
2435                     gettext("missing <device> specification\n"));
2436                 usage(B_FALSE);
2437         }
2438 
2439         poolname = argv[0];
2440         path = argv[1];
2441 
2442         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2443                 return (1);
2444 
2445         ret = zpool_vdev_detach(zhp, path);
2446 
2447         zpool_close(zhp);
2448 
2449         return (ret);
2450 }
2451 
2452 /*
2453  * zpool online <pool> <device> ...
2454  */
2455 int
2456 zpool_do_online(int argc, char **argv)
2457 {
2458         int c, i;
2459         char *poolname;
2460         zpool_handle_t *zhp;
2461         int ret = 0;
2462         vdev_state_t newstate;
2463 
2464         /* check options */
2465         while ((c = getopt(argc, argv, "t")) != -1) {
2466                 switch (c) {
2467                 case 't':
2468                 case '?':
2469                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2470                             optopt);
2471                         usage(B_FALSE);
2472                 }
2473         }
2474 
2475         argc -= optind;
2476         argv += optind;
2477 
2478         /* get pool name and check number of arguments */
2479         if (argc < 1) {
2480                 (void) fprintf(stderr, gettext("missing pool name\n"));
2481                 usage(B_FALSE);
2482         }
2483         if (argc < 2) {
2484                 (void) fprintf(stderr, gettext("missing device name\n"));
2485                 usage(B_FALSE);
2486         }
2487 
2488         poolname = argv[0];
2489 
2490         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2491                 return (1);
2492 
2493         for (i = 1; i < argc; i++) {
2494                 if (zpool_vdev_online(zhp, argv[i], 0, &newstate) == 0) {
2495                         if (newstate != VDEV_STATE_HEALTHY) {
2496                                 (void) printf(gettext("warning: device '%s' "
2497                                     "onlined, but remains in faulted state\n"),
2498                                     argv[i]);
2499                                 if (newstate == VDEV_STATE_FAULTED)
2500                                         (void) printf(gettext("use 'zpool "
2501                                             "clear' to restore a faulted "
2502                                             "device\n"));
2503                                 else
2504                                         (void) printf(gettext("use 'zpool "
2505                                             "replace' to replace devices "
2506                                             "that are no longer present\n"));
2507                         }
2508                 } else {
2509                         ret = 1;
2510                 }
2511         }
2512 
2513         zpool_close(zhp);
2514 
2515         return (ret);
2516 }
2517 
2518 /*
2519  * zpool offline [-ft] <pool> <device> ...
2520  *
2521  *      -f      Force the device into the offline state, even if doing
2522  *              so would appear to compromise pool availability.
2523  *              (not supported yet)
2524  *
2525  *      -t      Only take the device off-line temporarily.  The offline
2526  *              state will not be persistent across reboots.
2527  */
2528 /* ARGSUSED */
2529 int
2530 zpool_do_offline(int argc, char **argv)
2531 {
2532         int c, i;
2533         char *poolname;
2534         zpool_handle_t *zhp;
2535         int ret = 0;
2536         boolean_t istmp = B_FALSE;
2537 
2538         /* check options */
2539         while ((c = getopt(argc, argv, "ft")) != -1) {
2540                 switch (c) {
2541                 case 't':
2542                         istmp = B_TRUE;
2543                         break;
2544                 case 'f':
2545                 case '?':
2546                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2547                             optopt);
2548                         usage(B_FALSE);
2549                 }
2550         }
2551 
2552         argc -= optind;
2553         argv += optind;
2554 
2555         /* get pool name and check number of arguments */
2556         if (argc < 1) {
2557                 (void) fprintf(stderr, gettext("missing pool name\n"));
2558                 usage(B_FALSE);
2559         }
2560         if (argc < 2) {
2561                 (void) fprintf(stderr, gettext("missing device name\n"));
2562                 usage(B_FALSE);
2563         }
2564 
2565         poolname = argv[0];
2566 
2567         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2568                 return (1);
2569 
2570         for (i = 1; i < argc; i++) {
2571                 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
2572                         ret = 1;
2573         }
2574 
2575         zpool_close(zhp);
2576 
2577         return (ret);
2578 }
2579 
2580 /*
2581  * zpool clear <pool> [device]
2582  *
2583  * Clear all errors associated with a pool or a particular device.
2584  */
2585 int
2586 zpool_do_clear(int argc, char **argv)
2587 {
2588         int ret = 0;
2589         zpool_handle_t *zhp;
2590         char *pool, *device;
2591 
2592         if (argc < 2) {
2593                 (void) fprintf(stderr, gettext("missing pool name\n"));
2594                 usage(B_FALSE);
2595         }
2596 
2597         if (argc > 3) {
2598                 (void) fprintf(stderr, gettext("too many arguments\n"));
2599                 usage(B_FALSE);
2600         }
2601 
2602         pool = argv[1];
2603         device = argc == 3 ? argv[2] : NULL;
2604 
2605         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
2606                 return (1);
2607 
2608         if (zpool_clear(zhp, device) != 0)
2609                 ret = 1;
2610 
2611         zpool_close(zhp);
2612 
2613         return (ret);
2614 }
2615 
2616 typedef struct scrub_cbdata {
2617         int     cb_type;
2618         int     cb_argc;
2619         char    **cb_argv;
2620 } scrub_cbdata_t;
2621 
2622 int
2623 scrub_callback(zpool_handle_t *zhp, void *data)
2624 {
2625         scrub_cbdata_t *cb = data;
2626         int err;
2627 
2628         /*
2629          * Ignore faulted pools.
2630          */
2631         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
2632                 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
2633                     "currently unavailable\n"), zpool_get_name(zhp));
2634                 return (1);
2635         }
2636 
2637         err = zpool_scrub(zhp, cb->cb_type);
2638 
2639         return (err != 0);
2640 }
2641 
2642 /*
2643  * zpool scrub [-s] <pool> ...
2644  *
2645  *      -s      Stop.  Stops any in-progress scrub.
2646  */
2647 int
2648 zpool_do_scrub(int argc, char **argv)
2649 {
2650         int c;
2651         scrub_cbdata_t cb;
2652 
2653         cb.cb_type = POOL_SCRUB_EVERYTHING;
2654 
2655         /* check options */
2656         while ((c = getopt(argc, argv, "s")) != -1) {
2657                 switch (c) {
2658                 case 's':
2659                         cb.cb_type = POOL_SCRUB_NONE;
2660                         break;
2661                 case '?':
2662                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2663                             optopt);
2664                         usage(B_FALSE);
2665                 }
2666         }
2667 
2668         cb.cb_argc = argc;
2669         cb.cb_argv = argv;
2670         argc -= optind;
2671         argv += optind;
2672 
2673         if (argc < 1) {
2674                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2675                 usage(B_FALSE);
2676         }
2677 
2678         return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
2679 }
2680 
2681 typedef struct status_cbdata {
2682         int             cb_count;
2683         boolean_t       cb_allpools;
2684         boolean_t       cb_verbose;
2685         boolean_t       cb_explain;
2686         boolean_t       cb_first;
2687 } status_cbdata_t;
2688 
2689 /*
2690  * Print out detailed scrub status.
2691  */
2692 void
2693 print_scrub_status(nvlist_t *nvroot)
2694 {
2695         vdev_stat_t *vs;
2696         uint_t vsc;
2697         time_t start, end, now;
2698         double fraction_done;
2699         uint64_t examined, total, minutes_left, minutes_taken;
2700         char *scrub_type;
2701 
2702         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
2703             (uint64_t **)&vs, &vsc) == 0);
2704 
2705         /*
2706          * If there's never been a scrub, there's not much to say.
2707          */
2708         if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) {
2709                 (void) printf(gettext("none requested\n"));
2710                 return;
2711         }
2712 
2713         scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2714             "resilver" : "scrub";
2715 
2716         start = vs->vs_scrub_start;
2717         end = vs->vs_scrub_end;
2718         now = time(NULL);
2719         examined = vs->vs_scrub_examined;
2720         total = vs->vs_alloc;
2721 
2722         if (end != 0) {
2723                 minutes_taken = (uint64_t)((end - start) / 60);
2724 
2725                 (void) printf(gettext("%s %s after %lluh%um with %llu errors "
2726                     "on %s"),
2727                     scrub_type, vs->vs_scrub_complete ? "completed" : "stopped",
2728                     (u_longlong_t)(minutes_taken / 60),
2729                     (uint_t)(minutes_taken % 60),
2730                     (u_longlong_t)vs->vs_scrub_errors, ctime(&end));
2731                 return;
2732         }
2733 
2734         if (examined == 0)
2735                 examined = 1;
2736         if (examined > total)
2737                 total = examined;
2738 
2739         fraction_done = (double)examined / total;
2740         minutes_left = (uint64_t)((now - start) *
2741             (1 - fraction_done) / fraction_done / 60);
2742         minutes_taken = (uint64_t)((now - start) / 60);
2743 
2744         (void) printf(gettext("%s in progress for %lluh%um, %.2f%% done, "
2745             "%lluh%um to go\n"),
2746             scrub_type, (u_longlong_t)(minutes_taken / 60),
2747             (uint_t)(minutes_taken % 60), 100 * fraction_done,
2748             (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60));
2749 }
2750 
2751 typedef struct spare_cbdata {
2752         uint64_t        cb_guid;
2753         zpool_handle_t  *cb_zhp;
2754 } spare_cbdata_t;
2755 
2756 static boolean_t
2757 find_vdev(nvlist_t *nv, uint64_t search)
2758 {
2759         uint64_t guid;
2760         nvlist_t **child;
2761         uint_t c, children;
2762 
2763         if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
2764             search == guid)
2765                 return (B_TRUE);
2766 
2767         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2768             &child, &children) == 0) {
2769                 for (c = 0; c < children; c++)
2770                         if (find_vdev(child[c], search))
2771                                 return (B_TRUE);
2772         }
2773 
2774         return (B_FALSE);
2775 }
2776 
2777 static int
2778 find_spare(zpool_handle_t *zhp, void *data)
2779 {
2780         spare_cbdata_t *cbp = data;
2781         nvlist_t *config, *nvroot;
2782 
2783         config = zpool_get_config(zhp, NULL);
2784         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2785             &nvroot) == 0);
2786 
2787         if (find_vdev(nvroot, cbp->cb_guid)) {
2788                 cbp->cb_zhp = zhp;
2789                 return (1);
2790         }
2791 
2792         zpool_close(zhp);
2793         return (0);
2794 }
2795 
2796 /*
2797  * Print out configuration state as requested by status_callback.
2798  */
2799 void
2800 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
2801     int namewidth, int depth, boolean_t isspare, boolean_t print_logs)
2802 {
2803         nvlist_t **child;
2804         uint_t c, children;
2805         vdev_stat_t *vs;
2806         char rbuf[6], wbuf[6], cbuf[6], repaired[7];
2807         char *vname;
2808         uint64_t notpresent;
2809         spare_cbdata_t cb;
2810         char *state;
2811 
2812         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
2813             (uint64_t **)&vs, &c) == 0);
2814 
2815         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2816             &child, &children) != 0)
2817                 children = 0;
2818 
2819         state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
2820         if (isspare) {
2821                 /*
2822                  * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
2823                  * online drives.
2824                  */
2825                 if (vs->vs_aux == VDEV_AUX_SPARED)
2826                         state = "INUSE";
2827                 else if (vs->vs_state == VDEV_STATE_HEALTHY)
2828                         state = "AVAIL";
2829         }
2830 
2831         (void) printf("\t%*s%-*s  %-8s", depth, "", namewidth - depth,
2832             name, state);
2833 
2834         if (!isspare) {
2835                 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
2836                 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
2837                 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
2838                 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
2839         }
2840 
2841         if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
2842             &notpresent) == 0) {
2843                 char *path;
2844                 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2845                 (void) printf("  was %s", path);
2846         } else if (vs->vs_aux != 0) {
2847                 (void) printf("  ");
2848 
2849                 switch (vs->vs_aux) {
2850                 case VDEV_AUX_OPEN_FAILED:
2851                         (void) printf(gettext("cannot open"));
2852                         break;
2853 
2854                 case VDEV_AUX_BAD_GUID_SUM:
2855                         (void) printf(gettext("missing device"));
2856                         break;
2857 
2858                 case VDEV_AUX_NO_REPLICAS:
2859                         (void) printf(gettext("insufficient replicas"));
2860                         break;
2861 
2862                 case VDEV_AUX_VERSION_NEWER:
2863                         (void) printf(gettext("newer version"));
2864                         break;
2865 
2866                 case VDEV_AUX_SPARED:
2867                         verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
2868                             &cb.cb_guid) == 0);
2869                         if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
2870                                 if (strcmp(zpool_get_name(cb.cb_zhp),
2871                                     zpool_get_name(zhp)) == 0)
2872                                         (void) printf(gettext("currently in "
2873                                             "use"));
2874                                 else
2875                                         (void) printf(gettext("in use by "
2876                                             "pool '%s'"),
2877                                             zpool_get_name(cb.cb_zhp));
2878                                 zpool_close(cb.cb_zhp);
2879                         } else {
2880                                 (void) printf(gettext("currently in use"));
2881                         }
2882                         break;
2883 
2884                 case VDEV_AUX_ERR_EXCEEDED:
2885                         (void) printf(gettext("too many errors"));
2886                         break;
2887 
2888                 case VDEV_AUX_IO_FAILURE:
2889                         (void) printf(gettext("experienced I/O failures"));
2890                         break;
2891 
2892                 case VDEV_AUX_BAD_LOG:
2893                         (void) printf(gettext("bad intent log"));
2894                         break;
2895 
2896                 default:
2897                         (void) printf(gettext("corrupted data"));
2898                         break;
2899                 }
2900         } else if (vs->vs_scrub_repaired != 0 && children == 0) {
2901                 /*
2902                  * Report bytes resilvered/repaired on leaf devices.
2903                  */
2904                 zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired));
2905                 (void) printf(gettext("  %s %s"), repaired,
2906                     (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2907                     "resilvered" : "repaired");
2908         }
2909 
2910         (void) printf("\n");
2911 
2912         for (c = 0; c < children; c++) {
2913                 uint64_t is_log = B_FALSE;
2914 
2915                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2916                     &is_log);
2917                 if ((is_log && !print_logs) || (!is_log && print_logs))
2918                         continue;
2919                 vname = zpool_vdev_name(g_zfs, zhp, child[c]);
2920                 print_status_config(zhp, vname, child[c],
2921                     namewidth, depth + 2, isspare, B_FALSE);
2922                 free(vname);
2923         }
2924 }
2925 
2926 static void
2927 print_error_log(zpool_handle_t *zhp)
2928 {
2929         nvlist_t *nverrlist = NULL;
2930         nvpair_t *elem;
2931         char *pathname;
2932         size_t len = MAXPATHLEN * 2;
2933 
2934         if (zpool_get_errlog(zhp, &nverrlist) != 0) {
2935                 (void) printf("errors: List of errors unavailable "
2936                     "(insufficient privileges)\n");
2937                 return;
2938         }
2939 
2940         (void) printf("errors: Permanent errors have been "
2941             "detected in the following files:\n\n");
2942 
2943         pathname = safe_malloc(len);
2944         elem = NULL;
2945         while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
2946                 nvlist_t *nv;
2947                 uint64_t dsobj, obj;
2948 
2949                 verify(nvpair_value_nvlist(elem, &nv) == 0);
2950                 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
2951                     &dsobj) == 0);
2952                 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
2953                     &obj) == 0);
2954                 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
2955                 (void) printf("%7s %s\n", "", pathname);
2956         }
2957         free(pathname);
2958         nvlist_free(nverrlist);
2959 }
2960 
2961 static void
2962 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
2963     int namewidth)
2964 {
2965         uint_t i;
2966         char *name;
2967 
2968         if (nspares == 0)
2969                 return;
2970 
2971         (void) printf(gettext("\tspares\n"));
2972 
2973         for (i = 0; i < nspares; i++) {
2974                 name = zpool_vdev_name(g_zfs, zhp, spares[i]);
2975                 print_status_config(zhp, name, spares[i],
2976                     namewidth, 2, B_TRUE, B_FALSE);
2977                 free(name);
2978         }
2979 }
2980 
2981 static void
2982 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
2983     int namewidth)
2984 {
2985         uint_t i;
2986         char *name;
2987 
2988         if (nl2cache == 0)
2989                 return;
2990 
2991         (void) printf(gettext("\tcache\n"));
2992 
2993         for (i = 0; i < nl2cache; i++) {
2994                 name = zpool_vdev_name(g_zfs, zhp, l2cache[i]);
2995                 print_status_config(zhp, name, l2cache[i],
2996                     namewidth, 2, B_FALSE, B_FALSE);
2997                 free(name);
2998         }
2999 }
3000 
3001 /*
3002  * Display a summary of pool status.  Displays a summary such as:
3003  *
3004  *        pool: tank
3005  *      status: DEGRADED
3006  *      reason: One or more devices ...
3007  *         see: http://www.sun.com/msg/ZFS-xxxx-01
3008  *      config:
3009  *              mirror          DEGRADED
3010  *                c1t0d0        OK
3011  *                c2t0d0        UNAVAIL
3012  *
3013  * When given the '-v' option, we print out the complete config.  If the '-e'
3014  * option is specified, then we print out error rate information as well.
3015  */
3016 int
3017 status_callback(zpool_handle_t *zhp, void *data)
3018 {
3019         status_cbdata_t *cbp = data;
3020         nvlist_t *config, *nvroot;
3021         char *msgid;
3022         int reason;
3023         const char *health;
3024         uint_t c;
3025         vdev_stat_t *vs;
3026         char keystatus[MAXNAMELEN];
3027         zprop_source_t srctype;
3028 
3029         config = zpool_get_config(zhp, NULL);
3030         reason = zpool_get_status(zhp, &msgid);
3031 
3032         cbp->cb_count++;
3033 
3034         /*
3035          * If we were given 'zpool status -x', only report those pools with
3036          * problems.
3037          */
3038         if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) {
3039                 if (!cbp->cb_allpools) {
3040                         (void) printf(gettext("pool '%s' is healthy\n"),
3041                             zpool_get_name(zhp));
3042                         if (cbp->cb_first)
3043                                 cbp->cb_first = B_FALSE;
3044                 }
3045                 return (0);
3046         }
3047 
3048         if (cbp->cb_first)
3049                 cbp->cb_first = B_FALSE;
3050         else
3051                 (void) printf("\n");
3052 
3053         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3054             &nvroot) == 0);
3055         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
3056             (uint64_t **)&vs, &c) == 0);
3057         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
3058 
3059         (void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
3060         (void) printf(gettext(" state: %s\n"), health);
3061 
3062         (void) zpool_get_prop(zhp, ZPOOL_PROP_KEYSTATUS, keystatus,
3063             sizeof (keystatus), &srctype);
3064 
3065         (void) printf(gettext("   key: %s\n"), keystatus);
3066 
3067         switch (reason) {
3068         case ZPOOL_STATUS_MISSING_DEV_R:
3069                 (void) printf(gettext("status: One or more devices could not "
3070                     "be opened.  Sufficient replicas exist for\n\tthe pool to "
3071                     "continue functioning in a degraded state.\n"));
3072                 (void) printf(gettext("action: Attach the missing device and "
3073                     "online it using 'zpool online'.\n"));
3074                 break;
3075 
3076         case ZPOOL_STATUS_MISSING_DEV_NR:
3077                 (void) printf(gettext("status: One or more devices could not "
3078                     "be opened.  There are insufficient\n\treplicas for the "
3079                     "pool to continue functioning.\n"));
3080                 (void) printf(gettext("action: Attach the missing device and "
3081                     "online it using 'zpool online'.\n"));
3082                 break;
3083 
3084         case ZPOOL_STATUS_CORRUPT_LABEL_R:
3085                 (void) printf(gettext("status: One or more devices could not "
3086                     "be used because the label is missing or\n\tinvalid.  "
3087                     "Sufficient replicas exist for the pool to continue\n\t"
3088                     "functioning in a degraded state.\n"));
3089                 (void) printf(gettext("action: Replace the device using "
3090                     "'zpool replace'.\n"));
3091                 break;
3092 
3093         case ZPOOL_STATUS_CORRUPT_LABEL_NR:
3094                 (void) printf(gettext("status: One or more devices could not "
3095                     "be used because the label is missing \n\tor invalid.  "
3096                     "There are insufficient replicas for the pool to "
3097                     "continue\n\tfunctioning.\n"));
3098                 (void) printf(gettext("action: Destroy and re-create the pool "
3099                     "from a backup source.\n"));
3100                 break;
3101 
3102         case ZPOOL_STATUS_FAILING_DEV:
3103                 (void) printf(gettext("status: One or more devices has "
3104                     "experienced an unrecoverable error.  An\n\tattempt was "
3105                     "made to correct the error.  Applications are "
3106                     "unaffected.\n"));
3107                 (void) printf(gettext("action: Determine if the device needs "
3108                     "to be replaced, and clear the errors\n\tusing "
3109                     "'zpool clear' or replace the device with 'zpool "
3110                     "replace'.\n"));
3111                 break;
3112 
3113         case ZPOOL_STATUS_OFFLINE_DEV:
3114                 (void) printf(gettext("status: One or more devices has "
3115                     "been taken offline by the administrator.\n\tSufficient "
3116                     "replicas exist for the pool to continue functioning in "
3117                     "a\n\tdegraded state.\n"));
3118                 (void) printf(gettext("action: Online the device using "
3119                     "'zpool online' or replace the device with\n\t'zpool "
3120                     "replace'.\n"));
3121                 break;
3122 
3123         case ZPOOL_STATUS_RESILVERING:
3124                 (void) printf(gettext("status: One or more devices is "
3125                     "currently being resilvered.  The pool will\n\tcontinue "
3126                     "to function, possibly in a degraded state.\n"));
3127                 (void) printf(gettext("action: Wait for the resilver to "
3128                     "complete.\n"));
3129                 break;
3130 
3131         case ZPOOL_STATUS_CORRUPT_DATA:
3132                 (void) printf(gettext("status: One or more devices has "
3133                     "experienced an error resulting in data\n\tcorruption.  "
3134                     "Applications may be affected.\n"));
3135                 (void) printf(gettext("action: Restore the file in question "
3136                     "if possible.  Otherwise restore the\n\tentire pool from "
3137                     "backup.\n"));
3138                 break;
3139 
3140         case ZPOOL_STATUS_CORRUPT_POOL:
3141                 (void) printf(gettext("status: The pool metadata is corrupted "
3142                     "and the pool cannot be opened.\n"));
3143                 (void) printf(gettext("action: Destroy and re-create the pool "
3144                     "from a backup source.\n"));
3145                 break;
3146 
3147         case ZPOOL_STATUS_VERSION_OLDER:
3148                 (void) printf(gettext("status: The pool is formatted using an "
3149                     "older on-disk format.  The pool can\n\tstill be used, but "
3150                     "some features are unavailable.\n"));
3151                 (void) printf(gettext("action: Upgrade the pool using 'zpool "
3152                     "upgrade'.  Once this is done, the\n\tpool will no longer "
3153                     "be accessible on older software versions.\n"));
3154                 break;
3155 
3156         case ZPOOL_STATUS_VERSION_NEWER:
3157                 (void) printf(gettext("status: The pool has been upgraded to a "
3158                     "newer, incompatible on-disk version.\n\tThe pool cannot "
3159                     "be accessed on this system.\n"));
3160                 (void) printf(gettext("action: Access the pool from a system "
3161                     "running more recent software, or\n\trestore the pool from "
3162                     "backup.\n"));
3163                 break;
3164 
3165         case ZPOOL_STATUS_FAULTED_DEV_R:
3166                 (void) printf(gettext("status: One or more devices are "
3167                     "faulted in response to persistent errors.\n\tSufficient "
3168                     "replicas exist for the pool to continue functioning "
3169                     "in a\n\tdegraded state.\n"));
3170                 (void) printf(gettext("action: Replace the faulted device, "
3171                     "or use 'zpool clear' to mark the device\n\trepaired.\n"));
3172                 break;
3173 
3174         case ZPOOL_STATUS_FAULTED_DEV_NR:
3175                 (void) printf(gettext("status: One or more devices are "
3176                     "faulted in response to persistent errors.  There are "
3177                     "insufficient replicas for the pool to\n\tcontinue "
3178                     "functioning.\n"));
3179                 (void) printf(gettext("action: Destroy and re-create the pool "
3180                     "from a backup source.  Manually marking the device\n"
3181                     "\trepaired using 'zpool clear' may allow some data "
3182                     "to be recovered.\n"));
3183                 break;
3184 
3185         case ZPOOL_STATUS_IO_FAILURE_WAIT:
3186         case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
3187                 (void) printf(gettext("status: One or more devices are "
3188                     "faulted in response to IO failures.\n"));
3189                 (void) printf(gettext("action: Make sure the affected devices "
3190                     "are connected, then run 'zpool clear'.\n"));
3191                 break;
3192 
3193         case ZPOOL_STATUS_BAD_LOG:
3194                 (void) printf(gettext("status: An intent log record "
3195                     "could not be read.\n"
3196                     "\tWaiting for adminstrator intervention to fix the "
3197                     "faulted pool.\n"));
3198                 (void) printf(gettext("action: Either restore the affected "
3199                     "device(s) and run 'zpool online',\n"
3200                     "\tor ignore the intent log records by running "
3201                     "'zpool clear'.\n"));
3202                 break;
3203 
3204         default:
3205                 /*
3206                  * The remaining errors can't actually be generated, yet.
3207                  */
3208                 assert(reason == ZPOOL_STATUS_OK);
3209         }
3210 
3211         if (msgid != NULL)
3212                 (void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
3213                     msgid);
3214 
3215         if (config != NULL) {
3216                 int namewidth;
3217                 uint64_t nerr;
3218                 nvlist_t **spares, **l2cache;
3219                 uint_t nspares, nl2cache;
3220 
3221 
3222                 (void) printf(gettext(" scrub: "));
3223                 print_scrub_status(nvroot);
3224 
3225                 namewidth = max_width(zhp, nvroot, 0, 0);
3226                 if (namewidth < 10)
3227                         namewidth = 10;
3228 
3229                 (void) printf(gettext("config:\n\n"));
3230                 (void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
3231                     "NAME", "STATE", "READ", "WRITE", "CKSUM");
3232                 print_status_config(zhp, zpool_get_name(zhp), nvroot,
3233                     namewidth, 0, B_FALSE, B_FALSE);
3234                 if (num_logs(nvroot) > 0)
3235                         print_status_config(zhp, "logs", nvroot, namewidth, 0,
3236                             B_FALSE, B_TRUE);
3237 
3238                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
3239                     &l2cache, &nl2cache) == 0)
3240                         print_l2cache(zhp, l2cache, nl2cache, namewidth);
3241 
3242                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
3243                     &spares, &nspares) == 0)
3244                         print_spares(zhp, spares, nspares, namewidth);
3245 
3246                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
3247                     &nerr) == 0) {
3248                         nvlist_t *nverrlist = NULL;
3249 
3250                         /*
3251                          * If the approximate error count is small, get a
3252                          * precise count by fetching the entire log and
3253                          * uniquifying the results.
3254                          */
3255                         if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
3256                             zpool_get_errlog(zhp, &nverrlist) == 0) {
3257                                 nvpair_t *elem;
3258 
3259                                 elem = NULL;
3260                                 nerr = 0;
3261                                 while ((elem = nvlist_next_nvpair(nverrlist,
3262                                     elem)) != NULL) {
3263                                         nerr++;
3264                                 }
3265                         }
3266                         nvlist_free(nverrlist);
3267 
3268                         (void) printf("\n");
3269 
3270                         if (nerr == 0)
3271                                 (void) printf(gettext("errors: No known data "
3272                                     "errors\n"));
3273                         else if (!cbp->cb_verbose)
3274                                 (void) printf(gettext("errors: %llu data "
3275                                     "errors, use '-v' for a list\n"),
3276                                     (u_longlong_t)nerr);
3277                         else
3278                                 print_error_log(zhp);
3279                 }
3280         } else {
3281                 (void) printf(gettext("config: The configuration cannot be "
3282                     "determined.\n"));
3283         }
3284 
3285         return (0);
3286 }
3287 
3288 /*
3289  * zpool status [-vx] [pool] ...
3290  *
3291  *      -v      Display complete error logs
3292  *      -x      Display only pools with potential problems
3293  *
3294  * Describes the health status of all pools or some subset.
3295  */
3296 int
3297 zpool_do_status(int argc, char **argv)
3298 {
3299         int c;
3300         int ret;
3301         status_cbdata_t cb = { 0 };
3302 
3303         /* check options */
3304         while ((c = getopt(argc, argv, "vx")) != -1) {
3305                 switch (c) {
3306                 case 'v':
3307                         cb.cb_verbose = B_TRUE;
3308                         break;
3309                 case 'x':
3310                         cb.cb_explain = B_TRUE;
3311                         break;
3312                 case '?':
3313                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3314                             optopt);
3315                         usage(B_FALSE);
3316                 }
3317         }
3318 
3319         argc -= optind;
3320         argv += optind;
3321 
3322         cb.cb_first = B_TRUE;
3323 
3324         if (argc == 0)
3325                 cb.cb_allpools = B_TRUE;
3326 
3327         ret = for_each_pool(argc, argv, B_TRUE, NULL, status_callback, &cb);
3328 
3329         if (argc == 0 && cb.cb_count == 0)
3330                 (void) printf(gettext("no pools available\n"));
3331         else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
3332                 (void) printf(gettext("all pools are healthy\n"));
3333 
3334         return (ret);
3335 }
3336 
3337 typedef struct upgrade_cbdata {
3338         int     cb_all;
3339         int     cb_first;
3340         int     cb_newer;
3341         int     cb_argc;
3342         uint64_t cb_version;
3343         char    **cb_argv;
3344 } upgrade_cbdata_t;
3345 
3346 static int
3347 upgrade_cb(zpool_handle_t *zhp, void *arg)
3348 {
3349         upgrade_cbdata_t *cbp = arg;
3350         nvlist_t *config;
3351         uint64_t version;
3352         int ret = 0;
3353 
3354         config = zpool_get_config(zhp, NULL);
3355         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
3356             &version) == 0);
3357 
3358         if (!cbp->cb_newer && version < SPA_VERSION) {
3359                 if (!cbp->cb_all) {
3360                         if (cbp->cb_first) {
3361                                 (void) printf(gettext("The following pools are "
3362                                     "out of date, and can be upgraded.  After "
3363                                     "being\nupgraded, these pools will no "
3364                                     "longer be accessible by older software "
3365                                     "versions.\n\n"));
3366                                 (void) printf(gettext("VER  POOL\n"));
3367                                 (void) printf(gettext("---  ------------\n"));
3368                                 cbp->cb_first = B_FALSE;
3369                         }
3370 
3371                         (void) printf("%2llu   %s\n", (u_longlong_t)version,
3372                             zpool_get_name(zhp));
3373                 } else {
3374                         cbp->cb_first = B_FALSE;
3375                         ret = zpool_upgrade(zhp, cbp->cb_version);
3376                         if (!ret) {
3377                                 (void) printf(gettext("Successfully upgraded "
3378                                     "'%s'\n\n"), zpool_get_name(zhp));
3379                         }
3380                 }
3381         } else if (cbp->cb_newer && version > SPA_VERSION) {
3382                 assert(!cbp->cb_all);
3383 
3384                 if (cbp->cb_first) {
3385                         (void) printf(gettext("The following pools are "
3386                             "formatted using a newer software version and\n"
3387                             "cannot be accessed on the current system.\n\n"));
3388                         (void) printf(gettext("VER  POOL\n"));
3389                         (void) printf(gettext("---  ------------\n"));
3390                         cbp->cb_first = B_FALSE;
3391                 }
3392 
3393                 (void) printf("%2llu   %s\n", (u_longlong_t)version,
3394                     zpool_get_name(zhp));
3395         }
3396 
3397         zpool_close(zhp);
3398         return (ret);
3399 }
3400 
3401 /* ARGSUSED */
3402 static int
3403 upgrade_one(zpool_handle_t *zhp, void *data)
3404 {
3405         upgrade_cbdata_t *cbp = data;
3406         uint64_t cur_version;
3407         int ret;
3408 
3409         if (strcmp("log", zpool_get_name(zhp)) == 0) {
3410                 (void) printf(gettext("'log' is now a reserved word\n"
3411                     "Pool 'log' must be renamed using export and import"
3412                     " to upgrade.\n"));
3413                 return (1);
3414         }
3415 
3416         cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
3417         if (cur_version > cbp->cb_version) {
3418                 (void) printf(gettext("Pool '%s' is already formatted "
3419                     "using more current version '%llu'.\n"),
3420                     zpool_get_name(zhp), cur_version);
3421                 return (0);
3422         }
3423         if (cur_version == cbp->cb_version) {
3424                 (void) printf(gettext("Pool '%s' is already formatted "
3425                     "using the current version.\n"), zpool_get_name(zhp));
3426                 return (0);
3427         }
3428 
3429         ret = zpool_upgrade(zhp, cbp->cb_version);
3430 
3431         if (!ret) {
3432                 (void) printf(gettext("Successfully upgraded '%s' "
3433                     "from version %llu to version %llu\n\n"),
3434                     zpool_get_name(zhp), (u_longlong_t)cur_version,
3435                     (u_longlong_t)cbp->cb_version);
3436         }
3437 
3438         return (ret != 0);
3439 }
3440 
3441 /*
3442  * zpool upgrade
3443  * zpool upgrade -v
3444  * zpool upgrade [-V version] <-a | pool ...>
3445  *
3446  * With no arguments, display downrev'd ZFS pool available for upgrade.
3447  * Individual pools can be upgraded by specifying the pool, and '-a' will
3448  * upgrade all pools.
3449  */
3450 int
3451 zpool_do_upgrade(int argc, char **argv)
3452 {
3453         int c;
3454         upgrade_cbdata_t cb = { 0 };
3455         int ret = 0;
3456         boolean_t showversions = B_FALSE;
3457         char *end;
3458 
3459 
3460         /* check options */
3461         while ((c = getopt(argc, argv, "avV:")) != -1) {
3462                 switch (c) {
3463                 case 'a':
3464                         cb.cb_all = B_TRUE;
3465                         break;
3466                 case 'v':
3467                         showversions = B_TRUE;
3468                         break;
3469                 case 'V':
3470                         cb.cb_version = strtoll(optarg, &end, 10);
3471                         if (*end != '\0' || cb.cb_version > SPA_VERSION ||
3472                             cb.cb_version < SPA_VERSION_1) {
3473                                 (void) fprintf(stderr,
3474                                     gettext("invalid version '%s'\n"), optarg);
3475                                 usage(B_FALSE);
3476                         }
3477                         break;
3478                 case '?':
3479                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3480                             optopt);
3481                         usage(B_FALSE);
3482                 }
3483         }
3484 
3485         cb.cb_argc = argc;
3486         cb.cb_argv = argv;
3487         argc -= optind;
3488         argv += optind;
3489 
3490         if (cb.cb_version == 0) {
3491                 cb.cb_version = SPA_VERSION;
3492         } else if (!cb.cb_all && argc == 0) {
3493                 (void) fprintf(stderr, gettext("-V option is "
3494                     "incompatible with other arguments\n"));
3495                 usage(B_FALSE);
3496         }
3497 
3498         if (showversions) {
3499                 if (cb.cb_all || argc != 0) {
3500                         (void) fprintf(stderr, gettext("-v option is "
3501                             "incompatible with other arguments\n"));
3502                         usage(B_FALSE);
3503                 }
3504         } else if (cb.cb_all) {
3505                 if (argc != 0) {
3506                         (void) fprintf(stderr, gettext("-a option should not "
3507                             "be used along with a pool name\n"));
3508                         usage(B_FALSE);
3509                 }
3510         }
3511 
3512         (void) printf(gettext("This system is currently running "
3513             "ZFS pool version %llu.\n\n"), SPA_VERSION);
3514         cb.cb_first = B_TRUE;
3515         if (showversions) {
3516                 (void) printf(gettext("The following versions are "
3517                     "supported:\n\n"));
3518                 (void) printf(gettext("VER  DESCRIPTION\n"));
3519                 (void) printf("---  -----------------------------------------"
3520                     "---------------\n");
3521                 (void) printf(gettext(" 1   Initial ZFS version\n"));
3522                 (void) printf(gettext(" 2   Ditto blocks "
3523                     "(replicated metadata)\n"));
3524                 (void) printf(gettext(" 3   Hot spares and double parity "
3525                     "RAID-Z\n"));
3526                 (void) printf(gettext(" 4   zpool history\n"));
3527                 (void) printf(gettext(" 5   Compression using the gzip "
3528                     "algorithm\n"));
3529                 (void) printf(gettext(" 6   bootfs pool property\n"));
3530                 (void) printf(gettext(" 7   Separate intent log devices\n"));
3531                 (void) printf(gettext(" 8   Delegated administration\n"));
3532                 (void) printf(gettext(" 9   refquota and refreservation "
3533                     "properties\n"));
3534                 (void) printf(gettext(" 10  Cache devices\n"));
3535                 (void) printf(gettext(" 11  Improved scrub performance\n"));
3536                 (void) printf(gettext(" 12  Snapshot properties\n"));
3537                 (void) printf(gettext(" 13  snapused property\n"));
3538                 (void) printf(gettext(" 14  passthrough-x aclinherit "
3539                     "support\n"));
3540                 (void) printf(gettext(" 15  Cryptographic support.\n"));
3541                 (void) printf(gettext("For more information on a particular "
3542                     "version, including supported releases, see:\n\n"));
3543                 (void) printf("http://www.opensolaris.org/os/community/zfs/"
3544                     "version/N\n\n");
3545                 (void) printf(gettext("Where 'N' is the version number.\n"));
3546         } else if (argc == 0) {
3547                 int notfound;
3548 
3549                 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3550                 notfound = cb.cb_first;
3551 
3552                 if (!cb.cb_all && ret == 0) {
3553                         if (!cb.cb_first)
3554                                 (void) printf("\n");
3555                         cb.cb_first = B_TRUE;
3556                         cb.cb_newer = B_TRUE;
3557                         ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3558                         if (!cb.cb_first) {
3559                                 notfound = B_FALSE;
3560                                 (void) printf("\n");
3561                         }
3562                 }
3563 
3564                 if (ret == 0) {
3565                         if (notfound)
3566                                 (void) printf(gettext("All pools are formatted "
3567                                     "using this version.\n"));
3568                         else if (!cb.cb_all)
3569                                 (void) printf(gettext("Use 'zpool upgrade -v' "
3570                                     "for a list of available versions and "
3571                                     "their associated\nfeatures.\n"));
3572                 }
3573         } else {
3574                 ret = for_each_pool(argc, argv, B_FALSE, NULL,
3575                     upgrade_one, &cb);
3576         }
3577 
3578         return (ret);
3579 }
3580 
3581 typedef struct hist_cbdata {
3582         boolean_t first;
3583         int longfmt;
3584         int internal;
3585 } hist_cbdata_t;
3586 
3587 char *hist_event_table[LOG_END] = {
3588         "invalid event",
3589         "pool create",
3590         "vdev add",
3591         "pool remove",
3592         "pool destroy",
3593         "pool export",
3594         "pool import",
3595         "vdev attach",
3596         "vdev replace",
3597         "vdev detach",
3598         "vdev online",
3599         "vdev offline",
3600         "vdev upgrade",
3601         "pool clear",
3602         "pool scrub",
3603         "pool property set",
3604         "create",
3605         "clone",
3606         "destroy",
3607         "destroy_begin_sync",
3608         "inherit",
3609         "property set",
3610         "quota set",
3611         "permission update",
3612         "permission remove",
3613         "permission who remove",
3614         "promote",
3615         "receive",
3616         "rename",
3617         "reservation set",
3618         "replay_inc_sync",
3619         "replay_full_sync",
3620         "rollback",
3621         "snapshot",
3622         "filesystem version upgrade",
3623         "refquota set",
3624         "refreservation set",
3625         "pool scrub done",
3626         "crypto key create",
3627 };
3628 
3629 /*
3630  * Print out the command history for a specific pool.
3631  */
3632 static int
3633 get_history_one(zpool_handle_t *zhp, void *data)
3634 {
3635         nvlist_t *nvhis;
3636         nvlist_t **records;
3637         uint_t numrecords;
3638         char *cmdstr;
3639         char *pathstr;
3640         uint64_t dst_time;
3641         time_t tsec;
3642         struct tm t;
3643         char tbuf[30];
3644         int ret, i;
3645         uint64_t who;
3646         struct passwd *pwd;
3647         char *hostname;
3648         char *zonename;
3649         char internalstr[MAXPATHLEN];
3650         hist_cbdata_t *cb = (hist_cbdata_t *)data;
3651         uint64_t txg;
3652         uint64_t ievent;
3653 
3654         cb->first = B_FALSE;
3655 
3656         (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
3657 
3658         if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
3659                 return (ret);
3660 
3661         verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
3662             &records, &numrecords) == 0);
3663         for (i = 0; i < numrecords; i++) {
3664                 if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME,
3665                     &dst_time) != 0)
3666                         continue;
3667 
3668                 /* is it an internal event or a standard event? */
3669                 if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD,
3670                     &cmdstr) != 0) {
3671                         if (cb->internal == 0)
3672                                 continue;
3673 
3674                         if (nvlist_lookup_uint64(records[i],
3675                             ZPOOL_HIST_INT_EVENT, &ievent) != 0)
3676                                 continue;
3677                         verify(nvlist_lookup_uint64(records[i],
3678                             ZPOOL_HIST_TXG, &txg) == 0);
3679                         verify(nvlist_lookup_string(records[i],
3680                             ZPOOL_HIST_INT_STR, &pathstr) == 0);
3681                         if (ievent >= LOG_END)
3682                                 continue;
3683                         (void) snprintf(internalstr,
3684                             sizeof (internalstr),
3685                             "[internal %s txg:%lld] %s",
3686                             hist_event_table[ievent], txg,
3687                             pathstr);
3688                         cmdstr = internalstr;
3689                 }
3690                 tsec = dst_time;
3691                 (void) localtime_r(&tsec, &t);
3692                 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
3693                 (void) printf("%s %s", tbuf, cmdstr);
3694 
3695                 if (!cb->longfmt) {
3696                         (void) printf("\n");
3697                         continue;
3698                 }
3699                 (void) printf(" [");
3700                 if (nvlist_lookup_uint64(records[i],
3701                     ZPOOL_HIST_WHO, &who) == 0) {
3702                         pwd = getpwuid((uid_t)who);
3703                         if (pwd)
3704                                 (void) printf("user %s on",
3705                                     pwd->pw_name);
3706                         else
3707                                 (void) printf("user %d on",
3708                                     (int)who);
3709                 } else {
3710                         (void) printf(gettext("no info]\n"));
3711                         continue;
3712                 }
3713                 if (nvlist_lookup_string(records[i],
3714                     ZPOOL_HIST_HOST, &hostname) == 0) {
3715                         (void) printf(" %s", hostname);
3716                 }
3717                 if (nvlist_lookup_string(records[i],
3718                     ZPOOL_HIST_ZONE, &zonename) == 0) {
3719                         (void) printf(":%s", zonename);
3720                 }
3721 
3722                 (void) printf("]");
3723                 (void) printf("\n");
3724         }
3725         (void) printf("\n");
3726         nvlist_free(nvhis);
3727 
3728         return (ret);
3729 }
3730 
3731 /*
3732  * zpool history <pool>
3733  *
3734  * Displays the history of commands that modified pools.
3735  */
3736 
3737 
3738 int
3739 zpool_do_history(int argc, char **argv)
3740 {
3741         hist_cbdata_t cbdata = { 0 };
3742         int ret;
3743         int c;
3744 
3745         cbdata.first = B_TRUE;
3746         /* check options */
3747         while ((c = getopt(argc, argv, "li")) != -1) {
3748                 switch (c) {
3749                 case 'l':
3750                         cbdata.longfmt = 1;
3751                         break;
3752                 case 'i':
3753                         cbdata.internal = 1;
3754                         break;
3755                 case '?':
3756                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3757                             optopt);
3758                         usage(B_FALSE);
3759                 }
3760         }
3761         argc -= optind;
3762         argv += optind;
3763 
3764         ret = for_each_pool(argc, argv, B_FALSE,  NULL, get_history_one,
3765             &cbdata);
3766 
3767         if (argc == 0 && cbdata.first == B_TRUE) {
3768                 (void) printf(gettext("no pools available\n"));
3769                 return (0);
3770         }
3771 
3772         return (ret);
3773 }
3774 
3775 static int
3776 get_callback(zpool_handle_t *zhp, void *data)
3777 {
3778         zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
3779         char value[MAXNAMELEN];
3780         zprop_source_t srctype;
3781         zprop_list_t *pl;
3782 
3783         for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
3784 
3785                 /*
3786                  * Skip the special fake placeholder. This will also skip
3787                  * over the name property when 'all' is specified.
3788                  */
3789                 if (pl->pl_prop == ZPOOL_PROP_NAME &&
3790                     pl == cbp->cb_proplist)
3791                         continue;
3792 
3793                 if (zpool_get_prop(zhp, pl->pl_prop,
3794                     value, sizeof (value), &srctype) != 0)
3795                         continue;
3796 
3797                 zprop_print_one_property(zpool_get_name(zhp), cbp,
3798                     zpool_prop_to_name(pl->pl_prop), value, srctype, NULL);
3799         }
3800         return (0);
3801 }
3802 
3803 int
3804 zpool_do_get(int argc, char **argv)
3805 {
3806         zprop_get_cbdata_t cb = { 0 };
3807         zprop_list_t fake_name = { 0 };
3808         int ret;
3809 
3810         if (argc < 3)
3811                 usage(B_FALSE);
3812 
3813         cb.cb_first = B_TRUE;
3814         cb.cb_sources = ZPROP_SRC_ALL;
3815         cb.cb_columns[0] = GET_COL_NAME;
3816         cb.cb_columns[1] = GET_COL_PROPERTY;
3817         cb.cb_columns[2] = GET_COL_VALUE;
3818         cb.cb_columns[3] = GET_COL_SOURCE;
3819         cb.cb_type = ZFS_TYPE_POOL;
3820 
3821         if (zprop_get_list(g_zfs, argv[1],  &cb.cb_proplist,
3822             ZFS_TYPE_POOL) != 0)
3823                 usage(B_FALSE);
3824 
3825         if (cb.cb_proplist != NULL) {
3826                 fake_name.pl_prop = ZPOOL_PROP_NAME;
3827                 fake_name.pl_width = strlen(gettext("NAME"));
3828                 fake_name.pl_next = cb.cb_proplist;
3829                 cb.cb_proplist = &fake_name;
3830         }
3831 
3832         ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist,
3833             get_callback, &cb);
3834 
3835         if (cb.cb_proplist == &fake_name)
3836                 zprop_free_list(fake_name.pl_next);
3837         else
3838                 zprop_free_list(cb.cb_proplist);
3839 
3840         return (ret);
3841 }
3842 
3843 typedef struct set_cbdata {
3844         char *cb_propname;
3845         char *cb_value;
3846         boolean_t cb_any_successful;
3847 } set_cbdata_t;
3848 
3849 int
3850 set_callback(zpool_handle_t *zhp, void *data)
3851 {
3852         int error;
3853         set_cbdata_t *cb = (set_cbdata_t *)data;
3854 
3855         error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);

3856         if (!error)
3857                 cb->cb_any_successful = B_TRUE;
3858 
3859         return (error);
3860 }
3861 
3862 int
3863 zpool_do_set(int argc, char **argv)
3864 {
3865         set_cbdata_t cb = { 0 };
3866         int error;
3867 
3868         if (argc > 1 && argv[1][0] == '-') {
3869                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3870                     argv[1][1]);
3871                 usage(B_FALSE);
3872         }
3873 
3874         if (argc < 2) {
3875                 (void) fprintf(stderr, gettext("missing property=value "
3876                     "argument\n"));
3877                 usage(B_FALSE);
3878         }
3879 
3880         if (argc < 3) {
3881                 (void) fprintf(stderr, gettext("missing pool name\n"));
3882                 usage(B_FALSE);
3883         }
3884 
3885         if (argc > 3) {
3886                 (void) fprintf(stderr, gettext("too many pool names\n"));
3887                 usage(B_FALSE);
3888         }
3889 
3890         cb.cb_propname = argv[1];
3891         cb.cb_value = strchr(cb.cb_propname, '=');
3892         if (cb.cb_value == NULL) {
3893                 (void) fprintf(stderr, gettext("missing value in "
3894                     "property=value argument\n"));
3895                 usage(B_FALSE);
3896         }
3897 
3898         *(cb.cb_value) = '\0';
3899         cb.cb_value++;
3900 
3901         error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
3902             set_callback, &cb);
3903 
3904         return (error);
3905 }
3906 
3907 
3908 static int
3909 /* LINTED E_FUNC_ARG_UNUSED */
3910 key_callback_load(zpool_handle_t *zhp, void *data)
3911 {
3912         int ret;
3913         if (zpool_keysource_prompt(zhp)) {
3914                 char *smf_fmri = getenv("SMF_FMRI");
3915 
3916                 if (smf_fmri != NULL &&
3917                     strcmp(smf_fmri, "svc:/system/device/local") == 0) {
3918                         return (0);
3919                 }
3920         }
3921         ret = zpool_cmd_key_load(zhp);
3922         if (ret != 0 && !(ret == EEXIST || ret == ENOTSUP)) {
3923                 return (1);
3924         }
3925 
3926         return (0);
3927 }
3928 
3929 static int
3930 /* LINTED E_FUNC_ARG_UNUSED */
3931 key_callback_unload(zpool_handle_t *zhp, void *data)
3932 {
3933         int ret;
3934 
3935         ret = zpool_cmd_key_unload(zhp);
3936         if (ret != 0 && !(ret == ENOENT || ret == ENOTSUP)) {
3937                 return (1);
3938         }
3939 
3940         return (0);
3941 }
3942 
3943 
3944 static int
3945 zpool_do_key(int argc, char **argv)
3946 {
3947         int error = 1, options = 0;
3948         nvlist_t *props = NULL;
3949         char c, *propval = NULL;
3950         boolean_t load = B_FALSE, unload = B_FALSE, change = B_FALSE;
3951         boolean_t do_all = B_FALSE;
3952         zpool_handle_t *zhp = NULL;
3953 
3954         while ((c = getopt(argc, argv, "aluco:")) != -1) {
3955                 switch (c) {
3956                 case 'a':
3957                         do_all = B_TRUE;
3958                         break;
3959 
3960                 case 'l':
3961                         load = B_TRUE;
3962                         break;
3963 
3964                 case 'u':
3965                         unload = B_TRUE;
3966                         break;
3967 
3968                 case 'c':
3969                         change = B_TRUE;
3970                         break;
3971 
3972                 case 'o':
3973                         if ((propval = strchr(optarg, '=')) == NULL) {
3974                                 (void) fprintf(stderr, gettext("missing "
3975                                     "'=' for -o option\n"));
3976                                 return (error);
3977                         }
3978 
3979                         *propval = '\0';
3980                         propval++;
3981                         if (strcmp(optarg, "keysource") != 0) {
3982                                 (void) fprintf(stderr, gettext(
3983                                     "Invalid property for key change: "
3984                                     "\"%s\"\n"),
3985                                     optarg);
3986                                 return (error);
3987                         }
3988                         if (add_prop_list(optarg, propval, &props, B_TRUE))
3989                                 return (error);
3990 
3991                         options += 2;
3992                         break;
3993 
3994                 }
3995         }
3996 
3997         if (!change && props != NULL) {
3998                 (void) fprintf(stderr, gettext("Properties are not allowed to "
3999                     "be used in this command.\n"));
4000                 goto error;
4001         }
4002 
4003         if (((load || unload) && (argc > 3)) ||
4004             (change && ((argc - options) > 3))) {
4005                         (void) fprintf(stderr,
4006                             gettext("too many arguments\n"));
4007                         usage(B_FALSE);
4008                         goto error;
4009         } else if ((load || unload) && (argc < 3)) {
4010                         (void) fprintf(stderr, gettext("missing dataset "
4011                             "argument (specify -a for all)\n"));
4012                         usage(B_FALSE);
4013                         goto error;
4014         } else if (change && ((argc - options) < 3)) {
4015                         (void) fprintf(stderr, gettext("missing dataset "
4016                             "argument\n"));
4017                         usage(B_FALSE);
4018                         goto error;
4019         }
4020 
4021         if (do_all == B_FALSE) {
4022                 zhp = zpool_open(g_zfs, argv[argc - 1]);
4023                 if (zhp == NULL)
4024                         goto error;
4025         }
4026 
4027         if (load) {
4028                 if (do_all)
4029                         error = for_each_pool(0, NULL, B_TRUE, NULL,
4030                             key_callback_load, NULL);
4031                 else
4032                         error = zpool_cmd_key_load(zhp);
4033 
4034         } else if (unload) {
4035                 if (do_all)
4036                         error = for_each_pool(0, NULL, B_TRUE, NULL,
4037                             key_callback_unload, NULL);
4038                 else
4039                         error = zpool_cmd_key_unload(zhp);
4040 
4041         } else if (change) {
4042                 if (do_all) {
4043                         (void) fprintf(stderr, gettext("cannot use '-a' with "
4044                             "change operation.\n"));
4045                         usage(B_FALSE);
4046                         goto error;
4047                 }
4048 
4049                 error = zpool_cmd_key_change(zhp, props);
4050 
4051         } else
4052                 usage(B_FALSE);
4053 
4054         if (zhp != NULL && !do_all)
4055                 zpool_close(zhp);
4056 
4057 error:
4058         nvlist_free(props);
4059         if (error != 0)
4060                 return (1);
4061         return (0);
4062 }
4063 
4064 static int
4065 find_command_idx(char *command, int *idx)
4066 {
4067         int i;
4068 
4069         for (i = 0; i < NCOMMAND; i++) {
4070                 if (command_table[i].name == NULL)
4071                         continue;
4072 
4073                 if (strcmp(command, command_table[i].name) == 0) {
4074                         *idx = i;
4075                         return (0);
4076                 }
4077         }
4078         return (1);
4079 }
4080 
4081 int
4082 main(int argc, char **argv)
4083 {
4084         int ret;
4085         int i;
4086         char *cmdname;
4087 
4088         (void) setlocale(LC_ALL, "");
4089         (void) textdomain(TEXT_DOMAIN);
4090 
4091         if ((g_zfs = libzfs_init()) == NULL) {
4092                 (void) fprintf(stderr, gettext("internal error: failed to "
4093                     "initialize ZFS library\n"));
4094                 return (1);
4095         }
4096 
4097         libzfs_print_on_error(g_zfs, B_TRUE);
4098 
4099         opterr = 0;
4100 
4101         /*
4102          * Make sure the user has specified some command.
4103          */
4104         if (argc < 2) {
4105                 (void) fprintf(stderr, gettext("missing command\n"));
4106                 usage(B_FALSE);
4107         }
4108 
4109         cmdname = argv[1];
4110 
4111         /*
4112          * Special case '-?'
4113          */
4114         if (strcmp(cmdname, "-?") == 0)
4115                 usage(B_TRUE);
4116 
4117         zpool_set_history_str("zpool", argc, argv, history_str);
4118         verify(zpool_stage_history(g_zfs, history_str) == 0);
4119 
4120         /*
4121          * Run the appropriate command.
4122          */
4123         if (find_command_idx(cmdname, &i) == 0) {
4124                 current_command = &command_table[i];
4125                 ret = command_table[i].func(argc - 1, argv + 1);
4126         } else if (strchr(cmdname, '=')) {
4127                 verify(find_command_idx("set", &i) == 0);
4128                 current_command = &command_table[i];
4129                 ret = command_table[i].func(argc, argv);
4130         } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
4131                 /*
4132                  * 'freeze' is a vile debugging abomination, so we treat
4133                  * it as such.
4134                  */
4135                 char buf[16384];
4136                 int fd = open(ZFS_DEV, O_RDWR);
4137                 (void) strcpy((void *)buf, argv[2]);
4138                 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
4139         } else {
4140                 (void) fprintf(stderr, gettext("unrecognized "
4141                     "command '%s'\n"), cmdname);
4142                 usage(B_FALSE);
4143         }
4144 
4145         libzfs_fini(g_zfs);
4146 
4147         /*
4148          * The 'ZFS_ABORT' environment variable causes us to dump core on exit
4149          * for the purposes of running ::findleaks.
4150          */
4151         if (getenv("ZFS_ABORT") != NULL) {
4152                 (void) printf("dumping core by request\n");
4153                 abort();
4154         }
4155 
4156         return (ret);
4157 }
--- EOF ---