Print this page
2619 asynchronous destruction of ZFS file systems
2747 SPA versioning with zfs feature flags
Reviewed by: Matt Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <gwilson@delphix.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>
Approved by: Dan McDonald <danmcd@nexenta.com>


  26  */
  27 
  28 #include <ctype.h>
  29 #include <errno.h>
  30 #include <devid.h>
  31 #include <fcntl.h>
  32 #include <libintl.h>
  33 #include <stdio.h>
  34 #include <stdlib.h>
  35 #include <strings.h>
  36 #include <unistd.h>
  37 #include <sys/efi_partition.h>
  38 #include <sys/vtoc.h>
  39 #include <sys/zfs_ioctl.h>
  40 #include <dlfcn.h>
  41 
  42 #include "zfs_namecheck.h"
  43 #include "zfs_prop.h"
  44 #include "libzfs_impl.h"
  45 #include "zfs_comutil.h"

  46 
  47 static int read_efi_label(nvlist_t *config, diskaddr_t *sb);
  48 
  49 #define DISK_ROOT       "/dev/dsk"
  50 #define RDISK_ROOT      "/dev/rdsk"
  51 #define BACKUP_SLICE    "s2"
  52 
  53 typedef struct prop_flags {
  54         int create:1;   /* Validate property on creation */
  55         int import:1;   /* Validate property on import */
  56 } prop_flags_t;
  57 
  58 /*
  59  * ====================================================================
  60  *   zpool property functions
  61  * ====================================================================
  62  */
  63 
  64 static int
  65 zpool_get_all_props(zpool_handle_t *zhp)


 256                 return (0);
 257         }
 258 
 259         if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) &&
 260             prop != ZPOOL_PROP_NAME)
 261                 return (-1);
 262 
 263         switch (zpool_prop_get_type(prop)) {
 264         case PROP_TYPE_STRING:
 265                 (void) strlcpy(buf, zpool_get_prop_string(zhp, prop, &src),
 266                     len);
 267                 break;
 268 
 269         case PROP_TYPE_NUMBER:
 270                 intval = zpool_get_prop_int(zhp, prop, &src);
 271 
 272                 switch (prop) {
 273                 case ZPOOL_PROP_SIZE:
 274                 case ZPOOL_PROP_ALLOCATED:
 275                 case ZPOOL_PROP_FREE:

 276                 case ZPOOL_PROP_EXPANDSZ:
 277                         (void) zfs_nicenum(intval, buf, len);
 278                         break;
 279 
 280                 case ZPOOL_PROP_CAPACITY:
 281                         (void) snprintf(buf, len, "%llu%%",
 282                             (u_longlong_t)intval);
 283                         break;
 284 
 285                 case ZPOOL_PROP_DEDUPRATIO:
 286                         (void) snprintf(buf, len, "%llu.%02llux",
 287                             (u_longlong_t)(intval / 100),
 288                             (u_longlong_t)(intval % 100));
 289                         break;
 290 
 291                 case ZPOOL_PROP_HEALTH:
 292                         verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
 293                             ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
 294                         verify(nvlist_lookup_uint64_array(nvroot,
 295                             ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &vsc)
 296                             == 0);
 297 
 298                         (void) strlcpy(buf, zpool_state_to_name(intval,
 299                             vs->vs_aux), len);
 300                         break;






 301                 default:
 302                         (void) snprintf(buf, len, "%llu", intval);
 303                 }
 304                 break;
 305 
 306         case PROP_TYPE_INDEX:
 307                 intval = zpool_get_prop_int(zhp, prop, &src);
 308                 if (zpool_prop_index_to_string(prop, intval, &strval)
 309                     != 0)
 310                         return (-1);
 311                 (void) strlcpy(buf, strval, len);
 312                 break;
 313 
 314         default:
 315                 abort();
 316         }
 317 
 318         if (srctype)
 319                 *srctype = src;
 320 


 383 {
 384         nvpair_t *elem;
 385         nvlist_t *retprops;
 386         zpool_prop_t prop;
 387         char *strval;
 388         uint64_t intval;
 389         char *slash, *check;
 390         struct stat64 statbuf;
 391         zpool_handle_t *zhp;
 392         nvlist_t *nvroot;
 393 
 394         if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) {
 395                 (void) no_memory(hdl);
 396                 return (NULL);
 397         }
 398 
 399         elem = NULL;
 400         while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
 401                 const char *propname = nvpair_name(elem);
 402 






































 403                 /*
 404                  * Make sure this property is valid and applies to this type.
 405                  */
 406                 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
 407                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 408                             "invalid property '%s'"), propname);
 409                         (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 410                         goto error;
 411                 }
 412 
 413                 if (zpool_prop_readonly(prop)) {
 414                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
 415                             "is readonly"), propname);
 416                         (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
 417                         goto error;
 418                 }
 419 
 420                 if (zprop_parse_value(hdl, elem, prop, ZFS_TYPE_POOL, retprops,
 421                     &strval, &intval, errbuf) != 0)
 422                         goto error;
 423 
 424                 /*
 425                  * Perform additional checking for specific properties.
 426                  */
 427                 switch (prop) {
 428                 case ZPOOL_PROP_VERSION:
 429                         if (intval < version || intval > SPA_VERSION) {

 430                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 431                                     "property '%s' number %d is invalid."),
 432                                     propname, intval);
 433                                 (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
 434                                 goto error;
 435                         }
 436                         break;
 437 
 438                 case ZPOOL_PROP_BOOTFS:
 439                         if (flags.create || flags.import) {
 440                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 441                                     "property '%s' cannot be set at creation "
 442                                     "or import time"), propname);
 443                                 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 444                                 goto error;
 445                         }
 446 
 447                         if (version < SPA_VERSION_BOOTFS) {
 448                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 449                                     "pool must be upgraded to support "


 631 
 632         ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SET_PROPS, &zc);
 633 
 634         zcmd_free_nvlists(&zc);
 635         nvlist_free(nvl);
 636 
 637         if (ret)
 638                 (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf);
 639         else
 640                 (void) zpool_props_refresh(zhp);
 641 
 642         return (ret);
 643 }
 644 
 645 int
 646 zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
 647 {
 648         libzfs_handle_t *hdl = zhp->zpool_hdl;
 649         zprop_list_t *entry;
 650         char buf[ZFS_MAXPROPLEN];



 651 
 652         if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0)
 653                 return (-1);
 654 
































































 655         for (entry = *plp; entry != NULL; entry = entry->pl_next) {
 656 
 657                 if (entry->pl_fixed)
 658                         continue;
 659 
 660                 if (entry->pl_prop != ZPROP_INVAL &&
 661                     zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf),
 662                     NULL) == 0) {
 663                         if (strlen(buf) > entry->pl_width)
 664                                 entry->pl_width = strlen(buf);
 665                 }
 666         }
 667 
 668         return (0);
 669 }
 670 












 671 
















































 672 /*
 673  * Don't start the slice at the default block of 34; many storage
 674  * devices will use a stripe width of 128k, so start there instead.
 675  */
 676 #define NEW_START_BLOCK 256
 677 
 678 /*
 679  * Validate the given pool name, optionally putting an extended error message in
 680  * 'buf'.
 681  */
 682 boolean_t
 683 zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool)
 684 {
 685         namecheck_err_t why;
 686         char what;
 687         int ret;
 688 
 689         ret = pool_namecheck(pool, &why, &what);
 690 
 691         /*


1237 
1238 int
1239 zpool_export_force(zpool_handle_t *zhp)
1240 {
1241         return (zpool_export_common(zhp, B_TRUE, B_TRUE));
1242 }
1243 
1244 static void
1245 zpool_rewind_exclaim(libzfs_handle_t *hdl, const char *name, boolean_t dryrun,
1246     nvlist_t *config)
1247 {
1248         nvlist_t *nv = NULL;
1249         uint64_t rewindto;
1250         int64_t loss = -1;
1251         struct tm t;
1252         char timestr[128];
1253 
1254         if (!hdl->libzfs_printerr || config == NULL)
1255                 return;
1256 
1257         if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0)

1258                 return;

1259 
1260         if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
1261                 return;
1262         (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss);
1263 
1264         if (localtime_r((time_t *)&rewindto, &t) != NULL &&
1265             strftime(timestr, 128, 0, &t) != 0) {
1266                 if (dryrun) {
1267                         (void) printf(dgettext(TEXT_DOMAIN,
1268                             "Would be able to return %s "
1269                             "to its state as of %s.\n"),
1270                             name, timestr);
1271                 } else {
1272                         (void) printf(dgettext(TEXT_DOMAIN,
1273                             "Pool %s returned to its state as of %s.\n"),
1274                             name, timestr);
1275                 }
1276                 if (loss > 120) {
1277                         (void) printf(dgettext(TEXT_DOMAIN,
1278                             "%s approximately %lld "),


1294 zpool_explain_recover(libzfs_handle_t *hdl, const char *name, int reason,
1295     nvlist_t *config)
1296 {
1297         nvlist_t *nv = NULL;
1298         int64_t loss = -1;
1299         uint64_t edata = UINT64_MAX;
1300         uint64_t rewindto;
1301         struct tm t;
1302         char timestr[128];
1303 
1304         if (!hdl->libzfs_printerr)
1305                 return;
1306 
1307         if (reason >= 0)
1308                 (void) printf(dgettext(TEXT_DOMAIN, "action: "));
1309         else
1310                 (void) printf(dgettext(TEXT_DOMAIN, "\t"));
1311 
1312         /* All attempted rewinds failed if ZPOOL_CONFIG_LOAD_TIME missing */
1313         if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||

1314             nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
1315                 goto no_info;
1316 
1317         (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss);
1318         (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_DATA_ERRORS,
1319             &edata);
1320 
1321         (void) printf(dgettext(TEXT_DOMAIN,
1322             "Recovery is possible, but will result in some data loss.\n"));
1323 
1324         if (localtime_r((time_t *)&rewindto, &t) != NULL &&
1325             strftime(timestr, 128, 0, &t) != 0) {
1326                 (void) printf(dgettext(TEXT_DOMAIN,
1327                     "\tReturning the pool to its state as of %s\n"
1328                     "\tshould correct the problem.  "),
1329                     timestr);
1330         } else {
1331                 (void) printf(dgettext(TEXT_DOMAIN,
1332                     "\tReverting the pool to an earlier state "
1333                     "should correct the problem.\n\t"));


1416         uint64_t is_log = 0;
1417 
1418         (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG,
1419             &is_log);
1420 
1421         if (name != NULL)
1422                 (void) printf("\t%*s%s%s\n", indent, "", name,
1423                     is_log ? " [log]" : "");
1424 
1425         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1426             &child, &children) != 0)
1427                 return;
1428 
1429         for (c = 0; c < children; c++) {
1430                 vname = zpool_vdev_name(hdl, NULL, child[c], B_TRUE);
1431                 print_vdev_tree(hdl, vname, child[c], indent + 2);
1432                 free(vname);
1433         }
1434 }
1435 
























1436 /*
1437  * Import the given pool using the known configuration and a list of
1438  * properties to be set. The configuration should have come from
1439  * zpool_find_import(). The 'newname' parameters control whether the pool
1440  * is imported with a different name.
1441  */
1442 int
1443 zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
1444     nvlist_t *props, int flags)
1445 {
1446         zfs_cmd_t zc = { 0 };
1447         zpool_rewind_policy_t policy;
1448         nvlist_t *nv = NULL;
1449         nvlist_t *nvinfo = NULL;
1450         nvlist_t *missing = NULL;
1451         char *thename;
1452         char *origname;
1453         int ret;
1454         int error = 0;
1455         char errbuf[1024];


1522                  * looks like if we found a best txg
1523                  */
1524                 if (policy.zrp_request & ZPOOL_TRY_REWIND) {
1525                         zpool_rewind_exclaim(hdl, newname ? origname : thename,
1526                             B_TRUE, nv);
1527                         nvlist_free(nv);
1528                         return (-1);
1529                 }
1530 
1531                 if (newname == NULL)
1532                         (void) snprintf(desc, sizeof (desc),
1533                             dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1534                             thename);
1535                 else
1536                         (void) snprintf(desc, sizeof (desc),
1537                             dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"),
1538                             origname, thename);
1539 
1540                 switch (error) {
1541                 case ENOTSUP:
















1542                         /*
1543                          * Unsupported version.
1544                          */
1545                         (void) zfs_error(hdl, EZFS_BADVERSION, desc);
1546                         break;
1547 
1548                 case EINVAL:
1549                         (void) zfs_error(hdl, EZFS_INVALCONFIG, desc);
1550                         break;
1551 
1552                 case EROFS:
1553                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1554                             "one or more devices is read only"));
1555                         (void) zfs_error(hdl, EZFS_BADDEV, desc);
1556                         break;
1557 
1558                 case ENXIO:
1559                         if (nv && nvlist_lookup_nvlist(nv,
1560                             ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 &&
1561                             nvlist_lookup_nvlist(nvinfo,




  26  */
  27 
  28 #include <ctype.h>
  29 #include <errno.h>
  30 #include <devid.h>
  31 #include <fcntl.h>
  32 #include <libintl.h>
  33 #include <stdio.h>
  34 #include <stdlib.h>
  35 #include <strings.h>
  36 #include <unistd.h>
  37 #include <sys/efi_partition.h>
  38 #include <sys/vtoc.h>
  39 #include <sys/zfs_ioctl.h>
  40 #include <dlfcn.h>
  41 
  42 #include "zfs_namecheck.h"
  43 #include "zfs_prop.h"
  44 #include "libzfs_impl.h"
  45 #include "zfs_comutil.h"
  46 #include "zfeature_common.h"
  47 
  48 static int read_efi_label(nvlist_t *config, diskaddr_t *sb);
  49 
  50 #define DISK_ROOT       "/dev/dsk"
  51 #define RDISK_ROOT      "/dev/rdsk"
  52 #define BACKUP_SLICE    "s2"
  53 
  54 typedef struct prop_flags {
  55         int create:1;   /* Validate property on creation */
  56         int import:1;   /* Validate property on import */
  57 } prop_flags_t;
  58 
  59 /*
  60  * ====================================================================
  61  *   zpool property functions
  62  * ====================================================================
  63  */
  64 
  65 static int
  66 zpool_get_all_props(zpool_handle_t *zhp)


 257                 return (0);
 258         }
 259 
 260         if (zhp->zpool_props == NULL && zpool_get_all_props(zhp) &&
 261             prop != ZPOOL_PROP_NAME)
 262                 return (-1);
 263 
 264         switch (zpool_prop_get_type(prop)) {
 265         case PROP_TYPE_STRING:
 266                 (void) strlcpy(buf, zpool_get_prop_string(zhp, prop, &src),
 267                     len);
 268                 break;
 269 
 270         case PROP_TYPE_NUMBER:
 271                 intval = zpool_get_prop_int(zhp, prop, &src);
 272 
 273                 switch (prop) {
 274                 case ZPOOL_PROP_SIZE:
 275                 case ZPOOL_PROP_ALLOCATED:
 276                 case ZPOOL_PROP_FREE:
 277                 case ZPOOL_PROP_FREEING:
 278                 case ZPOOL_PROP_EXPANDSZ:
 279                         (void) zfs_nicenum(intval, buf, len);
 280                         break;
 281 
 282                 case ZPOOL_PROP_CAPACITY:
 283                         (void) snprintf(buf, len, "%llu%%",
 284                             (u_longlong_t)intval);
 285                         break;
 286 
 287                 case ZPOOL_PROP_DEDUPRATIO:
 288                         (void) snprintf(buf, len, "%llu.%02llux",
 289                             (u_longlong_t)(intval / 100),
 290                             (u_longlong_t)(intval % 100));
 291                         break;
 292 
 293                 case ZPOOL_PROP_HEALTH:
 294                         verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
 295                             ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
 296                         verify(nvlist_lookup_uint64_array(nvroot,
 297                             ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &vsc)
 298                             == 0);
 299 
 300                         (void) strlcpy(buf, zpool_state_to_name(intval,
 301                             vs->vs_aux), len);
 302                         break;
 303                 case ZPOOL_PROP_VERSION:
 304                         if (intval >= SPA_VERSION_FEATURES) {
 305                                 (void) snprintf(buf, len, "-");
 306                                 break;
 307                         }
 308                         /* FALLTHROUGH */
 309                 default:
 310                         (void) snprintf(buf, len, "%llu", intval);
 311                 }
 312                 break;
 313 
 314         case PROP_TYPE_INDEX:
 315                 intval = zpool_get_prop_int(zhp, prop, &src);
 316                 if (zpool_prop_index_to_string(prop, intval, &strval)
 317                     != 0)
 318                         return (-1);
 319                 (void) strlcpy(buf, strval, len);
 320                 break;
 321 
 322         default:
 323                 abort();
 324         }
 325 
 326         if (srctype)
 327                 *srctype = src;
 328 


 391 {
 392         nvpair_t *elem;
 393         nvlist_t *retprops;
 394         zpool_prop_t prop;
 395         char *strval;
 396         uint64_t intval;
 397         char *slash, *check;
 398         struct stat64 statbuf;
 399         zpool_handle_t *zhp;
 400         nvlist_t *nvroot;
 401 
 402         if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) {
 403                 (void) no_memory(hdl);
 404                 return (NULL);
 405         }
 406 
 407         elem = NULL;
 408         while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
 409                 const char *propname = nvpair_name(elem);
 410 
 411                 prop = zpool_name_to_prop(propname);
 412                 if (prop == ZPROP_INVAL && zpool_prop_feature(propname)) {
 413                         int err;
 414                         zfeature_info_t *feature;
 415                         char *fname = strchr(propname, '@') + 1;
 416 
 417                         err = zfeature_lookup_name(fname, &feature);
 418                         if (err != 0) {
 419                                 ASSERT3U(err, ==, ENOENT);
 420                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 421                                     "invalid feature '%s'"), fname);
 422                                 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 423                                 goto error;
 424                         }
 425 
 426                         if (nvpair_type(elem) != DATA_TYPE_STRING) {
 427                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 428                                     "'%s' must be a string"), propname);
 429                                 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 430                                 goto error;
 431                         }
 432 
 433                         (void) nvpair_value_string(elem, &strval);
 434                         if (strcmp(strval, ZFS_FEATURE_ENABLED) != 0) {
 435                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 436                                     "property '%s' can only be set to "
 437                                     "'enabled'"), propname);
 438                                 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 439                                 goto error;
 440                         }
 441 
 442                         if (nvlist_add_uint64(retprops, propname, 0) != 0) {
 443                                 (void) no_memory(hdl);
 444                                 goto error;
 445                         }
 446                         continue;
 447                 }
 448 
 449                 /*
 450                  * Make sure this property is valid and applies to this type.
 451                  */
 452                 if (prop == ZPROP_INVAL) {
 453                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 454                             "invalid property '%s'"), propname);
 455                         (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 456                         goto error;
 457                 }
 458 
 459                 if (zpool_prop_readonly(prop)) {
 460                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
 461                             "is readonly"), propname);
 462                         (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
 463                         goto error;
 464                 }
 465 
 466                 if (zprop_parse_value(hdl, elem, prop, ZFS_TYPE_POOL, retprops,
 467                     &strval, &intval, errbuf) != 0)
 468                         goto error;
 469 
 470                 /*
 471                  * Perform additional checking for specific properties.
 472                  */
 473                 switch (prop) {
 474                 case ZPOOL_PROP_VERSION:
 475                         if (intval < version ||
 476                             !SPA_VERSION_IS_SUPPORTED(intval)) {
 477                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 478                                     "property '%s' number %d is invalid."),
 479                                     propname, intval);
 480                                 (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
 481                                 goto error;
 482                         }
 483                         break;
 484 
 485                 case ZPOOL_PROP_BOOTFS:
 486                         if (flags.create || flags.import) {
 487                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 488                                     "property '%s' cannot be set at creation "
 489                                     "or import time"), propname);
 490                                 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 491                                 goto error;
 492                         }
 493 
 494                         if (version < SPA_VERSION_BOOTFS) {
 495                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 496                                     "pool must be upgraded to support "


 678 
 679         ret = zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_SET_PROPS, &zc);
 680 
 681         zcmd_free_nvlists(&zc);
 682         nvlist_free(nvl);
 683 
 684         if (ret)
 685                 (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf);
 686         else
 687                 (void) zpool_props_refresh(zhp);
 688 
 689         return (ret);
 690 }
 691 
 692 int
 693 zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
 694 {
 695         libzfs_handle_t *hdl = zhp->zpool_hdl;
 696         zprop_list_t *entry;
 697         char buf[ZFS_MAXPROPLEN];
 698         nvlist_t *features = NULL;
 699         zprop_list_t **last;
 700         boolean_t firstexpand = (NULL == *plp);
 701 
 702         if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0)
 703                 return (-1);
 704 
 705         last = plp;
 706         while (*last != NULL)
 707                 last = &(*last)->pl_next;
 708 
 709         if ((*plp)->pl_all)
 710                 features = zpool_get_features(zhp);
 711 
 712         if ((*plp)->pl_all && firstexpand) {
 713                 for (int i = 0; i < SPA_FEATURES; i++) {
 714                         zprop_list_t *entry = zfs_alloc(hdl,
 715                             sizeof (zprop_list_t));
 716                         entry->pl_prop = ZPROP_INVAL;
 717                         entry->pl_user_prop = zfs_asprintf(hdl, "feature@%s",
 718                             spa_feature_table[i].fi_uname);
 719                         entry->pl_width = strlen(entry->pl_user_prop);
 720                         entry->pl_all = B_TRUE;
 721 
 722                         *last = entry;
 723                         last = &entry->pl_next;
 724                 }
 725         }
 726 
 727         /* add any unsupported features */
 728         for (nvpair_t *nvp = nvlist_next_nvpair(features, NULL);
 729             nvp != NULL; nvp = nvlist_next_nvpair(features, nvp)) {
 730                 char *propname;
 731                 boolean_t found;
 732                 zprop_list_t *entry;
 733 
 734                 if (zfeature_is_supported(nvpair_name(nvp)))
 735                         continue;
 736 
 737                 propname = zfs_asprintf(hdl, "unsupported@%s",
 738                     nvpair_name(nvp));
 739 
 740                 /*
 741                  * Before adding the property to the list make sure that no
 742                  * other pool already added the same property.
 743                  */
 744                 found = B_FALSE;
 745                 entry = *plp;
 746                 while (entry != NULL) {
 747                         if (entry->pl_user_prop != NULL &&
 748                             strcmp(propname, entry->pl_user_prop) == 0) {
 749                                 found = B_TRUE;
 750                                 break;
 751                         }
 752                         entry = entry->pl_next;
 753                 }
 754                 if (found) {
 755                         free(propname);
 756                         continue;
 757                 }
 758 
 759                 entry = zfs_alloc(hdl, sizeof (zprop_list_t));
 760                 entry->pl_prop = ZPROP_INVAL;
 761                 entry->pl_user_prop = propname;
 762                 entry->pl_width = strlen(entry->pl_user_prop);
 763                 entry->pl_all = B_TRUE;
 764 
 765                 *last = entry;
 766                 last = &entry->pl_next;
 767         }
 768 
 769         for (entry = *plp; entry != NULL; entry = entry->pl_next) {
 770 
 771                 if (entry->pl_fixed)
 772                         continue;
 773 
 774                 if (entry->pl_prop != ZPROP_INVAL &&
 775                     zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf),
 776                     NULL) == 0) {
 777                         if (strlen(buf) > entry->pl_width)
 778                                 entry->pl_width = strlen(buf);
 779                 }
 780         }
 781 
 782         return (0);
 783 }
 784 
 785 /*
 786  * Get the state for the given feature on the given ZFS pool.
 787  */
 788 int
 789 zpool_prop_get_feature(zpool_handle_t *zhp, const char *propname, char *buf,
 790     size_t len)
 791 {
 792         uint64_t refcount;
 793         boolean_t found = B_FALSE;
 794         nvlist_t *features = zpool_get_features(zhp);
 795         boolean_t supported;
 796         const char *feature = strchr(propname, '@') + 1;
 797 
 798         supported = zpool_prop_feature(propname);
 799         ASSERT(supported || zfs_prop_unsupported(propname));
 800 
 801         /*
 802          * Convert from feature name to feature guid. This conversion is
 803          * unecessary for unsupported@... properties because they already
 804          * use guids.
 805          */
 806         if (supported) {
 807                 int ret;
 808                 zfeature_info_t *fi;
 809 
 810                 ret = zfeature_lookup_name(feature, &fi);
 811                 if (ret != 0) {
 812                         (void) strlcpy(buf, "-", len);
 813                         return (ENOTSUP);
 814                 }
 815                 feature = fi->fi_guid;
 816         }
 817 
 818         if (nvlist_lookup_uint64(features, feature, &refcount) == 0)
 819                 found = B_TRUE;
 820 
 821         if (supported) {
 822                 if (!found) {
 823                         (void) strlcpy(buf, ZFS_FEATURE_DISABLED, len);
 824                 } else  {
 825                         if (refcount == 0)
 826                                 (void) strlcpy(buf, ZFS_FEATURE_ENABLED, len);
 827                         else
 828                                 (void) strlcpy(buf, ZFS_FEATURE_ACTIVE, len);
 829                 }
 830         } else {
 831                 if (found) {
 832                         if (refcount == 0) {
 833                                 (void) strcpy(buf, ZFS_UNSUPPORTED_INACTIVE);
 834                         } else {
 835                                 (void) strcpy(buf, ZFS_UNSUPPORTED_READONLY);
 836                         }
 837                 } else {
 838                         (void) strlcpy(buf, "-", len);
 839                         return (ENOTSUP);
 840                 }
 841         }
 842 
 843         return (0);
 844 }
 845 
 846 /*
 847  * Don't start the slice at the default block of 34; many storage
 848  * devices will use a stripe width of 128k, so start there instead.
 849  */
 850 #define NEW_START_BLOCK 256
 851 
 852 /*
 853  * Validate the given pool name, optionally putting an extended error message in
 854  * 'buf'.
 855  */
 856 boolean_t
 857 zpool_name_valid(libzfs_handle_t *hdl, boolean_t isopen, const char *pool)
 858 {
 859         namecheck_err_t why;
 860         char what;
 861         int ret;
 862 
 863         ret = pool_namecheck(pool, &why, &what);
 864 
 865         /*


1411 
1412 int
1413 zpool_export_force(zpool_handle_t *zhp)
1414 {
1415         return (zpool_export_common(zhp, B_TRUE, B_TRUE));
1416 }
1417 
1418 static void
1419 zpool_rewind_exclaim(libzfs_handle_t *hdl, const char *name, boolean_t dryrun,
1420     nvlist_t *config)
1421 {
1422         nvlist_t *nv = NULL;
1423         uint64_t rewindto;
1424         int64_t loss = -1;
1425         struct tm t;
1426         char timestr[128];
1427 
1428         if (!hdl->libzfs_printerr || config == NULL)
1429                 return;
1430 
1431         if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||
1432             nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0) {
1433                 return;
1434         }
1435 
1436         if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
1437                 return;
1438         (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss);
1439 
1440         if (localtime_r((time_t *)&rewindto, &t) != NULL &&
1441             strftime(timestr, 128, 0, &t) != 0) {
1442                 if (dryrun) {
1443                         (void) printf(dgettext(TEXT_DOMAIN,
1444                             "Would be able to return %s "
1445                             "to its state as of %s.\n"),
1446                             name, timestr);
1447                 } else {
1448                         (void) printf(dgettext(TEXT_DOMAIN,
1449                             "Pool %s returned to its state as of %s.\n"),
1450                             name, timestr);
1451                 }
1452                 if (loss > 120) {
1453                         (void) printf(dgettext(TEXT_DOMAIN,
1454                             "%s approximately %lld "),


1470 zpool_explain_recover(libzfs_handle_t *hdl, const char *name, int reason,
1471     nvlist_t *config)
1472 {
1473         nvlist_t *nv = NULL;
1474         int64_t loss = -1;
1475         uint64_t edata = UINT64_MAX;
1476         uint64_t rewindto;
1477         struct tm t;
1478         char timestr[128];
1479 
1480         if (!hdl->libzfs_printerr)
1481                 return;
1482 
1483         if (reason >= 0)
1484                 (void) printf(dgettext(TEXT_DOMAIN, "action: "));
1485         else
1486                 (void) printf(dgettext(TEXT_DOMAIN, "\t"));
1487 
1488         /* All attempted rewinds failed if ZPOOL_CONFIG_LOAD_TIME missing */
1489         if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||
1490             nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0 ||
1491             nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
1492                 goto no_info;
1493 
1494         (void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss);
1495         (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_DATA_ERRORS,
1496             &edata);
1497 
1498         (void) printf(dgettext(TEXT_DOMAIN,
1499             "Recovery is possible, but will result in some data loss.\n"));
1500 
1501         if (localtime_r((time_t *)&rewindto, &t) != NULL &&
1502             strftime(timestr, 128, 0, &t) != 0) {
1503                 (void) printf(dgettext(TEXT_DOMAIN,
1504                     "\tReturning the pool to its state as of %s\n"
1505                     "\tshould correct the problem.  "),
1506                     timestr);
1507         } else {
1508                 (void) printf(dgettext(TEXT_DOMAIN,
1509                     "\tReverting the pool to an earlier state "
1510                     "should correct the problem.\n\t"));


1593         uint64_t is_log = 0;
1594 
1595         (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG,
1596             &is_log);
1597 
1598         if (name != NULL)
1599                 (void) printf("\t%*s%s%s\n", indent, "", name,
1600                     is_log ? " [log]" : "");
1601 
1602         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1603             &child, &children) != 0)
1604                 return;
1605 
1606         for (c = 0; c < children; c++) {
1607                 vname = zpool_vdev_name(hdl, NULL, child[c], B_TRUE);
1608                 print_vdev_tree(hdl, vname, child[c], indent + 2);
1609                 free(vname);
1610         }
1611 }
1612 
1613 void
1614 zpool_print_unsup_feat(nvlist_t *config)
1615 {
1616         nvlist_t *nvinfo, *unsup_feat;
1617 
1618         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nvinfo) ==
1619             0);
1620         verify(nvlist_lookup_nvlist(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT,
1621             &unsup_feat) == 0);
1622 
1623         for (nvpair_t *nvp = nvlist_next_nvpair(unsup_feat, NULL); nvp != NULL;
1624             nvp = nvlist_next_nvpair(unsup_feat, nvp)) {
1625                 char *desc;
1626 
1627                 verify(nvpair_type(nvp) == DATA_TYPE_STRING);
1628                 verify(nvpair_value_string(nvp, &desc) == 0);
1629 
1630                 if (strlen(desc) > 0)
1631                         (void) printf("\t%s (%s)\n", nvpair_name(nvp), desc);
1632                 else
1633                         (void) printf("\t%s\n", nvpair_name(nvp));
1634         }
1635 }
1636 
1637 /*
1638  * Import the given pool using the known configuration and a list of
1639  * properties to be set. The configuration should have come from
1640  * zpool_find_import(). The 'newname' parameters control whether the pool
1641  * is imported with a different name.
1642  */
1643 int
1644 zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
1645     nvlist_t *props, int flags)
1646 {
1647         zfs_cmd_t zc = { 0 };
1648         zpool_rewind_policy_t policy;
1649         nvlist_t *nv = NULL;
1650         nvlist_t *nvinfo = NULL;
1651         nvlist_t *missing = NULL;
1652         char *thename;
1653         char *origname;
1654         int ret;
1655         int error = 0;
1656         char errbuf[1024];


1723                  * looks like if we found a best txg
1724                  */
1725                 if (policy.zrp_request & ZPOOL_TRY_REWIND) {
1726                         zpool_rewind_exclaim(hdl, newname ? origname : thename,
1727                             B_TRUE, nv);
1728                         nvlist_free(nv);
1729                         return (-1);
1730                 }
1731 
1732                 if (newname == NULL)
1733                         (void) snprintf(desc, sizeof (desc),
1734                             dgettext(TEXT_DOMAIN, "cannot import '%s'"),
1735                             thename);
1736                 else
1737                         (void) snprintf(desc, sizeof (desc),
1738                             dgettext(TEXT_DOMAIN, "cannot import '%s' as '%s'"),
1739                             origname, thename);
1740 
1741                 switch (error) {
1742                 case ENOTSUP:
1743                         if (nv != NULL && nvlist_lookup_nvlist(nv,
1744                             ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 &&
1745                             nvlist_exists(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT)) {
1746                                 (void) printf(dgettext(TEXT_DOMAIN, "This "
1747                                     "pool uses the following feature(s) not "
1748                                     "supported by this system:\n"));
1749                                 zpool_print_unsup_feat(nv);
1750                                 if (nvlist_exists(nvinfo,
1751                                     ZPOOL_CONFIG_CAN_RDONLY)) {
1752                                         (void) printf(dgettext(TEXT_DOMAIN,
1753                                             "All unsupported features are only "
1754                                             "required for writing to the pool."
1755                                             "\nThe pool can be imported using "
1756                                             "'-o readonly=on'.\n"));
1757                                 }
1758                         }
1759                         /*
1760                          * Unsupported version.
1761                          */
1762                         (void) zfs_error(hdl, EZFS_BADVERSION, desc);
1763                         break;
1764 
1765                 case EINVAL:
1766                         (void) zfs_error(hdl, EZFS_INVALCONFIG, desc);
1767                         break;
1768 
1769                 case EROFS:
1770                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1771                             "one or more devices is read only"));
1772                         (void) zfs_error(hdl, EZFS_BADDEV, desc);
1773                         break;
1774 
1775                 case ENXIO:
1776                         if (nv && nvlist_lookup_nvlist(nv,
1777                             ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 &&
1778                             nvlist_lookup_nvlist(nvinfo,