4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
  25  * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
  26  * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
  27  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
  28  * Copyright 2016 Nexenta Systems, Inc.
  29  * Copyright (c) 2017 Datto Inc.
  30  */
  31 
  32 #include <assert.h>
  33 #include <ctype.h>
  34 #include <dirent.h>
  35 #include <errno.h>
  36 #include <fcntl.h>
  37 #include <libgen.h>
  38 #include <libintl.h>
  39 #include <libuutil.h>
  40 #include <locale.h>
  41 #include <stdio.h>
  42 #include <stdlib.h>
  43 #include <string.h>
  44 #include <strings.h>
  45 #include <unistd.h>
  46 #include <priv.h>
  47 #include <pwd.h>
  48 #include <zone.h>
  49 #include <zfs_prop.h>
  50 #include <sys/fs/zfs.h>
  51 #include <sys/stat.h>
  52 
  53 #include <libzfs.h>
  54 
  55 #include "zpool_util.h"
  56 #include "zfs_comutil.h"
  57 #include "zfeature_common.h"
  58 
  59 #include "statcommon.h"
  60 
  61 static int zpool_do_create(int, char **);
  62 static int zpool_do_destroy(int, char **);
  63 
  64 static int zpool_do_add(int, char **);
  65 static int zpool_do_remove(int, char **);
  66 static int zpool_do_labelclear(int, char **);
  67 
  68 static int zpool_do_list(int, char **);
  69 static int zpool_do_iostat(int, char **);
  70 static int zpool_do_status(int, char **);
  71 
  72 static int zpool_do_online(int, char **);
  73 static int zpool_do_offline(int, char **);
  74 static int zpool_do_clear(int, char **);
  75 static int zpool_do_reopen(int, char **);
  76 
  77 static int zpool_do_reguid(int, char **);
  78 
  79 static int zpool_do_attach(int, char **);
  80 static int zpool_do_detach(int, char **);
  81 static int zpool_do_replace(int, char **);
  82 static int zpool_do_split(int, char **);
  83 
  84 static int zpool_do_scrub(int, char **);
  85 
  86 static int zpool_do_import(int, char **);
  87 static int zpool_do_export(int, char **);
  88 
  89 static int zpool_do_upgrade(int, char **);
  90 
  91 static int zpool_do_history(int, char **);
  92 
  93 static int zpool_do_get(int, char **);
  94 static int zpool_do_set(int, char **);
  95 
  96 /*
  97  * These libumem hooks provide a reasonable set of defaults for the allocator's
  98  * debugging facilities.
  99  */
 100 
 101 #ifdef DEBUG
 102 const char *
 103 _umem_debug_init(void)
 104 {
 105         return ("default,verbose"); /* $UMEM_DEBUG setting */
 106 }
 107 
 108 const char *
 109 _umem_logging_init(void)
 110 {
 111         return ("fail,contents"); /* $UMEM_LOGGING setting */
 112 }
 113 #endif
 114 
 115 typedef enum {
 116         HELP_ADD,
 117         HELP_ATTACH,
 118         HELP_CLEAR,
 119         HELP_CREATE,
 120         HELP_DESTROY,
 121         HELP_DETACH,
 122         HELP_EXPORT,
 123         HELP_HISTORY,
 124         HELP_IMPORT,
 125         HELP_IOSTAT,
 126         HELP_LABELCLEAR,
 127         HELP_LIST,
 128         HELP_OFFLINE,
 129         HELP_ONLINE,
 130         HELP_REPLACE,
 131         HELP_REMOVE,
 132         HELP_SCRUB,
 133         HELP_STATUS,
 134         HELP_UPGRADE,
 135         HELP_GET,
 136         HELP_SET,
 137         HELP_SPLIT,
 138         HELP_REGUID,
 139         HELP_REOPEN
 140 } zpool_help_t;
 141 
 142 
 143 typedef struct zpool_command {
 144         const char      *name;
 145         int             (*func)(int, char **);
 146         zpool_help_t    usage;
 147 } zpool_command_t;
 148 
 149 /*
 150  * Master command table.  Each ZFS command has a name, associated function, and
 151  * usage message.  The usage messages need to be internationalized, so we have
 152  * to have a function to return the usage message based on a command index.
 153  *
 154  * These commands are organized according to how they are displayed in the usage
 155  * message.  An empty command (one with a NULL name) indicates an empty line in
 156  * the generic usage message.
 157  */
 158 static zpool_command_t command_table[] = {
 159         { "create",     zpool_do_create,        HELP_CREATE             },
 
 163         { "remove",     zpool_do_remove,        HELP_REMOVE             },
 164         { NULL },
 165         { "labelclear", zpool_do_labelclear,    HELP_LABELCLEAR         },
 166         { NULL },
 167         { "list",       zpool_do_list,          HELP_LIST               },
 168         { "iostat",     zpool_do_iostat,        HELP_IOSTAT             },
 169         { "status",     zpool_do_status,        HELP_STATUS             },
 170         { NULL },
 171         { "online",     zpool_do_online,        HELP_ONLINE             },
 172         { "offline",    zpool_do_offline,       HELP_OFFLINE            },
 173         { "clear",      zpool_do_clear,         HELP_CLEAR              },
 174         { "reopen",     zpool_do_reopen,        HELP_REOPEN             },
 175         { NULL },
 176         { "attach",     zpool_do_attach,        HELP_ATTACH             },
 177         { "detach",     zpool_do_detach,        HELP_DETACH             },
 178         { "replace",    zpool_do_replace,       HELP_REPLACE            },
 179         { "split",      zpool_do_split,         HELP_SPLIT              },
 180         { NULL },
 181         { "scrub",      zpool_do_scrub,         HELP_SCRUB              },
 182         { NULL },
 183         { "import",     zpool_do_import,        HELP_IMPORT             },
 184         { "export",     zpool_do_export,        HELP_EXPORT             },
 185         { "upgrade",    zpool_do_upgrade,       HELP_UPGRADE            },
 186         { "reguid",     zpool_do_reguid,        HELP_REGUID             },
 187         { NULL },
 188         { "history",    zpool_do_history,       HELP_HISTORY            },
 189         { "get",        zpool_do_get,           HELP_GET                },
 190         { "set",        zpool_do_set,           HELP_SET                },
 191 };
 192 
 193 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 194 
 195 static zpool_command_t *current_command;
 196 static char history_str[HIS_MAX_RECORD_LEN];
 197 static boolean_t log_history = B_TRUE;
 198 static uint_t timestamp_fmt = NODATE;
 199 
 200 static const char *
 201 get_usage(zpool_help_t idx)
 202 {
 203         switch (idx) {
 204         case HELP_ADD:
 205                 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
 206         case HELP_ATTACH:
 207                 return (gettext("\tattach [-f] <pool> <device> "
 208                     "<new-device>\n"));
 209         case HELP_CLEAR:
 210                 return (gettext("\tclear [-nF] <pool> [device]\n"));
 211         case HELP_CREATE:
 212                 return (gettext("\tcreate [-fnd] [-B] "
 213                     "[-o property=value] ... \n"
 214                     "\t    [-O file-system-property=value] ... \n"
 215                     "\t    [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
 216         case HELP_DESTROY:
 217                 return (gettext("\tdestroy [-f] <pool>\n"));
 218         case HELP_DETACH:
 219                 return (gettext("\tdetach <pool> <device>\n"));
 220         case HELP_EXPORT:
 221                 return (gettext("\texport [-f] <pool> ...\n"));
 222         case HELP_HISTORY:
 223                 return (gettext("\thistory [-il] [<pool>] ...\n"));
 224         case HELP_IMPORT:
 225                 return (gettext("\timport [-d dir] [-D]\n"
 226                     "\timport [-d dir | -c cachefile] [-F [-n]] <pool | id>\n"
 227                     "\timport [-o mntopts] [-o property=value] ... \n"
 228                     "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
 229                     "[-R root] [-F [-n]] -a\n"
 230                     "\timport [-o mntopts] [-o property=value] ... \n"
 231                     "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
 232                     "[-R root] [-F [-n]]\n"
 233                     "\t    <pool | id> [newpool]\n"));
 234         case HELP_IOSTAT:
 235                 return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
 236                     "[count]]\n"));
 237         case HELP_LABELCLEAR:
 238                 return (gettext("\tlabelclear [-f] <vdev>\n"));
 239         case HELP_LIST:
 240                 return (gettext("\tlist [-Hp] [-o property[,...]] "
 241                     "[-T d|u] [pool] ... [interval [count]]\n"));
 242         case HELP_OFFLINE:
 243                 return (gettext("\toffline [-t] <pool> <device> ...\n"));
 244         case HELP_ONLINE:
 245                 return (gettext("\tonline <pool> <device> ...\n"));
 246         case HELP_REPLACE:
 247                 return (gettext("\treplace [-f] <pool> <device> "
 248                     "[new-device]\n"));
 249         case HELP_REMOVE:
 250                 return (gettext("\tremove [-nps] <pool> <device> ...\n"));
 251         case HELP_REOPEN:
 252                 return (gettext("\treopen <pool>\n"));
 253         case HELP_SCRUB:
 254                 return (gettext("\tscrub [-s | -p] <pool> ...\n"));
 255         case HELP_STATUS:
 256                 return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
 257                     "[count]]\n"));
 258         case HELP_UPGRADE:
 259                 return (gettext("\tupgrade\n"
 260                     "\tupgrade -v\n"
 261                     "\tupgrade [-V version] <-a | pool ...>\n"));
 262         case HELP_GET:
 263                 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
 264                     "<\"all\" | property[,...]> <pool> ...\n"));
 265         case HELP_SET:
 266                 return (gettext("\tset <property=value> <pool> \n"));
 267         case HELP_SPLIT:
 268                 return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
 269                     "\t    [-o property=value] <pool> <newpool> "
 270                     "[<device> ...]\n"));
 271         case HELP_REGUID:
 272                 return (gettext("\treguid <pool>\n"));
 273         }
 274 
 275         abort();
 276         /* NOTREACHED */
 277 }
 278 
 279 
 280 /*
 281  * Callback routine that will print out a pool property value.
 282  */
 283 static int
 284 print_prop_cb(int prop, void *cb)
 285 {
 286         FILE *fp = cb;
 287 
 288         (void) fprintf(fp, "\t%-15s  ", zpool_prop_to_name(prop));
 289 
 290         if (zpool_prop_readonly(prop))
 291                 (void) fprintf(fp, "  NO   ");
 292         else
 293                 (void) fprintf(fp, " YES   ");
 294 
 295         if (zpool_prop_values(prop) == NULL)
 296                 (void) fprintf(fp, "-\n");
 297         else
 298                 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
 299 
 
 394 
 395 static boolean_t
 396 prop_list_contains_feature(nvlist_t *proplist)
 397 {
 398         nvpair_t *nvp;
 399         for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
 400             nvp = nvlist_next_nvpair(proplist, nvp)) {
 401                 if (zpool_prop_feature(nvpair_name(nvp)))
 402                         return (B_TRUE);
 403         }
 404         return (B_FALSE);
 405 }
 406 
 407 /*
 408  * Add a property pair (name, string-value) into a property nvlist.
 409  */
 410 static int
 411 add_prop_list(const char *propname, char *propval, nvlist_t **props,
 412     boolean_t poolprop)
 413 {
 414         zpool_prop_t prop = ZPOOL_PROP_INVAL;
 415         zfs_prop_t fprop;
 416         nvlist_t *proplist;
 417         const char *normnm;
 418         char *strval;
 419 
 420         if (*props == NULL &&
 421             nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
 422                 (void) fprintf(stderr,
 423                     gettext("internal error: out of memory\n"));
 424                 return (1);
 425         }
 426 
 427         proplist = *props;
 428 
 429         if (poolprop) {
 430                 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
 431 
 432                 if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL &&
 433                     !zpool_prop_feature(propname)) {
 434                         (void) fprintf(stderr, gettext("property '%s' is "
 435                             "not a valid pool property\n"), propname);
 436                         return (2);
 437                 }
 438 
 439                 /*
 440                  * feature@ properties and version should not be specified
 441                  * at the same time.
 442                  */
 443                 if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
 444                     nvlist_exists(proplist, vname)) ||
 445                     (prop == ZPOOL_PROP_VERSION &&
 446                     prop_list_contains_feature(proplist))) {
 447                         (void) fprintf(stderr, gettext("'feature@' and "
 448                             "'version' properties cannot be specified "
 449                             "together\n"));
 450                         return (2);
 451                 }
 452 
 453 
 454                 if (zpool_prop_feature(propname))
 455                         normnm = propname;
 456                 else
 457                         normnm = zpool_prop_to_name(prop);
 458         } else {
 459                 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
 460                         normnm = zfs_prop_to_name(fprop);
 461                 } else {
 462                         normnm = propname;
 463                 }
 464         }
 465 
 466         if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
 467             prop != ZPOOL_PROP_CACHEFILE) {
 468                 (void) fprintf(stderr, gettext("property '%s' "
 469                     "specified multiple times\n"), propname);
 470                 return (2);
 471         }
 472 
 473         if (nvlist_add_string(proplist, normnm, propval) != 0) {
 474                 (void) fprintf(stderr, gettext("internal "
 475                     "error: out of memory\n"));
 476                 return (1);
 477         }
 478 
 479         return (0);
 480 }
 481 
 482 /*
 483  * zpool add [-fn] <pool> <vdev> ...
 484  *
 485  *      -f      Force addition of devices, even if they appear in use
 486  *      -n      Do not add the devices, but display the resulting layout if
 487  *              they were to be added.
 488  *
 489  * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
 490  * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
 491  * libzfs.
 492  */
 493 int
 494 zpool_do_add(int argc, char **argv)
 495 {
 496         boolean_t force = B_FALSE;
 497         boolean_t dryrun = B_FALSE;
 498         int c;
 499         nvlist_t *nvroot;
 500         char *poolname;
 501         zpool_boot_label_t boot_type;
 502         uint64_t boot_size;
 
 580                         print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
 581                         print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
 582                 } else if (num_logs(nvroot) > 0) {
 583                         print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
 584                 }
 585 
 586                 ret = 0;
 587         } else {
 588                 ret = (zpool_add(zhp, nvroot) != 0);
 589         }
 590 
 591         nvlist_free(nvroot);
 592         zpool_close(zhp);
 593 
 594         return (ret);
 595 }
 596 
 597 /*
 598  * zpool remove  <pool> <vdev> ...
 599  *
 600  * Removes the given vdev from the pool.
 601  */
 602 int
 603 zpool_do_remove(int argc, char **argv)
 604 {
 605         char *poolname;
 606         int i, ret = 0;
 607         zpool_handle_t *zhp;
 608         boolean_t stop = B_FALSE;
 609         boolean_t noop = B_FALSE;
 610         boolean_t parsable = B_FALSE;
 611         char c;
 612 
 613         /* check options */
 614         while ((c = getopt(argc, argv, "nps")) != -1) {
 615                 switch (c) {
 616                 case 'n':
 617                         noop = B_TRUE;
 618                         break;
 619                 case 'p':
 620                         parsable = B_TRUE;
 621                         break;
 622                 case 's':
 623                         stop = B_TRUE;
 624                         break;
 625                 case '?':
 626                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
 627                             optopt);
 628                         usage(B_FALSE);
 629                 }
 630         }
 631 
 632         argc -= optind;
 633         argv += optind;
 634 
 635         /* get pool name and check number of arguments */
 636         if (argc < 1) {
 637                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
 638                 usage(B_FALSE);
 639         }
 640 
 641         poolname = argv[0];
 642 
 643         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
 644                 return (1);
 645 
 646         if (stop && noop) {
 647                 (void) fprintf(stderr, gettext("stop request ignored\n"));
 648                 return (0);
 649         }
 650 
 651         if (stop) {
 652                 if (argc > 1) {
 653                         (void) fprintf(stderr, gettext("too many arguments\n"));
 654                         usage(B_FALSE);
 655                 }
 656                 if (zpool_vdev_remove_cancel(zhp) != 0)
 657                         ret = 1;
 658         } else {
 659                 if (argc < 2) {
 660                         (void) fprintf(stderr, gettext("missing device\n"));
 661                         usage(B_FALSE);
 662                 }
 663 
 664                 for (i = 1; i < argc; i++) {
 665                         if (noop) {
 666                                 uint64_t size;
 667 
 668                                 if (zpool_vdev_indirect_size(zhp, argv[i],
 669                                     &size) != 0) {
 670                                         ret = 1;
 671                                         break;
 672                                 }
 673                                 if (parsable) {
 674                                         (void) printf("%s %llu\n",
 675                                             argv[i], size);
 676                                 } else {
 677                                         char valstr[32];
 678                                         zfs_nicenum(size, valstr,
 679                                             sizeof (valstr));
 680                                         (void) printf("Memory that will be "
 681                                             "used after removing %s: %s\n",
 682                                             argv[i], valstr);
 683                                 }
 684                         } else {
 685                                 if (zpool_vdev_remove(zhp, argv[i]) != 0)
 686                                         ret = 1;
 687                         }
 688                 }
 689         }
 690 
 691         return (ret);
 692 }
 693 
 694 /*
 695  * zpool labelclear [-f] <vdev>
 696  *
 697  *      -f      Force clearing the label for the vdevs which are members of
 698  *              the exported or foreign pools.
 699  *
 700  * Verifies that the vdev is not active and zeros out the label information
 701  * on the device.
 702  */
 703 int
 704 zpool_do_labelclear(int argc, char **argv)
 705 {
 706         char vdev[MAXPATHLEN];
 707         char *name = NULL;
 708         struct stat st;
 709         int c, fd, ret = 0;
 
1247                 usage(B_FALSE);
1248         }
1249         if (argc > 1) {
1250                 (void) fprintf(stderr, gettext("too many arguments\n"));
1251                 usage(B_FALSE);
1252         }
1253 
1254         pool = argv[0];
1255 
1256         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1257                 /*
1258                  * As a special case, check for use of '/' in the name, and
1259                  * direct the user to use 'zfs destroy' instead.
1260                  */
1261                 if (strchr(pool, '/') != NULL)
1262                         (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1263                             "destroy a dataset\n"));
1264                 return (1);
1265         }
1266 
1267         if (zpool_disable_datasets(zhp, force) != 0) {
1268                 (void) fprintf(stderr, gettext("could not destroy '%s': "
1269                     "could not unmount datasets\n"), zpool_get_name(zhp));
1270                 return (1);
1271         }
1272 
1273         /* The history must be logged as part of the export */
1274         log_history = B_FALSE;
1275 
1276         ret = (zpool_destroy(zhp, history_str) != 0);
1277 
1278         zpool_close(zhp);
1279 
1280         return (ret);
1281 }
1282 
1283 /*
1284  * zpool export [-f] <pool> ...
1285  *
1286  *      -f      Forcefully unmount datasets
1287  *
1288  * Export the given pools.  By default, the command will attempt to cleanly
1289  * unmount any active datasets within the pool.  If the '-f' flag is specified,
1290  * then the datasets will be forcefully unmounted.
1291  */
1292 int
1293 zpool_do_export(int argc, char **argv)
1294 {
1295         boolean_t force = B_FALSE;
1296         boolean_t hardforce = B_FALSE;
1297         int c;
1298         zpool_handle_t *zhp;
1299         int ret;
1300         int i;
1301 
1302         /* check options */
1303         while ((c = getopt(argc, argv, "fF")) != -1) {
1304                 switch (c) {
1305                 case 'f':
1306                         force = B_TRUE;
1307                         break;
1308                 case 'F':
1309                         hardforce = B_TRUE;
1310                         break;
1311                 case '?':
1312                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1313                             optopt);
1314                         usage(B_FALSE);
1315                 }
1316         }
1317 
1318         argc -= optind;
1319         argv += optind;
1320 
1321         /* check arguments */
1322         if (argc < 1) {
1323                 (void) fprintf(stderr, gettext("missing pool argument\n"));
1324                 usage(B_FALSE);
1325         }
1326 
1327         ret = 0;
1328         for (i = 0; i < argc; i++) {
1329                 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1330                         ret = 1;
1331                         continue;
1332                 }
1333 
1334                 if (zpool_disable_datasets(zhp, force) != 0) {
1335                         ret = 1;
1336                         zpool_close(zhp);
1337                         continue;
1338                 }
1339 
1340                 /* The history must be logged as part of the export */
1341                 log_history = B_FALSE;
1342 
1343                 if (hardforce) {
1344                         if (zpool_export_force(zhp, history_str) != 0)
1345                                 ret = 1;
1346                 } else if (zpool_export(zhp, force, history_str) != 0) {
1347                         ret = 1;
1348                 }
1349 
1350                 zpool_close(zhp);
1351         }
1352 
1353         return (ret);
1354 }
1355 
1356 /*
1357  * Given a vdev configuration, determine the maximum width needed for the device
1358  * name column.
1359  */
1360 static int
1361 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
1362 {
1363         char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
1364         nvlist_t **child;
1365         uint_t c, children;
1366         int ret;
 
1442         zpool_close(zhp);
1443         return (0);
1444 }
1445 
1446 /*
1447  * Print out configuration state as requested by status_callback.
1448  */
1449 void
1450 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
1451     int namewidth, int depth, boolean_t isspare)
1452 {
1453         nvlist_t **child;
1454         uint_t c, children;
1455         pool_scan_stat_t *ps = NULL;
1456         vdev_stat_t *vs;
1457         char rbuf[6], wbuf[6], cbuf[6];
1458         char *vname;
1459         uint64_t notpresent;
1460         spare_cbdata_t cb;
1461         const char *state;
1462         char *type;
1463 
1464         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1465             &child, &children) != 0)
1466                 children = 0;
1467 
1468         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1469             (uint64_t **)&vs, &c) == 0);
1470 
1471         verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1472 
1473         if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
1474                 return;
1475 
1476         state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1477         if (isspare) {
1478                 /*
1479                  * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1480                  * online drives.
1481                  */
1482                 if (vs->vs_aux == VDEV_AUX_SPARED)
1483                         state = "INUSE";
1484                 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1485                         state = "AVAIL";
1486         }
1487 
1488         (void) printf("\t%*s%-*s  %-8s", depth, "", namewidth - depth,
1489             name, state);
1490 
1491         if (!isspare) {
1492                 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1493                 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1494                 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1495                 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
 
1545                 case VDEV_AUX_ERR_EXCEEDED:
1546                         (void) printf(gettext("too many errors"));
1547                         break;
1548 
1549                 case VDEV_AUX_IO_FAILURE:
1550                         (void) printf(gettext("experienced I/O failures"));
1551                         break;
1552 
1553                 case VDEV_AUX_BAD_LOG:
1554                         (void) printf(gettext("bad intent log"));
1555                         break;
1556 
1557                 case VDEV_AUX_EXTERNAL:
1558                         (void) printf(gettext("external device fault"));
1559                         break;
1560 
1561                 case VDEV_AUX_SPLIT_POOL:
1562                         (void) printf(gettext("split into new pool"));
1563                         break;
1564 
1565                 case VDEV_AUX_CHILDREN_OFFLINE:
1566                         (void) printf(gettext("all children offline"));
1567                         break;
1568 
1569                 default:
1570                         (void) printf(gettext("corrupted data"));
1571                         break;
1572                 }
1573         }
1574 
1575         (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1576             (uint64_t **)&ps, &c);
1577 
1578         if (ps && ps->pss_state == DSS_SCANNING &&
1579             vs->vs_scan_processed != 0 && children == 0) {
1580                 (void) printf(gettext("  (%s)"),
1581                     (ps->pss_func == POOL_SCAN_RESILVER) ?
1582                     "resilvering" : "repairing");
1583         }
1584 
1585         (void) printf("\n");
1586 
1587         for (c = 0; c < children; c++) {
1588                 uint64_t islog = B_FALSE, ishole = B_FALSE;
1589 
1590                 /* Don't print logs or holes here */
1591                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1592                     &islog);
1593                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1594                     &ishole);
1595                 if (islog || ishole)
1596                         continue;
1597                 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1598                 print_status_config(zhp, vname, child[c],
1599                     namewidth, depth + 2, isspare);
1600                 free(vname);
1601         }
1602 }
1603 
1604 
1605 /*
1606  * Print the configuration of an exported pool.  Iterate over all vdevs in the
1607  * pool, printing out the name and status for each one.
1608  */
1609 void
1610 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1611 {
1612         nvlist_t **child;
1613         uint_t c, children;
1614         vdev_stat_t *vs;
1615         char *type, *vname;
 
1636                 case VDEV_AUX_BAD_GUID_SUM:
1637                         (void) printf(gettext("missing device"));
1638                         break;
1639 
1640                 case VDEV_AUX_NO_REPLICAS:
1641                         (void) printf(gettext("insufficient replicas"));
1642                         break;
1643 
1644                 case VDEV_AUX_VERSION_NEWER:
1645                         (void) printf(gettext("newer version"));
1646                         break;
1647 
1648                 case VDEV_AUX_UNSUP_FEAT:
1649                         (void) printf(gettext("unsupported feature(s)"));
1650                         break;
1651 
1652                 case VDEV_AUX_ERR_EXCEEDED:
1653                         (void) printf(gettext("too many errors"));
1654                         break;
1655 
1656                 case VDEV_AUX_CHILDREN_OFFLINE:
1657                         (void) printf(gettext("all children offline"));
1658                         break;
1659 
1660                 default:
1661                         (void) printf(gettext("corrupted data"));
1662                         break;
1663                 }
1664         }
1665         (void) printf("\n");
1666 
1667         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1668             &child, &children) != 0)
1669                 return;
1670 
1671         for (c = 0; c < children; c++) {
1672                 uint64_t is_log = B_FALSE;
1673 
1674                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1675                     &is_log);
1676                 if (is_log)
1677                         continue;
1678 
1679                 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1680                 print_import_config(vname, child[c], namewidth, depth + 2);
1681                 free(vname);
1682         }
1683 
1684         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1685             &child, &children) == 0) {
1686                 (void) printf(gettext("\tcache\n"));
1687                 for (c = 0; c < children; c++) {
1688                         vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1689                         (void) printf("\t  %s\n", vname);
1690                         free(vname);
1691                 }
1692         }
1693 
1694         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1695             &child, &children) == 0) {
1696                 (void) printf(gettext("\tspares\n"));
 
1724 
1725         for (c = 0; c < children; c++) {
1726                 uint64_t is_log = B_FALSE;
1727                 char *name;
1728 
1729                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1730                     &is_log);
1731                 if (!is_log)
1732                         continue;
1733                 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1734                 if (verbose)
1735                         print_status_config(zhp, name, child[c], namewidth,
1736                             2, B_FALSE);
1737                 else
1738                         print_import_config(name, child[c], namewidth, 2);
1739                 free(name);
1740         }
1741 }
1742 
1743 /*
1744  * Display the status for the given pool.
1745  */
1746 static void
1747 show_import(nvlist_t *config)
1748 {
1749         uint64_t pool_state;
1750         vdev_stat_t *vs;
1751         char *name;
1752         uint64_t guid;
1753         char *msgid;
1754         nvlist_t *nvroot;
1755         int reason;
1756         const char *health;
1757         uint_t vsc;
1758         int namewidth;
1759         char *comment;
1760 
1761         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1762             &name) == 0);
1763         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
 
1938                 if (pool_state == POOL_STATE_DESTROYED)
1939                         (void) printf(gettext("\tThe pool was destroyed, "
1940                             "but can be imported using the '-Df' flags.\n"));
1941                 else if (pool_state != POOL_STATE_EXPORTED)
1942                         (void) printf(gettext("\tThe pool may be active on "
1943                             "another system, but can be imported using\n\t"
1944                             "the '-f' flag.\n"));
1945         }
1946 
1947         if (msgid != NULL)
1948                 (void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
1949                     msgid);
1950 
1951         (void) printf(gettext(" config:\n\n"));
1952 
1953         namewidth = max_width(NULL, nvroot, 0, 0);
1954         if (namewidth < 10)
1955                 namewidth = 10;
1956 
1957         print_import_config(name, nvroot, namewidth, 0);
1958         if (num_logs(nvroot) > 0)
1959                 print_logs(NULL, nvroot, namewidth, B_FALSE);
1960 
1961         if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1962                 (void) printf(gettext("\n\tAdditional devices are known to "
1963                     "be part of this pool, though their\n\texact "
1964                     "configuration cannot be determined.\n"));
1965         }
1966 }
1967 
1968 /*
1969  * Perform the import for the given configuration.  This passes the heavy
1970  * lifting off to zpool_import_props(), and then mounts the datasets contained
1971  * within the pool.
1972  */
1973 static int
1974 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1975     nvlist_t *props, int flags)
1976 {
1977         zpool_handle_t *zhp;
1978         char *name;
1979         uint64_t state;
1980         uint64_t version;
1981 
1982         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1983             &name) == 0);
1984 
1985         verify(nvlist_lookup_uint64(config,
1986             ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1987         verify(nvlist_lookup_uint64(config,
1988             ZPOOL_CONFIG_VERSION, &version) == 0);
1989         if (!SPA_VERSION_IS_SUPPORTED(version)) {
1990                 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1991                     "is formatted using an unsupported ZFS version\n"), name);
1992                 return (1);
1993         } else if (state != POOL_STATE_EXPORTED &&
1994             !(flags & ZFS_IMPORT_ANY_HOST)) {
1995                 uint64_t hostid;
 
2019                 } else {
2020                         (void) fprintf(stderr, gettext("cannot import '%s': "
2021                             "pool may be in use from other system\n"), name);
2022                         (void) fprintf(stderr, gettext("use '-f' to import "
2023                             "anyway\n"));
2024                         return (1);
2025                 }
2026         }
2027 
2028         if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2029                 return (1);
2030 
2031         if (newname != NULL)
2032                 name = (char *)newname;
2033 
2034         if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2035                 return (1);
2036 
2037         if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2038             !(flags & ZFS_IMPORT_ONLY) &&
2039             zpool_enable_datasets(zhp, mntopts, 0) != 0) {
2040                 zpool_close(zhp);
2041                 return (1);
2042         }
2043 
2044         zpool_close(zhp);
2045         return (0);
2046 }
2047 
2048 /*
2049  * zpool import [-d dir] [-D]
2050  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2051  *              [-d dir | -c cachefile] [-f] -a
2052  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2053  *              [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
2054  *
2055  *       -c     Read pool information from a cachefile instead of searching
2056  *              devices.
2057  *
2058  *       -d     Scan in a specific directory, other than /dev/dsk.  More than
2059  *              one directory can be specified using multiple '-d' options.
2060  *
2061  *       -D     Scan for previously destroyed pools or import all or only
2062  *              specified destroyed pools.
2063  *
2064  *       -R     Temporarily import the pool, with all mountpoints relative to
2065  *              the given root.  The pool will remain exported when the machine
2066  *              is rebooted.
2067  *
2068  *       -V     Import even in the presence of faulted vdevs.  This is an
2069  *              intentionally undocumented option for testing purposes, and
2070  *              treats the pool configuration as complete, leaving any bad
2071  *              vdevs in the FAULTED state. In other words, it does verbatim
2072  *              import.
2073  *
2074  *       -f     Force import, even if it appears that the pool is active.
2075  *
2076  *       -F     Attempt rewind if necessary.
2077  *
2078  *       -n     See if rewind would work, but don't actually rewind.
2079  *
2080  *       -N     Import the pool but don't mount datasets.
2081  *
2082  *       -T     Specify a starting txg to use for import. This option is
2083  *              intentionally undocumented option for testing purposes.
2084  *
2085  *       -a     Import all pools found.
2086  *
2087  *       -o     Set property=value and/or temporary mount options (without '=').
2088  *
2089  * The import command scans for pools to import, and import pools based on pool
2090  * name and GUID.  The pool can also be renamed as part of the import process.
2091  */
2092 int
2093 zpool_do_import(int argc, char **argv)
2094 {
2095         char **searchdirs = NULL;
2096         int nsearch = 0;
2097         int c;
2098         int err = 0;
2099         nvlist_t *pools = NULL;
2100         boolean_t do_all = B_FALSE;
2101         boolean_t do_destroyed = B_FALSE;
2102         char *mntopts = NULL;
2103         nvpair_t *elem;
2104         nvlist_t *config;
2105         uint64_t searchguid = 0;
2106         char *searchname = NULL;
2107         char *propval;
2108         nvlist_t *found_config;
2109         nvlist_t *policy = NULL;
2110         nvlist_t *props = NULL;
2111         boolean_t first;
2112         int flags = ZFS_IMPORT_NORMAL;
2113         uint32_t rewind_policy = ZPOOL_NO_REWIND;
2114         boolean_t dryrun = B_FALSE;
2115         boolean_t do_rewind = B_FALSE;
2116         boolean_t xtreme_rewind = B_FALSE;
2117         uint64_t pool_state, txg = -1ULL;
2118         char *cachefile = NULL;
2119         importargs_t idata = { 0 };
2120         char *endptr;
2121 
2122         /* check options */
2123         while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:rR:T:VX")) != -1) {
2124                 switch (c) {
2125                 case 'a':
2126                         do_all = B_TRUE;
2127                         break;
2128                 case 'c':
2129                         cachefile = optarg;
2130                         break;
2131                 case 'd':
2132                         if (searchdirs == NULL) {
2133                                 searchdirs = safe_malloc(sizeof (char *));
2134                         } else {
2135                                 char **tmp = safe_malloc((nsearch + 1) *
2136                                     sizeof (char *));
2137                                 bcopy(searchdirs, tmp, nsearch *
2138                                     sizeof (char *));
2139                                 free(searchdirs);
2140                                 searchdirs = tmp;
2141                         }
2142                         searchdirs[nsearch++] = optarg;
2143                         break;
 
2165                                 propval++;
2166                                 if (add_prop_list(optarg, propval,
2167                                     &props, B_TRUE))
2168                                         goto error;
2169                         } else {
2170                                 mntopts = optarg;
2171                         }
2172                         break;
2173                 case 'R':
2174                         if (add_prop_list(zpool_prop_to_name(
2175                             ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2176                                 goto error;
2177                         if (nvlist_lookup_string(props,
2178                             zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
2179                             &propval) == 0)
2180                                 break;
2181                         if (add_prop_list(zpool_prop_to_name(
2182                             ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2183                                 goto error;
2184                         break;
2185                 case 'T':
2186                         errno = 0;
2187                         txg = strtoull(optarg, &endptr, 0);
2188                         if (errno != 0 || *endptr != '\0') {
2189                                 (void) fprintf(stderr,
2190                                     gettext("invalid txg value\n"));
2191                                 usage(B_FALSE);
2192                         }
2193                         rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2194                         break;
2195                 case 'V':
2196                         flags |= ZFS_IMPORT_VERBATIM;
2197                         break;
2198                 case 'X':
2199                         xtreme_rewind = B_TRUE;
2200                         break;
2201                 case ':':
2202                         (void) fprintf(stderr, gettext("missing argument for "
2203                             "'%c' option\n"), optopt);
2204                         usage(B_FALSE);
 
2287                 errno = 0;
2288                 searchguid = strtoull(argv[0], &endptr, 10);
2289                 if (errno != 0 || *endptr != '\0') {
2290                         searchname = argv[0];
2291                         searchguid = 0;
2292                 }
2293                 found_config = NULL;
2294 
2295                 /*
2296                  * User specified a name or guid.  Ensure it's unique.
2297                  */
2298                 idata.unique = B_TRUE;
2299         }
2300 
2301 
2302         idata.path = searchdirs;
2303         idata.paths = nsearch;
2304         idata.poolname = searchname;
2305         idata.guid = searchguid;
2306         idata.cachefile = cachefile;
2307         idata.policy = policy;
2308 
2309         pools = zpool_search_import(g_zfs, &idata);
2310 
2311         if (pools != NULL && idata.exists &&
2312             (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2313                 (void) fprintf(stderr, gettext("cannot import '%s': "
2314                     "a pool with that name already exists\n"),
2315                     argv[0]);
2316                 (void) fprintf(stderr, gettext("use the form '%s "
2317                     "<pool | id> <newpool>' to give it a new name\n"),
2318                     "zpool import");
2319                 err = 1;
2320         } else if (pools == NULL && idata.exists) {
2321                 (void) fprintf(stderr, gettext("cannot import '%s': "
2322                     "a pool with that name is already created/imported,\n"),
2323                     argv[0]);
2324                 (void) fprintf(stderr, gettext("and no additional pools "
2325                     "with that name were found\n"));
2326                 err = 1;
2327         } else if (pools == NULL) {
 
2352                 verify(nvpair_value_nvlist(elem, &config) == 0);
2353 
2354                 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2355                     &pool_state) == 0);
2356                 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2357                         continue;
2358                 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2359                         continue;
2360 
2361                 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
2362                     policy) == 0);
2363 
2364                 if (argc == 0) {
2365                         if (first)
2366                                 first = B_FALSE;
2367                         else if (!do_all)
2368                                 (void) printf("\n");
2369 
2370                         if (do_all) {
2371                                 err |= do_import(config, NULL, mntopts,
2372                                     props, flags);
2373                         } else {
2374                                 show_import(config);
2375                         }
2376                 } else if (searchname != NULL) {
2377                         char *name;
2378 
2379                         /*
2380                          * We are searching for a pool based on name.
2381                          */
2382                         verify(nvlist_lookup_string(config,
2383                             ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2384 
2385                         if (strcmp(name, searchname) == 0) {
2386                                 if (found_config != NULL) {
2387                                         (void) fprintf(stderr, gettext(
2388                                             "cannot import '%s': more than "
2389                                             "one matching pool\n"), searchname);
2390                                         (void) fprintf(stderr, gettext(
2391                                             "import by numeric ID instead\n"));
2392                                         err = B_TRUE;
 
2401                          */
2402                         verify(nvlist_lookup_uint64(config,
2403                             ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2404 
2405                         if (guid == searchguid)
2406                                 found_config = config;
2407                 }
2408         }
2409 
2410         /*
2411          * If we were searching for a specific pool, verify that we found a
2412          * pool, and then do the import.
2413          */
2414         if (argc != 0 && err == 0) {
2415                 if (found_config == NULL) {
2416                         (void) fprintf(stderr, gettext("cannot import '%s': "
2417                             "no such pool available\n"), argv[0]);
2418                         err = B_TRUE;
2419                 } else {
2420                         err |= do_import(found_config, argc == 1 ? NULL :
2421                             argv[1], mntopts, props, flags);
2422                 }
2423         }
2424 
2425         /*
2426          * If we were just looking for pools, report an error if none were
2427          * found.
2428          */
2429         if (argc == 0 && first)
2430                 (void) fprintf(stderr,
2431                     gettext("no pools available to import\n"));
2432 
2433 error:
2434         nvlist_free(props);
2435         nvlist_free(pools);
2436         nvlist_free(policy);
2437         free(searchdirs);
2438 
2439         return (err ? 1 : 0);
2440 }
2441 
2442 typedef struct iostat_cbdata {
2443         boolean_t cb_verbose;
2444         int cb_namewidth;
2445         int cb_iteration;
2446         zpool_list_t *cb_list;
2447 } iostat_cbdata_t;
2448 
2449 static void
2450 print_iostat_separator(iostat_cbdata_t *cb)
2451 {
2452         int i = 0;
2453 
2454         for (i = 0; i < cb->cb_namewidth; i++)
2455                 (void) printf("-");
2456         (void) printf("  -----  -----  -----  -----  -----  -----\n");
2457 }
2458 
2459 static void
2460 print_iostat_header(iostat_cbdata_t *cb)
2461 {
2462         (void) printf("%*s     capacity     operations    bandwidth\n",
2463             cb->cb_namewidth, "");
2464         (void) printf("%-*s  alloc   free   read  write   read  write\n",
2465             cb->cb_namewidth, "pool");
2466         print_iostat_separator(cb);
2467 }
2468 
2469 /*
2470  * Display a single statistic.
2471  */
2472 static void
2473 print_one_stat(uint64_t value)
2474 {
2475         char buf[64];
2476 
2477         zfs_nicenum(value, buf, sizeof (buf));
2478         (void) printf("  %5s", buf);
2479 }
2480 
2481 /*
2482  * Print out all the statistics for the given vdev.  This can either be the
2483  * toplevel configuration, or called recursively.  If 'name' is NULL, then this
2484  * is a verbose output, and we don't want to display the toplevel pool stats.
2485  */
2486 void
2487 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2488     nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2489 {
2490         nvlist_t **oldchild, **newchild;
2491         uint_t c, children;
2492         vdev_stat_t *oldvs, *newvs;
2493         vdev_stat_t zerovs = { 0 };
2494         uint64_t tdelta;
2495         double scale;
2496         char *vname;
2497 
2498         if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
2499                 return;
2500 
2501         if (oldnv != NULL) {
2502                 verify(nvlist_lookup_uint64_array(oldnv,
2503                     ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2504         } else {
2505                 oldvs = &zerovs;
2506         }
2507 
2508         verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2509             (uint64_t **)&newvs, &c) == 0);
2510 
2511         if (strlen(name) + depth > cb->cb_namewidth)
2512                 (void) printf("%*s%s", depth, "", name);
2513         else
2514                 (void) printf("%*s%s%*s", depth, "", name,
2515                     (int)(cb->cb_namewidth - strlen(name) - depth), "");
2516 
2517         tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2518 
2519         if (tdelta == 0)
2520                 scale = 1.0;
 
2524         /* only toplevel vdevs have capacity stats */
2525         if (newvs->vs_space == 0) {
2526                 (void) printf("      -      -");
2527         } else {
2528                 print_one_stat(newvs->vs_alloc);
2529                 print_one_stat(newvs->vs_space - newvs->vs_alloc);
2530         }
2531 
2532         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2533             oldvs->vs_ops[ZIO_TYPE_READ])));
2534 
2535         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2536             oldvs->vs_ops[ZIO_TYPE_WRITE])));
2537 
2538         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2539             oldvs->vs_bytes[ZIO_TYPE_READ])));
2540 
2541         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2542             oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2543 
2544         (void) printf("\n");
2545 
2546         if (!cb->cb_verbose)
2547                 return;
2548 
2549         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2550             &newchild, &children) != 0)
2551                 return;
2552 
2553         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2554             &oldchild, &c) != 0)
2555                 return;
2556 
2557         for (c = 0; c < children; c++) {
2558                 uint64_t ishole = B_FALSE, islog = B_FALSE;
2559 
2560                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2561                     &ishole);
2562 
2563                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2564                     &islog);
2565 
2566                 if (ishole || islog)
2567                         continue;
2568 
2569                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2570                 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2571                     newchild[c], cb, depth + 2);
2572                 free(vname);
2573         }
2574 
2575         /*
2576          * Log device section
2577          */
2578 
2579         if (num_logs(newnv) > 0) {
2580                 (void) printf("%-*s      -      -      -      -      -      "
2581                     "-\n", cb->cb_namewidth, "logs");
2582 
2583                 for (c = 0; c < children; c++) {
2584                         uint64_t islog = B_FALSE;
2585                         (void) nvlist_lookup_uint64(newchild[c],
2586                             ZPOOL_CONFIG_IS_LOG, &islog);
2587 
2588                         if (islog) {
2589                                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2590                                     B_FALSE);
2591                                 print_vdev_stats(zhp, vname, oldnv ?
2592                                     oldchild[c] : NULL, newchild[c],
2593                                     cb, depth + 2);
2594                                 free(vname);
2595                         }
2596                 }
2597 
2598         }
2599 
2600         /*
2601          * Include level 2 ARC devices in iostat output
2602          */
2603         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2604             &newchild, &children) != 0)
2605                 return;
2606 
2607         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2608             &oldchild, &c) != 0)
2609                 return;
2610 
2611         if (children > 0) {
2612                 (void) printf("%-*s      -      -      -      -      -      "
2613                     "-\n", cb->cb_namewidth, "cache");
2614                 for (c = 0; c < children; c++) {
2615                         vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2616                             B_FALSE);
2617                         print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2618                             newchild[c], cb, depth + 2);
 
3087 void
3088 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
3089     list_cbdata_t *cb, int depth)
3090 {
3091         nvlist_t **child;
3092         vdev_stat_t *vs;
3093         uint_t c, children;
3094         char *vname;
3095         boolean_t scripted = cb->cb_scripted;
3096         uint64_t islog = B_FALSE;
3097         boolean_t haslog = B_FALSE;
3098         char *dashes = "%-*s      -      -      -         -      -      -\n";
3099 
3100         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3101             (uint64_t **)&vs, &c) == 0);
3102 
3103         if (name != NULL) {
3104                 boolean_t toplevel = (vs->vs_space != 0);
3105                 uint64_t cap;
3106 
3107                 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
3108                         return;
3109 
3110                 if (scripted)
3111                         (void) printf("\t%s", name);
3112                 else if (strlen(name) + depth > cb->cb_namewidth)
3113                         (void) printf("%*s%s", depth, "", name);
3114                 else
3115                         (void) printf("%*s%s%*s", depth, "", name,
3116                             (int)(cb->cb_namewidth - strlen(name) - depth), "");
3117 
3118                 /*
3119                  * Print the properties for the individual vdevs. Some
3120                  * properties are only applicable to toplevel vdevs. The
3121                  * 'toplevel' boolean value is passed to the print_one_column()
3122                  * to indicate that the value is valid.
3123                  */
3124                 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
3125                     toplevel);
3126                 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
3127                     toplevel);
3128                 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
3129                     scripted, toplevel);
 
3221 }
3222 
3223 /*
3224  * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3225  *
3226  *      -H      Scripted mode.  Don't display headers, and separate properties
3227  *              by a single tab.
3228  *      -o      List of properties to display.  Defaults to
3229  *              "name,size,allocated,free,expandsize,fragmentation,capacity,"
3230  *              "dedupratio,health,altroot"
3231  *      -p      Diplay values in parsable (exact) format.
3232  *      -T      Display a timestamp in date(1) or Unix format
3233  *
3234  * List all pools in the system, whether or not they're healthy.  Output space
3235  * statistics for each one, as well as health status summary.
3236  */
3237 int
3238 zpool_do_list(int argc, char **argv)
3239 {
3240         int c;
3241         int ret;
3242         list_cbdata_t cb = { 0 };
3243         static char default_props[] =
3244             "name,size,allocated,free,expandsize,fragmentation,capacity,"
3245             "dedupratio,health,altroot";
3246         char *props = default_props;
3247         unsigned long interval = 0, count = 0;
3248         zpool_list_t *list;
3249         boolean_t first = B_TRUE;
3250 
3251         /* check options */
3252         while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
3253                 switch (c) {
3254                 case 'H':
3255                         cb.cb_scripted = B_TRUE;
3256                         break;
3257                 case 'o':
3258                         props = optarg;
3259                         break;
3260                 case 'p':
3261                         cb.cb_literal = B_TRUE;
 
3965 int
3966 scrub_callback(zpool_handle_t *zhp, void *data)
3967 {
3968         scrub_cbdata_t *cb = data;
3969         int err;
3970 
3971         /*
3972          * Ignore faulted pools.
3973          */
3974         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
3975                 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
3976                     "currently unavailable\n"), zpool_get_name(zhp));
3977                 return (1);
3978         }
3979 
3980         err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
3981 
3982         return (err != 0);
3983 }
3984 
3985 /*
3986  * zpool scrub [-s | -p] <pool> ...
3987  *
3988  *      -s      Stop.  Stops any in-progress scrub.
3989  *      -p      Pause. Pause in-progress scrub.
3990  */
3991 int
3992 zpool_do_scrub(int argc, char **argv)
3993 {
3994         int c;
3995         scrub_cbdata_t cb;
3996 
3997         cb.cb_type = POOL_SCAN_SCRUB;
3998         cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
3999 
4000         /* check options */
4001         while ((c = getopt(argc, argv, "sp")) != -1) {
4002                 switch (c) {
4003                 case 's':
4004                         cb.cb_type = POOL_SCAN_NONE;
4005                         break;
4006                 case 'p':
4007                         cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
4008                         break;
4009                 case '?':
4010                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4011                             optopt);
4012                         usage(B_FALSE);
4013                 }
4014         }
4015 
4016         if (cb.cb_type == POOL_SCAN_NONE &&
4017             cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
4018                 (void) fprintf(stderr, gettext("invalid option combination: "
4019                     "-s and -p are mutually exclusive\n"));
4020                 usage(B_FALSE);
4021         }
4022 
4023         cb.cb_argc = argc;
4024         cb.cb_argv = argv;
4025         argc -= optind;
4026         argv += optind;
4027 
4028         if (argc < 1) {
4029                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4030                 usage(B_FALSE);
4031         }
4032 
4033         return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
4034 }
4035 
4036 typedef struct status_cbdata {
4037         int             cb_count;
4038         boolean_t       cb_allpools;
4039         boolean_t       cb_verbose;
4040         boolean_t       cb_explain;
4041         boolean_t       cb_first;
4042         boolean_t       cb_dedup_stats;
4043 } status_cbdata_t;
4044 
4045 /*
4046  * Print out detailed scrub status.
4047  */
4048 static void
4049 print_scan_status(pool_scan_stat_t *ps)
4050 {
4051         time_t start, end, pause;
4052         uint64_t elapsed, mins_left, hours_left;
4053         uint64_t pass_exam, examined, total;
4054         uint_t rate;
4055         double fraction_done;
4056         char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4057 
4058         (void) printf(gettext("  scan: "));
4059 
4060         /* If there's never been a scan, there's not much to say. */
4061         if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
4062             ps->pss_func >= POOL_SCAN_FUNCS) {
4063                 (void) printf(gettext("none requested\n"));
4064                 return;
4065         }
4066 
4067         start = ps->pss_start_time;
4068         end = ps->pss_end_time;
4069         pause = ps->pss_pass_scrub_pause;
4070         zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
4071 
4072         assert(ps->pss_func == POOL_SCAN_SCRUB ||
4073             ps->pss_func == POOL_SCAN_RESILVER);
4074         /*
4075          * Scan is finished or canceled.
4076          */
4077         if (ps->pss_state == DSS_FINISHED) {
4078                 uint64_t minutes_taken = (end - start) / 60;
4079                 char *fmt = NULL;
4080 
4081                 if (ps->pss_func == POOL_SCAN_SCRUB) {
4082                         fmt = gettext("scrub repaired %s in %lluh%um with "
4083                             "%llu errors on %s");
4084                 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4085                         fmt = gettext("resilvered %s in %lluh%um with "
4086                             "%llu errors on %s");
4087                 }
4088                 /* LINTED */
4089                 (void) printf(fmt, processed_buf,
4090                     (u_longlong_t)(minutes_taken / 60),
4091                     (uint_t)(minutes_taken % 60),
4092                     (u_longlong_t)ps->pss_errors,
4093                     ctime((time_t *)&end));
4094                 return;
4095         } else if (ps->pss_state == DSS_CANCELED) {
4096                 if (ps->pss_func == POOL_SCAN_SCRUB) {
4097                         (void) printf(gettext("scrub canceled on %s"),
4098                             ctime(&end));
4099                 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4100                         (void) printf(gettext("resilver canceled on %s"),
4101                             ctime(&end));
4102                 }
4103                 return;
4104         }
4105 
4106         assert(ps->pss_state == DSS_SCANNING);
4107 
4108         /*
4109          * Scan is in progress.
4110          */
4111         if (ps->pss_func == POOL_SCAN_SCRUB) {
4112                 if (pause == 0) {
4113                         (void) printf(gettext("scrub in progress since %s"),
4114                             ctime(&start));
4115                 } else {
4116                         char buf[32];
4117                         struct tm *p = localtime(&pause);
4118                         (void) strftime(buf, sizeof (buf), "%a %b %e %T %Y", p);
4119                         (void) printf(gettext("scrub paused since %s\n"), buf);
4120                         (void) printf(gettext("\tscrub started on   %s"),
4121                             ctime(&start));
4122                 }
4123         } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4124                 (void) printf(gettext("resilver in progress since %s"),
4125                     ctime(&start));
4126         }
4127 
4128         examined = ps->pss_examined ? ps->pss_examined : 1;
4129         total = ps->pss_to_examine;
4130         fraction_done = (double)examined / total;
4131 
4132         /* elapsed time for this pass */
4133         elapsed = time(NULL) - ps->pss_pass_start;
4134         elapsed -= ps->pss_pass_scrub_spent_paused;
4135         elapsed = elapsed ? elapsed : 1;
4136         pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1;
4137         rate = pass_exam / elapsed;
4138         rate = rate ? rate : 1;
4139         mins_left = ((total - examined) / rate) / 60;
4140         hours_left = mins_left / 60;
4141 
4142         zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
4143         zfs_nicenum(total, total_buf, sizeof (total_buf));
4144 
4145         /*
4146          * do not print estimated time if hours_left is more than 30 days
4147          * or we have a paused scrub
4148          */
4149         if (pause == 0) {
4150                 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4151                 (void) printf(gettext("\t%s scanned out of %s at %s/s"),
4152                     examined_buf, total_buf, rate_buf);
4153                 if (hours_left < (30 * 24)) {
4154                         (void) printf(gettext(", %lluh%um to go\n"),
4155                             (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4156                 } else {
4157                         (void) printf(gettext(
4158                             ", (scan is slow, no estimated time)\n"));
4159                 }
4160         } else {
4161                 (void) printf(gettext("\t%s scanned out of %s\n"),
4162                     examined_buf, total_buf);
4163         }
4164 
4165         if (ps->pss_func == POOL_SCAN_RESILVER) {
4166                 (void) printf(gettext("    %s resilvered, %.2f%% done\n"),
4167                     processed_buf, 100 * fraction_done);
4168         } else if (ps->pss_func == POOL_SCAN_SCRUB) {
4169                 (void) printf(gettext("    %s repaired, %.2f%% done\n"),
4170                     processed_buf, 100 * fraction_done);
4171         }
4172 }
4173 
4174 /*
4175  * Print out detailed removal status.
4176  */
4177 static void
4178 print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
4179 {
4180         char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4181         time_t start, end;
4182         nvlist_t *config, *nvroot;
4183         nvlist_t **child;
4184         uint_t children;
4185         char *vdev_name;
4186 
4187         if (prs == NULL || prs->prs_state == DSS_NONE)
4188                 return;
4189 
4190         /*
4191          * Determine name of vdev.
4192          */
4193         config = zpool_get_config(zhp, NULL);
4194         nvroot = fnvlist_lookup_nvlist(config,
4195             ZPOOL_CONFIG_VDEV_TREE);
4196         verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4197             &child, &children) == 0);
4198         assert(prs->prs_removing_vdev < children);
4199         vdev_name = zpool_vdev_name(g_zfs, zhp,
4200             child[prs->prs_removing_vdev], B_TRUE);
4201 
4202         (void) printf(gettext("remove: "));
4203 
4204         start = prs->prs_start_time;
4205         end = prs->prs_end_time;
4206         zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
4207 
4208         /*
4209          * Removal is finished or canceled.
4210          */
4211         if (prs->prs_state == DSS_FINISHED) {
4212                 uint64_t minutes_taken = (end - start) / 60;
4213 
4214                 (void) printf(gettext("Removal of vdev %llu copied %s "
4215                     "in %lluh%um, completed on %s"),
4216                     (longlong_t)prs->prs_removing_vdev,
4217                     copied_buf,
4218                     (u_longlong_t)(minutes_taken / 60),
4219                     (uint_t)(minutes_taken % 60),
4220                     ctime((time_t *)&end));
4221         } else if (prs->prs_state == DSS_CANCELED) {
4222                 (void) printf(gettext("Removal of %s canceled on %s"),
4223                     vdev_name, ctime(&end));
4224         } else {
4225                 uint64_t copied, total, elapsed, mins_left, hours_left;
4226                 double fraction_done;
4227                 uint_t rate;
4228 
4229                 assert(prs->prs_state == DSS_SCANNING);
4230 
4231                 /*
4232                  * Removal is in progress.
4233                  */
4234                 (void) printf(gettext(
4235                     "Evacuation of %s in progress since %s"),
4236                     vdev_name, ctime(&start));
4237 
4238                 copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
4239                 total = prs->prs_to_copy;
4240                 fraction_done = (double)copied / total;
4241 
4242                 /* elapsed time for this pass */
4243                 elapsed = time(NULL) - prs->prs_start_time;
4244                 elapsed = elapsed > 0 ? elapsed : 1;
4245                 rate = copied / elapsed;
4246                 rate = rate > 0 ? rate : 1;
4247                 mins_left = ((total - copied) / rate) / 60;
4248                 hours_left = mins_left / 60;
4249 
4250                 zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
4251                 zfs_nicenum(total, total_buf, sizeof (total_buf));
4252                 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4253 
4254                 /*
4255                  * do not print estimated time if hours_left is more than
4256                  * 30 days
4257                  */
4258                 (void) printf(gettext("    %s copied out of %s at %s/s, "
4259                     "%.2f%% done"),
4260                     examined_buf, total_buf, rate_buf, 100 * fraction_done);
4261                 if (hours_left < (30 * 24)) {
4262                         (void) printf(gettext(", %lluh%um to go\n"),
4263                             (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4264                 } else {
4265                         (void) printf(gettext(
4266                             ", (copy is slow, no estimated time)\n"));
4267                 }
4268         }
4269 
4270         if (prs->prs_mapping_memory > 0) {
4271                 char mem_buf[7];
4272                 zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
4273                 (void) printf(gettext("    %s memory used for "
4274                     "removed device mappings\n"),
4275                     mem_buf);
4276         }
4277 }
4278 
4279 static void
4280 print_error_log(zpool_handle_t *zhp)
4281 {
4282         nvlist_t *nverrlist = NULL;
4283         nvpair_t *elem;
4284         char *pathname;
4285         size_t len = MAXPATHLEN * 2;
4286 
4287         if (zpool_get_errlog(zhp, &nverrlist) != 0) {
4288                 (void) printf("errors: List of errors unavailable "
4289                     "(insufficient privileges)\n");
4290                 return;
4291         }
4292 
4293         (void) printf("errors: Permanent errors have been "
4294             "detected in the following files:\n\n");
4295 
 
4371         (void) printf("\n");
4372         (void) printf(gettext(" dedup: "));
4373         if (ddo->ddo_count == 0) {
4374                 (void) printf(gettext("no DDT entries\n"));
4375                 return;
4376         }
4377 
4378         (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
4379             (u_longlong_t)ddo->ddo_count,
4380             (u_longlong_t)ddo->ddo_dspace,
4381             (u_longlong_t)ddo->ddo_mspace);
4382 
4383         verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
4384             (uint64_t **)&dds, &c) == 0);
4385         verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
4386             (uint64_t **)&ddh, &c) == 0);
4387         zpool_dump_ddt(dds, ddh);
4388 }
4389 
4390 /*
4391  * Display a summary of pool status.  Displays a summary such as:
4392  *
4393  *        pool: tank
4394  *      status: DEGRADED
4395  *      reason: One or more devices ...
4396  *         see: http://illumos.org/msg/ZFS-xxxx-01
4397  *      config:
4398  *              mirror          DEGRADED
4399  *                c1t0d0        OK
4400  *                c2t0d0        UNAVAIL
4401  *
4402  * When given the '-v' option, we print out the complete config.  If the '-e'
4403  * option is specified, then we print out error rate information as well.
4404  */
4405 int
4406 status_callback(zpool_handle_t *zhp, void *data)
4407 {
4408         status_cbdata_t *cbp = data;
4409         nvlist_t *config, *nvroot;
4410         char *msgid;
 
4423          * problems.
4424          */
4425         if (cbp->cb_explain &&
4426             (reason == ZPOOL_STATUS_OK ||
4427             reason == ZPOOL_STATUS_VERSION_OLDER ||
4428             reason == ZPOOL_STATUS_FEAT_DISABLED)) {
4429                 if (!cbp->cb_allpools) {
4430                         (void) printf(gettext("pool '%s' is healthy\n"),
4431                             zpool_get_name(zhp));
4432                         if (cbp->cb_first)
4433                                 cbp->cb_first = B_FALSE;
4434                 }
4435                 return (0);
4436         }
4437 
4438         if (cbp->cb_first)
4439                 cbp->cb_first = B_FALSE;
4440         else
4441                 (void) printf("\n");
4442 
4443         nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4444         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
4445             (uint64_t **)&vs, &c) == 0);
4446         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
4447 
4448         (void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
4449         (void) printf(gettext(" state: %s\n"), health);
4450 
4451         switch (reason) {
4452         case ZPOOL_STATUS_MISSING_DEV_R:
4453                 (void) printf(gettext("status: One or more devices could not "
4454                     "be opened.  Sufficient replicas exist for\n\tthe pool to "
4455                     "continue functioning in a degraded state.\n"));
4456                 (void) printf(gettext("action: Attach the missing device and "
4457                     "online it using 'zpool online'.\n"));
4458                 break;
4459 
4460         case ZPOOL_STATUS_MISSING_DEV_NR:
4461                 (void) printf(gettext("status: One or more devices could not "
4462                     "be opened.  There are insufficient\n\treplicas for the "
4463                     "pool to continue functioning.\n"));
 
4631                     "'zpool clear'.\n"));
4632                 break;
4633 
4634         default:
4635                 /*
4636                  * The remaining errors can't actually be generated, yet.
4637                  */
4638                 assert(reason == ZPOOL_STATUS_OK);
4639         }
4640 
4641         if (msgid != NULL)
4642                 (void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
4643                     msgid);
4644 
4645         if (config != NULL) {
4646                 int namewidth;
4647                 uint64_t nerr;
4648                 nvlist_t **spares, **l2cache;
4649                 uint_t nspares, nl2cache;
4650                 pool_scan_stat_t *ps = NULL;
4651                 pool_removal_stat_t *prs = NULL;
4652 
4653                 (void) nvlist_lookup_uint64_array(nvroot,
4654                     ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4655                 print_scan_status(ps);
4656 
4657                 (void) nvlist_lookup_uint64_array(nvroot,
4658                     ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
4659                 print_removal_status(zhp, prs);
4660 
4661                 namewidth = max_width(zhp, nvroot, 0, 0);
4662                 if (namewidth < 10)
4663                         namewidth = 10;
4664 
4665                 (void) printf(gettext("config:\n\n"));
4666                 (void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
4667                     "NAME", "STATE", "READ", "WRITE", "CKSUM");
4668                 print_status_config(zhp, zpool_get_name(zhp), nvroot,
4669                     namewidth, 0, B_FALSE);
4670 
4671                 if (num_logs(nvroot) > 0)
4672                         print_logs(zhp, nvroot, namewidth, B_TRUE);
4673                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
4674                     &l2cache, &nl2cache) == 0)
4675                         print_l2cache(zhp, l2cache, nl2cache, namewidth);
4676 
4677                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
4678                     &spares, &nspares) == 0)
4679                         print_spares(zhp, spares, nspares, namewidth);
4680 
4681                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
4682                     &nerr) == 0) {
4683                         nvlist_t *nverrlist = NULL;
4684 
4685                         /*
4686                          * If the approximate error count is small, get a
4687                          * precise count by fetching the entire log and
4688                          * uniquifying the results.
4689                          */
4690                         if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
 
4830                     "'%s' from version %llu to feature flags.\n"),
4831                     zpool_get_name(zhp), oldversion);
4832         } else {
4833                 (void) printf(gettext("Successfully upgraded "
4834                     "'%s' from version %llu to version %llu.\n"),
4835                     zpool_get_name(zhp), oldversion, version);
4836         }
4837 
4838         return (0);
4839 }
4840 
4841 static int
4842 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
4843 {
4844         int i, ret, count;
4845         boolean_t firstff = B_TRUE;
4846         nvlist_t *enabled = zpool_get_features(zhp);
4847 
4848         count = 0;
4849         for (i = 0; i < SPA_FEATURES; i++) {
4850                 const char *fname = spa_feature_table[i].fi_uname;
4851                 const char *fguid = spa_feature_table[i].fi_guid;
4852                 if (!nvlist_exists(enabled, fguid)) {
4853                         char *propname;
4854                         verify(-1 != asprintf(&propname, "feature@%s", fname));
4855                         ret = zpool_set_prop(zhp, propname,
4856                             ZFS_FEATURE_ENABLED);
4857                         if (ret != 0) {
4858                                 free(propname);
4859                                 return (ret);
4860                         }
4861                         count++;
4862 
4863                         if (firstff) {
4864                                 (void) printf(gettext("Enabled the "
4865                                     "following features on '%s':\n"),
4866                                     zpool_get_name(zhp));
4867                                 firstff = B_FALSE;
4868                         }
4869                         (void) printf(gettext("  %s\n"), fname);
4870                         free(propname);
4871                 }
4872         }
4873 
 
5591 
5592         if (cb.cb_proplist != NULL) {
5593                 fake_name.pl_prop = ZPOOL_PROP_NAME;
5594                 fake_name.pl_width = strlen(gettext("NAME"));
5595                 fake_name.pl_next = cb.cb_proplist;
5596                 cb.cb_proplist = &fake_name;
5597         }
5598 
5599         ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
5600             get_callback, &cb);
5601 
5602         if (cb.cb_proplist == &fake_name)
5603                 zprop_free_list(fake_name.pl_next);
5604         else
5605                 zprop_free_list(cb.cb_proplist);
5606 
5607         return (ret);
5608 }
5609 
5610 typedef struct set_cbdata {
5611         char *cb_propname;
5612         char *cb_value;
5613         boolean_t cb_any_successful;
5614 } set_cbdata_t;
5615 
5616 int
5617 set_callback(zpool_handle_t *zhp, void *data)
5618 {
5619         int error;
5620         set_cbdata_t *cb = (set_cbdata_t *)data;
5621 
5622         error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
5623 
5624         if (!error)
5625                 cb->cb_any_successful = B_TRUE;
5626 
5627         return (error);
5628 }
5629 
5630 int
5631 zpool_do_set(int argc, char **argv)
5632 {
5633         set_cbdata_t cb = { 0 };
5634         int error;
5635 
5636         if (argc > 1 && argv[1][0] == '-') {
5637                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5638                     argv[1][1]);
5639                 usage(B_FALSE);
5640         }
5641 
5642         if (argc < 2) {
5643                 (void) fprintf(stderr, gettext("missing property=value "
5644                     "argument\n"));
5645                 usage(B_FALSE);
5646         }
5647 
5648         if (argc < 3) {
5649                 (void) fprintf(stderr, gettext("missing pool name\n"));
5650                 usage(B_FALSE);
5651         }
5652 
5653         if (argc > 3) {
5654                 (void) fprintf(stderr, gettext("too many pool names\n"));
5655                 usage(B_FALSE);
5656         }
5657 
5658         cb.cb_propname = argv[1];
5659         cb.cb_value = strchr(cb.cb_propname, '=');
5660         if (cb.cb_value == NULL) {
5661                 (void) fprintf(stderr, gettext("missing value in "
5662                     "property=value argument\n"));
5663                 usage(B_FALSE);
5664         }
5665 
5666         *(cb.cb_value) = '\0';
5667         cb.cb_value++;
5668 
5669         error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
5670             set_callback, &cb);
5671 
5672         return (error);
5673 }
5674 
5675 static int
5676 find_command_idx(char *command, int *idx)
5677 {
5678         int i;
5679 
5680         for (i = 0; i < NCOMMAND; i++) {
5681                 if (command_table[i].name == NULL)
5682                         continue;
5683 
5684                 if (strcmp(command, command_table[i].name) == 0) {
5685                         *idx = i;
5686                         return (0);
5687                 }
5688         }
5689         return (1);
5690 }
5691 
5692 int
5693 main(int argc, char **argv)
5694 {
5695         int ret = 0;
 
5709 
5710         opterr = 0;
5711 
5712         /*
5713          * Make sure the user has specified some command.
5714          */
5715         if (argc < 2) {
5716                 (void) fprintf(stderr, gettext("missing command\n"));
5717                 usage(B_FALSE);
5718         }
5719 
5720         cmdname = argv[1];
5721 
5722         /*
5723          * Special case '-?'
5724          */
5725         if (strcmp(cmdname, "-?") == 0)
5726                 usage(B_TRUE);
5727 
5728         zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
5729 
5730         /*
5731          * Run the appropriate command.
5732          */
5733         if (find_command_idx(cmdname, &i) == 0) {
5734                 current_command = &command_table[i];
5735                 ret = command_table[i].func(argc - 1, argv + 1);
5736         } else if (strchr(cmdname, '=')) {
5737                 verify(find_command_idx("set", &i) == 0);
5738                 current_command = &command_table[i];
5739                 ret = command_table[i].func(argc, argv);
5740         } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
5741                 /*
5742                  * 'freeze' is a vile debugging abomination, so we treat
5743                  * it as such.
5744                  */
5745                 char buf[16384];
5746                 int fd = open(ZFS_DEV, O_RDWR);
5747                 (void) strcpy((void *)buf, argv[2]);
5748                 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
 
 | 
 
 
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
  25  * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
  26  * Copyright (c) 2013 by Delphix. All rights reserved.
  27  * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
  28  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
  29  * Copyright 2016 Nexenta Systems, Inc.
  30  * Copyright (c) 2017 Datto Inc.
  31  */
  32 
  33 #include <assert.h>
  34 #include <ctype.h>
  35 #include <dirent.h>
  36 #include <errno.h>
  37 #include <fcntl.h>
  38 #include <libgen.h>
  39 #include <libintl.h>
  40 #include <libuutil.h>
  41 #include <locale.h>
  42 #include <stdio.h>
  43 #include <stdlib.h>
  44 #include <string.h>
  45 #include <strings.h>
  46 #include <unistd.h>
  47 #include <priv.h>
  48 #include <pwd.h>
  49 #include <zone.h>
  50 #include <zfs_prop.h>
  51 #include <sys/fs/zfs.h>
  52 #include <sys/stat.h>
  53 
  54 #include <libzfs.h>
  55 
  56 #include "zpool_util.h"
  57 #include "zfs_comutil.h"
  58 #include "zfeature_common.h"
  59 
  60 #include "statcommon.h"
  61 
  62 #ifndef MAX
  63 #define MAX(x, y)       ((x) > (y) ? (x) : (y))
  64 #endif  /* MAX */
  65 
  66 static int zpool_do_create(int, char **);
  67 static int zpool_do_destroy(int, char **);
  68 
  69 static int zpool_do_add(int, char **);
  70 static int zpool_do_remove(int, char **);
  71 static int zpool_do_labelclear(int, char **);
  72 
  73 static int zpool_do_list(int, char **);
  74 static int zpool_do_iostat(int, char **);
  75 static int zpool_do_status(int, char **);
  76 
  77 static int zpool_do_online(int, char **);
  78 static int zpool_do_offline(int, char **);
  79 static int zpool_do_clear(int, char **);
  80 static int zpool_do_reopen(int, char **);
  81 
  82 static int zpool_do_reguid(int, char **);
  83 
  84 static int zpool_do_attach(int, char **);
  85 static int zpool_do_detach(int, char **);
  86 static int zpool_do_replace(int, char **);
  87 static int zpool_do_split(int, char **);
  88 
  89 static int zpool_do_scrub(int, char **);
  90 static int zpool_do_trim(int, char **);
  91 
  92 static int zpool_do_import(int, char **);
  93 static int zpool_do_export(int, char **);
  94 
  95 static int zpool_do_upgrade(int, char **);
  96 
  97 static int zpool_do_history(int, char **);
  98 
  99 static int zpool_do_get(int, char **);
 100 static int zpool_do_set(int, char **);
 101 
 102 static int zpool_do_vdev_get(int, char **);
 103 static int zpool_do_vdev_set(int, char **);
 104 
 105 static int zpool_do_cos_alloc(int, char **);
 106 static int zpool_do_cos_free(int, char **);
 107 static int zpool_do_cos_list(int, char **);
 108 static int zpool_do_cos_get(int, char **);
 109 static int zpool_do_cos_set(int, char **);
 110 
 111 static boolean_t nexenta_meta_enable();
 112 
 113 /*
 114  * These libumem hooks provide a reasonable set of defaults for the allocator's
 115  * debugging facilities.
 116  */
 117 
 118 #ifdef DEBUG
 119 const char *
 120 _umem_debug_init(void)
 121 {
 122         return ("default,verbose"); /* $UMEM_DEBUG setting */
 123 }
 124 
 125 const char *
 126 _umem_logging_init(void)
 127 {
 128         return ("fail,contents"); /* $UMEM_LOGGING setting */
 129 }
 130 #endif
 131 
 132 typedef enum {
 133         HELP_ADD,
 134         HELP_ATTACH,
 135         HELP_CLEAR,
 136         HELP_CREATE,
 137         HELP_DESTROY,
 138         HELP_DETACH,
 139         HELP_EXPORT,
 140         HELP_HISTORY,
 141         HELP_IMPORT,
 142         HELP_IOSTAT,
 143         HELP_LABELCLEAR,
 144         HELP_LIST,
 145         HELP_OFFLINE,
 146         HELP_ONLINE,
 147         HELP_REPLACE,
 148         HELP_REMOVE,
 149         HELP_SCRUB,
 150         HELP_TRIM,
 151         HELP_STATUS,
 152         HELP_UPGRADE,
 153         HELP_GET,
 154         HELP_SET,
 155         HELP_SPLIT,
 156         HELP_REGUID,
 157         HELP_REOPEN,
 158         HELP_VDEV_GET,
 159         HELP_VDEV_SET,
 160         HELP_COS_ALLOC,
 161         HELP_COS_FREE,
 162         HELP_COS_LIST,
 163         HELP_COS_GET,
 164         HELP_COS_SET
 165 } zpool_help_t;
 166 
 167 
 168 typedef struct zpool_command {
 169         const char      *name;
 170         int             (*func)(int, char **);
 171         zpool_help_t    usage;
 172 } zpool_command_t;
 173 
 174 /*
 175  * Master command table.  Each ZFS command has a name, associated function, and
 176  * usage message.  The usage messages need to be internationalized, so we have
 177  * to have a function to return the usage message based on a command index.
 178  *
 179  * These commands are organized according to how they are displayed in the usage
 180  * message.  An empty command (one with a NULL name) indicates an empty line in
 181  * the generic usage message.
 182  */
 183 static zpool_command_t command_table[] = {
 184         { "create",     zpool_do_create,        HELP_CREATE             },
 
 188         { "remove",     zpool_do_remove,        HELP_REMOVE             },
 189         { NULL },
 190         { "labelclear", zpool_do_labelclear,    HELP_LABELCLEAR         },
 191         { NULL },
 192         { "list",       zpool_do_list,          HELP_LIST               },
 193         { "iostat",     zpool_do_iostat,        HELP_IOSTAT             },
 194         { "status",     zpool_do_status,        HELP_STATUS             },
 195         { NULL },
 196         { "online",     zpool_do_online,        HELP_ONLINE             },
 197         { "offline",    zpool_do_offline,       HELP_OFFLINE            },
 198         { "clear",      zpool_do_clear,         HELP_CLEAR              },
 199         { "reopen",     zpool_do_reopen,        HELP_REOPEN             },
 200         { NULL },
 201         { "attach",     zpool_do_attach,        HELP_ATTACH             },
 202         { "detach",     zpool_do_detach,        HELP_DETACH             },
 203         { "replace",    zpool_do_replace,       HELP_REPLACE            },
 204         { "split",      zpool_do_split,         HELP_SPLIT              },
 205         { NULL },
 206         { "scrub",      zpool_do_scrub,         HELP_SCRUB              },
 207         { NULL },
 208         { "trim",       zpool_do_trim,          HELP_TRIM               },
 209         { NULL },
 210         { "import",     zpool_do_import,        HELP_IMPORT             },
 211         { "export",     zpool_do_export,        HELP_EXPORT             },
 212         { "upgrade",    zpool_do_upgrade,       HELP_UPGRADE            },
 213         { "reguid",     zpool_do_reguid,        HELP_REGUID             },
 214         { NULL },
 215         { "history",    zpool_do_history,       HELP_HISTORY            },
 216         { "get",        zpool_do_get,           HELP_GET                },
 217         { "set",        zpool_do_set,           HELP_SET                },
 218         { "vdev-get",   zpool_do_vdev_get,      HELP_VDEV_GET           },
 219         { "vdev-set",   zpool_do_vdev_set,      HELP_VDEV_SET           },
 220         { "cos-alloc",  zpool_do_cos_alloc,     HELP_COS_ALLOC          },
 221         { "cos-free",   zpool_do_cos_free,      HELP_COS_FREE           },
 222         { "cos-list",   zpool_do_cos_list,      HELP_COS_LIST           },
 223         { "cos-get",    zpool_do_cos_get,       HELP_COS_GET            },
 224         { "cos-set",    zpool_do_cos_set,       HELP_COS_SET            }
 225 };
 226 
 227 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 228 
 229 static zpool_command_t *current_command;
 230 static char history_str[HIS_MAX_RECORD_LEN];
 231 static boolean_t log_history = B_TRUE;
 232 static uint_t timestamp_fmt = NODATE;
 233 
 234 static const char *
 235 get_usage(zpool_help_t idx)
 236 {
 237         switch (idx) {
 238         case HELP_ADD:
 239                 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
 240         case HELP_ATTACH:
 241                 return (gettext("\tattach [-f] <pool> <device> "
 242                     "<new-device>\n"));
 243         case HELP_CLEAR:
 244                 return (gettext("\tclear [-nF] <pool> [device]\n"));
 245         case HELP_CREATE:
 246                 return (gettext("\tcreate [-fnd] [-B] "
 247                     "[-o property=value] ... \n"
 248                     "\t    [-O file-system-property=value] ... \n"
 249                     "\t    [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
 250         case HELP_DESTROY:
 251                 return (gettext("\tdestroy [-f] <pool>\n"));
 252         case HELP_DETACH:
 253                 return (gettext("\tdetach <pool> <device>\n"));
 254         case HELP_EXPORT:
 255                 return (gettext("\texport [-f] <pool> ...\n"));
 256         case HELP_HISTORY:
 257                 return (gettext("\thistory [-il] [<pool>] ...\n"));
 258         case HELP_IMPORT:
 259                 return (gettext("\timport [-d dir] [-D] [-t num]\n"
 260                     "\timport [-d dir | -c cachefile] [-F [-n]] <pool | id>\n"
 261                     "\timport [-o mntopts] [-o property=value] ... \n"
 262                     "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
 263                     "[-R root] [-F [-n]] [-t num] -a\n"
 264                     "\timport [-o mntopts] [-o property=value] ... \n"
 265                     "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
 266                     "[-R root] [-F [-n]]\n"
 267                     "\t    <pool | id> [newpool]\n"));
 268         case HELP_IOSTAT:
 269                 return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
 270                     "[count]]\n"));
 271         case HELP_LABELCLEAR:
 272                 return (gettext("\tlabelclear [-f] <vdev>\n"));
 273         case HELP_LIST:
 274                 return (gettext("\tlist [-Hp] [-o property[,...]] "
 275                     "[-T d|u] [pool] ... [interval [count]]\n"));
 276         case HELP_OFFLINE:
 277                 return (gettext("\toffline [-t] <pool> <device> ...\n"));
 278         case HELP_ONLINE:
 279                 return (gettext("\tonline <pool> <device> ...\n"));
 280         case HELP_REPLACE:
 281                 return (gettext("\treplace [-f] <pool> <device> "
 282                     "[new-device]\n"));
 283         case HELP_REMOVE:
 284                 return (gettext("\tremove <pool> <device> ...\n"));
 285         case HELP_REOPEN:
 286                 return (gettext("\treopen <pool>\n"));
 287         case HELP_SCRUB:
 288                 return (gettext("\tscrub [-m|-M|-p|-s] <pool> ...\n"));
 289         case HELP_TRIM:
 290                 return (gettext("\ttrim [-s|-r <rate>] <pool> ...\n"));
 291         case HELP_STATUS:
 292                 return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
 293                     "[count]]\n"));
 294         case HELP_UPGRADE:
 295                 return (gettext("\tupgrade\n"
 296                     "\tupgrade -v\n"
 297                     "\tupgrade [-V version] <-a | pool ...>\n"));
 298         case HELP_GET:
 299                 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
 300                     "<\"all\" | property[,...]> <pool> ...\n"));
 301         case HELP_SET:
 302                 return (gettext("\tset <property=value> <pool> \n"));
 303         case HELP_SPLIT:
 304                 return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
 305                     "\t    [-o property=value] <pool> <newpool> "
 306                     "[<device> ...]\n"));
 307         case HELP_REGUID:
 308                 return (gettext("\treguid <pool>\n"));
 309         case HELP_VDEV_GET:
 310                 return (gettext("\tvdev-get <property | all> <pool> "
 311                     "<vdev name | GUID>\n"));
 312         case HELP_VDEV_SET:
 313                 return (gettext("\tvdev-set <property=value> <pool> "
 314                     "<vdev name | GUID>\n"));
 315         case HELP_COS_ALLOC:
 316                 return (gettext("\tcos-alloc <pool> <cos name | GUID>\n"));
 317         case HELP_COS_FREE:
 318                 return (gettext("\tcos-free [-f] <pool> <cos name | GUID>\n"));
 319         case HELP_COS_LIST:
 320                 return (gettext("\tcos-list <pool>\n"));
 321         case HELP_COS_GET:
 322                 return (gettext("\tcos-get <property | all> <pool>"
 323                     "<cos name | GUID>\n"));
 324         case HELP_COS_SET:
 325                 return (gettext("\tcos-set <property=value> <pool>"
 326                     "<cos name | GUID>\n"));
 327         }
 328 
 329         abort();
 330         /* NOTREACHED */
 331 }
 332 /*
 333  * Check if additional ZFS meta features are enabled.
 334  */
 335 static boolean_t
 336 nexenta_meta_enable()
 337 {
 338         if (getenv("nexenta_meta_enable") == NULL) {
 339                 (void) fprintf(stderr, gettext("feature not enabled\n"));
 340                 (void) fprintf(stderr,
 341                     gettext("set nexenta_meta_enable to access\n"));
 342                 return (B_FALSE);
 343         }
 344         return (B_TRUE);
 345 }
 346 
 347 /*
 348  * Callback routine that will print out a pool property value.
 349  */
 350 static int
 351 print_prop_cb(int prop, void *cb)
 352 {
 353         FILE *fp = cb;
 354 
 355         (void) fprintf(fp, "\t%-15s  ", zpool_prop_to_name(prop));
 356 
 357         if (zpool_prop_readonly(prop))
 358                 (void) fprintf(fp, "  NO   ");
 359         else
 360                 (void) fprintf(fp, " YES   ");
 361 
 362         if (zpool_prop_values(prop) == NULL)
 363                 (void) fprintf(fp, "-\n");
 364         else
 365                 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
 366 
 
 461 
 462 static boolean_t
 463 prop_list_contains_feature(nvlist_t *proplist)
 464 {
 465         nvpair_t *nvp;
 466         for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
 467             nvp = nvlist_next_nvpair(proplist, nvp)) {
 468                 if (zpool_prop_feature(nvpair_name(nvp)))
 469                         return (B_TRUE);
 470         }
 471         return (B_FALSE);
 472 }
 473 
 474 /*
 475  * Add a property pair (name, string-value) into a property nvlist.
 476  */
 477 static int
 478 add_prop_list(const char *propname, char *propval, nvlist_t **props,
 479     boolean_t poolprop)
 480 {
 481         zpool_prop_t prop = ZPROP_INVAL;
 482         zfs_prop_t fprop;
 483         nvlist_t *proplist;
 484         const char *normnm;
 485         char *strval;
 486 
 487         if (*props == NULL &&
 488             nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
 489                 (void) fprintf(stderr,
 490                     gettext("internal error: out of memory\n"));
 491                 return (1);
 492         }
 493 
 494         proplist = *props;
 495 
 496         if (poolprop) {
 497                 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
 498 
 499                 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
 500                     !zpool_prop_feature(propname)) {
 501                         (void) fprintf(stderr, gettext("property '%s' is "
 502                             "not a valid pool property\n"), propname);
 503                         return (2);
 504                 }
 505 
 506                 /*
 507                  * feature@ properties and version should not be specified
 508                  * at the same time.
 509                  */
 510                 if ((prop == ZPROP_INVAL && zpool_prop_feature(propname) &&
 511                     nvlist_exists(proplist, vname)) ||
 512                     (prop == ZPOOL_PROP_VERSION &&
 513                     prop_list_contains_feature(proplist))) {
 514                         (void) fprintf(stderr, gettext("'feature@' and "
 515                             "'version' properties cannot be specified "
 516                             "together\n"));
 517                         return (2);
 518                 }
 519 
 520 
 521                 if (zpool_prop_feature(propname))
 522                         normnm = propname;
 523                 else
 524                         normnm = zpool_prop_to_name(prop);
 525         } else {
 526                 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
 527                         normnm = zfs_prop_to_name(fprop);
 528                 } else {
 529                         normnm = propname;
 530                 }
 531         }
 532 
 533         if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
 534             prop != ZPOOL_PROP_CACHEFILE) {
 535                 (void) fprintf(stderr, gettext("property '%s' "
 536                     "specified multiple times\n"), propname);
 537                 return (2);
 538         }
 539 
 540         if (nvlist_add_string(proplist, normnm, propval) != 0) {
 541                 (void) fprintf(stderr, gettext("internal "
 542                     "error: out of memory\n"));
 543                 return (1);
 544         }
 545 
 546         return (0);
 547 }
 548 
 549 /*
 550  * Add a property pair (name, string-value) into a vdev property nvlist.
 551  */
 552 static int
 553 add_vdev_prop_list(const char *propname, char *propval, nvlist_t **props)
 554 {
 555         vdev_prop_t prop = ZPROP_INVAL;
 556         nvlist_t *proplist;
 557         const char *normnm;
 558 
 559         if (*props == NULL && nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
 560                 (void) fprintf(stderr,
 561                     gettext("internal error: out of memory\n"));
 562                 return (1);
 563         }
 564 
 565         proplist = *props;
 566         if ((prop = vdev_name_to_prop(propname)) == ZPROP_INVAL) {
 567                 (void) fprintf(stderr, gettext("property '%s' is "
 568                     "not a valid vdev property\n"), propname);
 569                 return (2);
 570         }
 571         normnm = vdev_prop_to_name(prop);
 572 
 573         if (nvlist_add_string(proplist, normnm, propval) != 0) {
 574                 (void) fprintf(stderr, gettext("internal "
 575                     "error: out of memory\n"));
 576                 return (1);
 577         }
 578 
 579         return (0);
 580 }
 581 
 582 /*
 583  * Add a property pair (name, string-value) into a cos property nvlist.
 584  */
 585 static int
 586 add_cos_prop_list(const char *propname, char *propval, nvlist_t **props)
 587 {
 588         cos_prop_t prop = ZPROP_INVAL;
 589         nvlist_t *proplist;
 590         const char *normnm;
 591 
 592         if (*props == NULL && nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
 593                 (void) fprintf(stderr,
 594                     gettext("internal error: out of memory\n"));
 595                 return (1);
 596         }
 597 
 598         proplist = *props;
 599         if ((prop = cos_name_to_prop(propname)) == ZPROP_INVAL) {
 600                 (void) fprintf(stderr, gettext("property '%s' is "
 601                     "not a valid cos property\n"), propname);
 602                 return (2);
 603         }
 604         normnm = cos_prop_to_name(prop);
 605 
 606         if (nvlist_add_string(proplist, normnm, propval) != 0) {
 607                 (void) fprintf(stderr, gettext("internal "
 608                     "error: out of memory\n"));
 609                 return (1);
 610         }
 611 
 612         return (0);
 613 }
 614 
 615 /*
 616  * zpool add [-fn] <pool> <vdev> ...
 617  *
 618  *      -f      Force addition of devices, even if they appear in use
 619  *      -n      Do not add the devices, but display the resulting layout if
 620  *              they were to be added.
 621  *
 622  * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
 623  * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
 624  * libzfs.
 625  */
 626 int
 627 zpool_do_add(int argc, char **argv)
 628 {
 629         boolean_t force = B_FALSE;
 630         boolean_t dryrun = B_FALSE;
 631         int c;
 632         nvlist_t *nvroot;
 633         char *poolname;
 634         zpool_boot_label_t boot_type;
 635         uint64_t boot_size;
 
 713                         print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
 714                         print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
 715                 } else if (num_logs(nvroot) > 0) {
 716                         print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
 717                 }
 718 
 719                 ret = 0;
 720         } else {
 721                 ret = (zpool_add(zhp, nvroot) != 0);
 722         }
 723 
 724         nvlist_free(nvroot);
 725         zpool_close(zhp);
 726 
 727         return (ret);
 728 }
 729 
 730 /*
 731  * zpool remove  <pool> <vdev> ...
 732  *
 733  * Removes the given vdev from the pool.  Currently, this supports removing
 734  * spares, cache, and log devices from the pool.
 735  */
 736 int
 737 zpool_do_remove(int argc, char **argv)
 738 {
 739         char *poolname;
 740         int i, ret = 0;
 741         zpool_handle_t *zhp;
 742 
 743         argc--;
 744         argv++;
 745 
 746         /* get pool name and check number of arguments */
 747         if (argc < 1) {
 748                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
 749                 usage(B_FALSE);
 750         }
 751         if (argc < 2) {
 752                 (void) fprintf(stderr, gettext("missing device\n"));
 753                 usage(B_FALSE);
 754         }
 755 
 756         poolname = argv[0];
 757 
 758         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
 759                 return (1);
 760 
 761         for (i = 1; i < argc; i++) {
 762                 if (zpool_vdev_remove(zhp, argv[i]) != 0)
 763                         ret = 1;
 764         }
 765 
 766         return (ret);
 767 }
 768 
 769 /*
 770  * zpool labelclear [-f] <vdev>
 771  *
 772  *      -f      Force clearing the label for the vdevs which are members of
 773  *              the exported or foreign pools.
 774  *
 775  * Verifies that the vdev is not active and zeros out the label information
 776  * on the device.
 777  */
 778 int
 779 zpool_do_labelclear(int argc, char **argv)
 780 {
 781         char vdev[MAXPATHLEN];
 782         char *name = NULL;
 783         struct stat st;
 784         int c, fd, ret = 0;
 
1322                 usage(B_FALSE);
1323         }
1324         if (argc > 1) {
1325                 (void) fprintf(stderr, gettext("too many arguments\n"));
1326                 usage(B_FALSE);
1327         }
1328 
1329         pool = argv[0];
1330 
1331         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1332                 /*
1333                  * As a special case, check for use of '/' in the name, and
1334                  * direct the user to use 'zfs destroy' instead.
1335                  */
1336                 if (strchr(pool, '/') != NULL)
1337                         (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1338                             "destroy a dataset\n"));
1339                 return (1);
1340         }
1341 
1342         ret = zfs_check_krrp(g_zfs, argv[0]);
1343         /*
1344          * ENOTSUP means that autosnaper doesn't handle this pool.
1345          */
1346         if (ret != ENOTSUP) {
1347                 if (ret == ECHILD || ret == EBUSY || ret == EUSERS)
1348                         ret = EBUSY;
1349 
1350                 if (ret) {
1351                         (void) zpool_standard_error(g_zfs,
1352                             ret, gettext("cannnot destroy pool because "
1353                             "of krrp"));
1354                         zpool_close(zhp);
1355                         ret = 1;
1356                         return (ret);
1357                 }
1358         } else {
1359                 ret = 0;
1360         }
1361 
1362         if (zpool_disable_datasets(zhp, force) != 0) {
1363                 (void) fprintf(stderr, gettext("could not destroy '%s': "
1364                     "could not unmount datasets\n"), zpool_get_name(zhp));
1365                 return (1);
1366         }
1367 
1368         /* The history must be logged as part of the export */
1369         log_history = B_FALSE;
1370 
1371         ret = (zpool_destroy(zhp, history_str) != 0);
1372 
1373         zpool_close(zhp);
1374 
1375         return (ret);
1376 }
1377 
1378 /*
1379  * zpool export [-f] <pool> ...
1380  *
1381  *      -f      Forcefully unmount datasets
1382  *
1383  * Export the given pools.  By default, the command will attempt to cleanly
1384  * unmount any active datasets within the pool.  If the '-f' flag is specified,
1385  * then the datasets will be forcefully unmounted.
1386  */
1387 int
1388 zpool_do_export(int argc, char **argv)
1389 {
1390         boolean_t force = B_FALSE;
1391         boolean_t hardforce = B_FALSE;
1392         boolean_t saveconfig = B_FALSE;
1393         int c;
1394         int n_threads = sysconf(_SC_NPROCESSORS_ONLN) * 2;
1395         zpool_handle_t *zhp;
1396         int ret;
1397         int i;
1398 
1399         /* check options */
1400         while ((c = getopt(argc, argv, ":fFct:")) != -1) {
1401                 switch (c) {
1402                 case 'f':
1403                         force = B_TRUE;
1404                         break;
1405                 case 'F':
1406                         hardforce = B_TRUE;
1407                         break;
1408                 case 'c':
1409                         saveconfig = B_TRUE;
1410                         break;
1411                 case 't':
1412                         n_threads = atoi(optarg);
1413                         break;
1414                 case '?':
1415                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1416                             optopt);
1417                         usage(B_FALSE);
1418                         break;
1419                 case ':':
1420                         (void) fprintf(stderr, gettext("missing argument "
1421                             "for option '%c'\n"), optopt);
1422                         usage(B_FALSE);
1423                         break;
1424                 }
1425         }
1426 
1427         argc -= optind;
1428         argv += optind;
1429 
1430         /* check arguments */
1431         if (argc < 1) {
1432                 (void) fprintf(stderr, gettext("missing pool argument\n"));
1433                 usage(B_FALSE);
1434         }
1435 
1436         ret = 0;
1437         for (i = 0; i < argc; i++) {
1438                 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1439                         ret = 1;
1440                         continue;
1441                 }
1442 
1443                 ret = zfs_check_krrp(g_zfs, argv[0]);
1444                 /*
1445                  * ENOTSUP means that autosnaper doesn't handle this pool.
1446                  */
1447                 if (ret != ENOTSUP) {
1448                         if (ret == ECHILD || ret == EBUSY || ret == EUSERS)
1449                                 ret = EBUSY;
1450 
1451                         if (ret) {
1452                                 (void) zpool_standard_error(g_zfs,
1453                                     ret, gettext("cannnot export pool because "
1454                                     "of krrp"));
1455                                 zpool_close(zhp);
1456                                 ret = 1;
1457                                 continue;
1458                         }
1459                 } else {
1460                         ret = 0;
1461                 }
1462 
1463                 if (zpool_disable_datasets_ex(zhp, force, n_threads) != 0) {
1464                         ret = 1;
1465                         zpool_close(zhp);
1466                         continue;
1467                 }
1468 
1469                 /* The history must be logged as part of the export */
1470                 log_history = B_FALSE;
1471 
1472                 if (hardforce) {
1473                         if (zpool_export_force(zhp, saveconfig, history_str)
1474                             != 0)
1475                                 ret = 1;
1476                 } else if (zpool_export(zhp, force, saveconfig, history_str)
1477                     != 0) {
1478                         ret = 1;
1479                 }
1480 
1481                 zpool_close(zhp);
1482         }
1483 
1484         return (ret);
1485 }
1486 
1487 /*
1488  * Given a vdev configuration, determine the maximum width needed for the device
1489  * name column.
1490  */
1491 static int
1492 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
1493 {
1494         char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
1495         nvlist_t **child;
1496         uint_t c, children;
1497         int ret;
 
1573         zpool_close(zhp);
1574         return (0);
1575 }
1576 
1577 /*
1578  * Print out configuration state as requested by status_callback.
1579  */
1580 void
1581 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
1582     int namewidth, int depth, boolean_t isspare)
1583 {
1584         nvlist_t **child;
1585         uint_t c, children;
1586         pool_scan_stat_t *ps = NULL;
1587         vdev_stat_t *vs;
1588         char rbuf[6], wbuf[6], cbuf[6];
1589         char *vname;
1590         uint64_t notpresent;
1591         spare_cbdata_t cb;
1592         const char *state;
1593 
1594         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1595             &child, &children) != 0)
1596                 children = 0;
1597 
1598         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1599             (uint64_t **)&vs, &c) == 0);
1600 
1601         state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1602         if (isspare) {
1603                 /*
1604                  * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1605                  * online drives.
1606                  */
1607                 if (vs->vs_aux == VDEV_AUX_SPARED)
1608                         state = "INUSE";
1609                 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1610                         state = "AVAIL";
1611         }
1612 
1613         (void) printf("\t%*s%-*s  %-8s", depth, "", namewidth - depth,
1614             name, state);
1615 
1616         if (!isspare) {
1617                 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1618                 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1619                 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1620                 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
 
1670                 case VDEV_AUX_ERR_EXCEEDED:
1671                         (void) printf(gettext("too many errors"));
1672                         break;
1673 
1674                 case VDEV_AUX_IO_FAILURE:
1675                         (void) printf(gettext("experienced I/O failures"));
1676                         break;
1677 
1678                 case VDEV_AUX_BAD_LOG:
1679                         (void) printf(gettext("bad intent log"));
1680                         break;
1681 
1682                 case VDEV_AUX_EXTERNAL:
1683                         (void) printf(gettext("external device fault"));
1684                         break;
1685 
1686                 case VDEV_AUX_SPLIT_POOL:
1687                         (void) printf(gettext("split into new pool"));
1688                         break;
1689 
1690                 default:
1691                         (void) printf(gettext("corrupted data"));
1692                         break;
1693                 }
1694         }
1695 
1696         (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1697             (uint64_t **)&ps, &c);
1698 
1699         if (ps != NULL && (ps->pss_state == DSS_SCANNING ||
1700             ps->pss_state == DSS_FINISHING) && vs->vs_scan_processed != 0 &&
1701             children == 0) {
1702                 (void) printf(gettext("  (%s)"),
1703                     (ps->pss_func == POOL_SCAN_RESILVER) ?
1704                     "resilvering" : "repairing");
1705         }
1706 
1707         (void) printf("\n");
1708 
1709         for (c = 0; c < children; c++) {
1710                 uint64_t islog = B_FALSE, ishole = B_FALSE, isspecial = B_FALSE;
1711 
1712                 /* Don't print logs or holes here */
1713                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1714                     &islog);
1715                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1716                     &ishole);
1717                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_SPECIAL,
1718                     &isspecial);
1719                 if (islog || ishole || isspecial)
1720                         continue;
1721                 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1722                 print_status_config(zhp, vname, child[c],
1723                     namewidth, depth + 2, isspare);
1724                 free(vname);
1725         }
1726 }
1727 
1728 
1729 /*
1730  * Print the configuration of an exported pool.  Iterate over all vdevs in the
1731  * pool, printing out the name and status for each one.
1732  */
1733 void
1734 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1735 {
1736         nvlist_t **child;
1737         uint_t c, children;
1738         vdev_stat_t *vs;
1739         char *type, *vname;
 
1760                 case VDEV_AUX_BAD_GUID_SUM:
1761                         (void) printf(gettext("missing device"));
1762                         break;
1763 
1764                 case VDEV_AUX_NO_REPLICAS:
1765                         (void) printf(gettext("insufficient replicas"));
1766                         break;
1767 
1768                 case VDEV_AUX_VERSION_NEWER:
1769                         (void) printf(gettext("newer version"));
1770                         break;
1771 
1772                 case VDEV_AUX_UNSUP_FEAT:
1773                         (void) printf(gettext("unsupported feature(s)"));
1774                         break;
1775 
1776                 case VDEV_AUX_ERR_EXCEEDED:
1777                         (void) printf(gettext("too many errors"));
1778                         break;
1779 
1780                 default:
1781                         (void) printf(gettext("corrupted data"));
1782                         break;
1783                 }
1784         }
1785         (void) printf("\n");
1786 
1787         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1788             &child, &children) != 0)
1789                 return;
1790 
1791         for (c = 0; c < children; c++) {
1792                 uint64_t is_log = B_FALSE, is_special = B_FALSE;
1793 
1794                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1795                     &is_log);
1796                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_SPECIAL,
1797                     &is_special);
1798                 if (is_log || is_special)
1799                         continue;
1800 
1801                 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1802                 print_import_config(vname, child[c], namewidth, depth + 2);
1803                 free(vname);
1804         }
1805 
1806         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1807             &child, &children) == 0) {
1808                 (void) printf(gettext("\tcache\n"));
1809                 for (c = 0; c < children; c++) {
1810                         vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1811                         (void) printf("\t  %s\n", vname);
1812                         free(vname);
1813                 }
1814         }
1815 
1816         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1817             &child, &children) == 0) {
1818                 (void) printf(gettext("\tspares\n"));
 
1846 
1847         for (c = 0; c < children; c++) {
1848                 uint64_t is_log = B_FALSE;
1849                 char *name;
1850 
1851                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1852                     &is_log);
1853                 if (!is_log)
1854                         continue;
1855                 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1856                 if (verbose)
1857                         print_status_config(zhp, name, child[c], namewidth,
1858                             2, B_FALSE);
1859                 else
1860                         print_import_config(name, child[c], namewidth, 2);
1861                 free(name);
1862         }
1863 }
1864 
1865 /*
1866  * Print special vdevs.
1867  * Special vdevs are recorded as top level vdevs in the main pool child array
1868  * but with "is_special" set to 1. We use either print_status_config() or
1869  * print_import_config() to print the top level logs then any log
1870  * children (eg mirrored slogs) are printed recursively - which
1871  * works because only the top level vdev is marked "is_special"
1872  */
1873 static void
1874 print_special(zpool_handle_t *zhp, nvlist_t *nv, int namewidth,
1875     boolean_t verbose)
1876 {
1877         uint_t c, children;
1878         nvlist_t **child;
1879 
1880         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1881             &children) != 0)
1882                 return;
1883 
1884         (void) printf(gettext("\tspecial\n"));
1885 
1886         for (c = 0; c < children; c++) {
1887                 uint64_t is_special = B_FALSE;
1888                 char *name;
1889 
1890                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_SPECIAL,
1891                     &is_special);
1892                 if (!is_special)
1893                         continue;
1894                 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1895                 if (verbose)
1896                         print_status_config(zhp, name, child[c], namewidth,
1897                             2, B_FALSE);
1898                 else
1899                         print_import_config(name, child[c], namewidth, 2);
1900                 free(name);
1901         }
1902 }
1903 
1904 /*
1905  * Display the status for the given pool.
1906  */
1907 static void
1908 show_import(nvlist_t *config)
1909 {
1910         uint64_t pool_state;
1911         vdev_stat_t *vs;
1912         char *name;
1913         uint64_t guid;
1914         char *msgid;
1915         nvlist_t *nvroot;
1916         int reason;
1917         const char *health;
1918         uint_t vsc;
1919         int namewidth;
1920         char *comment;
1921 
1922         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1923             &name) == 0);
1924         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
 
2099                 if (pool_state == POOL_STATE_DESTROYED)
2100                         (void) printf(gettext("\tThe pool was destroyed, "
2101                             "but can be imported using the '-Df' flags.\n"));
2102                 else if (pool_state != POOL_STATE_EXPORTED)
2103                         (void) printf(gettext("\tThe pool may be active on "
2104                             "another system, but can be imported using\n\t"
2105                             "the '-f' flag.\n"));
2106         }
2107 
2108         if (msgid != NULL)
2109                 (void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
2110                     msgid);
2111 
2112         (void) printf(gettext(" config:\n\n"));
2113 
2114         namewidth = max_width(NULL, nvroot, 0, 0);
2115         if (namewidth < 10)
2116                 namewidth = 10;
2117 
2118         print_import_config(name, nvroot, namewidth, 0);
2119         if (num_special(nvroot) > 0)
2120                 print_special(NULL, nvroot, namewidth, B_FALSE);
2121 
2122         if (num_logs(nvroot) > 0)
2123                 print_logs(NULL, nvroot, namewidth, B_FALSE);
2124 
2125         if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
2126                 (void) printf(gettext("\n\tAdditional devices are known to "
2127                     "be part of this pool, though their\n\texact "
2128                     "configuration cannot be determined.\n"));
2129         }
2130 }
2131 
2132 /*
2133  * Perform the import for the given configuration.  This passes the heavy
2134  * lifting off to zpool_import_props(), and then mounts the datasets contained
2135  * within the pool.
2136  */
2137 static int
2138 do_import(nvlist_t *config, const char *newname, const char *mntopts,
2139     nvlist_t *props, int flags, int n_threads)
2140 {
2141         zpool_handle_t *zhp;
2142         char *name;
2143         uint64_t state;
2144         uint64_t version;
2145 
2146         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2147             &name) == 0);
2148 
2149         verify(nvlist_lookup_uint64(config,
2150             ZPOOL_CONFIG_POOL_STATE, &state) == 0);
2151         verify(nvlist_lookup_uint64(config,
2152             ZPOOL_CONFIG_VERSION, &version) == 0);
2153         if (!SPA_VERSION_IS_SUPPORTED(version)) {
2154                 (void) fprintf(stderr, gettext("cannot import '%s': pool "
2155                     "is formatted using an unsupported ZFS version\n"), name);
2156                 return (1);
2157         } else if (state != POOL_STATE_EXPORTED &&
2158             !(flags & ZFS_IMPORT_ANY_HOST)) {
2159                 uint64_t hostid;
 
2183                 } else {
2184                         (void) fprintf(stderr, gettext("cannot import '%s': "
2185                             "pool may be in use from other system\n"), name);
2186                         (void) fprintf(stderr, gettext("use '-f' to import "
2187                             "anyway\n"));
2188                         return (1);
2189                 }
2190         }
2191 
2192         if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2193                 return (1);
2194 
2195         if (newname != NULL)
2196                 name = (char *)newname;
2197 
2198         if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2199                 return (1);
2200 
2201         if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2202             !(flags & ZFS_IMPORT_ONLY) &&
2203             zpool_enable_datasets_ex(zhp, mntopts, 0, n_threads) != 0) {
2204                 zpool_close(zhp);
2205                 return (1);
2206         }
2207 
2208         zpool_close(zhp);
2209         return (0);
2210 }
2211 
2212 /*
2213  * zpool import [-d dir] [-D]
2214  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-t num]
2215  *              [-d dir | -c cachefile] [-f] -a
2216  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-t num]
2217  *              [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
2218  *
2219  *       -c     Read pool information from a cachefile instead of searching
2220  *              devices.
2221  *
2222  *       -d     Scan in a specific directory, other than /dev/dsk.  More than
2223  *              one directory can be specified using multiple '-d' options.
2224  *
2225  *       -D     Scan for previously destroyed pools or import all or only
2226  *              specified destroyed pools.
2227  *
2228  *       -R     Temporarily import the pool, with all mountpoints relative to
2229  *              the given root.  The pool will remain exported when the machine
2230  *              is rebooted.
2231  *
2232  *       -V     Import even in the presence of faulted vdevs.  This is an
2233  *              intentionally undocumented option for testing purposes, and
2234  *              treats the pool configuration as complete, leaving any bad
2235  *              vdevs in the FAULTED state. In other words, it does verbatim
2236  *              import.
2237  *
2238  *       -f     Force import, even if it appears that the pool is active.
2239  *
2240  *       -F     Attempt rewind if necessary.
2241  *
2242  *       -n     See if rewind would work, but don't actually rewind.
2243  *
2244  *       -N     Import the pool but don't mount datasets.
2245  *
2246  *       -t     Use up to num threads to mount datasets in parallel.
2247  *
2248  *       -T     Specify a starting txg to use for import. This option is
2249  *              intentionally undocumented option for testing purposes.
2250  *
2251  *       -a     Import all pools found.
2252  *
2253  *       -o     Set property=value and/or temporary mount options (without '=').
2254  *
2255  * The import command scans for pools to import, and import pools based on pool
2256  * name and GUID.  The pool can also be renamed as part of the import process.
2257  */
2258 int
2259 zpool_do_import(int argc, char **argv)
2260 {
2261         char **searchdirs = NULL;
2262         int nsearch = 0;
2263         int c;
2264         int err = 0;
2265         nvlist_t *pools = NULL;
2266         boolean_t do_all = B_FALSE;
2267         boolean_t do_destroyed = B_FALSE;
2268         char *mntopts = NULL;
2269         nvpair_t *elem;
2270         nvlist_t *config;
2271         uint64_t searchguid = 0;
2272         char *searchname = NULL;
2273         char *propval;
2274         nvlist_t *found_config;
2275         nvlist_t *policy = NULL;
2276         nvlist_t *props = NULL;
2277         boolean_t first;
2278         int flags = ZFS_IMPORT_NORMAL;
2279         uint32_t rewind_policy = ZPOOL_NO_REWIND;
2280         boolean_t dryrun = B_FALSE;
2281         boolean_t do_rewind = B_FALSE;
2282         boolean_t xtreme_rewind = B_FALSE;
2283         uint64_t pool_state, txg = -1ULL;
2284         char *cachefile = NULL;
2285         importargs_t idata = { 0 };
2286         unsigned long n_threads = sysconf(_SC_NPROCESSORS_ONLN) * 2;
2287         char *endptr;
2288 
2289         /* check options */
2290         while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:rR:t:T:VX")) != -1) {
2291                 switch (c) {
2292                 case 'a':
2293                         do_all = B_TRUE;
2294                         break;
2295                 case 'c':
2296                         cachefile = optarg;
2297                         break;
2298                 case 'd':
2299                         if (searchdirs == NULL) {
2300                                 searchdirs = safe_malloc(sizeof (char *));
2301                         } else {
2302                                 char **tmp = safe_malloc((nsearch + 1) *
2303                                     sizeof (char *));
2304                                 bcopy(searchdirs, tmp, nsearch *
2305                                     sizeof (char *));
2306                                 free(searchdirs);
2307                                 searchdirs = tmp;
2308                         }
2309                         searchdirs[nsearch++] = optarg;
2310                         break;
 
2332                                 propval++;
2333                                 if (add_prop_list(optarg, propval,
2334                                     &props, B_TRUE))
2335                                         goto error;
2336                         } else {
2337                                 mntopts = optarg;
2338                         }
2339                         break;
2340                 case 'R':
2341                         if (add_prop_list(zpool_prop_to_name(
2342                             ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2343                                 goto error;
2344                         if (nvlist_lookup_string(props,
2345                             zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
2346                             &propval) == 0)
2347                                 break;
2348                         if (add_prop_list(zpool_prop_to_name(
2349                             ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2350                                 goto error;
2351                         break;
2352                 case 't':
2353                         errno = 0;
2354                         n_threads = strtol(optarg, &endptr, 10);
2355                         if (errno != 0 || *endptr != '\0') {
2356                                 (void) fprintf(stderr,
2357                                     gettext("invalid num value\n"));
2358                                 usage(B_FALSE);
2359                         }
2360                         break;
2361                 case 'T':
2362                         errno = 0;
2363                         txg = strtoull(optarg, &endptr, 0);
2364                         if (errno != 0 || *endptr != '\0') {
2365                                 (void) fprintf(stderr,
2366                                     gettext("invalid txg value\n"));
2367                                 usage(B_FALSE);
2368                         }
2369                         rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2370                         break;
2371                 case 'V':
2372                         flags |= ZFS_IMPORT_VERBATIM;
2373                         break;
2374                 case 'X':
2375                         xtreme_rewind = B_TRUE;
2376                         break;
2377                 case ':':
2378                         (void) fprintf(stderr, gettext("missing argument for "
2379                             "'%c' option\n"), optopt);
2380                         usage(B_FALSE);
 
2463                 errno = 0;
2464                 searchguid = strtoull(argv[0], &endptr, 10);
2465                 if (errno != 0 || *endptr != '\0') {
2466                         searchname = argv[0];
2467                         searchguid = 0;
2468                 }
2469                 found_config = NULL;
2470 
2471                 /*
2472                  * User specified a name or guid.  Ensure it's unique.
2473                  */
2474                 idata.unique = B_TRUE;
2475         }
2476 
2477 
2478         idata.path = searchdirs;
2479         idata.paths = nsearch;
2480         idata.poolname = searchname;
2481         idata.guid = searchguid;
2482         idata.cachefile = cachefile;
2483 
2484         pools = zpool_search_import(g_zfs, &idata);
2485 
2486         if (pools != NULL && idata.exists &&
2487             (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2488                 (void) fprintf(stderr, gettext("cannot import '%s': "
2489                     "a pool with that name already exists\n"),
2490                     argv[0]);
2491                 (void) fprintf(stderr, gettext("use the form '%s "
2492                     "<pool | id> <newpool>' to give it a new name\n"),
2493                     "zpool import");
2494                 err = 1;
2495         } else if (pools == NULL && idata.exists) {
2496                 (void) fprintf(stderr, gettext("cannot import '%s': "
2497                     "a pool with that name is already created/imported,\n"),
2498                     argv[0]);
2499                 (void) fprintf(stderr, gettext("and no additional pools "
2500                     "with that name were found\n"));
2501                 err = 1;
2502         } else if (pools == NULL) {
 
2527                 verify(nvpair_value_nvlist(elem, &config) == 0);
2528 
2529                 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2530                     &pool_state) == 0);
2531                 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2532                         continue;
2533                 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2534                         continue;
2535 
2536                 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
2537                     policy) == 0);
2538 
2539                 if (argc == 0) {
2540                         if (first)
2541                                 first = B_FALSE;
2542                         else if (!do_all)
2543                                 (void) printf("\n");
2544 
2545                         if (do_all) {
2546                                 err |= do_import(config, NULL, mntopts,
2547                                     props, flags, n_threads);
2548                         } else {
2549                                 show_import(config);
2550                         }
2551                 } else if (searchname != NULL) {
2552                         char *name;
2553 
2554                         /*
2555                          * We are searching for a pool based on name.
2556                          */
2557                         verify(nvlist_lookup_string(config,
2558                             ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2559 
2560                         if (strcmp(name, searchname) == 0) {
2561                                 if (found_config != NULL) {
2562                                         (void) fprintf(stderr, gettext(
2563                                             "cannot import '%s': more than "
2564                                             "one matching pool\n"), searchname);
2565                                         (void) fprintf(stderr, gettext(
2566                                             "import by numeric ID instead\n"));
2567                                         err = B_TRUE;
 
2576                          */
2577                         verify(nvlist_lookup_uint64(config,
2578                             ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2579 
2580                         if (guid == searchguid)
2581                                 found_config = config;
2582                 }
2583         }
2584 
2585         /*
2586          * If we were searching for a specific pool, verify that we found a
2587          * pool, and then do the import.
2588          */
2589         if (argc != 0 && err == 0) {
2590                 if (found_config == NULL) {
2591                         (void) fprintf(stderr, gettext("cannot import '%s': "
2592                             "no such pool available\n"), argv[0]);
2593                         err = B_TRUE;
2594                 } else {
2595                         err |= do_import(found_config, argc == 1 ? NULL :
2596                             argv[1], mntopts, props, flags, n_threads);
2597                 }
2598         }
2599 
2600         /*
2601          * If we were just looking for pools, report an error if none were
2602          * found.
2603          */
2604         if (argc == 0 && first)
2605                 (void) fprintf(stderr,
2606                     gettext("no pools available to import\n"));
2607 
2608 error:
2609         nvlist_free(props);
2610         nvlist_free(pools);
2611         nvlist_free(policy);
2612         free(searchdirs);
2613 
2614         return (err ? 1 : 0);
2615 }
2616 
2617 typedef struct iostat_cbdata {
2618         boolean_t cb_verbose;
2619         int cb_namewidth;
2620         int cb_iteration;
2621         zpool_list_t *cb_list;
2622 } iostat_cbdata_t;
2623 
2624 static void
2625 print_iostat_separator(iostat_cbdata_t *cb)
2626 {
2627         int i = 0;
2628 
2629         for (i = 0; i < cb->cb_namewidth; i++)
2630                 (void) printf("-");
2631         (void) printf("  -----  -----  -----  -----  -----  -----  -----  "
2632             "-----\n");
2633 }
2634 
2635 static void
2636 print_iostat_header(iostat_cbdata_t *cb)
2637 {
2638         (void) printf("%*s     capacity     operations    bandwidth      "
2639             "latency\n", cb->cb_namewidth, "");
2640         (void) printf("%-*s  alloc   free   read  write   read  write   read  "
2641             "write\n", cb->cb_namewidth, "pool");
2642         print_iostat_separator(cb);
2643 }
2644 
2645 /*
2646  * Display a single statistic.
2647  */
2648 static void
2649 print_one_stat(uint64_t value)
2650 {
2651         char buf[64];
2652 
2653         zfs_nicenum(value, buf, sizeof (buf));
2654         (void) printf("  %5s", buf);
2655 }
2656 
2657 /*
2658  * Display latency statistic (extra care needed)
2659  */
2660 static void
2661 print_one_latency_stat(uint64_t iotime, uint64_t ops)
2662 {
2663         char buf[64];
2664         double value = 0.0; /* latency in milliseconds */
2665 
2666         if (ops != 0) {
2667                 value = (double)iotime;
2668                 value /= (double)ops;
2669                 value /= (double)(MICROSEC / MILLISEC);
2670         }
2671 
2672         (void) sprintf(buf, "%.2f", value);
2673         (void) printf("  %5s", buf);
2674 }
2675 
2676 /*
2677  * Print out all the statistics for the given vdev.  This can either be the
2678  * toplevel configuration, or called recursively.  If 'name' is NULL, then this
2679  * is a verbose output, and we don't want to display the toplevel pool stats.
2680  */
2681 void
2682 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2683     nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2684 {
2685         nvlist_t **oldchild, **newchild;
2686         uint_t c, children;
2687         vdev_stat_t *oldvs, *newvs;
2688         vdev_stat_t zerovs = { 0 };
2689         uint64_t tdelta;
2690         double scale;
2691         char *vname;
2692 
2693         if (oldnv != NULL) {
2694                 verify(nvlist_lookup_uint64_array(oldnv,
2695                     ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2696         } else {
2697                 oldvs = &zerovs;
2698         }
2699 
2700         verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2701             (uint64_t **)&newvs, &c) == 0);
2702 
2703         if (strlen(name) + depth > cb->cb_namewidth)
2704                 (void) printf("%*s%s", depth, "", name);
2705         else
2706                 (void) printf("%*s%s%*s", depth, "", name,
2707                     (int)(cb->cb_namewidth - strlen(name) - depth), "");
2708 
2709         tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2710 
2711         if (tdelta == 0)
2712                 scale = 1.0;
 
2716         /* only toplevel vdevs have capacity stats */
2717         if (newvs->vs_space == 0) {
2718                 (void) printf("      -      -");
2719         } else {
2720                 print_one_stat(newvs->vs_alloc);
2721                 print_one_stat(newvs->vs_space - newvs->vs_alloc);
2722         }
2723 
2724         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2725             oldvs->vs_ops[ZIO_TYPE_READ])));
2726 
2727         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2728             oldvs->vs_ops[ZIO_TYPE_WRITE])));
2729 
2730         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2731             oldvs->vs_bytes[ZIO_TYPE_READ])));
2732 
2733         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2734             oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2735 
2736         /*
2737          * No scale needed here since we are dividing in
2738          * print_one_latency_stat()
2739          */
2740 
2741         print_one_latency_stat(
2742             newvs->vs_iotime[ZIO_TYPE_READ] - oldvs->vs_iotime[ZIO_TYPE_READ],
2743             newvs->vs_ops[ZIO_TYPE_READ] - oldvs->vs_ops[ZIO_TYPE_READ]);
2744 
2745         print_one_latency_stat(
2746             newvs->vs_iotime[ZIO_TYPE_WRITE] - oldvs->vs_iotime[ZIO_TYPE_WRITE],
2747             newvs->vs_ops[ZIO_TYPE_WRITE] - oldvs->vs_ops[ZIO_TYPE_WRITE]);
2748 
2749         (void) printf("\n");
2750 
2751         if (!cb->cb_verbose)
2752                 return;
2753 
2754         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2755             &newchild, &children) != 0)
2756                 return;
2757 
2758         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2759             &oldchild, &c) != 0)
2760                 return;
2761 
2762         for (c = 0; c < children; c++) {
2763                 uint64_t ishole = B_FALSE, islog = B_FALSE, isspec = B_FALSE;
2764 
2765                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2766                     &ishole);
2767 
2768                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2769                     &islog);
2770 
2771                 (void) nvlist_lookup_uint64(newchild[c],
2772                     ZPOOL_CONFIG_IS_SPECIAL, &isspec);
2773 
2774                 if (ishole || islog || isspec)
2775                         continue;
2776 
2777                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2778                 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2779                     newchild[c], cb, depth + 2);
2780                 free(vname);
2781         }
2782 
2783         /*
2784          * Log device section
2785          */
2786 
2787         if (num_logs(newnv) > 0) {
2788                 (void) printf("%-*s      -      -      -      -      -      "
2789                     "-\n", cb->cb_namewidth, "logs");
2790 
2791                 for (c = 0; c < children; c++) {
2792                         uint64_t islog = B_FALSE;
2793                         (void) nvlist_lookup_uint64(newchild[c],
2794                             ZPOOL_CONFIG_IS_LOG, &islog);
2795 
2796                         if (islog) {
2797                                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2798                                     B_FALSE);
2799                                 print_vdev_stats(zhp, vname, oldnv ?
2800                                     oldchild[c] : NULL, newchild[c],
2801                                     cb, depth + 2);
2802                                 free(vname);
2803                         }
2804                 }
2805         }
2806 
2807         /*
2808          * Special device section
2809          */
2810 
2811         if (num_special(newnv) > 0) {
2812                 (void) printf("%-*s      -      -      -      -      -      "
2813                     "-\n", cb->cb_namewidth, "special");
2814 
2815                 for (c = 0; c < children; c++) {
2816                         uint64_t isspec = B_FALSE;
2817                         (void) nvlist_lookup_uint64(newchild[c],
2818                             ZPOOL_CONFIG_IS_SPECIAL, &isspec);
2819 
2820                         if (isspec) {
2821                                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2822                                     B_FALSE);
2823                                 print_vdev_stats(zhp, vname, oldnv ?
2824                                     oldchild[c] : NULL, newchild[c],
2825                                     cb, depth + 2);
2826                                 free(vname);
2827                         }
2828                 }
2829         }
2830 
2831         /*
2832          * Include level 2 ARC devices in iostat output
2833          */
2834         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2835             &newchild, &children) != 0)
2836                 return;
2837 
2838         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2839             &oldchild, &c) != 0)
2840                 return;
2841 
2842         if (children > 0) {
2843                 (void) printf("%-*s      -      -      -      -      -      "
2844                     "-\n", cb->cb_namewidth, "cache");
2845                 for (c = 0; c < children; c++) {
2846                         vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2847                             B_FALSE);
2848                         print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2849                             newchild[c], cb, depth + 2);
 
3318 void
3319 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
3320     list_cbdata_t *cb, int depth)
3321 {
3322         nvlist_t **child;
3323         vdev_stat_t *vs;
3324         uint_t c, children;
3325         char *vname;
3326         boolean_t scripted = cb->cb_scripted;
3327         uint64_t islog = B_FALSE;
3328         boolean_t haslog = B_FALSE;
3329         char *dashes = "%-*s      -      -      -         -      -      -\n";
3330 
3331         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3332             (uint64_t **)&vs, &c) == 0);
3333 
3334         if (name != NULL) {
3335                 boolean_t toplevel = (vs->vs_space != 0);
3336                 uint64_t cap;
3337 
3338                 if (scripted)
3339                         (void) printf("\t%s", name);
3340                 else if (strlen(name) + depth > cb->cb_namewidth)
3341                         (void) printf("%*s%s", depth, "", name);
3342                 else
3343                         (void) printf("%*s%s%*s", depth, "", name,
3344                             (int)(cb->cb_namewidth - strlen(name) - depth), "");
3345 
3346                 /*
3347                  * Print the properties for the individual vdevs. Some
3348                  * properties are only applicable to toplevel vdevs. The
3349                  * 'toplevel' boolean value is passed to the print_one_column()
3350                  * to indicate that the value is valid.
3351                  */
3352                 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
3353                     toplevel);
3354                 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
3355                     toplevel);
3356                 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
3357                     scripted, toplevel);
 
3449 }
3450 
3451 /*
3452  * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3453  *
3454  *      -H      Scripted mode.  Don't display headers, and separate properties
3455  *              by a single tab.
3456  *      -o      List of properties to display.  Defaults to
3457  *              "name,size,allocated,free,expandsize,fragmentation,capacity,"
3458  *              "dedupratio,health,altroot"
3459  *      -p      Diplay values in parsable (exact) format.
3460  *      -T      Display a timestamp in date(1) or Unix format
3461  *
3462  * List all pools in the system, whether or not they're healthy.  Output space
3463  * statistics for each one, as well as health status summary.
3464  */
3465 int
3466 zpool_do_list(int argc, char **argv)
3467 {
3468         int c;
3469         int ret = 0;
3470         list_cbdata_t cb = { 0 };
3471         static char default_props[] =
3472             "name,size,allocated,free,expandsize,fragmentation,capacity,"
3473             "dedupratio,health,altroot";
3474         char *props = default_props;
3475         unsigned long interval = 0, count = 0;
3476         zpool_list_t *list;
3477         boolean_t first = B_TRUE;
3478 
3479         /* check options */
3480         while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
3481                 switch (c) {
3482                 case 'H':
3483                         cb.cb_scripted = B_TRUE;
3484                         break;
3485                 case 'o':
3486                         props = optarg;
3487                         break;
3488                 case 'p':
3489                         cb.cb_literal = B_TRUE;
 
4193 int
4194 scrub_callback(zpool_handle_t *zhp, void *data)
4195 {
4196         scrub_cbdata_t *cb = data;
4197         int err;
4198 
4199         /*
4200          * Ignore faulted pools.
4201          */
4202         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4203                 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
4204                     "currently unavailable\n"), zpool_get_name(zhp));
4205                 return (1);
4206         }
4207 
4208         err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
4209 
4210         return (err != 0);
4211 }
4212 
4213 typedef struct trim_cbdata {
4214         boolean_t       cb_start;
4215         uint64_t        cb_rate;
4216 } trim_cbdata_t;
4217 
4218 int
4219 trim_callback(zpool_handle_t *zhp, void *data)
4220 {
4221         trim_cbdata_t *cb = data;
4222         int err;
4223 
4224         /*
4225          * Ignore faulted pools.
4226          */
4227         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4228                 (void) fprintf(stderr, gettext("cannot trim '%s': pool is "
4229                     "currently unavailable\n"), zpool_get_name(zhp));
4230                 return (1);
4231         }
4232 
4233         err = zpool_trim(zhp, cb->cb_start, cb->cb_rate);
4234 
4235         return (err != 0);
4236 }
4237 
4238 /*
4239  * zpool scrub [-s | -p] <pool> ...
4240  *
4241  *      -s      Stop.  Stops any in-progress scrub.
4242  *      -p      Pause. Pause in-progress scrub.
4243  */
4244 int
4245 zpool_do_scrub(int argc, char **argv)
4246 {
4247         int c;
4248         scrub_cbdata_t cb;
4249 
4250         cb.cb_type = POOL_SCAN_SCRUB;
4251         cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
4252 
4253         /* check options */
4254         while ((c = getopt(argc, argv, "mMps")) != -1) {
4255                 switch (c) {
4256                 case 's':
4257                         if (cb.cb_type != POOL_SCAN_SCRUB) {
4258                                 (void) fprintf(stderr,
4259                                     gettext("incompatible options\n"));
4260                                 usage(B_FALSE);
4261                         } else
4262                                 cb.cb_type = POOL_SCAN_NONE;
4263                         break;
4264                 case 'M':
4265                         if (cb.cb_type != POOL_SCAN_SCRUB) {
4266                                 (void) fprintf(stderr,
4267                                     gettext("incompatible options\n"));
4268                                 usage(B_FALSE);
4269                         } else
4270                                 cb.cb_type = POOL_SCAN_MOS;
4271                         break;
4272                 case 'm':
4273                         if (cb.cb_type != POOL_SCAN_SCRUB) {
4274                                 (void) fprintf(stderr,
4275                                     gettext("incompatible options\n"));
4276                                 usage(B_FALSE);
4277                         } else
4278                                 cb.cb_type = POOL_SCAN_META;
4279                         break;
4280                 case 'p':
4281                         cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
4282                         break;
4283                 case '?':
4284                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4285                             optopt);
4286                         usage(B_FALSE);
4287                 }
4288         }
4289 
4290         if (cb.cb_type == POOL_SCAN_NONE &&
4291             cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
4292                 (void) fprintf(stderr, gettext("invalid option combination: "
4293                     "-s and -p are mutually exclusive\n"));
4294                 usage(B_FALSE);
4295         }
4296 
4297         cb.cb_argc = argc;
4298         cb.cb_argv = argv;
4299         argc -= optind;
4300         argv += optind;
4301 
4302         if (argc < 1) {
4303                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4304                 usage(B_FALSE);
4305         }
4306 
4307         return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
4308 }
4309 
4310 /*
4311  * zpool trim [-s|-r <rate>] <pool> ...
4312  *
4313  *      -s              Stop. Stops any in-progress trim.
4314  *      -r <rate> Sets the TRIM rate.
4315  */
4316 int
4317 zpool_do_trim(int argc, char **argv)
4318 {
4319         int c;
4320         trim_cbdata_t cb;
4321 
4322         cb.cb_start = B_TRUE;
4323         cb.cb_rate = 0;
4324 
4325         /* check options */
4326         while ((c = getopt(argc, argv, "sr:")) != -1) {
4327                 switch (c) {
4328                 case 's':
4329                         cb.cb_start = B_FALSE;
4330                         break;
4331                 case 'r':
4332                         if (zfs_nicestrtonum(NULL, optarg, &cb.cb_rate) == -1) {
4333                                 (void) fprintf(stderr,
4334                                     gettext("invalid value for rate\n"));
4335                                 usage(B_FALSE);
4336                         }
4337                         break;
4338                 case '?':
4339                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4340                             optopt);
4341                         usage(B_FALSE);
4342                 }
4343         }
4344 
4345         argc -= optind;
4346         argv += optind;
4347 
4348         if (argc < 1) {
4349                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4350                 usage(B_FALSE);
4351         }
4352 
4353         return (for_each_pool(argc, argv, B_TRUE, NULL, trim_callback, &cb));
4354 }
4355 
4356 typedef struct status_cbdata {
4357         int             cb_count;
4358         boolean_t       cb_allpools;
4359         boolean_t       cb_verbose;
4360         boolean_t       cb_explain;
4361         boolean_t       cb_first;
4362         boolean_t       cb_dedup_stats;
4363 } status_cbdata_t;
4364 
4365 /*
4366  * Print out detailed scrub status.
4367  */
4368 void
4369 print_scan_status(pool_scan_stat_t *ps)
4370 {
4371         time_t start, end, pause;
4372         uint64_t elapsed, mins_left, hours_left;
4373         uint64_t examined, total;
4374         uint64_t rate, proc_rate;
4375         double fraction_done;
4376         char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7],
4377             issued_buf[7];
4378 
4379         (void) printf(gettext("  scan: "));
4380 
4381         /* If there's never been a scan, there's not much to say. */
4382         if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
4383             ps->pss_func >= POOL_SCAN_FUNCS) {
4384                 (void) printf(gettext("none requested\n"));
4385                 return;
4386         }
4387 
4388         start = ps->pss_start_time;
4389         end = ps->pss_end_time;
4390         pause = ps->pss_pass_scrub_pause;
4391         zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
4392 
4393         assert(ps->pss_func == POOL_SCAN_SCRUB ||
4394             ps->pss_func == POOL_SCAN_RESILVER ||
4395             ps->pss_func == POOL_SCAN_MOS ||
4396             ps->pss_func == POOL_SCAN_META);
4397         /*
4398          * Scan is finished or canceled.
4399          */
4400         if (ps->pss_state == DSS_FINISHED) {
4401                 uint64_t minutes_taken = (end - start) / 60;
4402                 char *fmt = NULL;
4403 
4404                 if (ps->pss_func == POOL_SCAN_SCRUB) {
4405                         fmt = gettext("scrub repaired %s in %lluh%um with "
4406                             "%llu errors on %s");
4407                 } else if (ps->pss_func == POOL_SCAN_MOS) {
4408                         fmt = gettext("MOS scrub repaired %s in %lluh%um with "
4409                             "%llu errors on %s");
4410                 } else if (ps->pss_func == POOL_SCAN_META) {
4411                         fmt = gettext("meta scrub repaired %s in %lluh%um with "
4412                             "%llu errors on %s");
4413                 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4414                         fmt = gettext("resilvered %s in %lluh%um with "
4415                             "%llu errors on %s");
4416                 }
4417                 /* LINTED */
4418                 (void) printf(fmt, processed_buf,
4419                     (u_longlong_t)(minutes_taken / 60),
4420                     (uint_t)(minutes_taken % 60),
4421                     (u_longlong_t)ps->pss_errors,
4422                     ctime((time_t *)&end));
4423                 return;
4424         } else if (ps->pss_state == DSS_CANCELED) {
4425                 if (ps->pss_func == POOL_SCAN_SCRUB) {
4426                         (void) printf(gettext("scrub canceled on %s"),
4427                             ctime(&end));
4428                 } else if (ps->pss_func == POOL_SCAN_MOS) {
4429                         (void) printf(gettext("MOS scrub canceled on %s"),
4430                             ctime(&end));
4431                 } else if (ps->pss_func == POOL_SCAN_META) {
4432                         (void) printf(gettext("meta scrub canceled on %s"),
4433                             ctime(&end));
4434                 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4435                         (void) printf(gettext("resilver canceled on %s"),
4436                             ctime(&end));
4437                 }
4438                 return;
4439         }
4440 
4441         assert(ps->pss_state == DSS_SCANNING || ps->pss_state == DSS_FINISHING);
4442 
4443         /*
4444          * Scan is in progress.
4445          */
4446         if (ps->pss_func == POOL_SCAN_SCRUB) {
4447                 if (pause == 0) {
4448                         (void) printf(gettext("scrub in progress since %s"),
4449                             ctime(&start));
4450                 } else {
4451                         char buf[32];
4452                         struct tm *p = localtime(&pause);
4453                         (void) strftime(buf, sizeof (buf), "%a %b %e %T %Y", p);
4454                         (void) printf(gettext("scrub paused since %s\n"), buf);
4455                         (void) printf(gettext("\tscrub started on   %s"),
4456                             ctime(&start));
4457                 }
4458         } else if (ps->pss_func == POOL_SCAN_MOS) {
4459                 (void) printf(gettext("MOS scrub in progress since %s"),
4460                     ctime(&start));
4461         } else if (ps->pss_func == POOL_SCAN_META) {
4462                 (void) printf(gettext("meta scrub in progress since %s"),
4463                     ctime(&start));
4464         } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4465                 (void) printf(gettext("resilver in progress since %s"),
4466                     ctime(&start));
4467         }
4468 
4469         examined = ps->pss_examined;
4470         total = ps->pss_to_examine;
4471         fraction_done = (double)ps->pss_issued / total;
4472 
4473         /* elapsed time for this pass */
4474         elapsed = MAX(time(NULL) - ps->pss_start_time -
4475             ps->pss_pass_scrub_spent_paused, 1);
4476         if (ps->pss_func == POOL_SCAN_RESILVER) {
4477                 rate = MAX(((ps->pss_issued + ps->pss_processed) / 2) /
4478                     elapsed, 1);
4479         } else {
4480                 rate = MAX(ps->pss_issued / elapsed, 1);
4481         }
4482         proc_rate = MAX(ps->pss_processed / elapsed, 1);
4483         if (ps->pss_func == POOL_SCAN_RESILVER)
4484                 mins_left = ((total - ps->pss_issued) / proc_rate) / 60;
4485         else
4486                 mins_left = ((total - ps->pss_issued) / rate) / 60;
4487         hours_left = mins_left / 60;
4488 
4489         zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
4490         zfs_nicenum(ps->pss_issued, issued_buf, sizeof (issued_buf));
4491         zfs_nicenum(total, total_buf, sizeof (total_buf));
4492         zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4493 
4494         if (pause == 0) {
4495                 (void) printf(gettext("        %s scanned, %s verified "
4496                     "out of %s at %s/s, %.2f%% done\n"), examined_buf,
4497                     issued_buf, total_buf, rate_buf, 100 * fraction_done);
4498         }
4499 
4500         if (ps->pss_func == POOL_SCAN_RESILVER) {
4501                 char proc_rate_buf[7];
4502                 zfs_nicenum(proc_rate, proc_rate_buf,
4503                     sizeof (proc_rate_buf));
4504                 (void) printf(gettext("        %s resilvered at %s/s"),
4505                     processed_buf, proc_rate_buf);
4506         } else if (ps->pss_func == POOL_SCAN_SCRUB ||
4507             ps->pss_func == POOL_SCAN_MOS ||
4508                     ps->pss_func == POOL_SCAN_META) {
4509                 (void) printf(gettext("        %s repaired"),
4510                     processed_buf);
4511         }
4512 
4513         /*
4514          * do not print estimated time if hours_left is more than 30 days
4515          * or we have a paused scrub
4516          */
4517         if (pause == 0) {
4518                 if (hours_left < (30 * 24)) {
4519                         (void) printf(gettext(", %lluh%um to go\n"),
4520                             (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4521                 } else {
4522                         (void) printf(gettext(
4523                             ", (scan is slow, no estimated time)\n"));
4524                 }
4525         } else {
4526                 (void) printf(gettext("\t%s scanned, %s verified out of %s\n"),
4527                     examined_buf, issued_buf, total_buf);
4528         }
4529 }
4530 
4531 static void
4532 print_trim_status(uint64_t trim_prog, uint64_t total_size, uint64_t rate,
4533     uint64_t start_time_u64, uint64_t end_time_u64)
4534 {
4535         time_t start_time = start_time_u64, end_time = end_time_u64;
4536         char *buf;
4537 
4538         assert(trim_prog <= total_size);
4539         if (trim_prog != 0 && trim_prog != total_size) {
4540                 buf = ctime(&start_time);
4541                 buf[strlen(buf) - 1] = '\0';    /* strip trailing newline */
4542                 if (rate != 0) {
4543                         char rate_str[32];
4544                         zfs_nicenum(rate, rate_str, sizeof (rate_str));
4545                         (void) printf("  trim: %.02f%%\tstarted: %s\t"
4546                             "(rate: %s/s)\n", (((double)trim_prog) /
4547                             total_size) * 100, buf, rate_str);
4548                 } else {
4549                         (void) printf("  trim: %.02f%%\tstarted: %s\t"
4550                             "(rate: max)\n", (((double)trim_prog) /
4551                             total_size) * 100, buf);
4552                 }
4553         } else {
4554                 if (start_time != 0) {
4555                         /*
4556                          * Non-zero start time means we were run at some point
4557                          * in the past.
4558                          */
4559                         if (end_time != 0) {
4560                                 /* Non-zero end time means we completed */
4561                                 time_t diff = end_time - start_time;
4562                                 int hrs, mins;
4563 
4564                                 buf = ctime(&end_time);
4565                                 buf[strlen(buf) - 1] = '\0';
4566                                 hrs = diff / 3600;
4567                                 mins = (diff % 3600) / 60;
4568                                 (void) printf(gettext("  trim: completed on %s "
4569                                     "(after %dh%dm)\n"), buf, hrs, mins);
4570                         } else {
4571                                 buf = ctime(&start_time);
4572                                 buf[strlen(buf) - 1] = '\0';
4573                                 /* Zero end time means we were interrupted */
4574                                 (void) printf(gettext("  trim: interrupted\t"
4575                                     "(started %s)\n"), buf);
4576                         }
4577                 } else {
4578                         /* trim was never run */
4579                         (void) printf(gettext("  trim: none requested\n"));
4580                 }
4581         }
4582 }
4583 
4584 static void
4585 print_error_log(zpool_handle_t *zhp)
4586 {
4587         nvlist_t *nverrlist = NULL;
4588         nvpair_t *elem;
4589         char *pathname;
4590         size_t len = MAXPATHLEN * 2;
4591 
4592         if (zpool_get_errlog(zhp, &nverrlist) != 0) {
4593                 (void) printf("errors: List of errors unavailable "
4594                     "(insufficient privileges)\n");
4595                 return;
4596         }
4597 
4598         (void) printf("errors: Permanent errors have been "
4599             "detected in the following files:\n\n");
4600 
 
4676         (void) printf("\n");
4677         (void) printf(gettext(" dedup: "));
4678         if (ddo->ddo_count == 0) {
4679                 (void) printf(gettext("no DDT entries\n"));
4680                 return;
4681         }
4682 
4683         (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
4684             (u_longlong_t)ddo->ddo_count,
4685             (u_longlong_t)ddo->ddo_dspace,
4686             (u_longlong_t)ddo->ddo_mspace);
4687 
4688         verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
4689             (uint64_t **)&dds, &c) == 0);
4690         verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
4691             (uint64_t **)&ddh, &c) == 0);
4692         zpool_dump_ddt(dds, ddh);
4693 }
4694 
4695 /*
4696  * Calculates the total space available on log devices on the pool.
4697  * For whatever reason, this is not counted in the root vdev's space stats.
4698  */
4699 static uint64_t
4700 zpool_slog_space(nvlist_t *nvroot)
4701 {
4702         nvlist_t **newchild;
4703         uint_t c, children;
4704         uint64_t space = 0;
4705 
4706         verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4707             &newchild, &children) == 0);
4708 
4709         for (c = 0; c < children; c++) {
4710                 uint64_t islog = B_FALSE;
4711                 vdev_stat_t *vs;
4712                 uint_t n;
4713                 uint_t n_subchildren = 1;
4714                 nvlist_t **subchild;
4715 
4716                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
4717                     &islog);
4718                 if (!islog)
4719                         continue;
4720                 verify(nvlist_lookup_uint64_array(newchild[c],
4721                     ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &n) == 0);
4722 
4723                 /* vdev can be non-leaf, so multiply by number of children */
4724                 (void) nvlist_lookup_nvlist_array(newchild[c],
4725                     ZPOOL_CONFIG_CHILDREN, &subchild, &n_subchildren);
4726                 space += n_subchildren * vs->vs_space;
4727         }
4728 
4729         return (space);
4730 }
4731 
4732 /*
4733  * Display a summary of pool status.  Displays a summary such as:
4734  *
4735  *        pool: tank
4736  *      status: DEGRADED
4737  *      reason: One or more devices ...
4738  *         see: http://illumos.org/msg/ZFS-xxxx-01
4739  *      config:
4740  *              mirror          DEGRADED
4741  *                c1t0d0        OK
4742  *                c2t0d0        UNAVAIL
4743  *
4744  * When given the '-v' option, we print out the complete config.  If the '-e'
4745  * option is specified, then we print out error rate information as well.
4746  */
4747 int
4748 status_callback(zpool_handle_t *zhp, void *data)
4749 {
4750         status_cbdata_t *cbp = data;
4751         nvlist_t *config, *nvroot;
4752         char *msgid;
 
4765          * problems.
4766          */
4767         if (cbp->cb_explain &&
4768             (reason == ZPOOL_STATUS_OK ||
4769             reason == ZPOOL_STATUS_VERSION_OLDER ||
4770             reason == ZPOOL_STATUS_FEAT_DISABLED)) {
4771                 if (!cbp->cb_allpools) {
4772                         (void) printf(gettext("pool '%s' is healthy\n"),
4773                             zpool_get_name(zhp));
4774                         if (cbp->cb_first)
4775                                 cbp->cb_first = B_FALSE;
4776                 }
4777                 return (0);
4778         }
4779 
4780         if (cbp->cb_first)
4781                 cbp->cb_first = B_FALSE;
4782         else
4783                 (void) printf("\n");
4784 
4785         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
4786             &nvroot) == 0);
4787         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
4788             (uint64_t **)&vs, &c) == 0);
4789         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
4790 
4791         (void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
4792         (void) printf(gettext(" state: %s\n"), health);
4793 
4794         switch (reason) {
4795         case ZPOOL_STATUS_MISSING_DEV_R:
4796                 (void) printf(gettext("status: One or more devices could not "
4797                     "be opened.  Sufficient replicas exist for\n\tthe pool to "
4798                     "continue functioning in a degraded state.\n"));
4799                 (void) printf(gettext("action: Attach the missing device and "
4800                     "online it using 'zpool online'.\n"));
4801                 break;
4802 
4803         case ZPOOL_STATUS_MISSING_DEV_NR:
4804                 (void) printf(gettext("status: One or more devices could not "
4805                     "be opened.  There are insufficient\n\treplicas for the "
4806                     "pool to continue functioning.\n"));
 
4974                     "'zpool clear'.\n"));
4975                 break;
4976 
4977         default:
4978                 /*
4979                  * The remaining errors can't actually be generated, yet.
4980                  */
4981                 assert(reason == ZPOOL_STATUS_OK);
4982         }
4983 
4984         if (msgid != NULL)
4985                 (void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
4986                     msgid);
4987 
4988         if (config != NULL) {
4989                 int namewidth;
4990                 uint64_t nerr;
4991                 nvlist_t **spares, **l2cache;
4992                 uint_t nspares, nl2cache;
4993                 pool_scan_stat_t *ps = NULL;
4994                 uint64_t trim_prog, trim_rate, trim_start_time, trim_stop_time;
4995 
4996                 (void) nvlist_lookup_uint64_array(nvroot,
4997                     ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4998                 print_scan_status(ps);
4999 
5000                 /* Grab trim stats if the pool supports it */
5001                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_PROG,
5002                     &trim_prog) == 0 &&
5003                     nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_RATE,
5004                     &trim_rate) == 0 &&
5005                     nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_START_TIME,
5006                     &trim_start_time) == 0 &&
5007                     nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_STOP_TIME,
5008                     &trim_stop_time) == 0) {
5009                         /*
5010                          * For whatever reason, root vdev_stats_t don't
5011                          * include log devices.
5012                          */
5013                         print_trim_status(trim_prog, vs->vs_space +
5014                             zpool_slog_space(nvroot), trim_rate,
5015                             trim_start_time, trim_stop_time);
5016                 }
5017 
5018                 namewidth = max_width(zhp, nvroot, 0, 0);
5019                 if (namewidth < 10)
5020                         namewidth = 10;
5021 
5022                 (void) printf(gettext("config:\n\n"));
5023                 (void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
5024                     "NAME", "STATE", "READ", "WRITE", "CKSUM");
5025                 print_status_config(zhp, zpool_get_name(zhp), nvroot,
5026                     namewidth, 0, B_FALSE);
5027 
5028                 if (num_special(nvroot) > 0)
5029                         print_special(zhp, nvroot, namewidth, B_TRUE);
5030                 if (num_logs(nvroot) > 0)
5031                         print_logs(zhp, nvroot, namewidth, B_TRUE);
5032                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
5033                     &l2cache, &nl2cache) == 0)
5034                         print_l2cache(zhp, l2cache, nl2cache, namewidth);
5035 
5036                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
5037                     &spares, &nspares) == 0)
5038                         print_spares(zhp, spares, nspares, namewidth);
5039 
5040                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
5041                     &nerr) == 0) {
5042                         nvlist_t *nverrlist = NULL;
5043 
5044                         /*
5045                          * If the approximate error count is small, get a
5046                          * precise count by fetching the entire log and
5047                          * uniquifying the results.
5048                          */
5049                         if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
 
5189                     "'%s' from version %llu to feature flags.\n"),
5190                     zpool_get_name(zhp), oldversion);
5191         } else {
5192                 (void) printf(gettext("Successfully upgraded "
5193                     "'%s' from version %llu to version %llu.\n"),
5194                     zpool_get_name(zhp), oldversion, version);
5195         }
5196 
5197         return (0);
5198 }
5199 
5200 static int
5201 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
5202 {
5203         int i, ret, count;
5204         boolean_t firstff = B_TRUE;
5205         nvlist_t *enabled = zpool_get_features(zhp);
5206 
5207         count = 0;
5208         for (i = 0; i < SPA_FEATURES; i++) {
5209                 zfeature_info_t *finfo = &spa_feature_table[i];
5210                 const char *fname = finfo->fi_uname;
5211                 const char *fguid = finfo->fi_guid;
5212                 if (!nvlist_exists(enabled, fguid)) {
5213                         char *propname;
5214 
5215                         /*
5216                          * SPA_FEATURE_WBC can be enabled only
5217                          * if 'special' vdev available
5218                          */
5219                         if (finfo->fi_feature == SPA_FEATURE_WBC)
5220                                 continue;
5221 
5222                         verify(-1 != asprintf(&propname, "feature@%s", fname));
5223                         ret = zpool_set_prop(zhp, propname,
5224                             ZFS_FEATURE_ENABLED);
5225                         if (ret != 0) {
5226                                 free(propname);
5227                                 return (ret);
5228                         }
5229                         count++;
5230 
5231                         if (firstff) {
5232                                 (void) printf(gettext("Enabled the "
5233                                     "following features on '%s':\n"),
5234                                     zpool_get_name(zhp));
5235                                 firstff = B_FALSE;
5236                         }
5237                         (void) printf(gettext("  %s\n"), fname);
5238                         free(propname);
5239                 }
5240         }
5241 
 
5959 
5960         if (cb.cb_proplist != NULL) {
5961                 fake_name.pl_prop = ZPOOL_PROP_NAME;
5962                 fake_name.pl_width = strlen(gettext("NAME"));
5963                 fake_name.pl_next = cb.cb_proplist;
5964                 cb.cb_proplist = &fake_name;
5965         }
5966 
5967         ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
5968             get_callback, &cb);
5969 
5970         if (cb.cb_proplist == &fake_name)
5971                 zprop_free_list(fake_name.pl_next);
5972         else
5973                 zprop_free_list(cb.cb_proplist);
5974 
5975         return (ret);
5976 }
5977 
5978 typedef struct set_cbdata {
5979         nvlist_t *cb_nvl;
5980         boolean_t cb_any_successful;
5981 } set_cbdata_t;
5982 
5983 int
5984 set_callback(zpool_handle_t *zhp, void *data)
5985 {
5986         int error;
5987         set_cbdata_t *cb = (set_cbdata_t *)data;
5988 
5989         error = zpool_set_proplist(zhp, cb->cb_nvl);
5990         if (!error)
5991                 cb->cb_any_successful = B_TRUE;
5992 
5993         return (error);
5994 }
5995 
5996 static void
5997 parse_props(char *propname, nvlist_t **nvl, zfs_type_t prop_type)
5998 {
5999         char *propval;
6000         char *delim;
6001         int err;
6002 
6003         do {
6004                 delim = strchr(propname, ',');
6005                 if (delim != NULL)
6006                         *delim++ = '\0';
6007 
6008                 propval = strchr(propname, '=');
6009                 if (propval == NULL) {
6010                         (void) fprintf(stderr, gettext("missing value "
6011                             "in property=value argument\n"));
6012                         if (*nvl != NULL)
6013                                 nvlist_free(*nvl);
6014                         usage(B_FALSE);
6015                 }
6016                 *propval++ = '\0';
6017                 switch (prop_type) {
6018                 case ZFS_TYPE_VDEV:
6019                         err = add_vdev_prop_list(propname, propval, nvl);
6020                         break;
6021                 case ZFS_TYPE_COS:
6022                         err = add_cos_prop_list(propname, propval, nvl);
6023                         break;
6024                 default:
6025                         err = add_prop_list(propname, propval, nvl, B_TRUE);
6026                 }
6027 
6028                 if (err) {
6029                         if (*nvl != NULL)
6030                                 nvlist_free(*nvl);
6031                         usage(B_FALSE);
6032                 }
6033 
6034                 propname = delim;
6035         } while (delim != NULL);
6036 }
6037 
6038 int
6039 zpool_do_set(int argc, char **argv)
6040 {
6041         set_cbdata_t cb = { 0 };
6042         int error;
6043 
6044         if (argc > 1 && argv[1][0] == '-') {
6045                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6046                     argv[1][1]);
6047                 usage(B_FALSE);
6048         }
6049 
6050         if (argc < 2) {
6051                 (void) fprintf(stderr, gettext("missing property=value "
6052                     "argument\n"));
6053                 usage(B_FALSE);
6054         }
6055 
6056         if (argc < 3) {
6057                 (void) fprintf(stderr, gettext("missing pool name\n"));
6058                 usage(B_FALSE);
6059         }
6060 
6061         if (argc > 3) {
6062                 (void) fprintf(stderr, gettext("too many pool names\n"));
6063                 usage(B_FALSE);
6064         }
6065 
6066         parse_props(argv[1], &cb.cb_nvl, ZFS_TYPE_POOL);
6067 
6068         error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
6069             set_callback, &cb);
6070 
6071         return (error);
6072 }
6073 
6074 typedef struct vdev_cbdata {
6075         char *vcb_vdev;
6076         nvlist_t *vcb_nvl; /* values */
6077         boolean_t vcb_any_successful;
6078 } vdev_cbdata_t;
6079 
6080 typedef struct vdev_get_cbdata {
6081         zprop_get_cbdata_t vcb_zprop_get_cbdata;
6082         char *vcb_vdev;
6083         nvlist_t *vcb_nvl; /* values */
6084         boolean_t vcb_any_successful;
6085 } vdev_get_cbdata_t;
6086 
6087 static int
6088 vdev_get_callback(zpool_handle_t *zhp, void *data)
6089 {
6090         int err;
6091         boolean_t l2cache, avail_space;
6092         vdev_get_cbdata_t *vcb = (vdev_get_cbdata_t *)data;
6093         zprop_get_cbdata_t *cb = &vcb->vcb_zprop_get_cbdata;
6094         char value[MAXNAMELEN];
6095         zprop_list_t *pl;
6096 
6097         (void) zpool_find_vdev(zhp, vcb->vcb_vdev, &avail_space,
6098             &l2cache, NULL, NULL);
6099         for (pl = cb->cb_proplist; pl != NULL; pl = pl->pl_next) {
6100                 if ((err = vdev_get_prop(zhp, vcb->vcb_vdev,
6101                     pl->pl_prop, value, sizeof (value))) != 0)
6102                         return (err);
6103 
6104                 /* don't show L2ARC prop for non L2ARC dev, can't set anyway */
6105                 if (!l2cache && pl->pl_prop == VDEV_PROP_L2ADDDT)
6106                         continue;
6107                 vdev_print_one_property(zpool_get_name(zhp), vcb->vcb_vdev, cb,
6108                     vdev_prop_to_name(pl->pl_prop), value);
6109         }
6110 
6111         return (0);
6112 }
6113 
6114 
6115 int
6116 zpool_do_vdev_get(int argc, char **argv)
6117 {
6118         vdev_get_cbdata_t vcb = { 0 };
6119         zprop_get_cbdata_t *cb = &vcb.vcb_zprop_get_cbdata;
6120         int error;
6121 
6122         if (argc > 1 && argv[1][0] == '-') {
6123                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6124                     argv[1][1]);
6125                 usage(B_FALSE);
6126         }
6127 
6128         if (argc < 2) {
6129                 (void) fprintf(stderr, gettext("missing property name\n"));
6130                 usage(B_FALSE);
6131         }
6132 
6133         if (argc < 3) {
6134                 (void) fprintf(stderr, gettext("missing pool name\n"));
6135                 usage(B_FALSE);
6136         }
6137 
6138         if (argc < 4) {
6139                 (void) fprintf(stderr,
6140                     gettext("at least one vdev name or guid is required\n"));
6141                 usage(B_FALSE);
6142         }
6143 
6144         cb->cb_first = B_TRUE;
6145         cb->cb_sources = ZPROP_SRC_ALL;
6146         cb->cb_columns[0] = GET_COL_NAME;
6147         cb->cb_columns[1] = GET_COL_SOURCE;
6148         cb->cb_columns[2] = GET_COL_PROPERTY;
6149         cb->cb_columns[3] = GET_COL_VALUE;
6150         cb->cb_type = ZFS_TYPE_VDEV;
6151 
6152         if (vdev_get_proplist(g_zfs, argv[1], &cb->cb_proplist) != 0)
6153                 usage(B_FALSE);
6154 
6155         vcb.vcb_vdev = argv[3];
6156         error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6157             vdev_get_callback, &vcb);
6158 
6159         zprop_free_list(cb->cb_proplist);
6160 
6161         return (error);
6162 }
6163 
6164 int
6165 vdev_set_callback(zpool_handle_t *zhp, void *data)
6166 {
6167         int error;
6168         vdev_cbdata_t *cb = (vdev_cbdata_t *)data;
6169 
6170         error = vdev_set_proplist(zhp, cb->vcb_vdev, cb->vcb_nvl);
6171         if (!error)
6172                 cb->vcb_any_successful = B_TRUE;
6173 
6174         return (error);
6175 }
6176 
6177 int
6178 zpool_do_vdev_set(int argc, char **argv)
6179 {
6180         vdev_cbdata_t cb = { 0 };
6181         int error;
6182 
6183         if (argc > 1 && argv[1][0] == '-') {
6184                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6185                     argv[1][1]);
6186                 usage(B_FALSE);
6187         }
6188 
6189         if (argc < 2) {
6190                 (void) fprintf(stderr, gettext("missing property=value "
6191                     "argument\n"));
6192                 usage(B_FALSE);
6193         }
6194 
6195         if (argc < 3) {
6196                 (void) fprintf(stderr, gettext("missing pool name\n"));
6197                 usage(B_FALSE);
6198         }
6199 
6200         if (argc < 4) {
6201                 (void) fprintf(stderr,
6202                     gettext("at least one vdev name or guid is required\n"));
6203                 usage(B_FALSE);
6204         }
6205 
6206         parse_props(argv[1], &cb.vcb_nvl, ZFS_TYPE_VDEV);
6207 
6208         cb.vcb_vdev = argv[3];
6209         error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6210             vdev_set_callback, &cb);
6211 
6212         return (error);
6213 }
6214 
6215 typedef struct cos_af_cbdata {
6216         char *cb_cos;
6217         uint64_t cb_guid;
6218         boolean_t cb_alloc;
6219         boolean_t cb_any_successful;
6220         boolean_t cb_force;
6221         nvlist_t *cb_nvl;
6222 } cos_af_cbdata_t;
6223 
6224 int
6225 cos_alloc_callback(zpool_handle_t *zhp, void *data)
6226 {
6227         int error;
6228         cos_af_cbdata_t *cb = (cos_af_cbdata_t *)data;
6229 
6230         if (cb->cb_alloc)
6231                 error = cos_alloc(zhp, cb->cb_cos, cb->cb_nvl);
6232         else
6233                 error = cos_free(zhp, cb->cb_cos, cb->cb_guid, cb->cb_force);
6234         if (!error)
6235                 cb->cb_any_successful = B_TRUE;
6236 
6237         if (error == ENOTSUP) {
6238                 (void) fprintf(stderr, gettext("operation failed: "
6239                     "CoS feature is disabled.\n"));
6240         }
6241 
6242         return (error);
6243 }
6244 
6245 int
6246 zpool_do_cos_alloc(int argc, char **argv)
6247 {
6248         nvlist_t *nvl;
6249         cos_af_cbdata_t cb = { 0 };
6250         int error;
6251 
6252         if (!nexenta_meta_enable())
6253                 return (-1);
6254 
6255         if (argc < 2) {
6256                 (void) fprintf(stderr, gettext("missing pool name\n"));
6257                 usage(B_FALSE);
6258         }
6259 
6260         if (argc < 3) {
6261                 (void) fprintf(stderr,
6262                     gettext("at least one cos name or id is required\n"));
6263                 usage(B_FALSE);
6264         }
6265 
6266         if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
6267                 (void) fprintf(stderr,
6268                     gettext("internal error: out of memory\n"));
6269                 return (1);
6270         }
6271 
6272         cb.cb_cos = argv[2];
6273         cb.cb_alloc = B_TRUE;
6274         cb.cb_nvl = nvl;
6275         error = for_each_pool(1, argv + 1, B_TRUE, NULL,
6276             cos_alloc_callback, &cb);
6277 
6278         nvlist_free(nvl);
6279 
6280         return (error);
6281 }
6282 
6283 int
6284 zpool_do_cos_free(int argc, char **argv)
6285 {
6286         cos_af_cbdata_t cb = { 0 };
6287         char *endp;
6288         int error;
6289 
6290         if (!nexenta_meta_enable())
6291                 return (-1);
6292 
6293         if (argc > 1 && strncmp(argv[1], "-f", sizeof ("-f")) == 0) {
6294                 /* -f - force option */
6295                 cb.cb_force = B_TRUE;
6296                 argc--;
6297                 argv++;
6298         }
6299 
6300         if (argc < 2) {
6301                 (void) fprintf(stderr, gettext("missing pool name\n"));
6302                 usage(B_FALSE);
6303         }
6304 
6305         if (argc < 3) {
6306                 (void) fprintf(stderr,
6307                     gettext("at least one cos name or id is required\n"));
6308                 usage(B_FALSE);
6309         }
6310 
6311         cb.cb_guid = strtoll(argv[2], &endp, 10);
6312         if (endp <  argv[2] + strlen(argv[2])) {
6313                 cb.cb_guid = 0;
6314         }
6315 
6316         if (cb.cb_guid == 0)
6317                 cb.cb_cos = argv[2];
6318         else
6319                 cb.cb_cos = "";
6320 
6321         error = for_each_pool(1, argv + 1, B_TRUE, NULL,
6322             cos_alloc_callback, &cb);
6323 
6324         return (error);
6325 }
6326 
6327 
6328 static int
6329 cos_list_callback(zpool_handle_t *zhp, void *data)
6330 {
6331         int err, i;
6332         nvlist_t *nvl = (nvlist_t *)data;
6333         nvpair_t *nvp;
6334 
6335         if ((err = cos_list(zhp, &nvl)) == 0) {
6336                 (void) printf("%-*s %s\n", MAXCOSNAMELEN, gettext("COSNAME"),
6337                     gettext("COSID"));
6338                 for (i = 0, nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
6339                     nvp = nvlist_next_nvpair(nvl, nvp), i++) {
6340                         uint64_t cosid;
6341                         char *cosname = nvpair_name(nvp);
6342                         if (nvpair_value_uint64(nvp, &cosid) == 0)
6343                                 (void) printf("%-*s %llu\n", MAXCOSNAMELEN,
6344                                     cosname, cosid);
6345                 }
6346 
6347                 if (!i)
6348                         (void) printf("%s\n", gettext("<no classes found>"));
6349         }
6350         return (err);
6351 }
6352 
6353 int
6354 zpool_do_cos_list(int argc, char **argv)
6355 {
6356         nvlist_t *nvl;
6357         int error;
6358 
6359         if (!nexenta_meta_enable())
6360                 return (-1);
6361 
6362         if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
6363                 (void) fprintf(stderr,
6364                     gettext("internal error: out of memory\n"));
6365                 return (1);
6366         }
6367 
6368         if (argc < 2) {
6369                 (void) fprintf(stderr, gettext("missing pool name\n"));
6370                 usage(B_FALSE);
6371         }
6372 
6373         error = for_each_pool(1, argv+1, B_TRUE, NULL,
6374             cos_list_callback, nvl);
6375 
6376         nvlist_free(nvl);
6377 
6378         return (error);
6379 
6380 }
6381 
6382 typedef struct cos_cbdata {
6383         char *vcb_cos;
6384         nvlist_t *vcb_nvl; /* values */
6385         boolean_t vcb_any_successful;
6386 } cos_cbdata_t;
6387 
6388 typedef struct cos_get_cbdata {
6389         zprop_get_cbdata_t vcb_zprop_get_cbdata;
6390         char *vcb_cos;
6391         nvlist_t *vcb_nvl; /* values */
6392         boolean_t vcb_any_successful;
6393 } cos_get_cbdata_t;
6394 
6395 static int
6396 cos_get_callback(zpool_handle_t *zhp, void *data)
6397 {
6398         int err;
6399         cos_get_cbdata_t *vcb = (cos_get_cbdata_t *)data;
6400         zprop_get_cbdata_t *cb = &vcb->vcb_zprop_get_cbdata;
6401         char value[MAXNAMELEN];
6402         zprop_list_t *pl;
6403         nvlist_t *nvl = NULL;
6404 
6405         for (pl = cb->cb_proplist; pl != NULL; pl = pl->pl_next) {
6406                 if ((err = cos_get_prop(zhp, vcb->vcb_cos,
6407                     pl->pl_prop, value, sizeof (value), &nvl)) != 0)
6408                         return (err);
6409 
6410                 cos_print_one_property(zpool_get_name(zhp), vcb->vcb_cos, cb,
6411                     cos_prop_to_name(pl->pl_prop), value);
6412         }
6413 
6414         return (0);
6415 }
6416 
6417 
6418 int
6419 zpool_do_cos_get(int argc, char **argv)
6420 {
6421         cos_get_cbdata_t vcb = { 0 };
6422         zprop_get_cbdata_t *cb = &vcb.vcb_zprop_get_cbdata;
6423         int error;
6424 
6425         if (!nexenta_meta_enable())
6426                 return (-1);
6427 
6428         if (argc > 1 && argv[1][0] == '-') {
6429                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6430                     argv[1][1]);
6431                 usage(B_FALSE);
6432         }
6433 
6434         if (argc < 2) {
6435                 (void) fprintf(stderr, gettext("missing property name\n"));
6436                 usage(B_FALSE);
6437         }
6438 
6439         if (argc < 3) {
6440                 (void) fprintf(stderr, gettext("missing pool name\n"));
6441                 usage(B_FALSE);
6442         }
6443 
6444         if (argc < 4) {
6445                 (void) fprintf(stderr,
6446                     gettext("at least one cos name or guid is required\n"));
6447                 usage(B_FALSE);
6448         }
6449 
6450         cb->cb_first = B_TRUE;
6451         cb->cb_sources = ZPROP_SRC_ALL;
6452         cb->cb_columns[0] = GET_COL_NAME;
6453         cb->cb_columns[1] = GET_COL_SOURCE;
6454         cb->cb_columns[2] = GET_COL_PROPERTY;
6455         cb->cb_columns[3] = GET_COL_VALUE;
6456         cb->cb_type = ZFS_TYPE_COS;
6457 
6458         if (cos_get_proplist(g_zfs, argv[1],  &cb->cb_proplist) != 0)
6459                 usage(B_FALSE);
6460 
6461         vcb.vcb_cos = argv[3];
6462         error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6463             cos_get_callback, &vcb);
6464 
6465         zprop_free_list(cb->cb_proplist);
6466 
6467         return (error);
6468 
6469 }
6470 
6471 int
6472 cos_set_callback(zpool_handle_t *zhp, void *data)
6473 {
6474         int error;
6475         cos_cbdata_t *cb = (cos_cbdata_t *)data;
6476 
6477         error = cos_set_proplist(zhp, cb->vcb_cos, cb->vcb_nvl);
6478         if (!error)
6479                 cb->vcb_any_successful = B_TRUE;
6480 
6481         return (error);
6482 }
6483 
6484 int
6485 zpool_do_cos_set(int argc, char **argv)
6486 {
6487         cos_cbdata_t cb = { 0 };
6488         int error;
6489 
6490         if (!nexenta_meta_enable())
6491                 return (-1);
6492 
6493         if (argc > 1 && argv[1][0] == '-') {
6494                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6495                     argv[1][1]);
6496                 usage(B_FALSE);
6497         }
6498 
6499         if (argc < 2) {
6500                 (void) fprintf(stderr, gettext("missing property=value "
6501                     "argument\n"));
6502                 usage(B_FALSE);
6503         }
6504 
6505         if (argc < 3) {
6506                 (void) fprintf(stderr, gettext("missing pool name\n"));
6507                 usage(B_FALSE);
6508         }
6509 
6510         if (argc < 4) {
6511                 (void) fprintf(stderr,
6512                     gettext("at least one cos name or id is required\n"));
6513                 usage(B_FALSE);
6514         }
6515 
6516         parse_props(argv[1], &cb.vcb_nvl, ZFS_TYPE_COS);
6517 
6518         cb.vcb_cos = argv[3];
6519         error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6520             cos_set_callback, &cb);
6521 
6522         return (error);
6523 }
6524 
6525 static int
6526 find_command_idx(char *command, int *idx)
6527 {
6528         int i;
6529 
6530         for (i = 0; i < NCOMMAND; i++) {
6531                 if (command_table[i].name == NULL)
6532                         continue;
6533 
6534                 if (strcmp(command, command_table[i].name) == 0) {
6535                         *idx = i;
6536                         return (0);
6537                 }
6538         }
6539         return (1);
6540 }
6541 
6542 int
6543 main(int argc, char **argv)
6544 {
6545         int ret = 0;
 
6559 
6560         opterr = 0;
6561 
6562         /*
6563          * Make sure the user has specified some command.
6564          */
6565         if (argc < 2) {
6566                 (void) fprintf(stderr, gettext("missing command\n"));
6567                 usage(B_FALSE);
6568         }
6569 
6570         cmdname = argv[1];
6571 
6572         /*
6573          * Special case '-?'
6574          */
6575         if (strcmp(cmdname, "-?") == 0)
6576                 usage(B_TRUE);
6577 
6578         zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
6579         verify(zpool_stage_history(g_zfs, history_str) == 0);
6580 
6581         /*
6582          * Run the appropriate command.
6583          */
6584         if (find_command_idx(cmdname, &i) == 0) {
6585                 current_command = &command_table[i];
6586                 ret = command_table[i].func(argc - 1, argv + 1);
6587         } else if (strchr(cmdname, '=')) {
6588                 verify(find_command_idx("set", &i) == 0);
6589                 current_command = &command_table[i];
6590                 ret = command_table[i].func(argc, argv);
6591         } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
6592                 /*
6593                  * 'freeze' is a vile debugging abomination, so we treat
6594                  * it as such.
6595                  */
6596                 char buf[16384];
6597                 int fd = open(ZFS_DEV, O_RDWR);
6598                 (void) strcpy((void *)buf, argv[2]);
6599                 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
 
 |