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