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