The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/lib/libzfs/libzfs_pool.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: fbed835d7eac48d4673feb8fc554e8f0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.