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