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/lib/libzfs/common/libzfs_pool.c
          +++ new/usr/src/lib/libzfs/common/libzfs_pool.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, 2017 by Delphix. All rights reserved.
  25   25   * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  26   26   * Copyright 2016 Nexenta Systems, Inc.
  27   27   * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
  28   28   * Copyright (c) 2017 Datto Inc.
  29   29   */
  30   30  
  31   31  #include <ctype.h>
  32   32  #include <errno.h>
  33   33  #include <devid.h>
  34   34  #include <fcntl.h>
  35   35  #include <libintl.h>
  36   36  #include <stdio.h>
  37   37  #include <stdlib.h>
  38   38  #include <strings.h>
  39   39  #include <unistd.h>
  40   40  #include <libgen.h>
  41   41  #include <sys/efi_partition.h>
  42   42  #include <sys/vtoc.h>
  43   43  #include <sys/zfs_ioctl.h>
  44   44  #include <dlfcn.h>
  45   45  
  46   46  #include "zfs_namecheck.h"
  47   47  #include "zfs_prop.h"
  48   48  #include "libzfs_impl.h"
  49   49  #include "zfs_comutil.h"
  50   50  #include "zfeature_common.h"
  51   51  
  52   52  static int read_efi_label(nvlist_t *, diskaddr_t *, boolean_t *);
  53   53  static boolean_t zpool_vdev_is_interior(const char *name);
  54   54  
  55   55  #define BACKUP_SLICE    "s2"
  56   56  
  57   57  typedef struct prop_flags {
  58   58          int create:1;   /* Validate property on creation */
  59   59          int import:1;   /* Validate property on import */
  60   60  } prop_flags_t;
  61   61  
  62   62  /*
  63   63   * ====================================================================
  64   64   *   zpool property functions
  65   65   * ====================================================================
  66   66   */
  67   67  
  68   68  static int
  69   69  zpool_get_all_props(zpool_handle_t *zhp)
  70   70  {
  71   71          zfs_cmd_t zc = { 0 };
  72   72          libzfs_handle_t *hdl = zhp->zpool_hdl;
  73   73  
  74   74          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
  75   75  
  76   76          if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0)
  77   77                  return (-1);
  78   78  
  79   79          while (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_PROPS, &zc) != 0) {
  80   80                  if (errno == ENOMEM) {
  81   81                          if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
  82   82                                  zcmd_free_nvlists(&zc);
  83   83                                  return (-1);
  84   84                          }
  85   85                  } else {
  86   86                          zcmd_free_nvlists(&zc);
  87   87                          return (-1);
  88   88                  }
  89   89          }
  90   90  
  91   91          if (zcmd_read_dst_nvlist(hdl, &zc, &zhp->zpool_props) != 0) {
  92   92                  zcmd_free_nvlists(&zc);
  93   93                  return (-1);
  94   94          }
  95   95  
  96   96          zcmd_free_nvlists(&zc);
  97   97  
  98   98          return (0);
  99   99  }
 100  100  
 101  101  static int
 102  102  zpool_props_refresh(zpool_handle_t *zhp)
 103  103  {
 104  104          nvlist_t *old_props;
 105  105  
 106  106          old_props = zhp->zpool_props;
 107  107  
 108  108          if (zpool_get_all_props(zhp) != 0)
 109  109                  return (-1);
 110  110  
 111  111          nvlist_free(old_props);
 112  112          return (0);
 113  113  }
 114  114  
 115  115  static char *
 116  116  zpool_get_prop_string(zpool_handle_t *zhp, zpool_prop_t prop,
 117  117      zprop_source_t *src)
 118  118  {
 119  119          nvlist_t *nv, *nvl;
 120  120          uint64_t ival;
 121  121          char *value;
 122  122          zprop_source_t source;
 123  123  
 124  124          nvl = zhp->zpool_props;
 125  125          if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) {
 126  126                  verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &ival) == 0);
 127  127                  source = ival;
 128  128                  verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
 129  129          } else {
 130  130                  source = ZPROP_SRC_DEFAULT;
 131  131                  if ((value = (char *)zpool_prop_default_string(prop)) == NULL)
 132  132                          value = "-";
 133  133          }
 134  134  
 135  135          if (src)
 136  136                  *src = source;
 137  137  
 138  138          return (value);
 139  139  }
 140  140  
 141  141  uint64_t
 142  142  zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop, zprop_source_t *src)
 143  143  {
 144  144          nvlist_t *nv, *nvl;
 145  145          uint64_t value;
 146  146          zprop_source_t source;
 147  147  
 148  148          if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) {
 149  149                  /*
 150  150                   * zpool_get_all_props() has most likely failed because
 151  151                   * the pool is faulted, but if all we need is the top level
 152  152                   * vdev's guid then get it from the zhp config nvlist.
 153  153                   */
 154  154                  if ((prop == ZPOOL_PROP_GUID) &&
 155  155                      (nvlist_lookup_nvlist(zhp->zpool_config,
 156  156                      ZPOOL_CONFIG_VDEV_TREE, &nv) == 0) &&
 157  157                      (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &value)
 158  158                      == 0)) {
 159  159                          return (value);
 160  160                  }
 161  161                  return (zpool_prop_default_numeric(prop));
 162  162          }
 163  163  
 164  164          nvl = zhp->zpool_props;
 165  165          if (nvlist_lookup_nvlist(nvl, zpool_prop_to_name(prop), &nv) == 0) {
 166  166                  verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE, &value) == 0);
 167  167                  source = value;
 168  168                  verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0);
 169  169          } else {
 170  170                  source = ZPROP_SRC_DEFAULT;
 171  171                  value = zpool_prop_default_numeric(prop);
 172  172          }
 173  173  
 174  174          if (src)
 175  175                  *src = source;
 176  176  
 177  177          return (value);
 178  178  }
 179  179  
 180  180  /*
 181  181   * Map VDEV STATE to printed strings.
 182  182   */
 183  183  const char *
 184  184  zpool_state_to_name(vdev_state_t state, vdev_aux_t aux)
 185  185  {
 186  186          switch (state) {
 187  187          case VDEV_STATE_CLOSED:
 188  188          case VDEV_STATE_OFFLINE:
 189  189                  return (gettext("OFFLINE"));
 190  190          case VDEV_STATE_REMOVED:
 191  191                  return (gettext("REMOVED"));
 192  192          case VDEV_STATE_CANT_OPEN:
 193  193                  if (aux == VDEV_AUX_CORRUPT_DATA || aux == VDEV_AUX_BAD_LOG)
 194  194                          return (gettext("FAULTED"));
 195  195                  else if (aux == VDEV_AUX_SPLIT_POOL)
 196  196                          return (gettext("SPLIT"));
 197  197                  else
 198  198                          return (gettext("UNAVAIL"));
 199  199          case VDEV_STATE_FAULTED:
 200  200                  return (gettext("FAULTED"));
 201  201          case VDEV_STATE_DEGRADED:
 202  202                  return (gettext("DEGRADED"));
 203  203          case VDEV_STATE_HEALTHY:
 204  204                  return (gettext("ONLINE"));
 205  205  
 206  206          default:
 207  207                  break;
 208  208          }
 209  209  
 210  210          return (gettext("UNKNOWN"));
 211  211  }
 212  212  
 213  213  /*
 214  214   * Map POOL STATE to printed strings.
 215  215   */
 216  216  const char *
 217  217  zpool_pool_state_to_name(pool_state_t state)
 218  218  {
 219  219          switch (state) {
 220  220          case POOL_STATE_ACTIVE:
 221  221                  return (gettext("ACTIVE"));
 222  222          case POOL_STATE_EXPORTED:
 223  223                  return (gettext("EXPORTED"));
 224  224          case POOL_STATE_DESTROYED:
 225  225                  return (gettext("DESTROYED"));
 226  226          case POOL_STATE_SPARE:
 227  227                  return (gettext("SPARE"));
 228  228          case POOL_STATE_L2CACHE:
 229  229                  return (gettext("L2CACHE"));
 230  230          case POOL_STATE_UNINITIALIZED:
 231  231                  return (gettext("UNINITIALIZED"));
 232  232          case POOL_STATE_UNAVAIL:
 233  233                  return (gettext("UNAVAIL"));
 234  234          case POOL_STATE_POTENTIALLY_ACTIVE:
 235  235                  return (gettext("POTENTIALLY_ACTIVE"));
 236  236          }
 237  237  
 238  238          return (gettext("UNKNOWN"));
 239  239  }
 240  240  
 241  241  /*
 242  242   * Get a zpool property value for 'prop' and return the value in
 243  243   * a pre-allocated buffer.
 244  244   */
 245  245  int
 246  246  zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
 247  247      zprop_source_t *srctype, boolean_t literal)
 248  248  {
 249  249          uint64_t intval;
 250  250          const char *strval;
 251  251          zprop_source_t src = ZPROP_SRC_NONE;
 252  252          nvlist_t *nvroot;
 253  253          vdev_stat_t *vs;
 254  254          uint_t vsc;
 255  255  
 256  256          if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
 257  257                  switch (prop) {
 258  258                  case ZPOOL_PROP_NAME:
 259  259                          (void) strlcpy(buf, zpool_get_name(zhp), len);
 260  260                          break;
 261  261  
 262  262                  case ZPOOL_PROP_HEALTH:
 263  263                          (void) strlcpy(buf, "FAULTED", len);
 264  264                          break;
 265  265  
 266  266                  case ZPOOL_PROP_GUID:
 267  267                          intval = zpool_get_prop_int(zhp, prop, &src);
 268  268                          (void) snprintf(buf, len, "%llu", intval);
 269  269                          break;
 270  270  
 271  271                  case ZPOOL_PROP_ALTROOT:
 272  272                  case ZPOOL_PROP_CACHEFILE:
 273  273                  case ZPOOL_PROP_COMMENT:
 274  274                          if (zhp->zpool_props != NULL ||
 275  275                              zpool_get_all_props(zhp) == 0) {
 276  276                                  (void) strlcpy(buf,
 277  277                                      zpool_get_prop_string(zhp, prop, &src),
 278  278                                      len);
 279  279                                  break;
 280  280                          }
 281  281                          /* FALLTHROUGH */
 282  282                  default:
 283  283                          (void) strlcpy(buf, "-", len);
 284  284                          break;
 285  285                  }
 286  286  
 287  287                  if (srctype != NULL)
 288  288                          *srctype = src;
 289  289                  return (0);
 290  290          }
 291  291  
 292  292          if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) &&
 293  293              prop != ZPOOL_PROP_NAME)
 294  294                  return (-1);
 295  295  
 296  296          switch (zpool_prop_get_type(prop)) {
 297  297          case PROP_TYPE_STRING:
 298  298                  (void) strlcpy(buf, zpool_get_prop_string(zhp, prop, &src),
 299  299                      len);
 300  300                  break;
 301  301  
 302  302          case PROP_TYPE_NUMBER:
 303  303                  intval = zpool_get_prop_int(zhp, prop, &src);
 304  304  
 305  305                  switch (prop) {
 306  306                  case ZPOOL_PROP_SIZE:
 307  307                  case ZPOOL_PROP_ALLOCATED:
 308  308                  case ZPOOL_PROP_FREE:
 309  309                  case ZPOOL_PROP_FREEING:
 310  310                  case ZPOOL_PROP_LEAKED:
 311  311                          if (literal) {
 312  312                                  (void) snprintf(buf, len, "%llu",
 313  313                                      (u_longlong_t)intval);
 314  314                          } else {
 315  315                                  (void) zfs_nicenum(intval, buf, len);
 316  316                          }
 317  317                          break;
 318  318                  case ZPOOL_PROP_BOOTSIZE:
 319  319                  case ZPOOL_PROP_EXPANDSZ:
 320  320                  case ZPOOL_PROP_CHECKPOINT:
 321  321                          if (intval == 0) {
 322  322                                  (void) strlcpy(buf, "-", len);
 323  323                          } else if (literal) {
 324  324                                  (void) snprintf(buf, len, "%llu",
 325  325                                      (u_longlong_t)intval);
 326  326                          } else {
 327  327                                  (void) zfs_nicenum(intval, buf, len);
 328  328                          }
 329  329                          break;
 330  330                  case ZPOOL_PROP_CAPACITY:
 331  331                          if (literal) {
 332  332                                  (void) snprintf(buf, len, "%llu",
 333  333                                      (u_longlong_t)intval);
 334  334                          } else {
 335  335                                  (void) snprintf(buf, len, "%llu%%",
 336  336                                      (u_longlong_t)intval);
 337  337                          }
 338  338                          break;
 339  339                  case ZPOOL_PROP_FRAGMENTATION:
 340  340                          if (intval == UINT64_MAX) {
 341  341                                  (void) strlcpy(buf, "-", len);
 342  342                          } else {
 343  343                                  (void) snprintf(buf, len, "%llu%%",
 344  344                                      (u_longlong_t)intval);
 345  345                          }
 346  346                          break;
 347  347                  case ZPOOL_PROP_DEDUPRATIO:
 348  348                          (void) snprintf(buf, len, "%llu.%02llux",
 349  349                              (u_longlong_t)(intval / 100),
 350  350                              (u_longlong_t)(intval % 100));
 351  351                          break;
 352  352                  case ZPOOL_PROP_HEALTH:
 353  353                          verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
 354  354                              ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
 355  355                          verify(nvlist_lookup_uint64_array(nvroot,
 356  356                              ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &vsc)
 357  357                              == 0);
 358  358  
 359  359                          (void) strlcpy(buf, zpool_state_to_name(intval,
 360  360                              vs->vs_aux), len);
 361  361                          break;
 362  362                  case ZPOOL_PROP_VERSION:
 363  363                          if (intval >= SPA_VERSION_FEATURES) {
 364  364                                  (void) snprintf(buf, len, "-");
 365  365                                  break;
 366  366                          }
 367  367                          /* FALLTHROUGH */
 368  368                  default:
 369  369                          (void) snprintf(buf, len, "%llu", intval);
 370  370                  }
 371  371                  break;
 372  372  
 373  373          case PROP_TYPE_INDEX:
 374  374                  intval = zpool_get_prop_int(zhp, prop, &src);
 375  375                  if (zpool_prop_index_to_string(prop, intval, &strval)
 376  376                      != 0)
 377  377                          return (-1);
 378  378                  (void) strlcpy(buf, strval, len);
 379  379                  break;
 380  380  
 381  381          default:
 382  382                  abort();
 383  383          }
 384  384  
 385  385          if (srctype)
 386  386                  *srctype = src;
 387  387  
 388  388          return (0);
 389  389  }
 390  390  
 391  391  /*
 392  392   * Check if the bootfs name has the same pool name as it is set to.
 393  393   * Assuming bootfs is a valid dataset name.
 394  394   */
 395  395  static boolean_t
 396  396  bootfs_name_valid(const char *pool, char *bootfs)
 397  397  {
 398  398          int len = strlen(pool);
 399  399          if (bootfs[0] == '\0')
 400  400                  return (B_TRUE);
 401  401  
 402  402          if (!zfs_name_valid(bootfs, ZFS_TYPE_FILESYSTEM|ZFS_TYPE_SNAPSHOT))
 403  403                  return (B_FALSE);
 404  404  
 405  405          if (strncmp(pool, bootfs, len) == 0 &&
 406  406              (bootfs[len] == '/' || bootfs[len] == '\0'))
 407  407                  return (B_TRUE);
 408  408  
 409  409          return (B_FALSE);
 410  410  }
 411  411  
 412  412  boolean_t
 413  413  zpool_is_bootable(zpool_handle_t *zhp)
 414  414  {
 415  415          char bootfs[ZFS_MAX_DATASET_NAME_LEN];
 416  416  
 417  417          return (zpool_get_prop(zhp, ZPOOL_PROP_BOOTFS, bootfs,
 418  418              sizeof (bootfs), NULL, B_FALSE) == 0 && strncmp(bootfs, "-",
 419  419              sizeof (bootfs)) != 0);
 420  420  }
 421  421  
 422  422  
 423  423  /*
 424  424   * Given an nvlist of zpool properties to be set, validate that they are
 425  425   * correct, and parse any numeric properties (index, boolean, etc) if they are
 426  426   * specified as strings.
 427  427   */
 428  428  static nvlist_t *
 429  429  zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
 430  430      nvlist_t *props, uint64_t version, prop_flags_t flags, char *errbuf)
 431  431  {
 432  432          nvpair_t *elem;
 433  433          nvlist_t *retprops;
 434  434          zpool_prop_t prop;
 435  435          char *strval;
 436  436          uint64_t intval;
 437  437          char *slash, *check;
 438  438          struct stat64 statbuf;
 439  439          zpool_handle_t *zhp;
 440  440  
 441  441          if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) {
 442  442                  (void) no_memory(hdl);
 443  443                  return (NULL);
 444  444          }
 445  445  
 446  446          elem = NULL;
 447  447          while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
 448  448                  const char *propname = nvpair_name(elem);
 449  449  
 450  450                  prop = zpool_name_to_prop(propname);
 451  451                  if (prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname)) {
 452  452                          int err;
 453  453                          char *fname = strchr(propname, '@') + 1;
 454  454  
 455  455                          err = zfeature_lookup_name(fname, NULL);
 456  456                          if (err != 0) {
 457  457                                  ASSERT3U(err, ==, ENOENT);
 458  458                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 459  459                                      "invalid feature '%s'"), fname);
 460  460                                  (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 461  461                                  goto error;
 462  462                          }
 463  463  
 464  464                          if (nvpair_type(elem) != DATA_TYPE_STRING) {
 465  465                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 466  466                                      "'%s' must be a string"), propname);
 467  467                                  (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 468  468                                  goto error;
 469  469                          }
 470  470  
 471  471                          (void) nvpair_value_string(elem, &strval);
 472  472                          if (strcmp(strval, ZFS_FEATURE_ENABLED) != 0) {
 473  473                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 474  474                                      "property '%s' can only be set to "
 475  475                                      "'enabled'"), propname);
 476  476                                  (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 477  477                                  goto error;
 478  478                          }
 479  479  
 480  480                          if (nvlist_add_uint64(retprops, propname, 0) != 0) {
 481  481                                  (void) no_memory(hdl);
 482  482                                  goto error;
 483  483                          }
 484  484                          continue;
 485  485                  }
 486  486  
 487  487                  /*
 488  488                   * Make sure this property is valid and applies to this type.
 489  489                   */
 490  490                  if (prop == ZPOOL_PROP_INVAL) {
 491  491                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 492  492                              "invalid property '%s'"), propname);
 493  493                          (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 494  494                          goto error;
 495  495                  }
 496  496  
 497  497                  if (zpool_prop_readonly(prop)) {
 498  498                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
 499  499                              "is readonly"), propname);
 500  500                          (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
 501  501                          goto error;
 502  502                  }
 503  503  
 504  504                  if (zprop_parse_value(hdl, elem, prop, ZFS_TYPE_POOL, retprops,
 505  505                      &strval, &intval, errbuf) != 0)
 506  506                          goto error;
 507  507  
 508  508                  /*
 509  509                   * Perform additional checking for specific properties.
 510  510                   */
 511  511                  switch (prop) {
 512  512                  case ZPOOL_PROP_VERSION:
 513  513                          if (intval < version ||
 514  514                              !SPA_VERSION_IS_SUPPORTED(intval)) {
 515  515                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 516  516                                      "property '%s' number %d is invalid."),
 517  517                                      propname, intval);
 518  518                                  (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
 519  519                                  goto error;
 520  520                          }
 521  521                          break;
 522  522  
 523  523                  case ZPOOL_PROP_BOOTSIZE:
 524  524                          if (!flags.create) {
 525  525                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 526  526                                      "property '%s' can only be set during pool "
 527  527                                      "creation"), propname);
 528  528                                  (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 529  529                                  goto error;
 530  530                          }
 531  531                          break;
 532  532  
 533  533                  case ZPOOL_PROP_BOOTFS:
 534  534                          if (flags.create || flags.import) {
 535  535                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 536  536                                      "property '%s' cannot be set at creation "
 537  537                                      "or import time"), propname);
 538  538                                  (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 539  539                                  goto error;
 540  540                          }
 541  541  
 542  542                          if (version < SPA_VERSION_BOOTFS) {
 543  543                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 544  544                                      "pool must be upgraded to support "
 545  545                                      "'%s' property"), propname);
 546  546                                  (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
 547  547                                  goto error;
 548  548                          }
 549  549  
 550  550                          /*
 551  551                           * bootfs property value has to be a dataset name and
 552  552                           * the dataset has to be in the same pool as it sets to.
 553  553                           */
 554  554                          if (!bootfs_name_valid(poolname, strval)) {
 555  555                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
 556  556                                      "is an invalid name"), strval);
 557  557                                  (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
 558  558                                  goto error;
 559  559                          }
 560  560  
 561  561                          if ((zhp = zpool_open_canfail(hdl, poolname)) == NULL) {
 562  562                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 563  563                                      "could not open pool '%s'"), poolname);
 564  564                                  (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf);
 565  565                                  goto error;
 566  566                          }
 567  567                          zpool_close(zhp);
 568  568                          break;
 569  569  
 570  570                  case ZPOOL_PROP_ALTROOT:
 571  571                          if (!flags.create && !flags.import) {
 572  572                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 573  573                                      "property '%s' can only be set during pool "
 574  574                                      "creation or import"), propname);
 575  575                                  (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 576  576                                  goto error;
 577  577                          }
 578  578  
 579  579                          if (strval[0] != '/') {
 580  580                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 581  581                                      "bad alternate root '%s'"), strval);
 582  582                                  (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
 583  583                                  goto error;
 584  584                          }
 585  585                          break;
 586  586  
 587  587                  case ZPOOL_PROP_CACHEFILE:
 588  588                          if (strval[0] == '\0')
 589  589                                  break;
 590  590  
 591  591                          if (strcmp(strval, "none") == 0)
 592  592                                  break;
 593  593  
 594  594                          if (strval[0] != '/') {
 595  595                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 596  596                                      "property '%s' must be empty, an "
 597  597                                      "absolute path, or 'none'"), propname);
 598  598                                  (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
 599  599                                  goto error;
 600  600                          }
 601  601  
 602  602                          slash = strrchr(strval, '/');
 603  603  
 604  604                          if (slash[1] == '\0' || strcmp(slash, "/.") == 0 ||
 605  605                              strcmp(slash, "/..") == 0) {
 606  606                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 607  607                                      "'%s' is not a valid file"), strval);
 608  608                                  (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
 609  609                                  goto error;
 610  610                          }
 611  611  
 612  612                          *slash = '\0';
 613  613  
 614  614                          if (strval[0] != '\0' &&
 615  615                              (stat64(strval, &statbuf) != 0 ||
 616  616                              !S_ISDIR(statbuf.st_mode))) {
 617  617                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 618  618                                      "'%s' is not a valid directory"),
 619  619                                      strval);
 620  620                                  (void) zfs_error(hdl, EZFS_BADPATH, errbuf);
 621  621                                  goto error;
 622  622                          }
 623  623  
 624  624                          *slash = '/';
 625  625                          break;
 626  626  
 627  627                  case ZPOOL_PROP_COMMENT:
 628  628                          for (check = strval; *check != '\0'; check++) {
 629  629                                  if (!isprint(*check)) {
 630  630                                          zfs_error_aux(hdl,
 631  631                                              dgettext(TEXT_DOMAIN,
 632  632                                              "comment may only have printable "
 633  633                                              "characters"));
 634  634                                          (void) zfs_error(hdl, EZFS_BADPROP,
 635  635                                              errbuf);
 636  636                                          goto error;
  
    | 
      ↓ open down ↓ | 
    636 lines elided | 
    
      ↑ open up ↑ | 
  
 637  637                                  }
 638  638                          }
 639  639                          if (strlen(strval) > ZPROP_MAX_COMMENT) {
 640  640                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 641  641                                      "comment must not exceed %d characters"),
 642  642                                      ZPROP_MAX_COMMENT);
 643  643                                  (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 644  644                                  goto error;
 645  645                          }
 646  646                          break;
      647 +
 647  648                  case ZPOOL_PROP_READONLY:
 648  649                          if (!flags.import) {
 649  650                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 650  651                                      "property '%s' can only be set at "
 651  652                                      "import time"), propname);
 652  653                                  (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 653  654                                  goto error;
      655 +                        }
      656 +                        break;
      657 +
      658 +                case ZPOOL_PROP_TNAME:
      659 +                        if (!flags.create) {
      660 +                                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
      661 +                                    "property '%s' can only be set at "
      662 +                                    "creation time"), propname);
      663 +                                (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
      664 +                                goto error;
 654  665                          }
 655  666                          break;
 656  667  
 657  668                  default:
 658  669                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 659  670                              "property '%s'(%d) not defined"), propname, prop);
 660  671                          break;
 661  672                  }
 662  673          }
 663  674  
 664  675          return (retprops);
 665  676  error:
 666  677          nvlist_free(retprops);
 667  678          return (NULL);
 668  679  }
 669  680  
 670  681  /*
 671  682   * Set zpool property : propname=propval.
 672  683   */
 673  684  int
 674  685  zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval)
 675  686  {
 676  687          zfs_cmd_t zc = { 0 };
 677  688          int ret = -1;
 678  689          char errbuf[1024];
 679  690          nvlist_t *nvl = NULL;
 680  691          nvlist_t *realprops;
 681  692          uint64_t version;
 682  693          prop_flags_t flags = { 0 };
 683  694  
 684  695          (void) snprintf(errbuf, sizeof (errbuf),
 685  696              dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
 686  697              zhp->zpool_name);
 687  698  
 688  699          if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
 689  700                  return (no_memory(zhp->zpool_hdl));
 690  701  
 691  702          if (nvlist_add_string(nvl, propname, propval) != 0) {
 692  703                  nvlist_free(nvl);
 693  704                  return (no_memory(zhp->zpool_hdl));
 694  705          }
 695  706  
 696  707          version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
 697  708          if ((realprops = zpool_valid_proplist(zhp->zpool_hdl,
 698  709              zhp->zpool_name, nvl, version, flags, errbuf)) == NULL) {
 699  710                  nvlist_free(nvl);
 700  711                  return (-1);
 701  712          }
 702  713  
 703  714          nvlist_free(nvl);
 704  715          nvl = realprops;
 705  716  
 706  717          /*
 707  718           * Execute the corresponding ioctl() to set this property.
 708  719           */
 709  720          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
 710  721  
 711  722          if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl) != 0) {
 712  723                  nvlist_free(nvl);
 713  724                  return (-1);
 714  725          }
 715  726  
 716  727          ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SET_PROPS, &zc);
 717  728  
 718  729          zcmd_free_nvlists(&zc);
 719  730          nvlist_free(nvl);
 720  731  
 721  732          if (ret)
 722  733                  (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf);
 723  734          else
 724  735                  (void) zpool_props_refresh(zhp);
 725  736  
 726  737          return (ret);
 727  738  }
 728  739  
 729  740  int
 730  741  zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
 731  742  {
 732  743          libzfs_handle_t *hdl = zhp->zpool_hdl;
 733  744          zprop_list_t *entry;
 734  745          char buf[ZFS_MAXPROPLEN];
 735  746          nvlist_t *features = NULL;
 736  747          zprop_list_t **last;
 737  748          boolean_t firstexpand = (NULL == *plp);
 738  749  
 739  750          if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0)
 740  751                  return (-1);
 741  752  
 742  753          last = plp;
 743  754          while (*last != NULL)
 744  755                  last = &(*last)->pl_next;
 745  756  
 746  757          if ((*plp)->pl_all)
 747  758                  features = zpool_get_features(zhp);
 748  759  
 749  760          if ((*plp)->pl_all && firstexpand) {
 750  761                  for (int i = 0; i < SPA_FEATURES; i++) {
 751  762                          zprop_list_t *entry = zfs_alloc(hdl,
 752  763                              sizeof (zprop_list_t));
 753  764                          entry->pl_prop = ZPROP_INVAL;
 754  765                          entry->pl_user_prop = zfs_asprintf(hdl, "feature@%s",
 755  766                              spa_feature_table[i].fi_uname);
 756  767                          entry->pl_width = strlen(entry->pl_user_prop);
 757  768                          entry->pl_all = B_TRUE;
 758  769  
 759  770                          *last = entry;
 760  771                          last = &entry->pl_next;
 761  772                  }
 762  773          }
 763  774  
 764  775          /* add any unsupported features */
 765  776          for (nvpair_t *nvp = nvlist_next_nvpair(features, NULL);
 766  777              nvp != NULL; nvp = nvlist_next_nvpair(features, nvp)) {
 767  778                  char *propname;
 768  779                  boolean_t found;
 769  780                  zprop_list_t *entry;
 770  781  
 771  782                  if (zfeature_is_supported(nvpair_name(nvp)))
 772  783                          continue;
 773  784  
 774  785                  propname = zfs_asprintf(hdl, "unsupported@%s",
 775  786                      nvpair_name(nvp));
 776  787  
 777  788                  /*
 778  789                   * Before adding the property to the list make sure that no
 779  790                   * other pool already added the same property.
 780  791                   */
 781  792                  found = B_FALSE;
 782  793                  entry = *plp;
 783  794                  while (entry != NULL) {
 784  795                          if (entry->pl_user_prop != NULL &&
 785  796                              strcmp(propname, entry->pl_user_prop) == 0) {
 786  797                                  found = B_TRUE;
 787  798                                  break;
 788  799                          }
 789  800                          entry = entry->pl_next;
 790  801                  }
 791  802                  if (found) {
 792  803                          free(propname);
 793  804                          continue;
 794  805                  }
 795  806  
 796  807                  entry = zfs_alloc(hdl, sizeof (zprop_list_t));
 797  808                  entry->pl_prop = ZPROP_INVAL;
 798  809                  entry->pl_user_prop = propname;
 799  810                  entry->pl_width = strlen(entry->pl_user_prop);
 800  811                  entry->pl_all = B_TRUE;
 801  812  
 802  813                  *last = entry;
 803  814                  last = &entry->pl_next;
 804  815          }
 805  816  
 806  817          for (entry = *plp; entry != NULL; entry = entry->pl_next) {
 807  818  
 808  819                  if (entry->pl_fixed)
 809  820                          continue;
 810  821  
 811  822                  if (entry->pl_prop != ZPROP_INVAL &&
 812  823                      zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf),
 813  824                      NULL, B_FALSE) == 0) {
 814  825                          if (strlen(buf) > entry->pl_width)
 815  826                                  entry->pl_width = strlen(buf);
 816  827                  }
 817  828          }
 818  829  
 819  830          return (0);
 820  831  }
 821  832  
 822  833  /*
 823  834   * Get the state for the given feature on the given ZFS pool.
 824  835   */
 825  836  int
 826  837  zpool_prop_get_feature(zpool_handle_t *zhp, const char *propname, char *buf,
 827  838      size_t len)
 828  839  {
 829  840          uint64_t refcount;
 830  841          boolean_t found = B_FALSE;
 831  842          nvlist_t *features = zpool_get_features(zhp);
 832  843          boolean_t supported;
 833  844          const char *feature = strchr(propname, '@') + 1;
 834  845  
 835  846          supported = zpool_prop_feature(propname);
 836  847          ASSERT(supported || zpool_prop_unsupported(propname));
 837  848  
 838  849          /*
 839  850           * Convert from feature name to feature guid. This conversion is
 840  851           * unecessary for unsupported@... properties because they already
 841  852           * use guids.
 842  853           */
 843  854          if (supported) {
 844  855                  int ret;
 845  856                  spa_feature_t fid;
 846  857  
 847  858                  ret = zfeature_lookup_name(feature, &fid);
 848  859                  if (ret != 0) {
 849  860                          (void) strlcpy(buf, "-", len);
 850  861                          return (ENOTSUP);
 851  862                  }
 852  863                  feature = spa_feature_table[fid].fi_guid;
 853  864          }
 854  865  
 855  866          if (nvlist_lookup_uint64(features, feature, &refcount) == 0)
 856  867                  found = B_TRUE;
 857  868  
 858  869          if (supported) {
 859  870                  if (!found) {
 860  871                          (void) strlcpy(buf, ZFS_FEATURE_DISABLED, len);
 861  872                  } else  {
 862  873                          if (refcount == 0)
 863  874                                  (void) strlcpy(buf, ZFS_FEATURE_ENABLED, len);
 864  875                          else
 865  876                                  (void) strlcpy(buf, ZFS_FEATURE_ACTIVE, len);
 866  877                  }
 867  878          } else {
 868  879                  if (found) {
 869  880                          if (refcount == 0) {
 870  881                                  (void) strcpy(buf, ZFS_UNSUPPORTED_INACTIVE);
 871  882                          } else {
 872  883                                  (void) strcpy(buf, ZFS_UNSUPPORTED_READONLY);
 873  884                          }
 874  885                  } else {
 875  886                          (void) strlcpy(buf, "-", len);
 876  887                          return (ENOTSUP);
 877  888                  }
 878  889          }
 879  890  
 880  891          return (0);
 881  892  }
 882  893  
 883  894  /*
 884  895   * Don't start the slice at the default block of 34; many storage
 885  896   * devices will use a stripe width of 128k, so start there instead.
 886  897   */
 887  898  #define NEW_START_BLOCK 256
 888  899  
 889  900  /*
 890  901   * Validate the given pool name, optionally putting an extended error message in
 891  902   * 'buf'.
 892  903   */
 893  904  boolean_t
 894  905  zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool)
 895  906  {
 896  907          namecheck_err_t why;
 897  908          char what;
 898  909          int ret;
 899  910  
 900  911          ret = pool_namecheck(pool, &why, &what);
 901  912  
 902  913          /*
 903  914           * The rules for reserved pool names were extended at a later point.
 904  915           * But we need to support users with existing pools that may now be
 905  916           * invalid.  So we only check for this expanded set of names during a
 906  917           * create (or import), and only in userland.
 907  918           */
 908  919          if (ret == 0 && !isopen &&
 909  920              (strncmp(pool, "mirror", 6) == 0 ||
 910  921              strncmp(pool, "raidz", 5) == 0 ||
 911  922              strncmp(pool, "spare", 5) == 0 ||
 912  923              strcmp(pool, "log") == 0)) {
 913  924                  if (hdl != NULL)
 914  925                          zfs_error_aux(hdl,
 915  926                              dgettext(TEXT_DOMAIN, "name is reserved"));
 916  927                  return (B_FALSE);
 917  928          }
 918  929  
 919  930  
 920  931          if (ret != 0) {
 921  932                  if (hdl != NULL) {
 922  933                          switch (why) {
 923  934                          case NAME_ERR_TOOLONG:
 924  935                                  zfs_error_aux(hdl,
 925  936                                      dgettext(TEXT_DOMAIN, "name is too long"));
 926  937                                  break;
 927  938  
 928  939                          case NAME_ERR_INVALCHAR:
 929  940                                  zfs_error_aux(hdl,
 930  941                                      dgettext(TEXT_DOMAIN, "invalid character "
 931  942                                      "'%c' in pool name"), what);
 932  943                                  break;
 933  944  
 934  945                          case NAME_ERR_NOLETTER:
 935  946                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 936  947                                      "name must begin with a letter"));
 937  948                                  break;
 938  949  
 939  950                          case NAME_ERR_RESERVED:
 940  951                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 941  952                                      "name is reserved"));
 942  953                                  break;
 943  954  
 944  955                          case NAME_ERR_DISKLIKE:
 945  956                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 946  957                                      "pool name is reserved"));
 947  958                                  break;
 948  959  
 949  960                          case NAME_ERR_LEADING_SLASH:
 950  961                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 951  962                                      "leading slash in name"));
 952  963                                  break;
 953  964  
 954  965                          case NAME_ERR_EMPTY_COMPONENT:
 955  966                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 956  967                                      "empty component in name"));
 957  968                                  break;
 958  969  
 959  970                          case NAME_ERR_TRAILING_SLASH:
 960  971                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 961  972                                      "trailing slash in name"));
 962  973                                  break;
 963  974  
 964  975                          case NAME_ERR_MULTIPLE_DELIMITERS:
 965  976                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 966  977                                      "multiple '@' and/or '#' delimiters in "
 967  978                                      "name"));
 968  979                                  break;
 969  980  
 970  981                          default:
 971  982                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 972  983                                      "(%d) not defined"), why);
 973  984                                  break;
 974  985                          }
 975  986                  }
 976  987                  return (B_FALSE);
 977  988          }
 978  989  
 979  990          return (B_TRUE);
 980  991  }
 981  992  
 982  993  /*
 983  994   * Open a handle to the given pool, even if the pool is currently in the FAULTED
 984  995   * state.
 985  996   */
 986  997  zpool_handle_t *
 987  998  zpool_open_canfail(libzfs_handle_t *hdl, const char *pool)
 988  999  {
 989 1000          zpool_handle_t *zhp;
 990 1001          boolean_t missing;
 991 1002  
 992 1003          /*
 993 1004           * Make sure the pool name is valid.
 994 1005           */
 995 1006          if (!zpool_name_valid(hdl, B_TRUE, pool)) {
 996 1007                  (void) zfs_error_fmt(hdl, EZFS_INVALIDNAME,
 997 1008                      dgettext(TEXT_DOMAIN, "cannot open '%s'"),
 998 1009                      pool);
 999 1010                  return (NULL);
1000 1011          }
1001 1012  
1002 1013          if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
1003 1014                  return (NULL);
1004 1015  
1005 1016          zhp->zpool_hdl = hdl;
1006 1017          (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
1007 1018  
1008 1019          if (zpool_refresh_stats(zhp, &missing) != 0) {
1009 1020                  zpool_close(zhp);
1010 1021                  return (NULL);
1011 1022          }
1012 1023  
1013 1024          if (missing) {
1014 1025                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "no such pool"));
1015 1026                  (void) zfs_error_fmt(hdl, EZFS_NOENT,
1016 1027                      dgettext(TEXT_DOMAIN, "cannot open '%s'"), pool);
1017 1028                  zpool_close(zhp);
1018 1029                  return (NULL);
1019 1030          }
1020 1031  
1021 1032          return (zhp);
1022 1033  }
1023 1034  
1024 1035  /*
1025 1036   * Like the above, but silent on error.  Used when iterating over pools (because
1026 1037   * the configuration cache may be out of date).
1027 1038   */
1028 1039  int
1029 1040  zpool_open_silent(libzfs_handle_t *hdl, const char *pool, zpool_handle_t **ret)
1030 1041  {
1031 1042          zpool_handle_t *zhp;
1032 1043          boolean_t missing;
1033 1044  
1034 1045          if ((zhp = zfs_alloc(hdl, sizeof (zpool_handle_t))) == NULL)
1035 1046                  return (-1);
1036 1047  
1037 1048          zhp->zpool_hdl = hdl;
1038 1049          (void) strlcpy(zhp->zpool_name, pool, sizeof (zhp->zpool_name));
1039 1050  
1040 1051          if (zpool_refresh_stats(zhp, &missing) != 0) {
1041 1052                  zpool_close(zhp);
1042 1053                  return (-1);
1043 1054          }
1044 1055  
1045 1056          if (missing) {
1046 1057                  zpool_close(zhp);
1047 1058                  *ret = NULL;
1048 1059                  return (0);
1049 1060          }
1050 1061  
1051 1062          *ret = zhp;
1052 1063          return (0);
1053 1064  }
1054 1065  
1055 1066  /*
1056 1067   * Similar to zpool_open_canfail(), but refuses to open pools in the faulted
1057 1068   * state.
1058 1069   */
1059 1070  zpool_handle_t *
1060 1071  zpool_open(libzfs_handle_t *hdl, const char *pool)
1061 1072  {
1062 1073          zpool_handle_t *zhp;
1063 1074  
1064 1075          if ((zhp = zpool_open_canfail(hdl, pool)) == NULL)
1065 1076                  return (NULL);
1066 1077  
1067 1078          if (zhp->zpool_state == POOL_STATE_UNAVAIL) {
1068 1079                  (void) zfs_error_fmt(hdl, EZFS_POOLUNAVAIL,
1069 1080                      dgettext(TEXT_DOMAIN, "cannot open '%s'"), zhp->zpool_name);
1070 1081                  zpool_close(zhp);
1071 1082                  return (NULL);
1072 1083          }
1073 1084  
1074 1085          return (zhp);
1075 1086  }
1076 1087  
1077 1088  /*
1078 1089   * Close the handle.  Simply frees the memory associated with the handle.
1079 1090   */
1080 1091  void
1081 1092  zpool_close(zpool_handle_t *zhp)
1082 1093  {
1083 1094          nvlist_free(zhp->zpool_config);
1084 1095          nvlist_free(zhp->zpool_old_config);
1085 1096          nvlist_free(zhp->zpool_props);
1086 1097          free(zhp);
1087 1098  }
1088 1099  
1089 1100  /*
1090 1101   * Return the name of the pool.
1091 1102   */
1092 1103  const char *
1093 1104  zpool_get_name(zpool_handle_t *zhp)
1094 1105  {
1095 1106          return (zhp->zpool_name);
1096 1107  }
1097 1108  
1098 1109  
1099 1110  /*
1100 1111   * Return the state of the pool (ACTIVE or UNAVAILABLE)
1101 1112   */
1102 1113  int
1103 1114  zpool_get_state(zpool_handle_t *zhp)
1104 1115  {
1105 1116          return (zhp->zpool_state);
1106 1117  }
1107 1118  
1108 1119  /*
1109 1120   * Create the named pool, using the provided vdev list.  It is assumed
1110 1121   * that the consumer has already validated the contents of the nvlist, so we
1111 1122   * don't have to worry about error semantics.
1112 1123   */
1113 1124  int
1114 1125  zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
1115 1126      nvlist_t *props, nvlist_t *fsprops)
1116 1127  {
1117 1128          zfs_cmd_t zc = { 0 };
1118 1129          nvlist_t *zc_fsprops = NULL;
1119 1130          nvlist_t *zc_props = NULL;
1120 1131          char msg[1024];
1121 1132          int ret = -1;
1122 1133  
1123 1134          (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1124 1135              "cannot create '%s'"), pool);
1125 1136  
1126 1137          if (!zpool_name_valid(hdl, B_FALSE, pool))
1127 1138                  return (zfs_error(hdl, EZFS_INVALIDNAME, msg));
1128 1139  
1129 1140          if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
1130 1141                  return (-1);
1131 1142  
1132 1143          if (props) {
1133 1144                  prop_flags_t flags = { .create = B_TRUE, .import = B_FALSE };
1134 1145  
1135 1146                  if ((zc_props = zpool_valid_proplist(hdl, pool, props,
1136 1147                      SPA_VERSION_1, flags, msg)) == NULL) {
1137 1148                          goto create_failed;
1138 1149                  }
1139 1150          }
1140 1151  
1141 1152          if (fsprops) {
1142 1153                  uint64_t zoned;
1143 1154                  char *zonestr;
1144 1155  
1145 1156                  zoned = ((nvlist_lookup_string(fsprops,
1146 1157                      zfs_prop_to_name(ZFS_PROP_ZONED), &zonestr) == 0) &&
1147 1158                      strcmp(zonestr, "on") == 0);
1148 1159  
1149 1160                  if ((zc_fsprops = zfs_valid_proplist(hdl, ZFS_TYPE_FILESYSTEM,
1150 1161                      fsprops, zoned, NULL, NULL, msg)) == NULL) {
1151 1162                          goto create_failed;
1152 1163                  }
1153 1164                  if (!zc_props &&
1154 1165                      (nvlist_alloc(&zc_props, NV_UNIQUE_NAME, 0) != 0)) {
1155 1166                          goto create_failed;
1156 1167                  }
1157 1168                  if (nvlist_add_nvlist(zc_props,
1158 1169                      ZPOOL_ROOTFS_PROPS, zc_fsprops) != 0) {
1159 1170                          goto create_failed;
1160 1171                  }
1161 1172          }
1162 1173  
1163 1174          if (zc_props && zcmd_write_src_nvlist(hdl, &zc, zc_props) != 0)
1164 1175                  goto create_failed;
1165 1176  
1166 1177          (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name));
1167 1178  
1168 1179          if ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_CREATE, &zc)) != 0) {
1169 1180  
1170 1181                  zcmd_free_nvlists(&zc);
1171 1182                  nvlist_free(zc_props);
1172 1183                  nvlist_free(zc_fsprops);
1173 1184  
1174 1185                  switch (errno) {
1175 1186                  case EBUSY:
1176 1187                          /*
1177 1188                           * This can happen if the user has specified the same
1178 1189                           * device multiple times.  We can't reliably detect this
1179 1190                           * until we try to add it and see we already have a
1180 1191                           * label.
1181 1192                           */
1182 1193                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1183 1194                              "one or more vdevs refer to the same device"));
1184 1195                          return (zfs_error(hdl, EZFS_BADDEV, msg));
1185 1196  
1186 1197                  case ERANGE:
1187 1198                          /*
1188 1199                           * This happens if the record size is smaller or larger
1189 1200                           * than the allowed size range, or not a power of 2.
1190 1201                           *
1191 1202                           * NOTE: although zfs_valid_proplist is called earlier,
1192 1203                           * this case may have slipped through since the
1193 1204                           * pool does not exist yet and it is therefore
1194 1205                           * impossible to read properties e.g. max blocksize
1195 1206                           * from the pool.
1196 1207                           */
1197 1208                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1198 1209                              "record size invalid"));
1199 1210                          return (zfs_error(hdl, EZFS_BADPROP, msg));
1200 1211  
1201 1212                  case EOVERFLOW:
1202 1213                          /*
1203 1214                           * This occurs when one of the devices is below
1204 1215                           * SPA_MINDEVSIZE.  Unfortunately, we can't detect which
1205 1216                           * device was the problem device since there's no
1206 1217                           * reliable way to determine device size from userland.
1207 1218                           */
1208 1219                          {
1209 1220                                  char buf[64];
1210 1221  
1211 1222                                  zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
1212 1223  
1213 1224                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1214 1225                                      "one or more devices is less than the "
1215 1226                                      "minimum size (%s)"), buf);
1216 1227                          }
1217 1228                          return (zfs_error(hdl, EZFS_BADDEV, msg));
1218 1229  
1219 1230                  case ENOSPC:
1220 1231                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1221 1232                              "one or more devices is out of space"));
1222 1233                          return (zfs_error(hdl, EZFS_BADDEV, msg));
1223 1234  
1224 1235                  case ENOTBLK:
1225 1236                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1226 1237                              "cache device must be a disk or disk slice"));
1227 1238                          return (zfs_error(hdl, EZFS_BADDEV, msg));
1228 1239  
1229 1240                  default:
1230 1241                          return (zpool_standard_error(hdl, errno, msg));
1231 1242                  }
1232 1243          }
1233 1244  
1234 1245  create_failed:
1235 1246          zcmd_free_nvlists(&zc);
1236 1247          nvlist_free(zc_props);
1237 1248          nvlist_free(zc_fsprops);
1238 1249          return (ret);
1239 1250  }
1240 1251  
1241 1252  /*
1242 1253   * Destroy the given pool.  It is up to the caller to ensure that there are no
1243 1254   * datasets left in the pool.
1244 1255   */
1245 1256  int
1246 1257  zpool_destroy(zpool_handle_t *zhp, const char *log_str)
1247 1258  {
1248 1259          zfs_cmd_t zc = { 0 };
1249 1260          zfs_handle_t *zfp = NULL;
1250 1261          libzfs_handle_t *hdl = zhp->zpool_hdl;
1251 1262          char msg[1024];
1252 1263  
1253 1264          if (zhp->zpool_state == POOL_STATE_ACTIVE &&
1254 1265              (zfp = zfs_open(hdl, zhp->zpool_name, ZFS_TYPE_FILESYSTEM)) == NULL)
1255 1266                  return (-1);
1256 1267  
1257 1268          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1258 1269          zc.zc_history = (uint64_t)(uintptr_t)log_str;
1259 1270  
1260 1271          if (zfs_ioctl(hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
1261 1272                  (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1262 1273                      "cannot destroy '%s'"), zhp->zpool_name);
1263 1274  
1264 1275                  if (errno == EROFS) {
1265 1276                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1266 1277                              "one or more devices is read only"));
1267 1278                          (void) zfs_error(hdl, EZFS_BADDEV, msg);
1268 1279                  } else {
1269 1280                          (void) zpool_standard_error(hdl, errno, msg);
1270 1281                  }
1271 1282  
1272 1283                  if (zfp)
1273 1284                          zfs_close(zfp);
1274 1285                  return (-1);
1275 1286          }
1276 1287  
1277 1288          if (zfp) {
1278 1289                  remove_mountpoint(zfp);
1279 1290                  zfs_close(zfp);
1280 1291          }
1281 1292  
1282 1293          return (0);
1283 1294  }
1284 1295  
1285 1296  /*
1286 1297   * Create a checkpoint in the given pool.
1287 1298   */
1288 1299  int
1289 1300  zpool_checkpoint(zpool_handle_t *zhp)
1290 1301  {
1291 1302          libzfs_handle_t *hdl = zhp->zpool_hdl;
1292 1303          char msg[1024];
1293 1304          int error;
1294 1305  
1295 1306          error = lzc_pool_checkpoint(zhp->zpool_name);
1296 1307          if (error != 0) {
1297 1308                  (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1298 1309                      "cannot checkpoint '%s'"), zhp->zpool_name);
1299 1310                  (void) zpool_standard_error(hdl, error, msg);
1300 1311                  return (-1);
1301 1312          }
1302 1313  
1303 1314          return (0);
1304 1315  }
1305 1316  
1306 1317  /*
1307 1318   * Discard the checkpoint from the given pool.
1308 1319   */
1309 1320  int
1310 1321  zpool_discard_checkpoint(zpool_handle_t *zhp)
1311 1322  {
1312 1323          libzfs_handle_t *hdl = zhp->zpool_hdl;
1313 1324          char msg[1024];
1314 1325          int error;
1315 1326  
1316 1327          error = lzc_pool_checkpoint_discard(zhp->zpool_name);
1317 1328          if (error != 0) {
1318 1329                  (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1319 1330                      "cannot discard checkpoint in '%s'"), zhp->zpool_name);
1320 1331                  (void) zpool_standard_error(hdl, error, msg);
1321 1332                  return (-1);
1322 1333          }
1323 1334  
1324 1335          return (0);
1325 1336  }
1326 1337  
1327 1338  /*
1328 1339   * Add the given vdevs to the pool.  The caller must have already performed the
1329 1340   * necessary verification to ensure that the vdev specification is well-formed.
1330 1341   */
1331 1342  int
1332 1343  zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
1333 1344  {
1334 1345          zfs_cmd_t zc = { 0 };
1335 1346          int ret;
1336 1347          libzfs_handle_t *hdl = zhp->zpool_hdl;
1337 1348          char msg[1024];
1338 1349          nvlist_t **spares, **l2cache;
1339 1350          uint_t nspares, nl2cache;
1340 1351  
1341 1352          (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1342 1353              "cannot add to '%s'"), zhp->zpool_name);
1343 1354  
1344 1355          if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
1345 1356              SPA_VERSION_SPARES &&
1346 1357              nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
1347 1358              &spares, &nspares) == 0) {
1348 1359                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
1349 1360                      "upgraded to add hot spares"));
1350 1361                  return (zfs_error(hdl, EZFS_BADVERSION, msg));
1351 1362          }
1352 1363  
1353 1364          if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
1354 1365              SPA_VERSION_L2CACHE &&
1355 1366              nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
1356 1367              &l2cache, &nl2cache) == 0) {
1357 1368                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
1358 1369                      "upgraded to add cache devices"));
1359 1370                  return (zfs_error(hdl, EZFS_BADVERSION, msg));
1360 1371          }
1361 1372  
1362 1373          if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
1363 1374                  return (-1);
1364 1375          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1365 1376  
1366 1377          if (zfs_ioctl(hdl, ZFS_IOC_VDEV_ADD, &zc) != 0) {
1367 1378                  switch (errno) {
1368 1379                  case EBUSY:
1369 1380                          /*
1370 1381                           * This can happen if the user has specified the same
1371 1382                           * device multiple times.  We can't reliably detect this
1372 1383                           * until we try to add it and see we already have a
1373 1384                           * label.
1374 1385                           */
1375 1386                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1376 1387                              "one or more vdevs refer to the same device"));
1377 1388                          (void) zfs_error(hdl, EZFS_BADDEV, msg);
1378 1389                          break;
1379 1390  
1380 1391                  case EINVAL:
1381 1392                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1382 1393                              "invalid config; a pool with removing/removed "
1383 1394                              "vdevs does not support adding raidz vdevs"));
1384 1395                          (void) zfs_error(hdl, EZFS_BADDEV, msg);
1385 1396                          break;
1386 1397  
1387 1398                  case EOVERFLOW:
1388 1399                          /*
1389 1400                           * This occurrs when one of the devices is below
1390 1401                           * SPA_MINDEVSIZE.  Unfortunately, we can't detect which
1391 1402                           * device was the problem device since there's no
1392 1403                           * reliable way to determine device size from userland.
1393 1404                           */
1394 1405                          {
1395 1406                                  char buf[64];
1396 1407  
1397 1408                                  zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf));
1398 1409  
1399 1410                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1400 1411                                      "device is less than the minimum "
1401 1412                                      "size (%s)"), buf);
1402 1413                          }
1403 1414                          (void) zfs_error(hdl, EZFS_BADDEV, msg);
1404 1415                          break;
1405 1416  
1406 1417                  case ENOTSUP:
1407 1418                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1408 1419                              "pool must be upgraded to add these vdevs"));
1409 1420                          (void) zfs_error(hdl, EZFS_BADVERSION, msg);
1410 1421                          break;
1411 1422  
1412 1423                  case EDOM:
1413 1424                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1414 1425                              "root pool can not have multiple vdevs"
1415 1426                              " or separate logs"));
1416 1427                          (void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg);
1417 1428                          break;
1418 1429  
1419 1430                  case ENOTBLK:
1420 1431                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1421 1432                              "cache device must be a disk or disk slice"));
1422 1433                          (void) zfs_error(hdl, EZFS_BADDEV, msg);
1423 1434                          break;
1424 1435  
1425 1436                  default:
1426 1437                          (void) zpool_standard_error(hdl, errno, msg);
1427 1438                  }
1428 1439  
1429 1440                  ret = -1;
1430 1441          } else {
1431 1442                  ret = 0;
1432 1443          }
1433 1444  
1434 1445          zcmd_free_nvlists(&zc);
1435 1446  
1436 1447          return (ret);
1437 1448  }
1438 1449  
1439 1450  /*
1440 1451   * Exports the pool from the system.  The caller must ensure that there are no
1441 1452   * mounted datasets in the pool.
1442 1453   */
1443 1454  static int
1444 1455  zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce,
1445 1456      const char *log_str)
1446 1457  {
1447 1458          zfs_cmd_t zc = { 0 };
1448 1459          char msg[1024];
1449 1460  
1450 1461          (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1451 1462              "cannot export '%s'"), zhp->zpool_name);
1452 1463  
1453 1464          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1454 1465          zc.zc_cookie = force;
1455 1466          zc.zc_guid = hardforce;
1456 1467          zc.zc_history = (uint64_t)(uintptr_t)log_str;
1457 1468  
1458 1469          if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) {
1459 1470                  switch (errno) {
1460 1471                  case EXDEV:
1461 1472                          zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
1462 1473                              "use '-f' to override the following errors:\n"
1463 1474                              "'%s' has an active shared spare which could be"
1464 1475                              " used by other pools once '%s' is exported."),
1465 1476                              zhp->zpool_name, zhp->zpool_name);
1466 1477                          return (zfs_error(zhp->zpool_hdl, EZFS_ACTIVE_SPARE,
1467 1478                              msg));
1468 1479                  default:
1469 1480                          return (zpool_standard_error_fmt(zhp->zpool_hdl, errno,
1470 1481                              msg));
1471 1482                  }
1472 1483          }
1473 1484  
1474 1485          return (0);
1475 1486  }
1476 1487  
1477 1488  int
1478 1489  zpool_export(zpool_handle_t *zhp, boolean_t force, const char *log_str)
1479 1490  {
1480 1491          return (zpool_export_common(zhp, force, B_FALSE, log_str));
1481 1492  }
1482 1493  
1483 1494  int
1484 1495  zpool_export_force(zpool_handle_t *zhp, const char *log_str)
1485 1496  {
1486 1497          return (zpool_export_common(zhp, B_TRUE, B_TRUE, log_str));
1487 1498  }
1488 1499  
1489 1500  static void
1490 1501  zpool_rewind_exclaim(libzfs_handle_t *hdl, const char *name, boolean_t dryrun,
1491 1502      nvlist_t *config)
1492 1503  {
1493 1504          nvlist_t *nv = NULL;
1494 1505          uint64_t rewindto;
1495 1506          int64_t loss = -1;
1496 1507          struct tm t;
1497 1508          char timestr[128];
1498 1509  
1499 1510          if (!hdl->libzfs_printerr || config == NULL)
1500 1511                  return;
1501 1512  
1502 1513          if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||
1503 1514              nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0) {
1504 1515                  return;
1505 1516          }
1506 1517  
1507 1518          if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
1508 1519                  return;
1509 1520          (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss);
1510 1521  
1511 1522          if (localtime_r((time_t *)&rewindto, &t) != NULL &&
1512 1523              strftime(timestr, 128, 0, &t) != 0) {
1513 1524                  if (dryrun) {
1514 1525                          (void) printf(dgettext(TEXT_DOMAIN,
1515 1526                              "Would be able to return %s "
1516 1527                              "to its state as of %s.\n"),
1517 1528                              name, timestr);
1518 1529                  } else {
1519 1530                          (void) printf(dgettext(TEXT_DOMAIN,
1520 1531                              "Pool %s returned to its state as of %s.\n"),
1521 1532                              name, timestr);
1522 1533                  }
1523 1534                  if (loss > 120) {
1524 1535                          (void) printf(dgettext(TEXT_DOMAIN,
1525 1536                              "%s approximately %lld "),
1526 1537                              dryrun ? "Would discard" : "Discarded",
1527 1538                              (loss + 30) / 60);
1528 1539                          (void) printf(dgettext(TEXT_DOMAIN,
1529 1540                              "minutes of transactions.\n"));
1530 1541                  } else if (loss > 0) {
1531 1542                          (void) printf(dgettext(TEXT_DOMAIN,
1532 1543                              "%s approximately %lld "),
1533 1544                              dryrun ? "Would discard" : "Discarded", loss);
1534 1545                          (void) printf(dgettext(TEXT_DOMAIN,
1535 1546                              "seconds of transactions.\n"));
1536 1547                  }
1537 1548          }
1538 1549  }
1539 1550  
1540 1551  void
1541 1552  zpool_explain_recover(libzfs_handle_t *hdl, const char *name, int reason,
1542 1553      nvlist_t *config)
1543 1554  {
1544 1555          nvlist_t *nv = NULL;
1545 1556          int64_t loss = -1;
1546 1557          uint64_t edata = UINT64_MAX;
1547 1558          uint64_t rewindto;
1548 1559          struct tm t;
1549 1560          char timestr[128];
1550 1561  
1551 1562          if (!hdl->libzfs_printerr)
1552 1563                  return;
1553 1564  
1554 1565          if (reason >= 0)
1555 1566                  (void) printf(dgettext(TEXT_DOMAIN, "action: "));
1556 1567          else
1557 1568                  (void) printf(dgettext(TEXT_DOMAIN, "\t"));
1558 1569  
1559 1570          /* All attempted rewinds failed if ZPOOL_CONFIG_LOAD_TIME missing */
1560 1571          if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||
1561 1572              nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0 ||
1562 1573              nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
1563 1574                  goto no_info;
1564 1575  
1565 1576          (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss);
1566 1577          (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_DATA_ERRORS,
1567 1578              &edata);
1568 1579  
1569 1580          (void) printf(dgettext(TEXT_DOMAIN,
1570 1581              "Recovery is possible, but will result in some data loss.\n"));
1571 1582  
1572 1583          if (localtime_r((time_t *)&rewindto, &t) != NULL &&
1573 1584              strftime(timestr, 128, 0, &t) != 0) {
1574 1585                  (void) printf(dgettext(TEXT_DOMAIN,
1575 1586                      "\tReturning the pool to its state as of %s\n"
1576 1587                      "\tshould correct the problem.  "),
1577 1588                      timestr);
1578 1589          } else {
1579 1590                  (void) printf(dgettext(TEXT_DOMAIN,
1580 1591                      "\tReverting the pool to an earlier state "
1581 1592                      "should correct the problem.\n\t"));
1582 1593          }
1583 1594  
1584 1595          if (loss > 120) {
1585 1596                  (void) printf(dgettext(TEXT_DOMAIN,
1586 1597                      "Approximately %lld minutes of data\n"
1587 1598                      "\tmust be discarded, irreversibly.  "), (loss + 30) / 60);
1588 1599          } else if (loss > 0) {
1589 1600                  (void) printf(dgettext(TEXT_DOMAIN,
1590 1601                      "Approximately %lld seconds of data\n"
1591 1602                      "\tmust be discarded, irreversibly.  "), loss);
1592 1603          }
1593 1604          if (edata != 0 && edata != UINT64_MAX) {
1594 1605                  if (edata == 1) {
1595 1606                          (void) printf(dgettext(TEXT_DOMAIN,
1596 1607                              "After rewind, at least\n"
1597 1608                              "\tone persistent user-data error will remain.  "));
1598 1609                  } else {
1599 1610                          (void) printf(dgettext(TEXT_DOMAIN,
1600 1611                              "After rewind, several\n"
1601 1612                              "\tpersistent user-data errors will remain.  "));
1602 1613                  }
1603 1614          }
1604 1615          (void) printf(dgettext(TEXT_DOMAIN,
1605 1616              "Recovery can be attempted\n\tby executing 'zpool %s -F %s'.  "),
1606 1617              reason >= 0 ? "clear" : "import", name);
1607 1618  
1608 1619          (void) printf(dgettext(TEXT_DOMAIN,
1609 1620              "A scrub of the pool\n"
1610 1621              "\tis strongly recommended after recovery.\n"));
1611 1622          return;
1612 1623  
1613 1624  no_info:
1614 1625          (void) printf(dgettext(TEXT_DOMAIN,
1615 1626              "Destroy and re-create the pool from\n\ta backup source.\n"));
1616 1627  }
1617 1628  
1618 1629  /*
1619 1630   * zpool_import() is a contracted interface. Should be kept the same
1620 1631   * if possible.
1621 1632   *
1622 1633   * Applications should use zpool_import_props() to import a pool with
1623 1634   * new properties value to be set.
1624 1635   */
1625 1636  int
1626 1637  zpool_import(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
1627 1638      char *altroot)
1628 1639  {
1629 1640          nvlist_t *props = NULL;
1630 1641          int ret;
1631 1642  
1632 1643          if (altroot != NULL) {
1633 1644                  if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
1634 1645                          return (zfs_error_fmt(hdl, EZFS_NOMEM,
1635 1646                              dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1636 1647                              newname));
1637 1648                  }
1638 1649  
1639 1650                  if (nvlist_add_string(props,
1640 1651                      zpool_prop_to_name(ZPOOL_PROP_ALTROOT), altroot) != 0 ||
1641 1652                      nvlist_add_string(props,
1642 1653                      zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), "none") != 0) {
1643 1654                          nvlist_free(props);
1644 1655                          return (zfs_error_fmt(hdl, EZFS_NOMEM,
1645 1656                              dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1646 1657                              newname));
1647 1658                  }
1648 1659          }
1649 1660  
1650 1661          ret = zpool_import_props(hdl, config, newname, props,
1651 1662              ZFS_IMPORT_NORMAL);
1652 1663          nvlist_free(props);
1653 1664          return (ret);
1654 1665  }
1655 1666  
1656 1667  static void
1657 1668  print_vdev_tree(libzfs_handle_t *hdl, const char *name, nvlist_t *nv,
1658 1669      int indent)
1659 1670  {
1660 1671          nvlist_t **child;
1661 1672          uint_t c, children;
1662 1673          char *vname;
1663 1674          uint64_t is_log = 0;
1664 1675  
1665 1676          (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG,
1666 1677              &is_log);
1667 1678  
1668 1679          if (name != NULL)
1669 1680                  (void) printf("\t%*s%s%s\n", indent, "", name,
1670 1681                      is_log ? " [log]" : "");
1671 1682  
1672 1683          if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1673 1684              &child, &children) != 0)
1674 1685                  return;
1675 1686  
1676 1687          for (c = 0; c < children; c++) {
1677 1688                  vname = zpool_vdev_name(hdl, NULL, child[c], B_TRUE);
1678 1689                  print_vdev_tree(hdl, vname, child[c], indent + 2);
1679 1690                  free(vname);
1680 1691          }
1681 1692  }
1682 1693  
1683 1694  void
1684 1695  zpool_print_unsup_feat(nvlist_t *config)
1685 1696  {
1686 1697          nvlist_t *nvinfo, *unsup_feat;
1687 1698  
1688 1699          verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nvinfo) ==
1689 1700              0);
1690 1701          verify(nvlist_lookup_nvlist(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT,
1691 1702              &unsup_feat) == 0);
1692 1703  
1693 1704          for (nvpair_t *nvp = nvlist_next_nvpair(unsup_feat, NULL); nvp != NULL;
1694 1705              nvp = nvlist_next_nvpair(unsup_feat, nvp)) {
1695 1706                  char *desc;
1696 1707  
1697 1708                  verify(nvpair_type(nvp) == DATA_TYPE_STRING);
1698 1709                  verify(nvpair_value_string(nvp, &desc) == 0);
1699 1710  
1700 1711                  if (strlen(desc) > 0)
1701 1712                          (void) printf("\t%s (%s)\n", nvpair_name(nvp), desc);
1702 1713                  else
1703 1714                          (void) printf("\t%s\n", nvpair_name(nvp));
1704 1715          }
1705 1716  }
1706 1717  
1707 1718  /*
1708 1719   * Import the given pool using the known configuration and a list of
1709 1720   * properties to be set. The configuration should have come from
1710 1721   * zpool_find_import(). The 'newname' parameters control whether the pool
1711 1722   * is imported with a different name.
1712 1723   */
1713 1724  int
1714 1725  zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
1715 1726      nvlist_t *props, int flags)
1716 1727  {
1717 1728          zfs_cmd_t zc = { 0 };
1718 1729          zpool_load_policy_t policy;
1719 1730          nvlist_t *nv = NULL;
1720 1731          nvlist_t *nvinfo = NULL;
1721 1732          nvlist_t *missing = NULL;
1722 1733          char *thename;
1723 1734          char *origname;
1724 1735          int ret;
1725 1736          int error = 0;
1726 1737          char errbuf[1024];
1727 1738  
1728 1739          verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1729 1740              &origname) == 0);
1730 1741  
1731 1742          (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1732 1743              "cannot import pool '%s'"), origname);
1733 1744  
1734 1745          if (newname != NULL) {
1735 1746                  if (!zpool_name_valid(hdl, B_FALSE, newname))
1736 1747                          return (zfs_error_fmt(hdl, EZFS_INVALIDNAME,
1737 1748                              dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1738 1749                              newname));
1739 1750                  thename = (char *)newname;
1740 1751          } else {
1741 1752                  thename = origname;
1742 1753          }
1743 1754  
1744 1755          if (props != NULL) {
1745 1756                  uint64_t version;
1746 1757                  prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE };
1747 1758  
1748 1759                  verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
1749 1760                      &version) == 0);
1750 1761  
1751 1762                  if ((props = zpool_valid_proplist(hdl, origname,
1752 1763                      props, version, flags, errbuf)) == NULL)
1753 1764                          return (-1);
1754 1765                  if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
1755 1766                          nvlist_free(props);
1756 1767                          return (-1);
1757 1768                  }
1758 1769                  nvlist_free(props);
1759 1770          }
1760 1771  
1761 1772          (void) strlcpy(zc.zc_name, thename, sizeof (zc.zc_name));
1762 1773  
1763 1774          verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1764 1775              &zc.zc_guid) == 0);
1765 1776  
1766 1777          if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0) {
1767 1778                  zcmd_free_nvlists(&zc);
1768 1779                  return (-1);
1769 1780          }
1770 1781          if (zcmd_alloc_dst_nvlist(hdl, &zc, zc.zc_nvlist_conf_size * 2) != 0) {
1771 1782                  zcmd_free_nvlists(&zc);
1772 1783                  return (-1);
1773 1784          }
1774 1785  
1775 1786          zc.zc_cookie = flags;
1776 1787          while ((ret = zfs_ioctl(hdl, ZFS_IOC_POOL_IMPORT, &zc)) != 0 &&
1777 1788              errno == ENOMEM) {
1778 1789                  if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
1779 1790                          zcmd_free_nvlists(&zc);
1780 1791                          return (-1);
1781 1792                  }
1782 1793          }
1783 1794          if (ret != 0)
1784 1795                  error = errno;
1785 1796  
1786 1797          (void) zcmd_read_dst_nvlist(hdl, &zc, &nv);
1787 1798  
1788 1799          zcmd_free_nvlists(&zc);
1789 1800  
1790 1801          zpool_get_load_policy(config, &policy);
1791 1802  
1792 1803          if (error) {
1793 1804                  char desc[1024];
1794 1805  
1795 1806                  /*
1796 1807                   * Dry-run failed, but we print out what success
1797 1808                   * looks like if we found a best txg
1798 1809                   */
1799 1810                  if (policy.zlp_rewind & ZPOOL_TRY_REWIND) {
1800 1811                          zpool_rewind_exclaim(hdl, newname ? origname : thename,
1801 1812                              B_TRUE, nv);
1802 1813                          nvlist_free(nv);
1803 1814                          return (-1);
1804 1815                  }
1805 1816  
1806 1817                  if (newname == NULL)
1807 1818                          (void) snprintf(desc, sizeof (desc),
1808 1819                              dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1809 1820                              thename);
1810 1821                  else
1811 1822                          (void) snprintf(desc, sizeof (desc),
1812 1823                              dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"),
1813 1824                              origname, thename);
1814 1825  
1815 1826                  switch (error) {
1816 1827                  case ENOTSUP:
1817 1828                          if (nv != NULL && nvlist_lookup_nvlist(nv,
1818 1829                              ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 &&
1819 1830                              nvlist_exists(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT)) {
1820 1831                                  (void) printf(dgettext(TEXT_DOMAIN, "This "
1821 1832                                      "pool uses the following feature(s) not "
1822 1833                                      "supported by this system:\n"));
1823 1834                                  zpool_print_unsup_feat(nv);
1824 1835                                  if (nvlist_exists(nvinfo,
1825 1836                                      ZPOOL_CONFIG_CAN_RDONLY)) {
1826 1837                                          (void) printf(dgettext(TEXT_DOMAIN,
1827 1838                                              "All unsupported features are only "
1828 1839                                              "required for writing to the pool."
1829 1840                                              "\nThe pool can be imported using "
1830 1841                                              "'-o readonly=on'.\n"));
1831 1842                                  }
1832 1843                          }
1833 1844                          /*
1834 1845                           * Unsupported version.
1835 1846                           */
1836 1847                          (void) zfs_error(hdl, EZFS_BADVERSION, desc);
1837 1848                          break;
1838 1849  
1839 1850                  case EINVAL:
1840 1851                          (void) zfs_error(hdl, EZFS_INVALCONFIG, desc);
1841 1852                          break;
1842 1853  
1843 1854                  case EROFS:
1844 1855                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1845 1856                              "one or more devices is read only"));
1846 1857                          (void) zfs_error(hdl, EZFS_BADDEV, desc);
1847 1858                          break;
1848 1859  
1849 1860                  case ENXIO:
1850 1861                          if (nv && nvlist_lookup_nvlist(nv,
1851 1862                              ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 &&
1852 1863                              nvlist_lookup_nvlist(nvinfo,
1853 1864                              ZPOOL_CONFIG_MISSING_DEVICES, &missing) == 0) {
1854 1865                                  (void) printf(dgettext(TEXT_DOMAIN,
1855 1866                                      "The devices below are missing or "
1856 1867                                      "corrupted, use '-m' to import the pool "
1857 1868                                      "anyway:\n"));
1858 1869                                  print_vdev_tree(hdl, NULL, missing, 2);
1859 1870                                  (void) printf("\n");
1860 1871                          }
1861 1872                          (void) zpool_standard_error(hdl, error, desc);
1862 1873                          break;
1863 1874  
1864 1875                  case EEXIST:
1865 1876                          (void) zpool_standard_error(hdl, error, desc);
1866 1877                          break;
1867 1878                  case ENAMETOOLONG:
1868 1879                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1869 1880                              "new name of at least one dataset is longer than "
1870 1881                              "the maximum allowable length"));
1871 1882                          (void) zfs_error(hdl, EZFS_NAMETOOLONG, desc);
1872 1883                          break;
1873 1884                  default:
1874 1885                          (void) zpool_standard_error(hdl, error, desc);
1875 1886                          zpool_explain_recover(hdl,
1876 1887                              newname ? origname : thename, -error, nv);
1877 1888                          break;
1878 1889                  }
1879 1890  
1880 1891                  nvlist_free(nv);
1881 1892                  ret = -1;
1882 1893          } else {
1883 1894                  zpool_handle_t *zhp;
1884 1895  
1885 1896                  /*
1886 1897                   * This should never fail, but play it safe anyway.
1887 1898                   */
1888 1899                  if (zpool_open_silent(hdl, thename, &zhp) != 0)
1889 1900                          ret = -1;
1890 1901                  else if (zhp != NULL)
1891 1902                          zpool_close(zhp);
1892 1903                  if (policy.zlp_rewind &
1893 1904                      (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) {
1894 1905                          zpool_rewind_exclaim(hdl, newname ? origname : thename,
1895 1906                              ((policy.zlp_rewind & ZPOOL_TRY_REWIND) != 0), nv);
1896 1907                  }
1897 1908                  nvlist_free(nv);
1898 1909                  return (0);
1899 1910          }
1900 1911  
1901 1912          return (ret);
1902 1913  }
1903 1914  
1904 1915  /*
1905 1916   * Scan the pool.
1906 1917   */
1907 1918  int
1908 1919  zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd)
1909 1920  {
1910 1921          zfs_cmd_t zc = { 0 };
1911 1922          char msg[1024];
1912 1923          int err;
1913 1924          libzfs_handle_t *hdl = zhp->zpool_hdl;
1914 1925  
1915 1926          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
1916 1927          zc.zc_cookie = func;
1917 1928          zc.zc_flags = cmd;
1918 1929  
1919 1930          if (zfs_ioctl(hdl, ZFS_IOC_POOL_SCAN, &zc) == 0)
1920 1931                  return (0);
1921 1932  
1922 1933          err = errno;
1923 1934  
1924 1935          /* ECANCELED on a scrub means we resumed a paused scrub */
1925 1936          if (err == ECANCELED && func == POOL_SCAN_SCRUB &&
1926 1937              cmd == POOL_SCRUB_NORMAL)
1927 1938                  return (0);
1928 1939  
1929 1940          if (err == ENOENT && func != POOL_SCAN_NONE && cmd == POOL_SCRUB_NORMAL)
1930 1941                  return (0);
1931 1942  
1932 1943          if (func == POOL_SCAN_SCRUB) {
1933 1944                  if (cmd == POOL_SCRUB_PAUSE) {
1934 1945                          (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1935 1946                              "cannot pause scrubbing %s"), zc.zc_name);
1936 1947                  } else {
1937 1948                          assert(cmd == POOL_SCRUB_NORMAL);
1938 1949                          (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
1939 1950                              "cannot scrub %s"), zc.zc_name);
1940 1951                  }
1941 1952          } else if (func == POOL_SCAN_NONE) {
1942 1953                  (void) snprintf(msg, sizeof (msg),
1943 1954                      dgettext(TEXT_DOMAIN, "cannot cancel scrubbing %s"),
1944 1955                      zc.zc_name);
1945 1956          } else {
1946 1957                  assert(!"unexpected result");
1947 1958          }
1948 1959  
1949 1960          if (err == EBUSY) {
1950 1961                  nvlist_t *nvroot;
1951 1962                  pool_scan_stat_t *ps = NULL;
1952 1963                  uint_t psc;
1953 1964  
1954 1965                  verify(nvlist_lookup_nvlist(zhp->zpool_config,
1955 1966                      ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
1956 1967                  (void) nvlist_lookup_uint64_array(nvroot,
1957 1968                      ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &psc);
1958 1969                  if (ps && ps->pss_func == POOL_SCAN_SCRUB) {
1959 1970                          if (cmd == POOL_SCRUB_PAUSE)
1960 1971                                  return (zfs_error(hdl, EZFS_SCRUB_PAUSED, msg));
1961 1972                          else
1962 1973                                  return (zfs_error(hdl, EZFS_SCRUBBING, msg));
1963 1974                  } else {
1964 1975                          return (zfs_error(hdl, EZFS_RESILVERING, msg));
1965 1976                  }
1966 1977          } else if (err == ENOENT) {
1967 1978                  return (zfs_error(hdl, EZFS_NO_SCRUB, msg));
1968 1979          } else {
1969 1980                  return (zpool_standard_error(hdl, err, msg));
1970 1981          }
1971 1982  }
1972 1983  
1973 1984  static int
1974 1985  xlate_init_err(int err)
1975 1986  {
1976 1987          switch (err) {
1977 1988          case ENODEV:
1978 1989                  return (EZFS_NODEVICE);
1979 1990          case EINVAL:
1980 1991          case EROFS:
1981 1992                  return (EZFS_BADDEV);
1982 1993          case EBUSY:
1983 1994                  return (EZFS_INITIALIZING);
1984 1995          case ESRCH:
1985 1996                  return (EZFS_NO_INITIALIZE);
1986 1997          }
1987 1998          return (err);
1988 1999  }
1989 2000  
1990 2001  /*
1991 2002   * Begin, suspend, or cancel the initialization (initializing of all free
1992 2003   * blocks) for the given vdevs in the given pool.
1993 2004   */
1994 2005  int
1995 2006  zpool_initialize(zpool_handle_t *zhp, pool_initialize_func_t cmd_type,
1996 2007      nvlist_t *vds)
1997 2008  {
1998 2009          char msg[1024];
1999 2010          libzfs_handle_t *hdl = zhp->zpool_hdl;
2000 2011  
2001 2012          nvlist_t *errlist;
2002 2013  
2003 2014          /* translate vdev names to guids */
2004 2015          nvlist_t *vdev_guids = fnvlist_alloc();
2005 2016          nvlist_t *guids_to_paths = fnvlist_alloc();
2006 2017          boolean_t spare, cache;
2007 2018          nvlist_t *tgt;
2008 2019          nvpair_t *elem;
2009 2020  
2010 2021          for (elem = nvlist_next_nvpair(vds, NULL); elem != NULL;
2011 2022              elem = nvlist_next_nvpair(vds, elem)) {
2012 2023                  char *vd_path = nvpair_name(elem);
2013 2024                  tgt = zpool_find_vdev(zhp, vd_path, &spare, &cache, NULL);
2014 2025  
2015 2026                  if ((tgt == NULL) || cache || spare) {
2016 2027                          (void) snprintf(msg, sizeof (msg),
2017 2028                              dgettext(TEXT_DOMAIN, "cannot initialize '%s'"),
2018 2029                              vd_path);
2019 2030                          int err = (tgt == NULL) ? EZFS_NODEVICE :
2020 2031                              (spare ? EZFS_ISSPARE : EZFS_ISL2CACHE);
2021 2032                          fnvlist_free(vdev_guids);
2022 2033                          fnvlist_free(guids_to_paths);
2023 2034                          return (zfs_error(hdl, err, msg));
2024 2035                  }
2025 2036  
2026 2037                  uint64_t guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
2027 2038                  fnvlist_add_uint64(vdev_guids, vd_path, guid);
2028 2039  
2029 2040                  (void) snprintf(msg, sizeof (msg), "%llu", guid);
2030 2041                  fnvlist_add_string(guids_to_paths, msg, vd_path);
2031 2042          }
2032 2043  
2033 2044          int err = lzc_initialize(zhp->zpool_name, cmd_type, vdev_guids,
2034 2045              &errlist);
2035 2046          fnvlist_free(vdev_guids);
2036 2047  
2037 2048          if (err == 0) {
2038 2049                  fnvlist_free(guids_to_paths);
2039 2050                  return (0);
2040 2051          }
2041 2052  
2042 2053          nvlist_t *vd_errlist = NULL;
2043 2054          if (errlist != NULL) {
2044 2055                  vd_errlist = fnvlist_lookup_nvlist(errlist,
2045 2056                      ZPOOL_INITIALIZE_VDEVS);
2046 2057          }
2047 2058  
2048 2059          (void) snprintf(msg, sizeof (msg),
2049 2060              dgettext(TEXT_DOMAIN, "operation failed"));
2050 2061  
2051 2062          for (elem = nvlist_next_nvpair(vd_errlist, NULL); elem != NULL;
2052 2063              elem = nvlist_next_nvpair(vd_errlist, elem)) {
2053 2064                  int64_t vd_error = xlate_init_err(fnvpair_value_int64(elem));
2054 2065                  char *path = fnvlist_lookup_string(guids_to_paths,
2055 2066                      nvpair_name(elem));
2056 2067                  (void) zfs_error_fmt(hdl, vd_error, "cannot initialize '%s'",
2057 2068                      path);
2058 2069          }
2059 2070  
2060 2071          fnvlist_free(guids_to_paths);
2061 2072          if (vd_errlist != NULL)
2062 2073                  return (-1);
2063 2074  
2064 2075          return (zpool_standard_error(hdl, err, msg));
2065 2076  }
2066 2077  
2067 2078  /*
2068 2079   * This provides a very minimal check whether a given string is likely a
2069 2080   * c#t#d# style string.  Users of this are expected to do their own
2070 2081   * verification of the s# part.
2071 2082   */
2072 2083  #define CTD_CHECK(str)  (str && str[0] == 'c' && isdigit(str[1]))
2073 2084  
2074 2085  /*
2075 2086   * More elaborate version for ones which may start with "/dev/dsk/"
2076 2087   * and the like.
2077 2088   */
2078 2089  static int
2079 2090  ctd_check_path(char *str)
2080 2091  {
2081 2092          /*
2082 2093           * If it starts with a slash, check the last component.
2083 2094           */
2084 2095          if (str && str[0] == '/') {
2085 2096                  char *tmp = strrchr(str, '/');
2086 2097  
2087 2098                  /*
2088 2099                   * If it ends in "/old", check the second-to-last
2089 2100                   * component of the string instead.
2090 2101                   */
2091 2102                  if (tmp != str && strcmp(tmp, "/old") == 0) {
2092 2103                          for (tmp--; *tmp != '/'; tmp--)
2093 2104                                  ;
2094 2105                  }
2095 2106                  str = tmp + 1;
2096 2107          }
2097 2108          return (CTD_CHECK(str));
2098 2109  }
2099 2110  
2100 2111  /*
2101 2112   * Find a vdev that matches the search criteria specified. We use the
2102 2113   * the nvpair name to determine how we should look for the device.
2103 2114   * 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL
2104 2115   * spare; but FALSE if its an INUSE spare.
2105 2116   */
2106 2117  static nvlist_t *
2107 2118  vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
2108 2119      boolean_t *l2cache, boolean_t *log)
2109 2120  {
2110 2121          uint_t c, children;
2111 2122          nvlist_t **child;
2112 2123          nvlist_t *ret;
2113 2124          uint64_t is_log;
2114 2125          char *srchkey;
2115 2126          nvpair_t *pair = nvlist_next_nvpair(search, NULL);
2116 2127  
2117 2128          /* Nothing to look for */
2118 2129          if (search == NULL || pair == NULL)
2119 2130                  return (NULL);
2120 2131  
2121 2132          /* Obtain the key we will use to search */
2122 2133          srchkey = nvpair_name(pair);
2123 2134  
2124 2135          switch (nvpair_type(pair)) {
2125 2136          case DATA_TYPE_UINT64:
2126 2137                  if (strcmp(srchkey, ZPOOL_CONFIG_GUID) == 0) {
2127 2138                          uint64_t srchval, theguid;
2128 2139  
2129 2140                          verify(nvpair_value_uint64(pair, &srchval) == 0);
2130 2141                          verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
2131 2142                              &theguid) == 0);
2132 2143                          if (theguid == srchval)
2133 2144                                  return (nv);
2134 2145                  }
2135 2146                  break;
2136 2147  
2137 2148          case DATA_TYPE_STRING: {
2138 2149                  char *srchval, *val;
2139 2150  
2140 2151                  verify(nvpair_value_string(pair, &srchval) == 0);
2141 2152                  if (nvlist_lookup_string(nv, srchkey, &val) != 0)
2142 2153                          break;
2143 2154  
2144 2155                  /*
2145 2156                   * Search for the requested value. Special cases:
2146 2157                   *
2147 2158                   * - ZPOOL_CONFIG_PATH for whole disk entries. To support
2148 2159                   *   UEFI boot, these end in "s0" or "s0/old" or "s1" or
2149 2160                   *   "s1/old".   The "s0" or "s1" part is hidden from the user,
2150 2161                   *   but included in the string, so this matches around it.
2151 2162                   * - looking for a top-level vdev name (i.e. ZPOOL_CONFIG_TYPE).
2152 2163                   *
2153 2164                   * Otherwise, all other searches are simple string compares.
2154 2165                   */
2155 2166                  if (strcmp(srchkey, ZPOOL_CONFIG_PATH) == 0 &&
2156 2167                      ctd_check_path(val)) {
2157 2168                          uint64_t wholedisk = 0;
2158 2169  
2159 2170                          (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
2160 2171                              &wholedisk);
2161 2172                          if (wholedisk) {
2162 2173                                  int slen = strlen(srchval);
2163 2174                                  int vlen = strlen(val);
2164 2175  
2165 2176                                  if (slen != vlen - 2)
2166 2177                                          break;
2167 2178  
2168 2179                                  /*
2169 2180                                   * make_leaf_vdev() should only set
2170 2181                                   * wholedisk for ZPOOL_CONFIG_PATHs which
2171 2182                                   * will include "/dev/dsk/", giving plenty of
2172 2183                                   * room for the indices used next.
2173 2184                                   */
2174 2185                                  ASSERT(vlen >= 6);
2175 2186  
2176 2187                                  /*
2177 2188                                   * strings identical except trailing "s0"
2178 2189                                   */
2179 2190                                  if ((strcmp(&val[vlen - 2], "s0") == 0 ||
2180 2191                                      strcmp(&val[vlen - 2], "s1") == 0) &&
2181 2192                                      strncmp(srchval, val, slen) == 0)
2182 2193                                          return (nv);
2183 2194  
2184 2195                                  /*
2185 2196                                   * strings identical except trailing "s0/old"
2186 2197                                   */
2187 2198                                  if ((strcmp(&val[vlen - 6], "s0/old") == 0 ||
2188 2199                                      strcmp(&val[vlen - 6], "s1/old") == 0) &&
2189 2200                                      strcmp(&srchval[slen - 4], "/old") == 0 &&
2190 2201                                      strncmp(srchval, val, slen - 4) == 0)
2191 2202                                          return (nv);
2192 2203  
2193 2204                                  break;
2194 2205                          }
2195 2206                  } else if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0 && val) {
2196 2207                          char *type, *idx, *end, *p;
2197 2208                          uint64_t id, vdev_id;
2198 2209  
2199 2210                          /*
2200 2211                           * Determine our vdev type, keeping in mind
2201 2212                           * that the srchval is composed of a type and
2202 2213                           * vdev id pair (i.e. mirror-4).
2203 2214                           */
2204 2215                          if ((type = strdup(srchval)) == NULL)
2205 2216                                  return (NULL);
2206 2217  
2207 2218                          if ((p = strrchr(type, '-')) == NULL) {
2208 2219                                  free(type);
2209 2220                                  break;
2210 2221                          }
2211 2222                          idx = p + 1;
2212 2223                          *p = '\0';
2213 2224  
2214 2225                          /*
2215 2226                           * If the types don't match then keep looking.
2216 2227                           */
2217 2228                          if (strncmp(val, type, strlen(val)) != 0) {
2218 2229                                  free(type);
2219 2230                                  break;
2220 2231                          }
2221 2232  
2222 2233                          verify(zpool_vdev_is_interior(type));
2223 2234                          verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID,
2224 2235                              &id) == 0);
2225 2236  
2226 2237                          errno = 0;
2227 2238                          vdev_id = strtoull(idx, &end, 10);
2228 2239  
2229 2240                          free(type);
2230 2241                          if (errno != 0)
2231 2242                                  return (NULL);
2232 2243  
2233 2244                          /*
2234 2245                           * Now verify that we have the correct vdev id.
2235 2246                           */
2236 2247                          if (vdev_id == id)
2237 2248                                  return (nv);
2238 2249                  }
2239 2250  
2240 2251                  /*
2241 2252                   * Common case
2242 2253                   */
2243 2254                  if (strcmp(srchval, val) == 0)
2244 2255                          return (nv);
2245 2256                  break;
2246 2257          }
2247 2258  
2248 2259          default:
2249 2260                  break;
2250 2261          }
2251 2262  
2252 2263          if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2253 2264              &child, &children) != 0)
2254 2265                  return (NULL);
2255 2266  
2256 2267          for (c = 0; c < children; c++) {
2257 2268                  if ((ret = vdev_to_nvlist_iter(child[c], search,
2258 2269                      avail_spare, l2cache, NULL)) != NULL) {
2259 2270                          /*
2260 2271                           * The 'is_log' value is only set for the toplevel
2261 2272                           * vdev, not the leaf vdevs.  So we always lookup the
2262 2273                           * log device from the root of the vdev tree (where
2263 2274                           * 'log' is non-NULL).
2264 2275                           */
2265 2276                          if (log != NULL &&
2266 2277                              nvlist_lookup_uint64(child[c],
2267 2278                              ZPOOL_CONFIG_IS_LOG, &is_log) == 0 &&
2268 2279                              is_log) {
2269 2280                                  *log = B_TRUE;
2270 2281                          }
2271 2282                          return (ret);
2272 2283                  }
2273 2284          }
2274 2285  
2275 2286          if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
2276 2287              &child, &children) == 0) {
2277 2288                  for (c = 0; c < children; c++) {
2278 2289                          if ((ret = vdev_to_nvlist_iter(child[c], search,
2279 2290                              avail_spare, l2cache, NULL)) != NULL) {
2280 2291                                  *avail_spare = B_TRUE;
2281 2292                                  return (ret);
2282 2293                          }
2283 2294                  }
2284 2295          }
2285 2296  
2286 2297          if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
2287 2298              &child, &children) == 0) {
2288 2299                  for (c = 0; c < children; c++) {
2289 2300                          if ((ret = vdev_to_nvlist_iter(child[c], search,
2290 2301                              avail_spare, l2cache, NULL)) != NULL) {
2291 2302                                  *l2cache = B_TRUE;
2292 2303                                  return (ret);
2293 2304                          }
2294 2305                  }
2295 2306          }
2296 2307  
2297 2308          return (NULL);
2298 2309  }
2299 2310  
2300 2311  /*
2301 2312   * Given a physical path (minus the "/devices" prefix), find the
2302 2313   * associated vdev.
2303 2314   */
2304 2315  nvlist_t *
2305 2316  zpool_find_vdev_by_physpath(zpool_handle_t *zhp, const char *ppath,
2306 2317      boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log)
2307 2318  {
2308 2319          nvlist_t *search, *nvroot, *ret;
2309 2320  
2310 2321          verify(nvlist_alloc(&search, NV_UNIQUE_NAME, KM_SLEEP) == 0);
2311 2322          verify(nvlist_add_string(search, ZPOOL_CONFIG_PHYS_PATH, ppath) == 0);
2312 2323  
2313 2324          verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
2314 2325              &nvroot) == 0);
2315 2326  
2316 2327          *avail_spare = B_FALSE;
2317 2328          *l2cache = B_FALSE;
2318 2329          if (log != NULL)
2319 2330                  *log = B_FALSE;
2320 2331          ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log);
2321 2332          nvlist_free(search);
2322 2333  
2323 2334          return (ret);
2324 2335  }
2325 2336  
2326 2337  /*
2327 2338   * Determine if we have an "interior" top-level vdev (i.e mirror/raidz).
2328 2339   */
2329 2340  static boolean_t
2330 2341  zpool_vdev_is_interior(const char *name)
2331 2342  {
2332 2343          if (strncmp(name, VDEV_TYPE_RAIDZ, strlen(VDEV_TYPE_RAIDZ)) == 0 ||
2333 2344              strncmp(name, VDEV_TYPE_SPARE, strlen(VDEV_TYPE_SPARE)) == 0 ||
2334 2345              strncmp(name,
2335 2346              VDEV_TYPE_REPLACING, strlen(VDEV_TYPE_REPLACING)) == 0 ||
2336 2347              strncmp(name, VDEV_TYPE_MIRROR, strlen(VDEV_TYPE_MIRROR)) == 0)
2337 2348                  return (B_TRUE);
2338 2349          return (B_FALSE);
2339 2350  }
2340 2351  
2341 2352  nvlist_t *
2342 2353  zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
2343 2354      boolean_t *l2cache, boolean_t *log)
2344 2355  {
2345 2356          char buf[MAXPATHLEN];
2346 2357          char *end;
2347 2358          nvlist_t *nvroot, *search, *ret;
2348 2359          uint64_t guid;
2349 2360  
2350 2361          verify(nvlist_alloc(&search, NV_UNIQUE_NAME, KM_SLEEP) == 0);
2351 2362  
2352 2363          guid = strtoull(path, &end, 10);
2353 2364          if (guid != 0 && *end == '\0') {
2354 2365                  verify(nvlist_add_uint64(search, ZPOOL_CONFIG_GUID, guid) == 0);
2355 2366          } else if (zpool_vdev_is_interior(path)) {
2356 2367                  verify(nvlist_add_string(search, ZPOOL_CONFIG_TYPE, path) == 0);
2357 2368          } else if (path[0] != '/') {
2358 2369                  (void) snprintf(buf, sizeof (buf), "%s/%s", ZFS_DISK_ROOT,
2359 2370                      path);
2360 2371                  verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, buf) == 0);
2361 2372          } else {
2362 2373                  verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, path) == 0);
2363 2374          }
2364 2375  
2365 2376          verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
2366 2377              &nvroot) == 0);
2367 2378  
2368 2379          *avail_spare = B_FALSE;
2369 2380          *l2cache = B_FALSE;
2370 2381          if (log != NULL)
2371 2382                  *log = B_FALSE;
2372 2383          ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log);
2373 2384          nvlist_free(search);
2374 2385  
2375 2386          return (ret);
2376 2387  }
2377 2388  
2378 2389  static int
2379 2390  vdev_online(nvlist_t *nv)
2380 2391  {
2381 2392          uint64_t ival;
2382 2393  
2383 2394          if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_OFFLINE, &ival) == 0 ||
2384 2395              nvlist_lookup_uint64(nv, ZPOOL_CONFIG_FAULTED, &ival) == 0 ||
2385 2396              nvlist_lookup_uint64(nv, ZPOOL_CONFIG_REMOVED, &ival) == 0)
2386 2397                  return (0);
2387 2398  
2388 2399          return (1);
2389 2400  }
2390 2401  
2391 2402  /*
2392 2403   * Helper function for zpool_get_physpaths().
2393 2404   */
2394 2405  static int
2395 2406  vdev_get_one_physpath(nvlist_t *config, char *physpath, size_t physpath_size,
2396 2407      size_t *bytes_written)
2397 2408  {
2398 2409          size_t bytes_left, pos, rsz;
2399 2410          char *tmppath;
2400 2411          const char *format;
2401 2412  
2402 2413          if (nvlist_lookup_string(config, ZPOOL_CONFIG_PHYS_PATH,
2403 2414              &tmppath) != 0)
2404 2415                  return (EZFS_NODEVICE);
2405 2416  
2406 2417          pos = *bytes_written;
2407 2418          bytes_left = physpath_size - pos;
2408 2419          format = (pos == 0) ? "%s" : " %s";
2409 2420  
2410 2421          rsz = snprintf(physpath + pos, bytes_left, format, tmppath);
2411 2422          *bytes_written += rsz;
2412 2423  
2413 2424          if (rsz >= bytes_left) {
2414 2425                  /* if physpath was not copied properly, clear it */
2415 2426                  if (bytes_left != 0) {
2416 2427                          physpath[pos] = 0;
2417 2428                  }
2418 2429                  return (EZFS_NOSPC);
2419 2430          }
2420 2431          return (0);
2421 2432  }
2422 2433  
2423 2434  static int
2424 2435  vdev_get_physpaths(nvlist_t *nv, char *physpath, size_t phypath_size,
2425 2436      size_t *rsz, boolean_t is_spare)
2426 2437  {
2427 2438          char *type;
2428 2439          int ret;
2429 2440  
2430 2441          if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
2431 2442                  return (EZFS_INVALCONFIG);
2432 2443  
2433 2444          if (strcmp(type, VDEV_TYPE_DISK) == 0) {
2434 2445                  /*
2435 2446                   * An active spare device has ZPOOL_CONFIG_IS_SPARE set.
2436 2447                   * For a spare vdev, we only want to boot from the active
2437 2448                   * spare device.
2438 2449                   */
2439 2450                  if (is_spare) {
2440 2451                          uint64_t spare = 0;
2441 2452                          (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_SPARE,
2442 2453                              &spare);
2443 2454                          if (!spare)
2444 2455                                  return (EZFS_INVALCONFIG);
2445 2456                  }
2446 2457  
2447 2458                  if (vdev_online(nv)) {
2448 2459                          if ((ret = vdev_get_one_physpath(nv, physpath,
2449 2460                              phypath_size, rsz)) != 0)
2450 2461                                  return (ret);
2451 2462                  }
2452 2463          } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0 ||
2453 2464              strcmp(type, VDEV_TYPE_RAIDZ) == 0 ||
2454 2465              strcmp(type, VDEV_TYPE_REPLACING) == 0 ||
2455 2466              (is_spare = (strcmp(type, VDEV_TYPE_SPARE) == 0))) {
2456 2467                  nvlist_t **child;
2457 2468                  uint_t count;
2458 2469                  int i, ret;
2459 2470  
2460 2471                  if (nvlist_lookup_nvlist_array(nv,
2461 2472                      ZPOOL_CONFIG_CHILDREN, &child, &count) != 0)
2462 2473                          return (EZFS_INVALCONFIG);
2463 2474  
2464 2475                  for (i = 0; i < count; i++) {
2465 2476                          ret = vdev_get_physpaths(child[i], physpath,
2466 2477                              phypath_size, rsz, is_spare);
2467 2478                          if (ret == EZFS_NOSPC)
2468 2479                                  return (ret);
2469 2480                  }
2470 2481          }
2471 2482  
2472 2483          return (EZFS_POOL_INVALARG);
2473 2484  }
2474 2485  
2475 2486  /*
2476 2487   * Get phys_path for a root pool config.
2477 2488   * Return 0 on success; non-zero on failure.
2478 2489   */
2479 2490  static int
2480 2491  zpool_get_config_physpath(nvlist_t *config, char *physpath, size_t phypath_size)
2481 2492  {
2482 2493          size_t rsz;
2483 2494          nvlist_t *vdev_root;
2484 2495          nvlist_t **child;
2485 2496          uint_t count;
2486 2497          char *type;
2487 2498  
2488 2499          rsz = 0;
2489 2500  
2490 2501          if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2491 2502              &vdev_root) != 0)
2492 2503                  return (EZFS_INVALCONFIG);
2493 2504  
2494 2505          if (nvlist_lookup_string(vdev_root, ZPOOL_CONFIG_TYPE, &type) != 0 ||
2495 2506              nvlist_lookup_nvlist_array(vdev_root, ZPOOL_CONFIG_CHILDREN,
2496 2507              &child, &count) != 0)
2497 2508                  return (EZFS_INVALCONFIG);
2498 2509  
2499 2510          /*
2500 2511           * root pool can only have a single top-level vdev.
2501 2512           */
2502 2513          if (strcmp(type, VDEV_TYPE_ROOT) != 0 || count != 1)
2503 2514                  return (EZFS_POOL_INVALARG);
2504 2515  
2505 2516          (void) vdev_get_physpaths(child[0], physpath, phypath_size, &rsz,
2506 2517              B_FALSE);
2507 2518  
2508 2519          /* No online devices */
2509 2520          if (rsz == 0)
2510 2521                  return (EZFS_NODEVICE);
2511 2522  
2512 2523          return (0);
2513 2524  }
2514 2525  
2515 2526  /*
2516 2527   * Get phys_path for a root pool
2517 2528   * Return 0 on success; non-zero on failure.
2518 2529   */
2519 2530  int
2520 2531  zpool_get_physpath(zpool_handle_t *zhp, char *physpath, size_t phypath_size)
2521 2532  {
2522 2533          return (zpool_get_config_physpath(zhp->zpool_config, physpath,
2523 2534              phypath_size));
2524 2535  }
2525 2536  
2526 2537  /*
2527 2538   * If the device has being dynamically expanded then we need to relabel
2528 2539   * the disk to use the new unallocated space.
2529 2540   */
2530 2541  static int
2531 2542  zpool_relabel_disk(libzfs_handle_t *hdl, const char *name)
2532 2543  {
2533 2544          char path[MAXPATHLEN];
2534 2545          char errbuf[1024];
2535 2546          int fd, error;
2536 2547          int (*_efi_use_whole_disk)(int);
2537 2548  
2538 2549          if ((_efi_use_whole_disk = (int (*)(int))dlsym(RTLD_DEFAULT,
2539 2550              "efi_use_whole_disk")) == NULL)
2540 2551                  return (-1);
2541 2552  
2542 2553          (void) snprintf(path, sizeof (path), "%s/%s", ZFS_RDISK_ROOT, name);
2543 2554  
2544 2555          if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) {
2545 2556                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
2546 2557                      "relabel '%s': unable to open device"), name);
2547 2558                  return (zfs_error(hdl, EZFS_OPENFAILED, errbuf));
2548 2559          }
2549 2560  
2550 2561          /*
2551 2562           * It's possible that we might encounter an error if the device
2552 2563           * does not have any unallocated space left. If so, we simply
2553 2564           * ignore that error and continue on.
2554 2565           */
2555 2566          error = _efi_use_whole_disk(fd);
2556 2567          (void) close(fd);
2557 2568          if (error && error != VT_ENOSPC) {
2558 2569                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
2559 2570                      "relabel '%s': unable to read disk capacity"), name);
2560 2571                  return (zfs_error(hdl, EZFS_NOCAP, errbuf));
2561 2572          }
2562 2573          return (0);
2563 2574  }
2564 2575  
2565 2576  /*
2566 2577   * Bring the specified vdev online.   The 'flags' parameter is a set of the
2567 2578   * ZFS_ONLINE_* flags.
2568 2579   */
2569 2580  int
2570 2581  zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
2571 2582      vdev_state_t *newstate)
2572 2583  {
2573 2584          zfs_cmd_t zc = { 0 };
2574 2585          char msg[1024];
2575 2586          char *pathname;
2576 2587          nvlist_t *tgt;
2577 2588          boolean_t avail_spare, l2cache, islog;
2578 2589          libzfs_handle_t *hdl = zhp->zpool_hdl;
2579 2590  
2580 2591          if (flags & ZFS_ONLINE_EXPAND) {
2581 2592                  (void) snprintf(msg, sizeof (msg),
2582 2593                      dgettext(TEXT_DOMAIN, "cannot expand %s"), path);
2583 2594          } else {
2584 2595                  (void) snprintf(msg, sizeof (msg),
2585 2596                      dgettext(TEXT_DOMAIN, "cannot online %s"), path);
2586 2597          }
2587 2598  
2588 2599          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2589 2600          if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
2590 2601              &islog)) == NULL)
2591 2602                  return (zfs_error(hdl, EZFS_NODEVICE, msg));
2592 2603  
2593 2604          verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
2594 2605  
2595 2606          if (avail_spare)
2596 2607                  return (zfs_error(hdl, EZFS_ISSPARE, msg));
2597 2608  
2598 2609          if ((flags & ZFS_ONLINE_EXPAND ||
2599 2610              zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) &&
2600 2611              nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, &pathname) == 0) {
2601 2612                  uint64_t wholedisk = 0;
2602 2613  
2603 2614                  (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
2604 2615                      &wholedisk);
2605 2616  
2606 2617                  /*
2607 2618                   * XXX - L2ARC 1.0 devices can't support expansion.
2608 2619                   */
2609 2620                  if (l2cache) {
2610 2621                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2611 2622                              "cannot expand cache devices"));
2612 2623                          return (zfs_error(hdl, EZFS_VDEVNOTSUP, msg));
2613 2624                  }
2614 2625  
2615 2626                  if (wholedisk) {
2616 2627                          pathname += strlen(ZFS_DISK_ROOT) + 1;
2617 2628                          (void) zpool_relabel_disk(hdl, pathname);
2618 2629                  }
2619 2630          }
2620 2631  
2621 2632          zc.zc_cookie = VDEV_STATE_ONLINE;
2622 2633          zc.zc_obj = flags;
2623 2634  
2624 2635          if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) != 0) {
2625 2636                  if (errno == EINVAL) {
2626 2637                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "was split "
2627 2638                              "from this pool into a new one.  Use '%s' "
2628 2639                              "instead"), "zpool detach");
2629 2640                          return (zfs_error(hdl, EZFS_POSTSPLIT_ONLINE, msg));
2630 2641                  }
2631 2642                  return (zpool_standard_error(hdl, errno, msg));
2632 2643          }
2633 2644  
2634 2645          *newstate = zc.zc_cookie;
2635 2646          return (0);
2636 2647  }
2637 2648  
2638 2649  /*
2639 2650   * Take the specified vdev offline
2640 2651   */
2641 2652  int
2642 2653  zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
2643 2654  {
2644 2655          zfs_cmd_t zc = { 0 };
2645 2656          char msg[1024];
2646 2657          nvlist_t *tgt;
2647 2658          boolean_t avail_spare, l2cache;
2648 2659          libzfs_handle_t *hdl = zhp->zpool_hdl;
2649 2660  
2650 2661          (void) snprintf(msg, sizeof (msg),
2651 2662              dgettext(TEXT_DOMAIN, "cannot offline %s"), path);
2652 2663  
2653 2664          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2654 2665          if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
2655 2666              NULL)) == NULL)
2656 2667                  return (zfs_error(hdl, EZFS_NODEVICE, msg));
2657 2668  
2658 2669          verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
2659 2670  
2660 2671          if (avail_spare)
2661 2672                  return (zfs_error(hdl, EZFS_ISSPARE, msg));
2662 2673  
2663 2674          zc.zc_cookie = VDEV_STATE_OFFLINE;
2664 2675          zc.zc_obj = istmp ? ZFS_OFFLINE_TEMPORARY : 0;
2665 2676  
2666 2677          if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
2667 2678                  return (0);
2668 2679  
2669 2680          switch (errno) {
2670 2681          case EBUSY:
2671 2682  
2672 2683                  /*
2673 2684                   * There are no other replicas of this device.
2674 2685                   */
2675 2686                  return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
2676 2687  
2677 2688          case EEXIST:
2678 2689                  /*
2679 2690                   * The log device has unplayed logs
2680 2691                   */
2681 2692                  return (zfs_error(hdl, EZFS_UNPLAYED_LOGS, msg));
2682 2693  
2683 2694          default:
2684 2695                  return (zpool_standard_error(hdl, errno, msg));
2685 2696          }
2686 2697  }
2687 2698  
2688 2699  /*
2689 2700   * Mark the given vdev faulted.
2690 2701   */
2691 2702  int
2692 2703  zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
2693 2704  {
2694 2705          zfs_cmd_t zc = { 0 };
2695 2706          char msg[1024];
2696 2707          libzfs_handle_t *hdl = zhp->zpool_hdl;
2697 2708  
2698 2709          (void) snprintf(msg, sizeof (msg),
2699 2710              dgettext(TEXT_DOMAIN, "cannot fault %llu"), guid);
2700 2711  
2701 2712          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2702 2713          zc.zc_guid = guid;
2703 2714          zc.zc_cookie = VDEV_STATE_FAULTED;
2704 2715          zc.zc_obj = aux;
2705 2716  
2706 2717          if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
2707 2718                  return (0);
2708 2719  
2709 2720          switch (errno) {
2710 2721          case EBUSY:
2711 2722  
2712 2723                  /*
2713 2724                   * There are no other replicas of this device.
2714 2725                   */
2715 2726                  return (zfs_error(hdl, EZFS_NOREPLICAS, msg));
2716 2727  
2717 2728          default:
2718 2729                  return (zpool_standard_error(hdl, errno, msg));
2719 2730          }
2720 2731  
2721 2732  }
2722 2733  
2723 2734  /*
2724 2735   * Mark the given vdev degraded.
2725 2736   */
2726 2737  int
2727 2738  zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
2728 2739  {
2729 2740          zfs_cmd_t zc = { 0 };
2730 2741          char msg[1024];
2731 2742          libzfs_handle_t *hdl = zhp->zpool_hdl;
2732 2743  
2733 2744          (void) snprintf(msg, sizeof (msg),
2734 2745              dgettext(TEXT_DOMAIN, "cannot degrade %llu"), guid);
2735 2746  
2736 2747          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2737 2748          zc.zc_guid = guid;
2738 2749          zc.zc_cookie = VDEV_STATE_DEGRADED;
2739 2750          zc.zc_obj = aux;
2740 2751  
2741 2752          if (ioctl(hdl->libzfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
2742 2753                  return (0);
2743 2754  
2744 2755          return (zpool_standard_error(hdl, errno, msg));
2745 2756  }
2746 2757  
2747 2758  /*
2748 2759   * Returns TRUE if the given nvlist is a vdev that was originally swapped in as
2749 2760   * a hot spare.
2750 2761   */
2751 2762  static boolean_t
2752 2763  is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which)
2753 2764  {
2754 2765          nvlist_t **child;
2755 2766          uint_t c, children;
2756 2767          char *type;
2757 2768  
2758 2769          if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child,
2759 2770              &children) == 0) {
2760 2771                  verify(nvlist_lookup_string(search, ZPOOL_CONFIG_TYPE,
2761 2772                      &type) == 0);
2762 2773  
2763 2774                  if (strcmp(type, VDEV_TYPE_SPARE) == 0 &&
2764 2775                      children == 2 && child[which] == tgt)
2765 2776                          return (B_TRUE);
2766 2777  
2767 2778                  for (c = 0; c < children; c++)
2768 2779                          if (is_replacing_spare(child[c], tgt, which))
2769 2780                                  return (B_TRUE);
2770 2781          }
2771 2782  
2772 2783          return (B_FALSE);
2773 2784  }
2774 2785  
2775 2786  /*
2776 2787   * Attach new_disk (fully described by nvroot) to old_disk.
2777 2788   * If 'replacing' is specified, the new disk will replace the old one.
2778 2789   */
2779 2790  int
2780 2791  zpool_vdev_attach(zpool_handle_t *zhp,
2781 2792      const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing)
2782 2793  {
2783 2794          zfs_cmd_t zc = { 0 };
2784 2795          char msg[1024];
2785 2796          int ret;
2786 2797          nvlist_t *tgt;
2787 2798          boolean_t avail_spare, l2cache, islog;
2788 2799          uint64_t val;
2789 2800          char *newname;
2790 2801          nvlist_t **child;
2791 2802          uint_t children;
2792 2803          nvlist_t *config_root;
2793 2804          libzfs_handle_t *hdl = zhp->zpool_hdl;
2794 2805          boolean_t rootpool = zpool_is_bootable(zhp);
2795 2806  
2796 2807          if (replacing)
2797 2808                  (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
2798 2809                      "cannot replace %s with %s"), old_disk, new_disk);
2799 2810          else
2800 2811                  (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
2801 2812                      "cannot attach %s to %s"), new_disk, old_disk);
2802 2813  
2803 2814          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2804 2815          if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare, &l2cache,
2805 2816              &islog)) == NULL)
2806 2817                  return (zfs_error(hdl, EZFS_NODEVICE, msg));
2807 2818  
2808 2819          if (avail_spare)
2809 2820                  return (zfs_error(hdl, EZFS_ISSPARE, msg));
2810 2821  
2811 2822          if (l2cache)
2812 2823                  return (zfs_error(hdl, EZFS_ISL2CACHE, msg));
2813 2824  
2814 2825          verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
2815 2826          zc.zc_cookie = replacing;
2816 2827  
2817 2828          if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
2818 2829              &child, &children) != 0 || children != 1) {
2819 2830                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2820 2831                      "new device must be a single disk"));
2821 2832                  return (zfs_error(hdl, EZFS_INVALCONFIG, msg));
2822 2833          }
2823 2834  
2824 2835          verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
2825 2836              ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0);
2826 2837  
2827 2838          if ((newname = zpool_vdev_name(NULL, NULL, child[0], B_FALSE)) == NULL)
2828 2839                  return (-1);
2829 2840  
2830 2841          /*
2831 2842           * If the target is a hot spare that has been swapped in, we can only
2832 2843           * replace it with another hot spare.
2833 2844           */
2834 2845          if (replacing &&
2835 2846              nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 &&
2836 2847              (zpool_find_vdev(zhp, newname, &avail_spare, &l2cache,
2837 2848              NULL) == NULL || !avail_spare) &&
2838 2849              is_replacing_spare(config_root, tgt, 1)) {
2839 2850                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2840 2851                      "can only be replaced by another hot spare"));
2841 2852                  free(newname);
2842 2853                  return (zfs_error(hdl, EZFS_BADTARGET, msg));
2843 2854          }
2844 2855  
2845 2856          free(newname);
2846 2857  
2847 2858          if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
2848 2859                  return (-1);
2849 2860  
2850 2861          ret = zfs_ioctl(hdl, ZFS_IOC_VDEV_ATTACH, &zc);
2851 2862  
2852 2863          zcmd_free_nvlists(&zc);
2853 2864  
2854 2865          if (ret == 0) {
2855 2866                  if (rootpool) {
2856 2867                          /*
2857 2868                           * XXX need a better way to prevent user from
2858 2869                           * booting up a half-baked vdev.
2859 2870                           */
2860 2871                          (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Make "
2861 2872                              "sure to wait until resilver is done "
2862 2873                              "before rebooting.\n"));
2863 2874                  }
2864 2875                  return (0);
2865 2876          }
2866 2877  
2867 2878          switch (errno) {
2868 2879          case ENOTSUP:
2869 2880                  /*
2870 2881                   * Can't attach to or replace this type of vdev.
2871 2882                   */
2872 2883                  if (replacing) {
2873 2884                          uint64_t version = zpool_get_prop_int(zhp,
2874 2885                              ZPOOL_PROP_VERSION, NULL);
2875 2886  
2876 2887                          if (islog)
2877 2888                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2878 2889                                      "cannot replace a log with a spare"));
2879 2890                          else if (version >= SPA_VERSION_MULTI_REPLACE)
2880 2891                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2881 2892                                      "already in replacing/spare config; wait "
2882 2893                                      "for completion or use 'zpool detach'"));
2883 2894                          else
2884 2895                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2885 2896                                      "cannot replace a replacing device"));
2886 2897                  } else {
2887 2898                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2888 2899                              "can only attach to mirrors and top-level "
2889 2900                              "disks"));
2890 2901                  }
2891 2902                  (void) zfs_error(hdl, EZFS_BADTARGET, msg);
2892 2903                  break;
2893 2904  
2894 2905          case EINVAL:
2895 2906                  /*
2896 2907                   * The new device must be a single disk.
2897 2908                   */
2898 2909                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2899 2910                      "new device must be a single disk"));
2900 2911                  (void) zfs_error(hdl, EZFS_INVALCONFIG, msg);
2901 2912                  break;
2902 2913  
2903 2914          case EBUSY:
2904 2915                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy, "
2905 2916                      "or device removal is in progress"),
2906 2917                      new_disk);
2907 2918                  (void) zfs_error(hdl, EZFS_BADDEV, msg);
2908 2919                  break;
2909 2920  
2910 2921          case EOVERFLOW:
2911 2922                  /*
2912 2923                   * The new device is too small.
2913 2924                   */
2914 2925                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2915 2926                      "device is too small"));
2916 2927                  (void) zfs_error(hdl, EZFS_BADDEV, msg);
2917 2928                  break;
2918 2929  
2919 2930          case EDOM:
2920 2931                  /*
2921 2932                   * The new device has a different alignment requirement.
2922 2933                   */
2923 2934                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2924 2935                      "devices have different sector alignment"));
2925 2936                  (void) zfs_error(hdl, EZFS_BADDEV, msg);
2926 2937                  break;
2927 2938  
2928 2939          case ENAMETOOLONG:
2929 2940                  /*
2930 2941                   * The resulting top-level vdev spec won't fit in the label.
2931 2942                   */
2932 2943                  (void) zfs_error(hdl, EZFS_DEVOVERFLOW, msg);
2933 2944                  break;
2934 2945  
2935 2946          default:
2936 2947                  (void) zpool_standard_error(hdl, errno, msg);
2937 2948          }
2938 2949  
2939 2950          return (-1);
2940 2951  }
2941 2952  
2942 2953  /*
2943 2954   * Detach the specified device.
2944 2955   */
2945 2956  int
2946 2957  zpool_vdev_detach(zpool_handle_t *zhp, const char *path)
2947 2958  {
2948 2959          zfs_cmd_t zc = { 0 };
2949 2960          char msg[1024];
2950 2961          nvlist_t *tgt;
2951 2962          boolean_t avail_spare, l2cache;
2952 2963          libzfs_handle_t *hdl = zhp->zpool_hdl;
2953 2964  
2954 2965          (void) snprintf(msg, sizeof (msg),
2955 2966              dgettext(TEXT_DOMAIN, "cannot detach %s"), path);
2956 2967  
2957 2968          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
2958 2969          if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
2959 2970              NULL)) == NULL)
2960 2971                  return (zfs_error(hdl, EZFS_NODEVICE, msg));
2961 2972  
2962 2973          if (avail_spare)
2963 2974                  return (zfs_error(hdl, EZFS_ISSPARE, msg));
2964 2975  
2965 2976          if (l2cache)
2966 2977                  return (zfs_error(hdl, EZFS_ISL2CACHE, msg));
2967 2978  
2968 2979          verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
2969 2980  
2970 2981          if (zfs_ioctl(hdl, ZFS_IOC_VDEV_DETACH, &zc) == 0)
2971 2982                  return (0);
2972 2983  
2973 2984          switch (errno) {
2974 2985  
2975 2986          case ENOTSUP:
2976 2987                  /*
2977 2988                   * Can't detach from this type of vdev.
2978 2989                   */
2979 2990                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only "
2980 2991                      "applicable to mirror and replacing vdevs"));
2981 2992                  (void) zfs_error(hdl, EZFS_BADTARGET, msg);
2982 2993                  break;
2983 2994  
2984 2995          case EBUSY:
2985 2996                  /*
2986 2997                   * There are no other replicas of this device.
2987 2998                   */
2988 2999                  (void) zfs_error(hdl, EZFS_NOREPLICAS, msg);
2989 3000                  break;
2990 3001  
2991 3002          default:
2992 3003                  (void) zpool_standard_error(hdl, errno, msg);
2993 3004          }
2994 3005  
2995 3006          return (-1);
2996 3007  }
2997 3008  
2998 3009  /*
2999 3010   * Find a mirror vdev in the source nvlist.
3000 3011   *
3001 3012   * The mchild array contains a list of disks in one of the top-level mirrors
3002 3013   * of the source pool.  The schild array contains a list of disks that the
3003 3014   * user specified on the command line.  We loop over the mchild array to
3004 3015   * see if any entry in the schild array matches.
3005 3016   *
3006 3017   * If a disk in the mchild array is found in the schild array, we return
3007 3018   * the index of that entry.  Otherwise we return -1.
3008 3019   */
3009 3020  static int
3010 3021  find_vdev_entry(zpool_handle_t *zhp, nvlist_t **mchild, uint_t mchildren,
3011 3022      nvlist_t **schild, uint_t schildren)
3012 3023  {
3013 3024          uint_t mc;
3014 3025  
3015 3026          for (mc = 0; mc < mchildren; mc++) {
3016 3027                  uint_t sc;
3017 3028                  char *mpath = zpool_vdev_name(zhp->zpool_hdl, zhp,
3018 3029                      mchild[mc], B_FALSE);
3019 3030  
3020 3031                  for (sc = 0; sc < schildren; sc++) {
3021 3032                          char *spath = zpool_vdev_name(zhp->zpool_hdl, zhp,
3022 3033                              schild[sc], B_FALSE);
3023 3034                          boolean_t result = (strcmp(mpath, spath) == 0);
3024 3035  
3025 3036                          free(spath);
3026 3037                          if (result) {
3027 3038                                  free(mpath);
3028 3039                                  return (mc);
3029 3040                          }
3030 3041                  }
3031 3042  
3032 3043                  free(mpath);
3033 3044          }
3034 3045  
3035 3046          return (-1);
3036 3047  }
3037 3048  
3038 3049  /*
3039 3050   * Split a mirror pool.  If newroot points to null, then a new nvlist
3040 3051   * is generated and it is the responsibility of the caller to free it.
3041 3052   */
3042 3053  int
3043 3054  zpool_vdev_split(zpool_handle_t *zhp, char *newname, nvlist_t **newroot,
3044 3055      nvlist_t *props, splitflags_t flags)
3045 3056  {
3046 3057          zfs_cmd_t zc = { 0 };
3047 3058          char msg[1024];
3048 3059          nvlist_t *tree, *config, **child, **newchild, *newconfig = NULL;
3049 3060          nvlist_t **varray = NULL, *zc_props = NULL;
3050 3061          uint_t c, children, newchildren, lastlog = 0, vcount, found = 0;
3051 3062          libzfs_handle_t *hdl = zhp->zpool_hdl;
3052 3063          uint64_t vers;
3053 3064          boolean_t freelist = B_FALSE, memory_err = B_TRUE;
3054 3065          int retval = 0;
3055 3066  
3056 3067          (void) snprintf(msg, sizeof (msg),
3057 3068              dgettext(TEXT_DOMAIN, "Unable to split %s"), zhp->zpool_name);
3058 3069  
3059 3070          if (!zpool_name_valid(hdl, B_FALSE, newname))
3060 3071                  return (zfs_error(hdl, EZFS_INVALIDNAME, msg));
3061 3072  
3062 3073          if ((config = zpool_get_config(zhp, NULL)) == NULL) {
3063 3074                  (void) fprintf(stderr, gettext("Internal error: unable to "
3064 3075                      "retrieve pool configuration\n"));
3065 3076                  return (-1);
3066 3077          }
3067 3078  
3068 3079          verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &tree)
3069 3080              == 0);
3070 3081          verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, &vers) == 0);
3071 3082  
3072 3083          if (props) {
3073 3084                  prop_flags_t flags = { .create = B_FALSE, .import = B_TRUE };
3074 3085                  if ((zc_props = zpool_valid_proplist(hdl, zhp->zpool_name,
3075 3086                      props, vers, flags, msg)) == NULL)
3076 3087                          return (-1);
3077 3088          }
3078 3089  
3079 3090          if (nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN, &child,
3080 3091              &children) != 0) {
3081 3092                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3082 3093                      "Source pool is missing vdev tree"));
3083 3094                  nvlist_free(zc_props);
3084 3095                  return (-1);
3085 3096          }
3086 3097  
3087 3098          varray = zfs_alloc(hdl, children * sizeof (nvlist_t *));
3088 3099          vcount = 0;
3089 3100  
3090 3101          if (*newroot == NULL ||
3091 3102              nvlist_lookup_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN,
3092 3103              &newchild, &newchildren) != 0)
3093 3104                  newchildren = 0;
3094 3105  
3095 3106          for (c = 0; c < children; c++) {
3096 3107                  uint64_t is_log = B_FALSE, is_hole = B_FALSE;
3097 3108                  char *type;
3098 3109                  nvlist_t **mchild, *vdev;
3099 3110                  uint_t mchildren;
3100 3111                  int entry;
3101 3112  
3102 3113                  /*
3103 3114                   * Unlike cache & spares, slogs are stored in the
3104 3115                   * ZPOOL_CONFIG_CHILDREN array.  We filter them out here.
3105 3116                   */
3106 3117                  (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
3107 3118                      &is_log);
3108 3119                  (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
3109 3120                      &is_hole);
3110 3121                  if (is_log || is_hole) {
3111 3122                          /*
3112 3123                           * Create a hole vdev and put it in the config.
3113 3124                           */
3114 3125                          if (nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) != 0)
3115 3126                                  goto out;
3116 3127                          if (nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE,
3117 3128                              VDEV_TYPE_HOLE) != 0)
3118 3129                                  goto out;
3119 3130                          if (nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_HOLE,
3120 3131                              1) != 0)
3121 3132                                  goto out;
3122 3133                          if (lastlog == 0)
3123 3134                                  lastlog = vcount;
3124 3135                          varray[vcount++] = vdev;
3125 3136                          continue;
3126 3137                  }
3127 3138                  lastlog = 0;
3128 3139                  verify(nvlist_lookup_string(child[c], ZPOOL_CONFIG_TYPE, &type)
3129 3140                      == 0);
3130 3141                  if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
3131 3142                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3132 3143                              "Source pool must be composed only of mirrors\n"));
3133 3144                          retval = zfs_error(hdl, EZFS_INVALCONFIG, msg);
3134 3145                          goto out;
3135 3146                  }
3136 3147  
3137 3148                  verify(nvlist_lookup_nvlist_array(child[c],
3138 3149                      ZPOOL_CONFIG_CHILDREN, &mchild, &mchildren) == 0);
3139 3150  
3140 3151                  /* find or add an entry for this top-level vdev */
3141 3152                  if (newchildren > 0 &&
3142 3153                      (entry = find_vdev_entry(zhp, mchild, mchildren,
3143 3154                      newchild, newchildren)) >= 0) {
3144 3155                          /* We found a disk that the user specified. */
3145 3156                          vdev = mchild[entry];
3146 3157                          ++found;
3147 3158                  } else {
3148 3159                          /* User didn't specify a disk for this vdev. */
3149 3160                          vdev = mchild[mchildren - 1];
3150 3161                  }
3151 3162  
3152 3163                  if (nvlist_dup(vdev, &varray[vcount++], 0) != 0)
3153 3164                          goto out;
3154 3165          }
3155 3166  
3156 3167          /* did we find every disk the user specified? */
3157 3168          if (found != newchildren) {
3158 3169                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Device list must "
3159 3170                      "include at most one disk from each mirror"));
3160 3171                  retval = zfs_error(hdl, EZFS_INVALCONFIG, msg);
3161 3172                  goto out;
3162 3173          }
3163 3174  
3164 3175          /* Prepare the nvlist for populating. */
3165 3176          if (*newroot == NULL) {
3166 3177                  if (nvlist_alloc(newroot, NV_UNIQUE_NAME, 0) != 0)
3167 3178                          goto out;
3168 3179                  freelist = B_TRUE;
3169 3180                  if (nvlist_add_string(*newroot, ZPOOL_CONFIG_TYPE,
3170 3181                      VDEV_TYPE_ROOT) != 0)
3171 3182                          goto out;
3172 3183          } else {
3173 3184                  verify(nvlist_remove_all(*newroot, ZPOOL_CONFIG_CHILDREN) == 0);
3174 3185          }
3175 3186  
3176 3187          /* Add all the children we found */
3177 3188          if (nvlist_add_nvlist_array(*newroot, ZPOOL_CONFIG_CHILDREN, varray,
3178 3189              lastlog == 0 ? vcount : lastlog) != 0)
3179 3190                  goto out;
3180 3191  
3181 3192          /*
3182 3193           * If we're just doing a dry run, exit now with success.
3183 3194           */
3184 3195          if (flags.dryrun) {
3185 3196                  memory_err = B_FALSE;
3186 3197                  freelist = B_FALSE;
3187 3198                  goto out;
3188 3199          }
3189 3200  
3190 3201          /* now build up the config list & call the ioctl */
3191 3202          if (nvlist_alloc(&newconfig, NV_UNIQUE_NAME, 0) != 0)
3192 3203                  goto out;
3193 3204  
3194 3205          if (nvlist_add_nvlist(newconfig,
3195 3206              ZPOOL_CONFIG_VDEV_TREE, *newroot) != 0 ||
3196 3207              nvlist_add_string(newconfig,
3197 3208              ZPOOL_CONFIG_POOL_NAME, newname) != 0 ||
3198 3209              nvlist_add_uint64(newconfig, ZPOOL_CONFIG_VERSION, vers) != 0)
3199 3210                  goto out;
3200 3211  
3201 3212          /*
3202 3213           * The new pool is automatically part of the namespace unless we
3203 3214           * explicitly export it.
3204 3215           */
3205 3216          if (!flags.import)
3206 3217                  zc.zc_cookie = ZPOOL_EXPORT_AFTER_SPLIT;
3207 3218          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3208 3219          (void) strlcpy(zc.zc_string, newname, sizeof (zc.zc_string));
3209 3220          if (zcmd_write_conf_nvlist(hdl, &zc, newconfig) != 0)
3210 3221                  goto out;
3211 3222          if (zc_props != NULL && zcmd_write_src_nvlist(hdl, &zc, zc_props) != 0)
3212 3223                  goto out;
3213 3224  
3214 3225          if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SPLIT, &zc) != 0) {
3215 3226                  retval = zpool_standard_error(hdl, errno, msg);
3216 3227                  goto out;
3217 3228          }
3218 3229  
3219 3230          freelist = B_FALSE;
3220 3231          memory_err = B_FALSE;
3221 3232  
3222 3233  out:
3223 3234          if (varray != NULL) {
3224 3235                  int v;
3225 3236  
3226 3237                  for (v = 0; v < vcount; v++)
3227 3238                          nvlist_free(varray[v]);
3228 3239                  free(varray);
3229 3240          }
3230 3241          zcmd_free_nvlists(&zc);
3231 3242          nvlist_free(zc_props);
3232 3243          nvlist_free(newconfig);
3233 3244          if (freelist) {
3234 3245                  nvlist_free(*newroot);
3235 3246                  *newroot = NULL;
3236 3247          }
3237 3248  
3238 3249          if (retval != 0)
3239 3250                  return (retval);
3240 3251  
3241 3252          if (memory_err)
3242 3253                  return (no_memory(hdl));
3243 3254  
3244 3255          return (0);
3245 3256  }
3246 3257  
3247 3258  /*
3248 3259   * Remove the given device.
3249 3260   */
3250 3261  int
3251 3262  zpool_vdev_remove(zpool_handle_t *zhp, const char *path)
3252 3263  {
3253 3264          zfs_cmd_t zc = { 0 };
3254 3265          char msg[1024];
3255 3266          nvlist_t *tgt;
3256 3267          boolean_t avail_spare, l2cache, islog;
3257 3268          libzfs_handle_t *hdl = zhp->zpool_hdl;
3258 3269          uint64_t version;
3259 3270  
3260 3271          (void) snprintf(msg, sizeof (msg),
3261 3272              dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
3262 3273  
3263 3274          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3264 3275          if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
3265 3276              &islog)) == NULL)
3266 3277                  return (zfs_error(hdl, EZFS_NODEVICE, msg));
3267 3278  
3268 3279          version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
3269 3280          if (islog && version < SPA_VERSION_HOLES) {
3270 3281                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3271 3282                      "pool must be upgraded to support log removal"));
3272 3283                  return (zfs_error(hdl, EZFS_BADVERSION, msg));
3273 3284          }
3274 3285  
3275 3286          if (!islog && !avail_spare && !l2cache && zpool_is_bootable(zhp)) {
3276 3287                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3277 3288                      "root pool can not have removed devices, "
3278 3289                      "because GRUB does not understand them"));
3279 3290                  return (zfs_error(hdl, EINVAL, msg));
3280 3291          }
3281 3292  
3282 3293          zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
3283 3294  
3284 3295          if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0)
3285 3296                  return (0);
3286 3297  
3287 3298          switch (errno) {
3288 3299  
3289 3300          case EINVAL:
3290 3301                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3291 3302                      "invalid config; all top-level vdevs must "
3292 3303                      "have the same sector size and not be raidz."));
3293 3304                  (void) zfs_error(hdl, EZFS_INVALCONFIG, msg);
3294 3305                  break;
3295 3306  
3296 3307          case EBUSY:
3297 3308                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3298 3309                      "Pool busy; removal may already be in progress"));
3299 3310                  (void) zfs_error(hdl, EZFS_BUSY, msg);
3300 3311                  break;
3301 3312  
3302 3313          default:
3303 3314                  (void) zpool_standard_error(hdl, errno, msg);
3304 3315          }
3305 3316          return (-1);
3306 3317  }
3307 3318  
3308 3319  int
3309 3320  zpool_vdev_remove_cancel(zpool_handle_t *zhp)
3310 3321  {
3311 3322          zfs_cmd_t zc = { 0 };
3312 3323          char msg[1024];
3313 3324          libzfs_handle_t *hdl = zhp->zpool_hdl;
3314 3325  
3315 3326          (void) snprintf(msg, sizeof (msg),
3316 3327              dgettext(TEXT_DOMAIN, "cannot cancel removal"));
3317 3328  
3318 3329          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3319 3330          zc.zc_cookie = 1;
3320 3331  
3321 3332          if (zfs_ioctl(hdl, ZFS_IOC_VDEV_REMOVE, &zc) == 0)
3322 3333                  return (0);
3323 3334  
3324 3335          return (zpool_standard_error(hdl, errno, msg));
3325 3336  }
3326 3337  
3327 3338  int
3328 3339  zpool_vdev_indirect_size(zpool_handle_t *zhp, const char *path,
3329 3340      uint64_t *sizep)
3330 3341  {
3331 3342          char msg[1024];
3332 3343          nvlist_t *tgt;
3333 3344          boolean_t avail_spare, l2cache, islog;
3334 3345          libzfs_handle_t *hdl = zhp->zpool_hdl;
3335 3346  
3336 3347          (void) snprintf(msg, sizeof (msg),
3337 3348              dgettext(TEXT_DOMAIN, "cannot determine indirect size of %s"),
3338 3349              path);
3339 3350  
3340 3351          if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
3341 3352              &islog)) == NULL)
3342 3353                  return (zfs_error(hdl, EZFS_NODEVICE, msg));
3343 3354  
3344 3355          if (avail_spare || l2cache || islog) {
3345 3356                  *sizep = 0;
3346 3357                  return (0);
3347 3358          }
3348 3359  
3349 3360          if (nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_INDIRECT_SIZE, sizep) != 0) {
3350 3361                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3351 3362                      "indirect size not available"));
3352 3363                  return (zfs_error(hdl, EINVAL, msg));
3353 3364          }
3354 3365          return (0);
3355 3366  }
3356 3367  
3357 3368  /*
3358 3369   * Clear the errors for the pool, or the particular device if specified.
3359 3370   */
3360 3371  int
3361 3372  zpool_clear(zpool_handle_t *zhp, const char *path, nvlist_t *rewindnvl)
3362 3373  {
3363 3374          zfs_cmd_t zc = { 0 };
3364 3375          char msg[1024];
3365 3376          nvlist_t *tgt;
3366 3377          zpool_load_policy_t policy;
3367 3378          boolean_t avail_spare, l2cache;
3368 3379          libzfs_handle_t *hdl = zhp->zpool_hdl;
3369 3380          nvlist_t *nvi = NULL;
3370 3381          int error;
3371 3382  
3372 3383          if (path)
3373 3384                  (void) snprintf(msg, sizeof (msg),
3374 3385                      dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
3375 3386                      path);
3376 3387          else
3377 3388                  (void) snprintf(msg, sizeof (msg),
3378 3389                      dgettext(TEXT_DOMAIN, "cannot clear errors for %s"),
3379 3390                      zhp->zpool_name);
3380 3391  
3381 3392          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3382 3393          if (path) {
3383 3394                  if ((tgt = zpool_find_vdev(zhp, path, &avail_spare,
3384 3395                      &l2cache, NULL)) == NULL)
3385 3396                          return (zfs_error(hdl, EZFS_NODEVICE, msg));
3386 3397  
3387 3398                  /*
3388 3399                   * Don't allow error clearing for hot spares.  Do allow
3389 3400                   * error clearing for l2cache devices.
3390 3401                   */
3391 3402                  if (avail_spare)
3392 3403                          return (zfs_error(hdl, EZFS_ISSPARE, msg));
3393 3404  
3394 3405                  verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID,
3395 3406                      &zc.zc_guid) == 0);
3396 3407          }
3397 3408  
3398 3409          zpool_get_load_policy(rewindnvl, &policy);
3399 3410          zc.zc_cookie = policy.zlp_rewind;
3400 3411  
3401 3412          if (zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size * 2) != 0)
3402 3413                  return (-1);
3403 3414  
3404 3415          if (zcmd_write_src_nvlist(hdl, &zc, rewindnvl) != 0)
3405 3416                  return (-1);
3406 3417  
3407 3418          while ((error = zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc)) != 0 &&
3408 3419              errno == ENOMEM) {
3409 3420                  if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
3410 3421                          zcmd_free_nvlists(&zc);
3411 3422                          return (-1);
3412 3423                  }
3413 3424          }
3414 3425  
3415 3426          if (!error || ((policy.zlp_rewind & ZPOOL_TRY_REWIND) &&
3416 3427              errno != EPERM && errno != EACCES)) {
3417 3428                  if (policy.zlp_rewind &
3418 3429                      (ZPOOL_DO_REWIND | ZPOOL_TRY_REWIND)) {
3419 3430                          (void) zcmd_read_dst_nvlist(hdl, &zc, &nvi);
3420 3431                          zpool_rewind_exclaim(hdl, zc.zc_name,
3421 3432                              ((policy.zlp_rewind & ZPOOL_TRY_REWIND) != 0),
3422 3433                              nvi);
3423 3434                          nvlist_free(nvi);
3424 3435                  }
3425 3436                  zcmd_free_nvlists(&zc);
3426 3437                  return (0);
3427 3438          }
3428 3439  
3429 3440          zcmd_free_nvlists(&zc);
3430 3441          return (zpool_standard_error(hdl, errno, msg));
3431 3442  }
3432 3443  
3433 3444  /*
3434 3445   * Similar to zpool_clear(), but takes a GUID (used by fmd).
3435 3446   */
3436 3447  int
3437 3448  zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid)
3438 3449  {
3439 3450          zfs_cmd_t zc = { 0 };
3440 3451          char msg[1024];
3441 3452          libzfs_handle_t *hdl = zhp->zpool_hdl;
3442 3453  
3443 3454          (void) snprintf(msg, sizeof (msg),
3444 3455              dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"),
3445 3456              guid);
3446 3457  
3447 3458          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3448 3459          zc.zc_guid = guid;
3449 3460          zc.zc_cookie = ZPOOL_NO_REWIND;
3450 3461  
3451 3462          if (ioctl(hdl->libzfs_fd, ZFS_IOC_CLEAR, &zc) == 0)
3452 3463                  return (0);
3453 3464  
3454 3465          return (zpool_standard_error(hdl, errno, msg));
3455 3466  }
3456 3467  
3457 3468  /*
3458 3469   * Change the GUID for a pool.
3459 3470   */
3460 3471  int
3461 3472  zpool_reguid(zpool_handle_t *zhp)
3462 3473  {
3463 3474          char msg[1024];
3464 3475          libzfs_handle_t *hdl = zhp->zpool_hdl;
3465 3476          zfs_cmd_t zc = { 0 };
3466 3477  
3467 3478          (void) snprintf(msg, sizeof (msg),
3468 3479              dgettext(TEXT_DOMAIN, "cannot reguid '%s'"), zhp->zpool_name);
3469 3480  
3470 3481          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3471 3482          if (zfs_ioctl(hdl, ZFS_IOC_POOL_REGUID, &zc) == 0)
3472 3483                  return (0);
3473 3484  
3474 3485          return (zpool_standard_error(hdl, errno, msg));
3475 3486  }
3476 3487  
3477 3488  /*
3478 3489   * Reopen the pool.
3479 3490   */
3480 3491  int
3481 3492  zpool_reopen(zpool_handle_t *zhp)
3482 3493  {
3483 3494          zfs_cmd_t zc = { 0 };
3484 3495          char msg[1024];
3485 3496          libzfs_handle_t *hdl = zhp->zpool_hdl;
3486 3497  
3487 3498          (void) snprintf(msg, sizeof (msg),
3488 3499              dgettext(TEXT_DOMAIN, "cannot reopen '%s'"),
3489 3500              zhp->zpool_name);
3490 3501  
3491 3502          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3492 3503          if (zfs_ioctl(hdl, ZFS_IOC_POOL_REOPEN, &zc) == 0)
3493 3504                  return (0);
3494 3505          return (zpool_standard_error(hdl, errno, msg));
3495 3506  }
3496 3507  
3497 3508  /*
3498 3509   * Convert from a devid string to a path.
3499 3510   */
3500 3511  static char *
3501 3512  devid_to_path(char *devid_str)
3502 3513  {
3503 3514          ddi_devid_t devid;
3504 3515          char *minor;
3505 3516          char *path;
3506 3517          devid_nmlist_t *list = NULL;
3507 3518          int ret;
3508 3519  
3509 3520          if (devid_str_decode(devid_str, &devid, &minor) != 0)
3510 3521                  return (NULL);
3511 3522  
3512 3523          ret = devid_deviceid_to_nmlist("/dev", devid, minor, &list);
3513 3524  
3514 3525          devid_str_free(minor);
3515 3526          devid_free(devid);
3516 3527  
3517 3528          if (ret != 0)
3518 3529                  return (NULL);
3519 3530  
3520 3531          /*
3521 3532           * In a case the strdup() fails, we will just return NULL below.
3522 3533           */
3523 3534          path = strdup(list[0].devname);
3524 3535  
3525 3536          devid_free_nmlist(list);
3526 3537  
3527 3538          return (path);
3528 3539  }
3529 3540  
3530 3541  /*
3531 3542   * Convert from a path to a devid string.
3532 3543   */
3533 3544  static char *
3534 3545  path_to_devid(const char *path)
3535 3546  {
3536 3547          int fd;
3537 3548          ddi_devid_t devid;
3538 3549          char *minor, *ret;
3539 3550  
3540 3551          if ((fd = open(path, O_RDONLY)) < 0)
3541 3552                  return (NULL);
3542 3553  
3543 3554          minor = NULL;
3544 3555          ret = NULL;
3545 3556          if (devid_get(fd, &devid) == 0) {
3546 3557                  if (devid_get_minor_name(fd, &minor) == 0)
3547 3558                          ret = devid_str_encode(devid, minor);
3548 3559                  if (minor != NULL)
3549 3560                          devid_str_free(minor);
3550 3561                  devid_free(devid);
3551 3562          }
3552 3563          (void) close(fd);
3553 3564  
3554 3565          return (ret);
3555 3566  }
3556 3567  
3557 3568  /*
3558 3569   * Issue the necessary ioctl() to update the stored path value for the vdev.  We
3559 3570   * ignore any failure here, since a common case is for an unprivileged user to
3560 3571   * type 'zpool status', and we'll display the correct information anyway.
3561 3572   */
3562 3573  static void
3563 3574  set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path)
3564 3575  {
3565 3576          zfs_cmd_t zc = { 0 };
3566 3577  
3567 3578          (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3568 3579          (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value));
3569 3580          verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
3570 3581              &zc.zc_guid) == 0);
3571 3582  
3572 3583          (void) ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_SETPATH, &zc);
3573 3584  }
3574 3585  
3575 3586  /*
3576 3587   * Given a vdev, return the name to display in iostat.  If the vdev has a path,
3577 3588   * we use that, stripping off any leading "/dev/dsk/"; if not, we use the type.
3578 3589   * We also check if this is a whole disk, in which case we strip off the
3579 3590   * trailing 's0' slice name.
3580 3591   *
3581 3592   * This routine is also responsible for identifying when disks have been
3582 3593   * reconfigured in a new location.  The kernel will have opened the device by
3583 3594   * devid, but the path will still refer to the old location.  To catch this, we
3584 3595   * first do a path -> devid translation (which is fast for the common case).  If
3585 3596   * the devid matches, we're done.  If not, we do a reverse devid -> path
3586 3597   * translation and issue the appropriate ioctl() to update the path of the vdev.
3587 3598   * If 'zhp' is NULL, then this is an exported pool, and we don't need to do any
3588 3599   * of these checks.
3589 3600   */
3590 3601  char *
3591 3602  zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
3592 3603      boolean_t verbose)
3593 3604  {
3594 3605          char *path, *devid;
3595 3606          uint64_t value;
3596 3607          char buf[64];
3597 3608          vdev_stat_t *vs;
3598 3609          uint_t vsc;
3599 3610  
3600 3611          if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
3601 3612              &value) == 0) {
3602 3613                  verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
3603 3614                      &value) == 0);
3604 3615                  (void) snprintf(buf, sizeof (buf), "%llu",
3605 3616                      (u_longlong_t)value);
3606 3617                  path = buf;
3607 3618          } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
3608 3619  
3609 3620                  /*
3610 3621                   * If the device is dead (faulted, offline, etc) then don't
3611 3622                   * bother opening it.  Otherwise we may be forcing the user to
3612 3623                   * open a misbehaving device, which can have undesirable
3613 3624                   * effects.
3614 3625                   */
3615 3626                  if ((nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3616 3627                      (uint64_t **)&vs, &vsc) != 0 ||
3617 3628                      vs->vs_state >= VDEV_STATE_DEGRADED) &&
3618 3629                      zhp != NULL &&
3619 3630                      nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &devid) == 0) {
3620 3631                          /*
3621 3632                           * Determine if the current path is correct.
3622 3633                           */
3623 3634                          char *newdevid = path_to_devid(path);
3624 3635  
3625 3636                          if (newdevid == NULL ||
3626 3637                              strcmp(devid, newdevid) != 0) {
3627 3638                                  char *newpath;
3628 3639  
3629 3640                                  if ((newpath = devid_to_path(devid)) != NULL) {
3630 3641                                          /*
3631 3642                                           * Update the path appropriately.
3632 3643                                           */
3633 3644                                          set_path(zhp, nv, newpath);
3634 3645                                          if (nvlist_add_string(nv,
3635 3646                                              ZPOOL_CONFIG_PATH, newpath) == 0)
3636 3647                                                  verify(nvlist_lookup_string(nv,
3637 3648                                                      ZPOOL_CONFIG_PATH,
3638 3649                                                      &path) == 0);
3639 3650                                          free(newpath);
3640 3651                                  }
3641 3652                          }
3642 3653  
3643 3654                          if (newdevid)
3644 3655                                  devid_str_free(newdevid);
3645 3656                  }
3646 3657  
3647 3658                  if (strncmp(path, ZFS_DISK_ROOTD, strlen(ZFS_DISK_ROOTD)) == 0)
3648 3659                          path += strlen(ZFS_DISK_ROOTD);
3649 3660  
3650 3661                  if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
3651 3662                      &value) == 0 && value) {
3652 3663                          int pathlen = strlen(path);
3653 3664                          char *tmp = zfs_strdup(hdl, path);
3654 3665  
3655 3666                          /*
3656 3667                           * If it starts with c#, and ends with "s0" or "s1",
3657 3668                           * chop the slice off, or if it ends with "s0/old" or
3658 3669                           * "s1/old", remove the slice from the middle.
3659 3670                           */
3660 3671                          if (CTD_CHECK(tmp)) {
3661 3672                                  if (strcmp(&tmp[pathlen - 2], "s0") == 0 ||
3662 3673                                      strcmp(&tmp[pathlen - 2], "s1") == 0) {
3663 3674                                          tmp[pathlen - 2] = '\0';
3664 3675                                  } else if (pathlen > 6 &&
3665 3676                                      (strcmp(&tmp[pathlen - 6], "s0/old") == 0 ||
3666 3677                                      strcmp(&tmp[pathlen - 6], "s1/old") == 0)) {
3667 3678                                          (void) strcpy(&tmp[pathlen - 6],
3668 3679                                              "/old");
3669 3680                                  }
3670 3681                          }
3671 3682                          return (tmp);
3672 3683                  }
3673 3684          } else {
3674 3685                  verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0);
3675 3686  
3676 3687                  /*
3677 3688                   * If it's a raidz device, we need to stick in the parity level.
3678 3689                   */
3679 3690                  if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) {
3680 3691                          verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY,
3681 3692                              &value) == 0);
3682 3693                          (void) snprintf(buf, sizeof (buf), "%s%llu", path,
3683 3694                              (u_longlong_t)value);
3684 3695                          path = buf;
3685 3696                  }
3686 3697  
3687 3698                  /*
3688 3699                   * We identify each top-level vdev by using a <type-id>
3689 3700                   * naming convention.
3690 3701                   */
3691 3702                  if (verbose) {
3692 3703                          uint64_t id;
3693 3704  
3694 3705                          verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID,
3695 3706                              &id) == 0);
3696 3707                          (void) snprintf(buf, sizeof (buf), "%s-%llu", path,
3697 3708                              (u_longlong_t)id);
3698 3709                          path = buf;
3699 3710                  }
3700 3711          }
3701 3712  
3702 3713          return (zfs_strdup(hdl, path));
3703 3714  }
3704 3715  
3705 3716  static int
3706 3717  zbookmark_mem_compare(const void *a, const void *b)
3707 3718  {
3708 3719          return (memcmp(a, b, sizeof (zbookmark_phys_t)));
3709 3720  }
3710 3721  
3711 3722  /*
3712 3723   * Retrieve the persistent error log, uniquify the members, and return to the
3713 3724   * caller.
3714 3725   */
3715 3726  int
3716 3727  zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
3717 3728  {
3718 3729          zfs_cmd_t zc = { 0 };
3719 3730          uint64_t count;
3720 3731          zbookmark_phys_t *zb = NULL;
3721 3732          int i;
3722 3733  
3723 3734          /*
3724 3735           * Retrieve the raw error list from the kernel.  If the number of errors
3725 3736           * has increased, allocate more space and continue until we get the
3726 3737           * entire list.
3727 3738           */
3728 3739          verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT,
3729 3740              &count) == 0);
3730 3741          if (count == 0)
3731 3742                  return (0);
3732 3743          if ((zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl,
3733 3744              count * sizeof (zbookmark_phys_t))) == (uintptr_t)NULL)
3734 3745                  return (-1);
3735 3746          zc.zc_nvlist_dst_size = count;
3736 3747          (void) strcpy(zc.zc_name, zhp->zpool_name);
3737 3748          for (;;) {
3738 3749                  if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_ERROR_LOG,
3739 3750                      &zc) != 0) {
3740 3751                          free((void *)(uintptr_t)zc.zc_nvlist_dst);
3741 3752                          if (errno == ENOMEM) {
3742 3753                                  void *dst;
3743 3754  
3744 3755                                  count = zc.zc_nvlist_dst_size;
3745 3756                                  dst = zfs_alloc(zhp->zpool_hdl, count *
3746 3757                                      sizeof (zbookmark_phys_t));
3747 3758                                  if (dst == NULL)
3748 3759                                          return (-1);
3749 3760                                  zc.zc_nvlist_dst = (uintptr_t)dst;
3750 3761                          } else {
3751 3762                                  return (-1);
3752 3763                          }
3753 3764                  } else {
3754 3765                          break;
3755 3766                  }
3756 3767          }
3757 3768  
3758 3769          /*
3759 3770           * Sort the resulting bookmarks.  This is a little confusing due to the
3760 3771           * implementation of ZFS_IOC_ERROR_LOG.  The bookmarks are copied last
3761 3772           * to first, and 'zc_nvlist_dst_size' indicates the number of boomarks
3762 3773           * _not_ copied as part of the process.  So we point the start of our
3763 3774           * array appropriate and decrement the total number of elements.
3764 3775           */
3765 3776          zb = ((zbookmark_phys_t *)(uintptr_t)zc.zc_nvlist_dst) +
3766 3777              zc.zc_nvlist_dst_size;
3767 3778          count -= zc.zc_nvlist_dst_size;
3768 3779  
3769 3780          qsort(zb, count, sizeof (zbookmark_phys_t), zbookmark_mem_compare);
3770 3781  
3771 3782          verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0);
3772 3783  
3773 3784          /*
3774 3785           * Fill in the nverrlistp with nvlist's of dataset and object numbers.
3775 3786           */
3776 3787          for (i = 0; i < count; i++) {
3777 3788                  nvlist_t *nv;
3778 3789  
3779 3790                  /* ignoring zb_blkid and zb_level for now */
3780 3791                  if (i > 0 && zb[i-1].zb_objset == zb[i].zb_objset &&
3781 3792                      zb[i-1].zb_object == zb[i].zb_object)
3782 3793                          continue;
3783 3794  
3784 3795                  if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0)
3785 3796                          goto nomem;
3786 3797                  if (nvlist_add_uint64(nv, ZPOOL_ERR_DATASET,
3787 3798                      zb[i].zb_objset) != 0) {
3788 3799                          nvlist_free(nv);
3789 3800                          goto nomem;
3790 3801                  }
3791 3802                  if (nvlist_add_uint64(nv, ZPOOL_ERR_OBJECT,
3792 3803                      zb[i].zb_object) != 0) {
3793 3804                          nvlist_free(nv);
3794 3805                          goto nomem;
3795 3806                  }
3796 3807                  if (nvlist_add_nvlist(*nverrlistp, "ejk", nv) != 0) {
3797 3808                          nvlist_free(nv);
3798 3809                          goto nomem;
3799 3810                  }
3800 3811                  nvlist_free(nv);
3801 3812          }
3802 3813  
3803 3814          free((void *)(uintptr_t)zc.zc_nvlist_dst);
3804 3815          return (0);
3805 3816  
3806 3817  nomem:
3807 3818          free((void *)(uintptr_t)zc.zc_nvlist_dst);
3808 3819          return (no_memory(zhp->zpool_hdl));
3809 3820  }
3810 3821  
3811 3822  /*
3812 3823   * Upgrade a ZFS pool to the latest on-disk version.
3813 3824   */
3814 3825  int
3815 3826  zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version)
3816 3827  {
3817 3828          zfs_cmd_t zc = { 0 };
3818 3829          libzfs_handle_t *hdl = zhp->zpool_hdl;
3819 3830  
3820 3831          (void) strcpy(zc.zc_name, zhp->zpool_name);
3821 3832          zc.zc_cookie = new_version;
3822 3833  
3823 3834          if (zfs_ioctl(hdl, ZFS_IOC_POOL_UPGRADE, &zc) != 0)
3824 3835                  return (zpool_standard_error_fmt(hdl, errno,
3825 3836                      dgettext(TEXT_DOMAIN, "cannot upgrade '%s'"),
3826 3837                      zhp->zpool_name));
3827 3838          return (0);
3828 3839  }
3829 3840  
3830 3841  void
3831 3842  zfs_save_arguments(int argc, char **argv, char *string, int len)
3832 3843  {
3833 3844          (void) strlcpy(string, basename(argv[0]), len);
3834 3845          for (int i = 1; i < argc; i++) {
3835 3846                  (void) strlcat(string, " ", len);
3836 3847                  (void) strlcat(string, argv[i], len);
3837 3848          }
3838 3849  }
3839 3850  
3840 3851  int
3841 3852  zpool_log_history(libzfs_handle_t *hdl, const char *message)
3842 3853  {
3843 3854          zfs_cmd_t zc = { 0 };
3844 3855          nvlist_t *args;
3845 3856          int err;
3846 3857  
3847 3858          args = fnvlist_alloc();
3848 3859          fnvlist_add_string(args, "message", message);
3849 3860          err = zcmd_write_src_nvlist(hdl, &zc, args);
3850 3861          if (err == 0)
3851 3862                  err = ioctl(hdl->libzfs_fd, ZFS_IOC_LOG_HISTORY, &zc);
3852 3863          nvlist_free(args);
3853 3864          zcmd_free_nvlists(&zc);
3854 3865          return (err);
3855 3866  }
3856 3867  
3857 3868  /*
3858 3869   * Perform ioctl to get some command history of a pool.
3859 3870   *
3860 3871   * 'buf' is the buffer to fill up to 'len' bytes.  'off' is the
3861 3872   * logical offset of the history buffer to start reading from.
3862 3873   *
3863 3874   * Upon return, 'off' is the next logical offset to read from and
3864 3875   * 'len' is the actual amount of bytes read into 'buf'.
3865 3876   */
3866 3877  static int
3867 3878  get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len)
3868 3879  {
3869 3880          zfs_cmd_t zc = { 0 };
3870 3881          libzfs_handle_t *hdl = zhp->zpool_hdl;
3871 3882  
3872 3883          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
3873 3884  
3874 3885          zc.zc_history = (uint64_t)(uintptr_t)buf;
3875 3886          zc.zc_history_len = *len;
3876 3887          zc.zc_history_offset = *off;
3877 3888  
3878 3889          if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_GET_HISTORY, &zc) != 0) {
3879 3890                  switch (errno) {
3880 3891                  case EPERM:
3881 3892                          return (zfs_error_fmt(hdl, EZFS_PERM,
3882 3893                              dgettext(TEXT_DOMAIN,
3883 3894                              "cannot show history for pool '%s'"),
3884 3895                              zhp->zpool_name));
3885 3896                  case ENOENT:
3886 3897                          return (zfs_error_fmt(hdl, EZFS_NOHISTORY,
3887 3898                              dgettext(TEXT_DOMAIN, "cannot get history for pool "
3888 3899                              "'%s'"), zhp->zpool_name));
3889 3900                  case ENOTSUP:
3890 3901                          return (zfs_error_fmt(hdl, EZFS_BADVERSION,
3891 3902                              dgettext(TEXT_DOMAIN, "cannot get history for pool "
3892 3903                              "'%s', pool must be upgraded"), zhp->zpool_name));
3893 3904                  default:
3894 3905                          return (zpool_standard_error_fmt(hdl, errno,
3895 3906                              dgettext(TEXT_DOMAIN,
3896 3907                              "cannot get history for '%s'"), zhp->zpool_name));
3897 3908                  }
3898 3909          }
3899 3910  
3900 3911          *len = zc.zc_history_len;
3901 3912          *off = zc.zc_history_offset;
3902 3913  
3903 3914          return (0);
3904 3915  }
3905 3916  
3906 3917  /*
3907 3918   * Process the buffer of nvlists, unpacking and storing each nvlist record
3908 3919   * into 'records'.  'leftover' is set to the number of bytes that weren't
3909 3920   * processed as there wasn't a complete record.
3910 3921   */
3911 3922  int
3912 3923  zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover,
3913 3924      nvlist_t ***records, uint_t *numrecords)
3914 3925  {
3915 3926          uint64_t reclen;
3916 3927          nvlist_t *nv;
3917 3928          int i;
3918 3929  
3919 3930          while (bytes_read > sizeof (reclen)) {
3920 3931  
3921 3932                  /* get length of packed record (stored as little endian) */
3922 3933                  for (i = 0, reclen = 0; i < sizeof (reclen); i++)
3923 3934                          reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i);
3924 3935  
3925 3936                  if (bytes_read < sizeof (reclen) + reclen)
3926 3937                          break;
3927 3938  
3928 3939                  /* unpack record */
3929 3940                  if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0)
3930 3941                          return (ENOMEM);
3931 3942                  bytes_read -= sizeof (reclen) + reclen;
3932 3943                  buf += sizeof (reclen) + reclen;
3933 3944  
3934 3945                  /* add record to nvlist array */
3935 3946                  (*numrecords)++;
3936 3947                  if (ISP2(*numrecords + 1)) {
3937 3948                          *records = realloc(*records,
3938 3949                              *numrecords * 2 * sizeof (nvlist_t *));
3939 3950                  }
3940 3951                  (*records)[*numrecords - 1] = nv;
3941 3952          }
3942 3953  
3943 3954          *leftover = bytes_read;
3944 3955          return (0);
3945 3956  }
3946 3957  
3947 3958  /*
3948 3959   * Retrieve the command history of a pool.
3949 3960   */
3950 3961  int
3951 3962  zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
3952 3963  {
3953 3964          char *buf;
3954 3965          int buflen = 128 * 1024;
3955 3966          uint64_t off = 0;
3956 3967          nvlist_t **records = NULL;
3957 3968          uint_t numrecords = 0;
3958 3969          int err, i;
3959 3970  
3960 3971          buf = malloc(buflen);
3961 3972          if (buf == NULL)
3962 3973                  return (ENOMEM);
3963 3974          do {
3964 3975                  uint64_t bytes_read = buflen;
3965 3976                  uint64_t leftover;
3966 3977  
3967 3978                  if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0)
3968 3979                          break;
3969 3980  
3970 3981                  /* if nothing else was read in, we're at EOF, just return */
3971 3982                  if (!bytes_read)
3972 3983                          break;
3973 3984  
3974 3985                  if ((err = zpool_history_unpack(buf, bytes_read,
3975 3986                      &leftover, &records, &numrecords)) != 0)
3976 3987                          break;
3977 3988                  off -= leftover;
3978 3989                  if (leftover == bytes_read) {
3979 3990                          /*
3980 3991                           * no progress made, because buffer is not big enough
3981 3992                           * to hold this record; resize and retry.
3982 3993                           */
3983 3994                          buflen *= 2;
3984 3995                          free(buf);
3985 3996                          buf = malloc(buflen);
3986 3997                          if (buf == NULL)
3987 3998                                  return (ENOMEM);
3988 3999                  }
3989 4000  
3990 4001                  /* CONSTCOND */
3991 4002          } while (1);
3992 4003  
3993 4004          free(buf);
3994 4005  
3995 4006          if (!err) {
3996 4007                  verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0);
3997 4008                  verify(nvlist_add_nvlist_array(*nvhisp, ZPOOL_HIST_RECORD,
3998 4009                      records, numrecords) == 0);
3999 4010          }
4000 4011          for (i = 0; i < numrecords; i++)
4001 4012                  nvlist_free(records[i]);
4002 4013          free(records);
4003 4014  
4004 4015          return (err);
4005 4016  }
4006 4017  
4007 4018  void
4008 4019  zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
4009 4020      char *pathname, size_t len)
4010 4021  {
4011 4022          zfs_cmd_t zc = { 0 };
4012 4023          boolean_t mounted = B_FALSE;
4013 4024          char *mntpnt = NULL;
4014 4025          char dsname[ZFS_MAX_DATASET_NAME_LEN];
4015 4026  
4016 4027          if (dsobj == 0) {
4017 4028                  /* special case for the MOS */
4018 4029                  (void) snprintf(pathname, len, "<metadata>:<0x%llx>", obj);
4019 4030                  return;
4020 4031          }
4021 4032  
4022 4033          /* get the dataset's name */
4023 4034          (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
4024 4035          zc.zc_obj = dsobj;
4025 4036          if (ioctl(zhp->zpool_hdl->libzfs_fd,
4026 4037              ZFS_IOC_DSOBJ_TO_DSNAME, &zc) != 0) {
4027 4038                  /* just write out a path of two object numbers */
4028 4039                  (void) snprintf(pathname, len, "<0x%llx>:<0x%llx>",
4029 4040                      dsobj, obj);
4030 4041                  return;
4031 4042          }
4032 4043          (void) strlcpy(dsname, zc.zc_value, sizeof (dsname));
4033 4044  
4034 4045          /* find out if the dataset is mounted */
4035 4046          mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt);
4036 4047  
4037 4048          /* get the corrupted object's path */
4038 4049          (void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name));
4039 4050          zc.zc_obj = obj;
4040 4051          if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_OBJ_TO_PATH,
4041 4052              &zc) == 0) {
4042 4053                  if (mounted) {
4043 4054                          (void) snprintf(pathname, len, "%s%s", mntpnt,
4044 4055                              zc.zc_value);
4045 4056                  } else {
4046 4057                          (void) snprintf(pathname, len, "%s:%s",
4047 4058                              dsname, zc.zc_value);
4048 4059                  }
4049 4060          } else {
4050 4061                  (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, obj);
4051 4062          }
4052 4063          free(mntpnt);
4053 4064  }
4054 4065  
4055 4066  /*
4056 4067   * Read the EFI label from the config, if a label does not exist then
4057 4068   * pass back the error to the caller. If the caller has passed a non-NULL
4058 4069   * diskaddr argument then we set it to the starting address of the EFI
4059 4070   * partition. If the caller has passed a non-NULL boolean argument, then
4060 4071   * we set it to indicate if the disk does have efi system partition.
4061 4072   */
4062 4073  static int
4063 4074  read_efi_label(nvlist_t *config, diskaddr_t *sb, boolean_t *system)
4064 4075  {
4065 4076          char *path;
4066 4077          int fd;
4067 4078          char diskname[MAXPATHLEN];
4068 4079          boolean_t boot = B_FALSE;
4069 4080          int err = -1;
4070 4081          int slice;
4071 4082  
4072 4083          if (nvlist_lookup_string(config, ZPOOL_CONFIG_PATH, &path) != 0)
4073 4084                  return (err);
4074 4085  
4075 4086          (void) snprintf(diskname, sizeof (diskname), "%s%s", ZFS_RDISK_ROOT,
4076 4087              strrchr(path, '/'));
4077 4088          if ((fd = open(diskname, O_RDONLY|O_NDELAY)) >= 0) {
4078 4089                  struct dk_gpt *vtoc;
4079 4090  
4080 4091                  if ((err = efi_alloc_and_read(fd, &vtoc)) >= 0) {
4081 4092                          for (slice = 0; slice < vtoc->efi_nparts; slice++) {
4082 4093                                  if (vtoc->efi_parts[slice].p_tag == V_SYSTEM)
4083 4094                                          boot = B_TRUE;
4084 4095                                  if (vtoc->efi_parts[slice].p_tag == V_USR)
4085 4096                                          break;
4086 4097                          }
4087 4098                          if (sb != NULL && vtoc->efi_parts[slice].p_tag == V_USR)
4088 4099                                  *sb = vtoc->efi_parts[slice].p_start;
4089 4100                          if (system != NULL)
4090 4101                                  *system = boot;
4091 4102                          efi_free(vtoc);
4092 4103                  }
4093 4104                  (void) close(fd);
4094 4105          }
4095 4106          return (err);
4096 4107  }
4097 4108  
4098 4109  /*
4099 4110   * determine where a partition starts on a disk in the current
4100 4111   * configuration
4101 4112   */
4102 4113  static diskaddr_t
4103 4114  find_start_block(nvlist_t *config)
4104 4115  {
4105 4116          nvlist_t **child;
4106 4117          uint_t c, children;
4107 4118          diskaddr_t sb = MAXOFFSET_T;
4108 4119          uint64_t wholedisk;
4109 4120  
4110 4121          if (nvlist_lookup_nvlist_array(config,
4111 4122              ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) {
4112 4123                  if (nvlist_lookup_uint64(config,
4113 4124                      ZPOOL_CONFIG_WHOLE_DISK,
4114 4125                      &wholedisk) != 0 || !wholedisk) {
4115 4126                          return (MAXOFFSET_T);
4116 4127                  }
4117 4128                  if (read_efi_label(config, &sb, NULL) < 0)
4118 4129                          sb = MAXOFFSET_T;
4119 4130                  return (sb);
4120 4131          }
4121 4132  
4122 4133          for (c = 0; c < children; c++) {
4123 4134                  sb = find_start_block(child[c]);
4124 4135                  if (sb != MAXOFFSET_T) {
4125 4136                          return (sb);
4126 4137                  }
4127 4138          }
4128 4139          return (MAXOFFSET_T);
4129 4140  }
4130 4141  
4131 4142  /*
4132 4143   * Label an individual disk.  The name provided is the short name,
4133 4144   * stripped of any leading /dev path.
4134 4145   */
4135 4146  int
4136 4147  zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name,
4137 4148      zpool_boot_label_t boot_type, uint64_t boot_size, int *slice)
4138 4149  {
4139 4150          char path[MAXPATHLEN];
4140 4151          struct dk_gpt *vtoc;
4141 4152          int fd;
4142 4153          size_t resv = EFI_MIN_RESV_SIZE;
4143 4154          uint64_t slice_size;
4144 4155          diskaddr_t start_block;
4145 4156          char errbuf[1024];
4146 4157  
4147 4158          /* prepare an error message just in case */
4148 4159          (void) snprintf(errbuf, sizeof (errbuf),
4149 4160              dgettext(TEXT_DOMAIN, "cannot label '%s'"), name);
4150 4161  
4151 4162          if (zhp) {
4152 4163                  nvlist_t *nvroot;
4153 4164  
4154 4165                  verify(nvlist_lookup_nvlist(zhp->zpool_config,
4155 4166                      ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
4156 4167  
4157 4168                  if (zhp->zpool_start_block == 0)
4158 4169                          start_block = find_start_block(nvroot);
4159 4170                  else
4160 4171                          start_block = zhp->zpool_start_block;
4161 4172                  zhp->zpool_start_block = start_block;
4162 4173          } else {
4163 4174                  /* new pool */
4164 4175                  start_block = NEW_START_BLOCK;
4165 4176          }
4166 4177  
4167 4178          (void) snprintf(path, sizeof (path), "%s/%s%s", ZFS_RDISK_ROOT, name,
4168 4179              BACKUP_SLICE);
4169 4180  
4170 4181          if ((fd = open(path, O_RDWR | O_NDELAY)) < 0) {
4171 4182                  /*
4172 4183                   * This shouldn't happen.  We've long since verified that this
4173 4184                   * is a valid device.
4174 4185                   */
4175 4186                  zfs_error_aux(hdl,
4176 4187                      dgettext(TEXT_DOMAIN, "unable to open device"));
4177 4188                  return (zfs_error(hdl, EZFS_OPENFAILED, errbuf));
4178 4189          }
4179 4190  
4180 4191          if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) {
4181 4192                  /*
4182 4193                   * The only way this can fail is if we run out of memory, or we
4183 4194                   * were unable to read the disk's capacity
4184 4195                   */
4185 4196                  if (errno == ENOMEM)
4186 4197                          (void) no_memory(hdl);
4187 4198  
4188 4199                  (void) close(fd);
4189 4200                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4190 4201                      "unable to read disk capacity"), name);
4191 4202  
4192 4203                  return (zfs_error(hdl, EZFS_NOCAP, errbuf));
4193 4204          }
4194 4205  
4195 4206          /*
4196 4207           * Why we use V_USR: V_BACKUP confuses users, and is considered
4197 4208           * disposable by some EFI utilities (since EFI doesn't have a backup
4198 4209           * slice).  V_UNASSIGNED is supposed to be used only for zero size
4199 4210           * partitions, and efi_write() will fail if we use it.  V_ROOT, V_BOOT,
4200 4211           * etc. were all pretty specific.  V_USR is as close to reality as we
4201 4212           * can get, in the absence of V_OTHER.
4202 4213           */
4203 4214          /* first fix the partition start block */
4204 4215          if (start_block == MAXOFFSET_T)
4205 4216                  start_block = NEW_START_BLOCK;
4206 4217  
4207 4218          /*
4208 4219           * EFI System partition is using slice 0.
4209 4220           * ZFS is on slice 1 and slice 8 is reserved.
4210 4221           * We assume the GPT partition table without system
4211 4222           * partition has zfs p_start == NEW_START_BLOCK.
4212 4223           * If start_block != NEW_START_BLOCK, it means we have
4213 4224           * system partition. Correct solution would be to query/cache vtoc
4214 4225           * from existing vdev member.
4215 4226           */
4216 4227          if (boot_type == ZPOOL_CREATE_BOOT_LABEL) {
4217 4228                  if (boot_size % vtoc->efi_lbasize != 0) {
4218 4229                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4219 4230                              "boot partition size must be a multiple of %d"),
4220 4231                              vtoc->efi_lbasize);
4221 4232                          (void) close(fd);
4222 4233                          efi_free(vtoc);
4223 4234                          return (zfs_error(hdl, EZFS_LABELFAILED, errbuf));
4224 4235                  }
4225 4236                  /*
4226 4237                   * System partition size checks.
4227 4238                   * Note the 1MB is quite arbitrary value, since we
4228 4239                   * are creating dedicated pool, it should be enough
4229 4240                   * to hold fat + efi bootloader. May need to be
4230 4241                   * adjusted if the bootloader size will grow.
4231 4242                   */
4232 4243                  if (boot_size < 1024 * 1024) {
4233 4244                          char buf[64];
4234 4245                          zfs_nicenum(boot_size, buf, sizeof (buf));
4235 4246                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4236 4247                              "Specified size %s for EFI System partition is too "
4237 4248                              "small, the minimum size is 1MB."), buf);
4238 4249                          (void) close(fd);
4239 4250                          efi_free(vtoc);
4240 4251                          return (zfs_error(hdl, EZFS_LABELFAILED, errbuf));
4241 4252                  }
4242 4253                  /* 33MB is tested with mkfs -F pcfs */
4243 4254                  if (hdl->libzfs_printerr &&
4244 4255                      ((vtoc->efi_lbasize == 512 &&
4245 4256                      boot_size < 33 * 1024 * 1024) ||
4246 4257                      (vtoc->efi_lbasize == 4096 &&
4247 4258                      boot_size < 256 * 1024 * 1024)))  {
4248 4259                          char buf[64];
4249 4260                          zfs_nicenum(boot_size, buf, sizeof (buf));
4250 4261                          (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
4251 4262                              "Warning: EFI System partition size %s is "
4252 4263                              "not allowing to create FAT32 file\nsystem, which "
4253 4264                              "may result in unbootable system.\n"), buf);
4254 4265                  }
4255 4266                  /* Adjust zfs partition start by size of system partition. */
4256 4267                  start_block += boot_size / vtoc->efi_lbasize;
4257 4268          }
4258 4269  
4259 4270          if (start_block == NEW_START_BLOCK) {
4260 4271                  /*
4261 4272                   * Use default layout.
4262 4273                   * ZFS is on slice 0 and slice 8 is reserved.
4263 4274                   */
4264 4275                  slice_size = vtoc->efi_last_u_lba + 1;
4265 4276                  slice_size -= EFI_MIN_RESV_SIZE;
4266 4277                  slice_size -= start_block;
4267 4278                  if (slice != NULL)
4268 4279                          *slice = 0;
4269 4280  
4270 4281                  vtoc->efi_parts[0].p_start = start_block;
4271 4282                  vtoc->efi_parts[0].p_size = slice_size;
4272 4283  
4273 4284                  vtoc->efi_parts[0].p_tag = V_USR;
4274 4285                  (void) strcpy(vtoc->efi_parts[0].p_name, "zfs");
4275 4286  
4276 4287                  vtoc->efi_parts[8].p_start = slice_size + start_block;
4277 4288                  vtoc->efi_parts[8].p_size = resv;
4278 4289                  vtoc->efi_parts[8].p_tag = V_RESERVED;
4279 4290          } else {
4280 4291                  slice_size = start_block - NEW_START_BLOCK;
4281 4292                  vtoc->efi_parts[0].p_start = NEW_START_BLOCK;
4282 4293                  vtoc->efi_parts[0].p_size = slice_size;
4283 4294                  vtoc->efi_parts[0].p_tag = V_SYSTEM;
4284 4295                  (void) strcpy(vtoc->efi_parts[0].p_name, "loader");
4285 4296                  if (slice != NULL)
4286 4297                          *slice = 1;
4287 4298                  /* prepare slice 1 */
4288 4299                  slice_size = vtoc->efi_last_u_lba + 1 - slice_size;
4289 4300                  slice_size -= resv;
4290 4301                  slice_size -= NEW_START_BLOCK;
4291 4302                  vtoc->efi_parts[1].p_start = start_block;
4292 4303                  vtoc->efi_parts[1].p_size = slice_size;
4293 4304                  vtoc->efi_parts[1].p_tag = V_USR;
4294 4305                  (void) strcpy(vtoc->efi_parts[1].p_name, "zfs");
4295 4306  
4296 4307                  vtoc->efi_parts[8].p_start = slice_size + start_block;
4297 4308                  vtoc->efi_parts[8].p_size = resv;
4298 4309                  vtoc->efi_parts[8].p_tag = V_RESERVED;
4299 4310          }
4300 4311  
4301 4312          if (efi_write(fd, vtoc) != 0) {
4302 4313                  /*
4303 4314                   * Some block drivers (like pcata) may not support EFI
4304 4315                   * GPT labels.  Print out a helpful error message dir-
4305 4316                   * ecting the user to manually label the disk and give
4306 4317                   * a specific slice.
4307 4318                   */
4308 4319                  (void) close(fd);
4309 4320                  efi_free(vtoc);
4310 4321  
4311 4322                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4312 4323                      "try using fdisk(1M) and then provide a specific slice"));
4313 4324                  return (zfs_error(hdl, EZFS_LABELFAILED, errbuf));
4314 4325          }
4315 4326  
4316 4327          (void) close(fd);
4317 4328          efi_free(vtoc);
4318 4329          return (0);
4319 4330  }
4320 4331  
4321 4332  static boolean_t
4322 4333  supported_dump_vdev_type(libzfs_handle_t *hdl, nvlist_t *config, char *errbuf)
4323 4334  {
4324 4335          char *type;
4325 4336          nvlist_t **child;
4326 4337          uint_t children, c;
4327 4338  
4328 4339          verify(nvlist_lookup_string(config, ZPOOL_CONFIG_TYPE, &type) == 0);
4329 4340          if (strcmp(type, VDEV_TYPE_FILE) == 0 ||
4330 4341              strcmp(type, VDEV_TYPE_HOLE) == 0 ||
4331 4342              strcmp(type, VDEV_TYPE_MISSING) == 0) {
4332 4343                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4333 4344                      "vdev type '%s' is not supported"), type);
4334 4345                  (void) zfs_error(hdl, EZFS_VDEVNOTSUP, errbuf);
4335 4346                  return (B_FALSE);
4336 4347          }
4337 4348          if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN,
4338 4349              &child, &children) == 0) {
4339 4350                  for (c = 0; c < children; c++) {
4340 4351                          if (!supported_dump_vdev_type(hdl, child[c], errbuf))
4341 4352                                  return (B_FALSE);
4342 4353                  }
4343 4354          }
4344 4355          return (B_TRUE);
4345 4356  }
4346 4357  
4347 4358  /*
4348 4359   * Check if this zvol is allowable for use as a dump device; zero if
4349 4360   * it is, > 0 if it isn't, < 0 if it isn't a zvol.
4350 4361   *
4351 4362   * Allowable storage configurations include mirrors, all raidz variants, and
4352 4363   * pools with log, cache, and spare devices.  Pools which are backed by files or
4353 4364   * have missing/hole vdevs are not suitable.
4354 4365   */
4355 4366  int
4356 4367  zvol_check_dump_config(char *arg)
4357 4368  {
4358 4369          zpool_handle_t *zhp = NULL;
4359 4370          nvlist_t *config, *nvroot;
4360 4371          char *p, *volname;
4361 4372          nvlist_t **top;
4362 4373          uint_t toplevels;
4363 4374          libzfs_handle_t *hdl;
4364 4375          char errbuf[1024];
4365 4376          char poolname[ZFS_MAX_DATASET_NAME_LEN];
4366 4377          int pathlen = strlen(ZVOL_FULL_DEV_DIR);
4367 4378          int ret = 1;
4368 4379  
4369 4380          if (strncmp(arg, ZVOL_FULL_DEV_DIR, pathlen)) {
4370 4381                  return (-1);
4371 4382          }
4372 4383  
4373 4384          (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4374 4385              "dump is not supported on device '%s'"), arg);
4375 4386  
4376 4387          if ((hdl = libzfs_init()) == NULL)
4377 4388                  return (1);
4378 4389          libzfs_print_on_error(hdl, B_TRUE);
4379 4390  
4380 4391          volname = arg + pathlen;
4381 4392  
4382 4393          /* check the configuration of the pool */
4383 4394          if ((p = strchr(volname, '/')) == NULL) {
4384 4395                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4385 4396                      "malformed dataset name"));
4386 4397                  (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
4387 4398                  return (1);
4388 4399          } else if (p - volname >= ZFS_MAX_DATASET_NAME_LEN) {
4389 4400                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4390 4401                      "dataset name is too long"));
4391 4402                  (void) zfs_error(hdl, EZFS_NAMETOOLONG, errbuf);
4392 4403                  return (1);
4393 4404          } else {
4394 4405                  (void) strncpy(poolname, volname, p - volname);
4395 4406                  poolname[p - volname] = '\0';
4396 4407          }
4397 4408  
4398 4409          if ((zhp = zpool_open(hdl, poolname)) == NULL) {
4399 4410                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4400 4411                      "could not open pool '%s'"), poolname);
4401 4412                  (void) zfs_error(hdl, EZFS_OPENFAILED, errbuf);
4402 4413                  goto out;
4403 4414          }
4404 4415          config = zpool_get_config(zhp, NULL);
4405 4416          if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
4406 4417              &nvroot) != 0) {
4407 4418                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4408 4419                      "could not obtain vdev configuration for  '%s'"), poolname);
4409 4420                  (void) zfs_error(hdl, EZFS_INVALCONFIG, errbuf);
4410 4421                  goto out;
4411 4422          }
4412 4423  
4413 4424          verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4414 4425              &top, &toplevels) == 0);
4415 4426  
4416 4427          if (!supported_dump_vdev_type(hdl, top[0], errbuf)) {
4417 4428                  goto out;
4418 4429          }
4419 4430          ret = 0;
4420 4431  
4421 4432  out:
4422 4433          if (zhp)
4423 4434                  zpool_close(zhp);
4424 4435          libzfs_fini(hdl);
4425 4436          return (ret);
4426 4437  }
  
    | 
      ↓ open down ↓ | 
    3763 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX