]> git.proxmox.com Git - mirror_zfs.git/blobdiff - lib/libzfs/libzfs_pool.c
cstyle: Resolve C style issues
[mirror_zfs.git] / lib / libzfs / libzfs_pool.c
index bb184ed688dd0f444583fdd3ae4f39c384cb6cab..b822ace688c950b5570c57a44a2c230e33f9db08 100644 (file)
@@ -22,7 +22,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #include <ctype.h>
@@ -34,6 +34,7 @@
 #include <stdlib.h>
 #include <strings.h>
 #include <unistd.h>
+#include <libgen.h>
 #include <zone.h>
 #include <sys/stat.h>
 #include <sys/efi_partition.h>
@@ -45,6 +46,7 @@
 #include "zfs_prop.h"
 #include "libzfs_impl.h"
 #include "zfs_comutil.h"
+#include "zfeature_common.h"
 
 static int read_efi_label(nvlist_t *config, diskaddr_t *sb);
 
@@ -62,7 +64,7 @@ typedef struct prop_flags {
 static int
 zpool_get_all_props(zpool_handle_t *zhp)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
@@ -204,12 +206,52 @@ zpool_state_to_name(vdev_state_t state, vdev_aux_t aux)
 }
 
 /*
- * Get a zpool property value for 'prop' and return the value in
- * a pre-allocated buffer.
+ * Map POOL STATE to printed strings.
+ */
+const char *
+zpool_pool_state_to_name(pool_state_t state)
+{
+       switch (state) {
+       default:
+               break;
+       case POOL_STATE_ACTIVE:
+               return (gettext("ACTIVE"));
+       case POOL_STATE_EXPORTED:
+               return (gettext("EXPORTED"));
+       case POOL_STATE_DESTROYED:
+               return (gettext("DESTROYED"));
+       case POOL_STATE_SPARE:
+               return (gettext("SPARE"));
+       case POOL_STATE_L2CACHE:
+               return (gettext("L2CACHE"));
+       case POOL_STATE_UNINITIALIZED:
+               return (gettext("UNINITIALIZED"));
+       case POOL_STATE_UNAVAIL:
+               return (gettext("UNAVAIL"));
+       case POOL_STATE_POTENTIALLY_ACTIVE:
+               return (gettext("POTENTIALLY_ACTIVE"));
+       }
+
+       return (gettext("UNKNOWN"));
+}
+
+/*
+ * API compatibility wrapper around zpool_get_prop_literal
  */
 int
 zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
     zprop_source_t *srctype)
+{
+       return (zpool_get_prop_literal(zhp, prop, buf, len, srctype, B_FALSE));
+}
+
+/*
+ * Get a zpool property value for 'prop' and return the value in
+ * a pre-allocated buffer.
+ */
+int
+zpool_get_prop_literal(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
+    size_t len, zprop_source_t *srctype, boolean_t literal)
 {
        uint64_t intval;
        const char *strval;
@@ -235,6 +277,7 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
 
                case ZPOOL_PROP_ALTROOT:
                case ZPOOL_PROP_CACHEFILE:
+               case ZPOOL_PROP_COMMENT:
                        if (zhp->zpool_props != NULL ||
                            zpool_get_all_props(zhp) == 0) {
                                (void) strlcpy(buf,
@@ -272,8 +315,14 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
                case ZPOOL_PROP_SIZE:
                case ZPOOL_PROP_ALLOCATED:
                case ZPOOL_PROP_FREE:
+               case ZPOOL_PROP_FREEING:
+               case ZPOOL_PROP_EXPANDSZ:
                case ZPOOL_PROP_ASHIFT:
-                       (void) zfs_nicenum(intval, buf, len);
+                       if (literal)
+                               (void) snprintf(buf, len, "%llu",
+                                       (u_longlong_t)intval);
+                       else
+                               (void) zfs_nicenum(intval, buf, len);
                        break;
 
                case ZPOOL_PROP_CAPACITY:
@@ -297,6 +346,12 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
                        (void) strlcpy(buf, zpool_state_to_name(intval,
                            vs->vs_aux), len);
                        break;
+               case ZPOOL_PROP_VERSION:
+                       if (intval >= SPA_VERSION_FEATURES) {
+                               (void) snprintf(buf, len, "-");
+                               break;
+                       }
+                       /* FALLTHROUGH */
                default:
                        (void) snprintf(buf, len, "%llu", (u_longlong_t)intval);
                }
@@ -339,6 +394,7 @@ bootfs_name_valid(const char *pool, char *bootfs)
        return (B_FALSE);
 }
 
+#if defined(__sun__) || defined(__sun)
 /*
  * Inspect the configuration to determine if any of the devices contain
  * an EFI label.
@@ -359,9 +415,10 @@ pool_uses_efi(nvlist_t *config)
        }
        return (B_FALSE);
 }
+#endif
 
-static boolean_t
-pool_is_bootable(zpool_handle_t *zhp)
+boolean_t
+zpool_is_bootable(zpool_handle_t *zhp)
 {
        char bootfs[ZPOOL_MAXNAMELEN];
 
@@ -385,7 +442,7 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
        zpool_prop_t prop;
        char *strval;
        uint64_t intval;
-       char *slash;
+       char *slash, *check;
        struct stat64 statbuf;
        zpool_handle_t *zhp;
        nvlist_t *nvroot;
@@ -399,10 +456,48 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
        while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
                const char *propname = nvpair_name(elem);
 
+               prop = zpool_name_to_prop(propname);
+               if (prop == ZPROP_INVAL && zpool_prop_feature(propname)) {
+                       int err;
+                       zfeature_info_t *feature;
+                       char *fname = strchr(propname, '@') + 1;
+
+                       err = zfeature_lookup_name(fname, &feature);
+                       if (err != 0) {
+                               ASSERT3U(err, ==, ENOENT);
+                               zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                                   "invalid feature '%s'"), fname);
+                               (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
+                               goto error;
+                       }
+
+                       if (nvpair_type(elem) != DATA_TYPE_STRING) {
+                               zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                                   "'%s' must be a string"), propname);
+                               (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
+                               goto error;
+                       }
+
+                       (void) nvpair_value_string(elem, &strval);
+                       if (strcmp(strval, ZFS_FEATURE_ENABLED) != 0) {
+                               zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                                   "property '%s' can only be set to "
+                                   "'enabled'"), propname);
+                               (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
+                               goto error;
+                       }
+
+                       if (nvlist_add_uint64(retprops, propname, 0) != 0) {
+                               (void) no_memory(hdl);
+                               goto error;
+                       }
+                       continue;
+               }
+
                /*
                 * Make sure this property is valid and applies to this type.
                 */
-               if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
+               if (prop == ZPROP_INVAL) {
                        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                            "invalid property '%s'"), propname);
                        (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
@@ -427,7 +522,8 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
                default:
                        break;
                case ZPOOL_PROP_VERSION:
-                       if (intval < version || intval > SPA_VERSION) {
+                       if (intval < version ||
+                           !SPA_VERSION_IS_SUPPORTED(intval)) {
                                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                                    "property '%s' number %d is invalid."),
                                    propname, intval);
@@ -566,6 +662,26 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
                        *slash = '/';
                        break;
 
+               case ZPOOL_PROP_COMMENT:
+                       for (check = strval; *check != '\0'; check++) {
+                               if (!isprint(*check)) {
+                                       zfs_error_aux(hdl,
+                                           dgettext(TEXT_DOMAIN,
+                                           "comment may only have printable "
+                                           "characters"));
+                                       (void) zfs_error(hdl, EZFS_BADPROP,
+                                           errbuf);
+                                       goto error;
+                               }
+                       }
+                       if (strlen(strval) > ZPROP_MAX_COMMENT) {
+                               zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                                   "comment must not exceed %d characters"),
+                                   ZPROP_MAX_COMMENT);
+                               (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
+                               goto error;
+                       }
+                       break;
                case ZPOOL_PROP_READONLY:
                        if (!flags.import) {
                                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -590,7 +706,7 @@ error:
 int
 zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        int ret = -1;
        char errbuf[1024];
        nvlist_t *nvl = NULL;
@@ -649,10 +765,79 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
        libzfs_handle_t *hdl = zhp->zpool_hdl;
        zprop_list_t *entry;
        char buf[ZFS_MAXPROPLEN];
+       nvlist_t *features = NULL;
+       nvpair_t *nvp;
+       zprop_list_t **last;
+       boolean_t firstexpand = (NULL == *plp);
+       int i;
 
        if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0)
                return (-1);
 
+       last = plp;
+       while (*last != NULL)
+               last = &(*last)->pl_next;
+
+       if ((*plp)->pl_all)
+               features = zpool_get_features(zhp);
+
+       if ((*plp)->pl_all && firstexpand) {
+               for (i = 0; i < SPA_FEATURES; i++) {
+                       zprop_list_t *entry = zfs_alloc(hdl,
+                           sizeof (zprop_list_t));
+                       entry->pl_prop = ZPROP_INVAL;
+                       entry->pl_user_prop = zfs_asprintf(hdl, "feature@%s",
+                           spa_feature_table[i].fi_uname);
+                       entry->pl_width = strlen(entry->pl_user_prop);
+                       entry->pl_all = B_TRUE;
+
+                       *last = entry;
+                       last = &entry->pl_next;
+               }
+       }
+
+       /* add any unsupported features */
+       for (nvp = nvlist_next_nvpair(features, NULL);
+           nvp != NULL; nvp = nvlist_next_nvpair(features, nvp)) {
+               char *propname;
+               boolean_t found;
+               zprop_list_t *entry;
+
+               if (zfeature_is_supported(nvpair_name(nvp)))
+                       continue;
+
+               propname = zfs_asprintf(hdl, "unsupported@%s",
+                   nvpair_name(nvp));
+
+               /*
+                * Before adding the property to the list make sure that no
+                * other pool already added the same property.
+                */
+               found = B_FALSE;
+               entry = *plp;
+               while (entry != NULL) {
+                       if (entry->pl_user_prop != NULL &&
+                           strcmp(propname, entry->pl_user_prop) == 0) {
+                               found = B_TRUE;
+                               break;
+                       }
+                       entry = entry->pl_next;
+               }
+               if (found) {
+                       free(propname);
+                       continue;
+               }
+
+               entry = zfs_alloc(hdl, sizeof (zprop_list_t));
+               entry->pl_prop = ZPROP_INVAL;
+               entry->pl_user_prop = propname;
+               entry->pl_width = strlen(entry->pl_user_prop);
+               entry->pl_all = B_TRUE;
+
+               *last = entry;
+               last = &entry->pl_next;
+       }
+
        for (entry = *plp; entry != NULL; entry = entry->pl_next) {
 
                if (entry->pl_fixed)
@@ -669,6 +854,66 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
        return (0);
 }
 
+/*
+ * Get the state for the given feature on the given ZFS pool.
+ */
+int
+zpool_prop_get_feature(zpool_handle_t *zhp, const char *propname, char *buf,
+    size_t len)
+{
+       uint64_t refcount;
+       boolean_t found = B_FALSE;
+       nvlist_t *features = zpool_get_features(zhp);
+       boolean_t supported;
+       const char *feature = strchr(propname, '@') + 1;
+
+       supported = zpool_prop_feature(propname);
+       ASSERT(supported || zpool_prop_unsupported(propname));
+
+       /*
+        * Convert from feature name to feature guid. This conversion is
+        * unecessary for unsupported@... properties because they already
+        * use guids.
+        */
+       if (supported) {
+               int ret;
+               zfeature_info_t *fi;
+
+               ret = zfeature_lookup_name(feature, &fi);
+               if (ret != 0) {
+                       (void) strlcpy(buf, "-", len);
+                       return (ENOTSUP);
+               }
+               feature = fi->fi_guid;
+       }
+
+       if (nvlist_lookup_uint64(features, feature, &refcount) == 0)
+               found = B_TRUE;
+
+       if (supported) {
+               if (!found) {
+                       (void) strlcpy(buf, ZFS_FEATURE_DISABLED, len);
+               } else  {
+                       if (refcount == 0)
+                               (void) strlcpy(buf, ZFS_FEATURE_ENABLED, len);
+                       else
+                               (void) strlcpy(buf, ZFS_FEATURE_ACTIVE, len);
+               }
+       } else {
+               if (found) {
+                       if (refcount == 0) {
+                               (void) strcpy(buf, ZFS_UNSUPPORTED_INACTIVE);
+                       } else {
+                               (void) strcpy(buf, ZFS_UNSUPPORTED_READONLY);
+                       }
+               } else {
+                       (void) strlcpy(buf, "-", len);
+                       return (ENOTSUP);
+               }
+       }
+
+       return (0);
+}
 
 /*
  * Don't start the slice at the default block of 34; many storage
@@ -910,11 +1155,10 @@ int
 zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
     nvlist_t *props, nvlist_t *fsprops)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        nvlist_t *zc_fsprops = NULL;
        nvlist_t *zc_props = NULL;
        char msg[1024];
-       char *altroot;
        int ret = -1;
 
        (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
@@ -978,8 +1222,9 @@ zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
                         * part of an active md or lvm device.
                         */
                        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
-                           "one or more vdevs refer to the same device, or one of\n"
-                           "the devices is part of an active md or lvm device"));
+                           "one or more vdevs refer to the same device, or "
+                           "one of\nthe devices is part of an active md or "
+                           "lvm device"));
                        return (zfs_error(hdl, EZFS_BADDEV, msg));
 
                case EOVERFLOW:
@@ -1015,21 +1260,6 @@ zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
                }
        }
 
-       /*
-        * If this is an alternate root pool, then we automatically set the
-        * mountpoint of the root dataset to be '/'.
-        */
-       if (nvlist_lookup_string(props, zpool_prop_to_name(ZPOOL_PROP_ALTROOT),
-           &altroot) == 0) {
-               zfs_handle_t *zhp;
-
-               verify((zhp = zfs_open(hdl, pool, ZFS_TYPE_DATASET)) != NULL);
-               verify(zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
-                   "/") == 0);
-
-               zfs_close(zhp);
-       }
-
 create_failed:
        zcmd_free_nvlists(&zc);
        nvlist_free(zc_props);
@@ -1042,9 +1272,9 @@ create_failed:
  * datasets left in the pool.
  */
 int
-zpool_destroy(zpool_handle_t *zhp)
+zpool_destroy(zpool_handle_t *zhp, const char *log_str)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        zfs_handle_t *zfp = NULL;
        libzfs_handle_t *hdl = zhp->zpool_hdl;
        char msg[1024];
@@ -1054,6 +1284,7 @@ zpool_destroy(zpool_handle_t *zhp)
                return (-1);
 
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
+       zc.zc_history = (uint64_t)(uintptr_t)log_str;
 
        if (zfs_ioctl(hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
                (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
@@ -1087,7 +1318,7 @@ zpool_destroy(zpool_handle_t *zhp)
 int
 zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        int ret;
        libzfs_handle_t *hdl = zhp->zpool_hdl;
        char msg[1024];
@@ -1106,7 +1337,8 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
                return (zfs_error(hdl, EZFS_BADVERSION, msg));
        }
 
-       if (pool_is_bootable(zhp) && nvlist_lookup_nvlist_array(nvroot,
+#if defined(__sun__) || defined(__sun)
+       if (zpool_is_bootable(zhp) && nvlist_lookup_nvlist_array(nvroot,
            ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0) {
                uint64_t s;
 
@@ -1124,6 +1356,7 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
                        }
                }
        }
+#endif
 
        if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
            SPA_VERSION_L2CACHE &&
@@ -1177,13 +1410,6 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
                        (void) zfs_error(hdl, EZFS_BADVERSION, msg);
                        break;
 
-               case EDOM:
-                       zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
-                           "root pool can not have multiple vdevs"
-                           " or separate logs"));
-                       (void) zfs_error(hdl, EZFS_POOL_NOTSUP, msg);
-                       break;
-
                case ENOTBLK:
                        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                            "cache device must be a disk or disk slice"));
@@ -1208,10 +1434,11 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
  * Exports the pool from the system.  The caller must ensure that there are no
  * mounted datasets in the pool.
  */
-int
-zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce)
+static int
+zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce,
+    const char *log_str)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
 
        (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
@@ -1220,6 +1447,7 @@ zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce)
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
        zc.zc_cookie = force;
        zc.zc_guid = hardforce;
+       zc.zc_history = (uint64_t)(uintptr_t)log_str;
 
        if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) {
                switch (errno) {
@@ -1241,15 +1469,15 @@ zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce)
 }
 
 int
-zpool_export(zpool_handle_t *zhp, boolean_t force)
+zpool_export(zpool_handle_t *zhp, boolean_t force, const char *log_str)
 {
-       return (zpool_export_common(zhp, force, B_FALSE));
+       return (zpool_export_common(zhp, force, B_FALSE, log_str));
 }
 
 int
-zpool_export_force(zpool_handle_t *zhp)
+zpool_export_force(zpool_handle_t *zhp, const char *log_str)
 {
-       return (zpool_export_common(zhp, B_TRUE, B_TRUE));
+       return (zpool_export_common(zhp, B_TRUE, B_TRUE, log_str));
 }
 
 static void
@@ -1265,8 +1493,10 @@ zpool_rewind_exclaim(libzfs_handle_t *hdl, const char *name, boolean_t dryrun,
        if (!hdl->libzfs_printerr || config == NULL)
                return;
 
-       if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0)
+       if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||
+           nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0) {
                return;
+       }
 
        if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
                return;
@@ -1323,6 +1553,7 @@ zpool_explain_recover(libzfs_handle_t *hdl, const char *name, int reason,
 
        /* All attempted rewinds failed if ZPOOL_CONFIG_LOAD_TIME missing */
        if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nv) != 0 ||
+           nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_REWIND_INFO, &nv) != 0 ||
            nvlist_lookup_uint64(nv, ZPOOL_CONFIG_LOAD_TIME, &rewindto) != 0)
                goto no_info;
 
@@ -1447,6 +1678,31 @@ print_vdev_tree(libzfs_handle_t *hdl, const char *name, nvlist_t *nv,
        }
 }
 
+void
+zpool_print_unsup_feat(nvlist_t *config)
+{
+       nvlist_t *nvinfo, *unsup_feat;
+       nvpair_t *nvp;
+
+       verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO, &nvinfo) ==
+           0);
+       verify(nvlist_lookup_nvlist(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT,
+           &unsup_feat) == 0);
+
+       for (nvp = nvlist_next_nvpair(unsup_feat, NULL); nvp != NULL;
+           nvp = nvlist_next_nvpair(unsup_feat, nvp)) {
+               char *desc;
+
+               verify(nvpair_type(nvp) == DATA_TYPE_STRING);
+               verify(nvpair_value_string(nvp, &desc) == 0);
+
+               if (strlen(desc) > 0)
+                       (void) printf("\t%s (%s)\n", nvpair_name(nvp), desc);
+               else
+                       (void) printf("\t%s\n", nvpair_name(nvp));
+       }
+}
+
 /*
  * Import the given pool using the known configuration and a list of
  * properties to be set. The configuration should have come from
@@ -1457,7 +1713,7 @@ int
 zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
     nvlist_t *props, int flags)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        zpool_rewind_policy_t policy;
        nvlist_t *nv = NULL;
        nvlist_t *nvinfo = NULL;
@@ -1553,6 +1809,22 @@ zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
 
                switch (error) {
                case ENOTSUP:
+                       if (nv != NULL && nvlist_lookup_nvlist(nv,
+                           ZPOOL_CONFIG_LOAD_INFO, &nvinfo) == 0 &&
+                           nvlist_exists(nvinfo, ZPOOL_CONFIG_UNSUP_FEAT)) {
+                               (void) printf(dgettext(TEXT_DOMAIN, "This "
+                                   "pool uses the following feature(s) not "
+                                   "supported by this system:\n"));
+                               zpool_print_unsup_feat(nv);
+                               if (nvlist_exists(nvinfo,
+                                   ZPOOL_CONFIG_CAN_RDONLY)) {
+                                       (void) printf(dgettext(TEXT_DOMAIN,
+                                           "All unsupported features are only "
+                                           "required for writing to the pool."
+                                           "\nThe pool can be imported using "
+                                           "'-o readonly=on'.\n"));
+                               }
+                       }
                        /*
                         * Unsupported version.
                         */
@@ -1633,7 +1905,7 @@ zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
 int
 zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
@@ -1722,10 +1994,11 @@ vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
                /*
                 * Search for the requested value. Special cases:
                 *
-                * - ZPOOL_CONFIG_PATH for whole disk entries.  These end in with a
-                *   partition suffix "1", "-part1", or "p1".  The suffix is  hidden
-                *   from the user, but included in the string, so this matches around
-                *   it.
+                * - ZPOOL_CONFIG_PATH for whole disk entries.  These end in
+                *   "-part1", or "p1".  The suffix is hidden from the user,
+                *   but included in the string, so this matches around it.
+                * - ZPOOL_CONFIG_PATH for short names zfs_strcmp_shortname()
+                *   is used to check all possible expanded paths.
                 * - looking for a top-level vdev name (i.e. ZPOOL_CONFIG_TYPE).
                 *
                 * Otherwise, all other searches are simple string compares.
@@ -1735,15 +2008,9 @@ vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
 
                        (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
                            &wholedisk);
-                       if (wholedisk) {
-                               char buf[MAXPATHLEN];
-
-                               zfs_append_partition(srchval, buf, sizeof (buf));
-                               if (strcmp(val, buf) == 0)
-                                       return (nv);
+                       if (zfs_strcmp_pathname(srchval, val, wholedisk) == 0)
+                               return (nv);
 
-                               break;
-                       }
                } else if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0 && val) {
                        char *type, *idx, *end, *p;
                        uint64_t id, vdev_id;
@@ -1894,7 +2161,6 @@ nvlist_t *
 zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
     boolean_t *l2cache, boolean_t *log)
 {
-       char buf[MAXPATHLEN];
        char *end;
        nvlist_t *nvroot, *search, *ret;
        uint64_t guid;
@@ -1906,12 +2172,6 @@ zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
                verify(nvlist_add_uint64(search, ZPOOL_CONFIG_GUID, guid) == 0);
        } else if (zpool_vdev_is_interior(path)) {
                verify(nvlist_add_string(search, ZPOOL_CONFIG_TYPE, path) == 0);
-       } else if (path[0] != '/') {
-               if (zfs_resolve_shortname(path, buf, sizeof (buf)) < 0) {
-                       nvlist_free(search);
-                       return (NULL);
-               }
-               verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, buf) == 0);
        } else {
                verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, path) == 0);
        }
@@ -2049,6 +2309,7 @@ zpool_get_config_physpath(nvlist_t *config, char *physpath, size_t phypath_size)
            &child, &count) != 0)
                return (EZFS_INVALCONFIG);
 
+#if defined(__sun__) || defined(__sun)
        /*
         * root pool can not have EFI labeled disks and can only have
         * a single top-level vdev.
@@ -2056,6 +2317,7 @@ zpool_get_config_physpath(nvlist_t *config, char *physpath, size_t phypath_size)
        if (strcmp(type, VDEV_TYPE_ROOT) != 0 || count != 1 ||
            pool_uses_efi(vdev_root))
                return (EZFS_POOL_INVALARG);
+#endif
 
        (void) vdev_get_physpaths(child[0], physpath, phypath_size, &rsz,
            B_FALSE);
@@ -2083,28 +2345,30 @@ zpool_get_physpath(zpool_handle_t *zhp, char *physpath, size_t phypath_size)
  * the disk to use the new unallocated space.
  */
 static int
-zpool_relabel_disk(libzfs_handle_t *hdl, const char *path)
+zpool_relabel_disk(libzfs_handle_t *hdl, const char *path, const char *msg)
 {
-       char errbuf[1024];
        int fd, error;
 
        if ((fd = open(path, O_RDWR|O_DIRECT)) < 0) {
                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
                    "relabel '%s': unable to open device: %d"), path, errno);
-               return (zfs_error(hdl, EZFS_OPENFAILED, errbuf));
+               return (zfs_error(hdl, EZFS_OPENFAILED, msg));
        }
 
        /*
         * It's possible that we might encounter an error if the device
         * does not have any unallocated space left. If so, we simply
         * ignore that error and continue on.
+        *
+        * Also, we don't call efi_rescan() - that would just return EBUSY.
+        * The module will do it for us in vdev_disk_open().
         */
        error = efi_use_whole_disk(fd);
        (void) close(fd);
        if (error && error != VT_ENOSPC) {
                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
                    "relabel '%s': unable to read disk capacity"), path);
-               return (zfs_error(hdl, EZFS_NOCAP, errbuf));
+               return (zfs_error(hdl, EZFS_NOCAP, msg));
        }
        return (0);
 }
@@ -2117,11 +2381,12 @@ int
 zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
     vdev_state_t *newstate)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        nvlist_t *tgt;
        boolean_t avail_spare, l2cache, islog;
        libzfs_handle_t *hdl = zhp->zpool_hdl;
+       int error;
 
        if (flags & ZFS_ONLINE_EXPAND) {
                (void) snprintf(msg, sizeof (msg),
@@ -2143,13 +2408,10 @@ zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
 
        if (flags & ZFS_ONLINE_EXPAND ||
            zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) {
-               char *pathname = NULL;
                uint64_t wholedisk = 0;
 
                (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
                    &wholedisk);
-               verify(nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH,
-                   &pathname) == 0);
 
                /*
                 * XXX - L2ARC 1.0 devices can't support expansion.
@@ -2161,8 +2423,22 @@ zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
                }
 
                if (wholedisk) {
-                       pathname += strlen(DISK_ROOT) + 1;
-                       (void) zpool_relabel_disk(hdl, pathname);
+                       const char *fullpath = path;
+                       char buf[MAXPATHLEN];
+
+                       if (path[0] != '/') {
+                               error = zfs_resolve_shortname(path, buf,
+                                   sizeof (buf));
+                               if (error != 0)
+                                       return (zfs_error(hdl, EZFS_NODEVICE,
+                                           msg));
+
+                               fullpath = buf;
+                       }
+
+                       error = zpool_relabel_disk(hdl, fullpath, msg);
+                       if (error != 0)
+                               return (error);
                }
        }
 
@@ -2189,7 +2465,7 @@ zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
 int
 zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        nvlist_t *tgt;
        boolean_t avail_spare, l2cache;
@@ -2239,12 +2515,12 @@ zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
 int
 zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
        (void) snprintf(msg, sizeof (msg),
-           dgettext(TEXT_DOMAIN, "cannot fault %llu"), (u_longlong_t)guid);
+           dgettext(TEXT_DOMAIN, "cannot fault %llu"), (u_longlong_t)guid);
 
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
        zc.zc_guid = guid;
@@ -2274,12 +2550,12 @@ zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
 int
 zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
        (void) snprintf(msg, sizeof (msg),
-           dgettext(TEXT_DOMAIN, "cannot degrade %llu"), (u_longlong_t)guid);
+           dgettext(TEXT_DOMAIN, "cannot degrade %llu"), (u_longlong_t)guid);
 
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
        zc.zc_guid = guid;
@@ -2328,7 +2604,7 @@ int
 zpool_vdev_attach(zpool_handle_t *zhp,
     const char *old_disk, const char *new_disk, nvlist_t *nvroot, int replacing)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        int ret;
        nvlist_t *tgt;
@@ -2339,7 +2615,7 @@ zpool_vdev_attach(zpool_handle_t *zhp,
        uint_t children;
        nvlist_t *config_root;
        libzfs_handle_t *hdl = zhp->zpool_hdl;
-       boolean_t rootpool = pool_is_bootable(zhp);
+       boolean_t rootpool = zpool_is_bootable(zhp);
 
        if (replacing)
                (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
@@ -2348,6 +2624,7 @@ zpool_vdev_attach(zpool_handle_t *zhp,
                (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
                    "cannot attach %s to %s"), new_disk, old_disk);
 
+#if defined(__sun__) || defined(__sun)
        /*
         * If this is a root pool, make sure that we're not attaching an
         * EFI labeled device.
@@ -2357,6 +2634,7 @@ zpool_vdev_attach(zpool_handle_t *zhp,
                    "EFI labeled devices are not supported on root pools."));
                return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg));
        }
+#endif
 
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
        if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare, &l2cache,
@@ -2502,7 +2780,7 @@ zpool_vdev_attach(zpool_handle_t *zhp,
 int
 zpool_vdev_detach(zpool_handle_t *zhp, const char *path)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        nvlist_t *tgt;
        boolean_t avail_spare, l2cache;
@@ -2600,7 +2878,7 @@ int
 zpool_vdev_split(zpool_handle_t *zhp, char *newname, nvlist_t **newroot,
     nvlist_t *props, splitflags_t flags)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        nvlist_t *tree, *config, **child, **newchild, *newconfig = NULL;
        nvlist_t **varray = NULL, *zc_props = NULL;
@@ -2811,7 +3089,7 @@ out:
 int
 zpool_vdev_remove(zpool_handle_t *zhp, const char *path)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        nvlist_t *tgt;
        boolean_t avail_spare, l2cache, islog;
@@ -2856,7 +3134,7 @@ zpool_vdev_remove(zpool_handle_t *zhp, const char *path)
 int
 zpool_clear(zpool_handle_t *zhp, const char *path, nvlist_t *rewindnvl)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        nvlist_t *tgt;
        zpool_rewind_policy_t policy;
@@ -2932,13 +3210,13 @@ zpool_clear(zpool_handle_t *zhp, const char *path, nvlist_t *rewindnvl)
 int
 zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
        (void) snprintf(msg, sizeof (msg),
            dgettext(TEXT_DOMAIN, "cannot clear errors for %llx"),
-           (u_longlong_t)guid);
+           (u_longlong_t)guid);
 
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
        zc.zc_guid = guid;
@@ -2958,7 +3236,7 @@ zpool_reguid(zpool_handle_t *zhp)
 {
        char msg[1024];
        libzfs_handle_t *hdl = zhp->zpool_hdl;
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
 
        (void) snprintf(msg, sizeof (msg),
            dgettext(TEXT_DOMAIN, "cannot reguid '%s'"), zhp->zpool_name);
@@ -2970,6 +3248,26 @@ zpool_reguid(zpool_handle_t *zhp)
        return (zpool_standard_error(hdl, errno, msg));
 }
 
+/*
+ * Reopen the pool.
+ */
+int
+zpool_reopen(zpool_handle_t *zhp)
+{
+       zfs_cmd_t zc = {"\0"};
+       char msg[1024];
+       libzfs_handle_t *hdl = zhp->zpool_hdl;
+
+       (void) snprintf(msg, sizeof (msg),
+           dgettext(TEXT_DOMAIN, "cannot reopen '%s'"),
+           zhp->zpool_name);
+
+       (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
+       if (zfs_ioctl(hdl, ZFS_IOC_POOL_REOPEN, &zc) == 0)
+               return (0);
+       return (zpool_standard_error(hdl, errno, msg));
+}
+
 /*
  * Convert from a devid string to a path.
  */
@@ -3036,7 +3334,7 @@ path_to_devid(const char *path)
 static void
 set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
 
        (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
        (void) strncpy(zc.zc_value, path, sizeof (zc.zc_value));
@@ -3099,6 +3397,7 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
        char *path, *devid, *type;
        uint64_t value;
        char buf[PATH_BUF_LEN];
+       char tmpbuf[PATH_BUF_LEN];
        vdev_stat_t *vs;
        uint_t vsc;
 
@@ -3162,7 +3461,7 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
                 */
                if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
                    &value) == 0 && value) {
-                       return strip_partition(hdl, path);
+                       return (strip_partition(hdl, path));
                }
        } else {
                verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &path) == 0);
@@ -3171,13 +3470,12 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
                 * If it's a raidz device, we need to stick in the parity level.
                 */
                if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) {
-                       char tmpbuf[PATH_BUF_LEN];
 
                        verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY,
                            &value) == 0);
-                       (void) snprintf(tmpbuf, sizeof (tmpbuf), "%s%llu", path,
+                       (void) snprintf(buf, sizeof (buf), "%s%llu", path,
                            (u_longlong_t)value);
-                       path = tmpbuf;
+                       path = buf;
                }
 
                /*
@@ -3189,9 +3487,9 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
 
                        verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID,
                            &id) == 0);
-                       (void) snprintf(buf, sizeof (buf), "%s-%llu", path,
-                           (u_longlong_t)id);
-                       path = buf;
+                       (void) snprintf(tmpbuf, sizeof (tmpbuf), "%s-%llu",
+                           path, (u_longlong_t)id);
+                       path = tmpbuf;
                }
        }
 
@@ -3211,7 +3509,7 @@ zbookmark_compare(const void *a, const void *b)
 int
 zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        uint64_t count;
        zbookmark_t *zb = NULL;
        int i;
@@ -3307,7 +3605,7 @@ nomem:
 int
 zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
        (void) strcpy(zc.zc_name, zhp->zpool_name);
@@ -3321,40 +3619,32 @@ zpool_upgrade(zpool_handle_t *zhp, uint64_t new_version)
 }
 
 void
-zpool_set_history_str(const char *subcommand, int argc, char **argv,
-    char *history_str)
+zfs_save_arguments(int argc, char **argv, char *string, int len)
 {
        int i;
 
-       (void) strlcpy(history_str, subcommand, HIS_MAX_RECORD_LEN);
+       (void) strlcpy(string, basename(argv[0]), len);
        for (i = 1; i < argc; i++) {
-               if (strlen(history_str) + 1 + strlen(argv[i]) >
-                   HIS_MAX_RECORD_LEN)
-                       break;
-               (void) strlcat(history_str, " ", HIS_MAX_RECORD_LEN);
-               (void) strlcat(history_str, argv[i], HIS_MAX_RECORD_LEN);
+               (void) strlcat(string, " ", len);
+               (void) strlcat(string, argv[i], len);
        }
 }
 
-/*
- * Stage command history for logging.
- */
 int
-zpool_stage_history(libzfs_handle_t *hdl, const char *history_str)
+zpool_log_history(libzfs_handle_t *hdl, const char *message)
 {
-       if (history_str == NULL)
-               return (EINVAL);
-
-       if (strlen(history_str) > HIS_MAX_RECORD_LEN)
-               return (EINVAL);
-
-       if (hdl->libzfs_log_str != NULL)
-               free(hdl->libzfs_log_str);
-
-       if ((hdl->libzfs_log_str = strdup(history_str)) == NULL)
-               return (no_memory(hdl));
-
-       return (0);
+       zfs_cmd_t zc = {"\0"};
+       nvlist_t *args;
+       int err;
+
+       args = fnvlist_alloc();
+       fnvlist_add_string(args, "message", message);
+       err = zcmd_write_src_nvlist(hdl, &zc, args);
+       if (err == 0)
+               err = ioctl(hdl->libzfs_fd, ZFS_IOC_LOG_HISTORY, &zc);
+       nvlist_free(args);
+       zcmd_free_nvlists(&zc);
+       return (err);
 }
 
 /*
@@ -3369,7 +3659,7 @@ zpool_stage_history(libzfs_handle_t *hdl, const char *history_str)
 static int
 get_history(zpool_handle_t *zhp, char *buf, uint64_t *off, uint64_t *len)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        libzfs_handle_t *hdl = zhp->zpool_hdl;
 
        (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
@@ -3506,7 +3796,7 @@ int
 zpool_events_next(libzfs_handle_t *hdl, nvlist_t **nvp,
     int *dropped, int block, int cleanup_fd)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        int error = 0;
 
        *nvp = NULL;
@@ -3565,7 +3855,7 @@ out:
 int
 zpool_events_clear(libzfs_handle_t *hdl, int *count)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        char msg[1024];
 
        (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
@@ -3584,14 +3874,15 @@ void
 zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
     char *pathname, size_t len)
 {
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       zfs_cmd_t zc = {"\0"};
        boolean_t mounted = B_FALSE;
        char *mntpnt = NULL;
        char dsname[MAXNAMELEN];
 
        if (dsobj == 0) {
                /* special case for the MOS */
-               (void) snprintf(pathname, len, "<metadata>:<0x%llx>", (longlong_t)obj);
+               (void) snprintf(pathname, len, "<metadata>:<0x%llx>",
+                   (longlong_t)obj);
                return;
        }
 
@@ -3623,7 +3914,8 @@ zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
                            dsname, zc.zc_value);
                }
        } else {
-               (void) snprintf(pathname, len, "%s:<0x%llx>", dsname, (longlong_t)obj);
+               (void) snprintf(pathname, len, "%s:<0x%llx>", dsname,
+                   (longlong_t)obj);
        }
        free(mntpnt);
 }
@@ -3645,7 +3937,7 @@ read_efi_label(nvlist_t *config, diskaddr_t *sb)
        if (nvlist_lookup_string(config, ZPOOL_CONFIG_PATH, &path) != 0)
                return (err);
 
-       (void) snprintf(diskname, sizeof (diskname), "%s%s", RDISK_ROOT,
+       (void) snprintf(diskname, sizeof (diskname), "%s%s", DISK_ROOT,
            strrchr(path, '/'));
        if ((fd = open(diskname, O_RDWR|O_DIRECT)) >= 0) {
                struct dk_gpt *vtoc;
@@ -3723,22 +4015,22 @@ zpool_label_disk_check(char *path)
        int fd, err;
 
        if ((fd = open(path, O_RDWR|O_DIRECT)) < 0)
-               return errno;
+               return (errno);
 
        if ((err = efi_alloc_and_read(fd, &vtoc)) != 0) {
                (void) close(fd);
-               return err;
+               return (err);
        }
 
        if (vtoc->efi_flags & EFI_GPT_PRIMARY_CORRUPT) {
                efi_free(vtoc);
                (void) close(fd);
-               return EIDRM;
+               return (EIDRM);
        }
 
        efi_free(vtoc);
        (void) close(fd);
-       return 0;
+       return (0);
 }
 
 /*
@@ -3763,12 +4055,14 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
        if (zhp) {
                nvlist_t *nvroot;
 
-               if (pool_is_bootable(zhp)) {
+#if defined(__sun__) || defined(__sun)
+               if (zpool_is_bootable(zhp)) {
                        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                            "EFI labeled devices are not supported on root "
                            "pools."));
                        return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf));
                }
+#endif
 
                verify(nvlist_lookup_nvlist(zhp->zpool_config,
                    ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
@@ -3783,8 +4077,7 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
                start_block = NEW_START_BLOCK;
        }
 
-       (void) snprintf(path, sizeof (path), "%s/%s%s", RDISK_ROOT, name,
-           BACKUP_SLICE);
+       (void) snprintf(path, sizeof (path), "%s/%s", DISK_ROOT, name);
 
        if ((fd = open(path, O_RDWR|O_DIRECT)) < 0) {
                /*
@@ -3836,7 +4129,7 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
        vtoc->efi_parts[8].p_size = resv;
        vtoc->efi_parts[8].p_tag = V_RESERVED;
 
-       if ((rval = efi_write(fd, vtoc)) != 0) {
+       if ((rval = efi_write(fd, vtoc)) != 0 || (rval = efi_rescan(fd)) != 0) {
                /*
                 * Some block drivers (like pcata) may not support EFI
                 * GPT labels.  Print out a helpful error message dir-
@@ -3854,9 +4147,11 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
        (void) close(fd);
        efi_free(vtoc);
 
-       /* Wait for the first expected slice to appear. */
-       (void) snprintf(path, sizeof (path), "%s/%s%s%s", DISK_ROOT, name,
-           isdigit(name[strlen(name)-1]) ? "p" : "", FIRST_SLICE);
+       /* Wait for the first expected partition to appear. */
+
+       (void) snprintf(path, sizeof (path), "%s/%s", DISK_ROOT, name);
+       (void) zfs_append_partition(path, MAXPATHLEN);
+
        rval = zpool_label_disk_wait(path, 3000);
        if (rval) {
                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "failed to "
@@ -3875,5 +4170,5 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
                return (zfs_error(hdl, EZFS_LABELFAILED, errbuf));
        }
 
-       return 0;
+       return (0);
 }