]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/spa.c
OpenZFS 9075 - Improve ZFS pool import/load process and corrupted pool recovery
[mirror_zfs.git] / module / zfs / spa.c
index 9246495ee178c8498577c9c25e9eeec5e363e469..3177f9649c4087a44bd72dffb9fe0863dba466d4 100644 (file)
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
+ * Copyright (c) 2015, Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2013, 2014, Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
+ * Copyright 2013 Saso Kiselkov. All rights reserved.
+ * Copyright (c) 2014 Integros [integros.com]
+ * Copyright 2016 Toomas Soome <tsoome@me.com>
  * Copyright (c) 2016 Actifio, Inc. All rights reserved.
+ * Copyright (c) 2017 Datto Inc.
+ * Copyright 2017 Joyent, Inc.
  */
 
 /*
 #include <sys/zil.h>
 #include <sys/ddt.h>
 #include <sys/vdev_impl.h>
+#include <sys/vdev_removal.h>
+#include <sys/vdev_indirect_mapping.h>
+#include <sys/vdev_indirect_births.h>
 #include <sys/vdev_disk.h>
 #include <sys/metaslab.h>
 #include <sys/metaslab_impl.h>
+#include <sys/mmp.h>
 #include <sys/uberblock_impl.h>
 #include <sys/txg.h>
 #include <sys/avl.h>
+#include <sys/bpobj.h>
 #include <sys/dmu_traverse.h>
 #include <sys/dmu_objset.h>
 #include <sys/unique.h>
@@ -72,6 +83,8 @@
 #include <sys/zvol.h>
 
 #ifdef _KERNEL
+#include <sys/fm/protocol.h>
+#include <sys/fm/util.h>
 #include <sys/bootprops.h>
 #include <sys/callb.h>
 #include <sys/cpupart.h>
  * The interval, in seconds, at which failed configuration cache file writes
  * should be retried.
  */
-static int zfs_ccw_retry_interval = 300;
+int zfs_ccw_retry_interval = 300;
 
 typedef enum zti_modes {
        ZTI_MODE_FIXED,                 /* value is # of threads (min 1) */
@@ -144,9 +157,8 @@ const zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = {
 static void spa_sync_version(void *arg, dmu_tx_t *tx);
 static void spa_sync_props(void *arg, dmu_tx_t *tx);
 static boolean_t spa_has_active_shared_spare(spa_t *spa);
-static inline int spa_load_impl(spa_t *spa, uint64_t, nvlist_t *config,
-    spa_load_state_t state, spa_import_type_t type, boolean_t mosconfig,
-    char **ereport);
+static int spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport,
+    boolean_t reloading);
 static void spa_vdev_resilver_done(spa_t *spa);
 
 uint_t         zio_taskq_batch_pct = 75;       /* 1 thread per cpu in pset */
@@ -156,12 +168,66 @@ uint_t            zio_taskq_basedc = 80;          /* base duty cycle */
 
 boolean_t      spa_create_process = B_TRUE;    /* no process ==> no sysdc */
 
+/*
+ * Report any spa_load_verify errors found, but do not fail spa_load.
+ * This is used by zdb to analyze non-idle pools.
+ */
+boolean_t      spa_load_verify_dryrun = B_FALSE;
+
 /*
  * This (illegal) pool name is used when temporarily importing a spa_t in order
  * to get the vdev stats associated with the imported devices.
  */
 #define        TRYIMPORT_NAME  "$import"
 
+/*
+ * For debugging purposes: print out vdev tree during pool import.
+ */
+int            spa_load_print_vdev_tree = B_FALSE;
+
+/*
+ * A non-zero value for zfs_max_missing_tvds means that we allow importing
+ * pools with missing top-level vdevs. This is strictly intended for advanced
+ * pool recovery cases since missing data is almost inevitable. Pools with
+ * missing devices can only be imported read-only for safety reasons, and their
+ * fail-mode will be automatically set to "continue".
+ *
+ * With 1 missing vdev we should be able to import the pool and mount all
+ * datasets. User data that was not modified after the missing device has been
+ * added should be recoverable. This means that snapshots created prior to the
+ * addition of that device should be completely intact.
+ *
+ * With 2 missing vdevs, some datasets may fail to mount since there are
+ * dataset statistics that are stored as regular metadata. Some data might be
+ * recoverable if those vdevs were added recently.
+ *
+ * With 3 or more missing vdevs, the pool is severely damaged and MOS entries
+ * may be missing entirely. Chances of data recovery are very low. Note that
+ * there are also risks of performing an inadvertent rewind as we might be
+ * missing all the vdevs with the latest uberblocks.
+ */
+unsigned long  zfs_max_missing_tvds = 0;
+
+/*
+ * The parameters below are similar to zfs_max_missing_tvds but are only
+ * intended for a preliminary open of the pool with an untrusted config which
+ * might be incomplete or out-dated.
+ *
+ * We are more tolerant for pools opened from a cachefile since we could have
+ * an out-dated cachefile where a device removal was not registered.
+ * We could have set the limit arbitrarily high but in the case where devices
+ * are really missing we would want to return the proper error codes; we chose
+ * SPA_DVAS_PER_BP - 1 so that some copies of the MOS would still be available
+ * and we get a chance to retrieve the trusted config.
+ */
+uint64_t       zfs_max_missing_tvds_cachefile = SPA_DVAS_PER_BP - 1;
+/*
+ * In the case where config was assembled by scanning device paths (/dev/dsks
+ * by default) we are less tolerant since all the existing devices should have
+ * been detected and we want spa_load to return the right error codes.
+ */
+uint64_t       zfs_max_missing_tvds_scan = 0;
+
 /*
  * ==========================================================================
  * SPA properties routines
@@ -199,7 +265,7 @@ spa_prop_get_config(spa_t *spa, nvlist_t **nvp)
        vdev_t *rvd = spa->spa_root_vdev;
        dsl_pool_t *pool = spa->spa_dsl_pool;
        uint64_t size, alloc, cap, version;
-       zprop_source_t src = ZPROP_SRC_NONE;
+       const zprop_source_t src = ZPROP_SRC_NONE;
        spa_config_dirent_t *dp;
        metaslab_class_t *mc = spa_normal_class(spa);
 
@@ -231,11 +297,13 @@ spa_prop_get_config(spa_t *spa, nvlist_t **nvp)
                    rvd->vdev_state, src);
 
                version = spa_version(spa);
-               if (version == zpool_prop_default_numeric(ZPOOL_PROP_VERSION))
-                       src = ZPROP_SRC_DEFAULT;
-               else
-                       src = ZPROP_SRC_LOCAL;
-               spa_prop_add_list(*nvp, ZPOOL_PROP_VERSION, NULL, version, src);
+               if (version == zpool_prop_default_numeric(ZPOOL_PROP_VERSION)) {
+                       spa_prop_add_list(*nvp, ZPOOL_PROP_VERSION, NULL,
+                           version, ZPROP_SRC_DEFAULT);
+               } else {
+                       spa_prop_add_list(*nvp, ZPOOL_PROP_VERSION, NULL,
+                           version, ZPROP_SRC_LOCAL);
+               }
        }
 
        if (pool != NULL) {
@@ -281,6 +349,14 @@ spa_prop_get_config(spa_t *spa, nvlist_t **nvp)
                    SPA_OLD_MAXBLOCKSIZE, ZPROP_SRC_NONE);
        }
 
+       if (spa_feature_is_enabled(spa, SPA_FEATURE_LARGE_DNODE)) {
+               spa_prop_add_list(*nvp, ZPOOL_PROP_MAXDNODESIZE, NULL,
+                   DNODE_MAX_SIZE, ZPROP_SRC_NONE);
+       } else {
+               spa_prop_add_list(*nvp, ZPOOL_PROP_MAXDNODESIZE, NULL,
+                   DNODE_MIN_SIZE, ZPROP_SRC_NONE);
+       }
+
        if ((dp = list_head(&spa->spa_config_list)) != NULL) {
                if (dp->scd_path == NULL) {
                        spa_prop_add_list(*nvp, ZPOOL_PROP_CACHEFILE,
@@ -331,7 +407,7 @@ spa_prop_get(spa_t *spa, nvlist_t **nvp)
                zprop_source_t src = ZPROP_SRC_DEFAULT;
                zpool_prop_t prop;
 
-               if ((prop = zpool_name_to_prop(za.za_name)) == ZPROP_INVAL)
+               if ((prop = zpool_name_to_prop(za.za_name)) == ZPOOL_PROP_INVAL)
                        continue;
 
                switch (za.za_integer_length) {
@@ -353,8 +429,7 @@ spa_prop_get(spa_t *spa, nvlist_t **nvp)
                                        break;
                                }
 
-                               strval = kmem_alloc(
-                                   MAXNAMELEN + strlen(MOS_DIR_NAME) + 1,
+                               strval = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN,
                                    KM_SLEEP);
                                dsl_dataset_name(ds, strval);
                                dsl_dataset_rele(ds, FTAG);
@@ -367,8 +442,7 @@ spa_prop_get(spa_t *spa, nvlist_t **nvp)
                        spa_prop_add_list(*nvp, prop, strval, intval, src);
 
                        if (strval != NULL)
-                               kmem_free(strval,
-                                   MAXNAMELEN + strlen(MOS_DIR_NAME) + 1);
+                               kmem_free(strval, ZFS_MAX_DATASET_NAME_LEN);
 
                        break;
 
@@ -420,8 +494,8 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
                const char *propname = nvpair_name(elem);
                zpool_prop_t prop = zpool_name_to_prop(propname);
 
-               switch ((int)prop) {
-               case ZPROP_INVAL:
+               switch (prop) {
+               case ZPOOL_PROP_INVAL:
                        if (!zpool_prop_feature(propname)) {
                                error = SET_ERROR(EINVAL);
                                break;
@@ -472,6 +546,16 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
                                error = SET_ERROR(EINVAL);
                        break;
 
+               case ZPOOL_PROP_MULTIHOST:
+                       error = nvpair_value_uint64(elem, &intval);
+                       if (!error && intval > 1)
+                               error = SET_ERROR(EINVAL);
+
+                       if (!error && !spa_get_hostid())
+                               error = SET_ERROR(ENOTSUP);
+
+                       break;
+
                case ZPOOL_PROP_BOOTFS:
                        /*
                         * If the pool version is less than SPA_VERSION_BOOTFS,
@@ -512,7 +596,8 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
                                /*
                                 * Must be ZPL, and its property settings
                                 * must be supported by GRUB (compression
-                                * is not gzip, and large blocks are not used).
+                                * is not gzip, and large blocks or large
+                                * dnodes are not used).
                                 */
 
                                if (dmu_objset_type(os) != DMU_OST_ZFS) {
@@ -525,9 +610,9 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
                                        error = SET_ERROR(ENOTSUP);
                                } else if ((error =
                                    dsl_prop_get_int_ds(dmu_objset_ds(os),
-                                   zfs_prop_to_name(ZFS_PROP_RECORDSIZE),
+                                   zfs_prop_to_name(ZFS_PROP_DNODESIZE),
                                    &propval)) == 0 &&
-                                   propval > SPA_OLD_MAXBLOCKSIZE) {
+                                   propval != ZFS_DNSIZE_LEGACY) {
                                        error = SET_ERROR(ENOTSUP);
                                } else {
                                        objnum = dmu_objset_id(os);
@@ -538,8 +623,7 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
 
                case ZPOOL_PROP_FAILUREMODE:
                        error = nvpair_value_uint64(elem, &intval);
-                       if (!error && (intval < ZIO_FAILURE_MODE_WAIT ||
-                           intval > ZIO_FAILURE_MODE_PANIC))
+                       if (!error && intval > ZIO_FAILURE_MODE_PANIC)
                                error = SET_ERROR(EINVAL);
 
                        /*
@@ -668,7 +752,7 @@ spa_prop_set(spa_t *spa, nvlist_t *nvp)
                    prop == ZPOOL_PROP_READONLY)
                        continue;
 
-               if (prop == ZPOOL_PROP_VERSION || prop == ZPROP_INVAL) {
+               if (prop == ZPOOL_PROP_VERSION || prop == ZPOOL_PROP_INVAL) {
                        uint64_t ver;
 
                        if (prop == ZPOOL_PROP_VERSION) {
@@ -727,10 +811,10 @@ spa_prop_clear_bootfs(spa_t *spa, uint64_t dsobj, dmu_tx_t *tx)
 static int
 spa_change_guid_check(void *arg, dmu_tx_t *tx)
 {
+       ASSERTV(uint64_t *newguid = arg);
        spa_t *spa = dmu_tx_pool(tx)->dp_spa;
        vdev_t *rvd = spa->spa_root_vdev;
        uint64_t vdev_state;
-       ASSERTV(uint64_t *newguid = arg);
 
        spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
        vdev_state = rvd->vdev_state;
@@ -787,8 +871,8 @@ spa_change_guid(spa_t *spa)
            spa_change_guid_sync, &guid, 5, ZFS_SPACE_CHECK_RESERVED);
 
        if (error == 0) {
-               spa_config_sync(spa, B_FALSE, B_TRUE);
-               spa_event_notify(spa, NULL, FM_EREPORT_ZFS_POOL_REGUID);
+               spa_write_cachefile(spa, B_FALSE, B_TRUE);
+               spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_REGUID);
        }
 
        mutex_exit(&spa_namespace_lock);
@@ -806,19 +890,14 @@ spa_change_guid(spa_t *spa)
 static int
 spa_error_entry_compare(const void *a, const void *b)
 {
-       spa_error_entry_t *sa = (spa_error_entry_t *)a;
-       spa_error_entry_t *sb = (spa_error_entry_t *)b;
+       const spa_error_entry_t *sa = (const spa_error_entry_t *)a;
+       const spa_error_entry_t *sb = (const spa_error_entry_t *)b;
        int ret;
 
-       ret = bcmp(&sa->se_bookmark, &sb->se_bookmark,
+       ret = memcmp(&sa->se_bookmark, &sb->se_bookmark,
            sizeof (zbookmark_phys_t));
 
-       if (ret < 0)
-               return (-1);
-       else if (ret > 0)
-               return (1);
-       else
-               return (0);
+       return (AVL_ISIGN(ret));
 }
 
 /*
@@ -850,7 +929,7 @@ spa_taskqs_init(spa_t *spa, zio_type_t t, zio_taskq_type_t q)
        uint_t count = ztip->zti_count;
        spa_taskqs_t *tqs = &spa->spa_zio_taskq[t][q];
        char name[32];
-       uint_t i, flags = TASKQ_DYNAMIC;
+       uint_t flags = 0;
        boolean_t batch = B_FALSE;
 
        if (mode == ZTI_MODE_NULL) {
@@ -868,6 +947,7 @@ spa_taskqs_init(spa_t *spa, zio_type_t t, zio_taskq_type_t q)
        case ZTI_MODE_FIXED:
                ASSERT3U(value, >=, 1);
                value = MAX(value, 1);
+               flags |= TASKQ_DYNAMIC;
                break;
 
        case ZTI_MODE_BATCH:
@@ -883,7 +963,7 @@ spa_taskqs_init(spa_t *spa, zio_type_t t, zio_taskq_type_t q)
                break;
        }
 
-       for (i = 0; i < count; i++) {
+       for (uint_t i = 0; i < count; i++) {
                taskq_t *tq;
 
                if (count > 1) {
@@ -924,14 +1004,13 @@ static void
 spa_taskqs_fini(spa_t *spa, zio_type_t t, zio_taskq_type_t q)
 {
        spa_taskqs_t *tqs = &spa->spa_zio_taskq[t][q];
-       uint_t i;
 
        if (tqs->stqs_taskq == NULL) {
                ASSERT3U(tqs->stqs_count, ==, 0);
                return;
        }
 
-       for (i = 0; i < tqs->stqs_count; i++) {
+       for (uint_t i = 0; i < tqs->stqs_count; i++) {
                ASSERT3P(tqs->stqs_taskq[i], !=, NULL);
                taskq_destroy(tqs->stqs_taskq[i]);
        }
@@ -993,15 +1072,18 @@ spa_taskq_dispatch_sync(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
 static void
 spa_create_zio_taskqs(spa_t *spa)
 {
-       int t, q;
-
-       for (t = 0; t < ZIO_TYPES; t++) {
-               for (q = 0; q < ZIO_TASKQ_TYPES; q++) {
+       for (int t = 0; t < ZIO_TYPES; t++) {
+               for (int q = 0; q < ZIO_TASKQ_TYPES; q++) {
                        spa_taskqs_init(spa, t, q);
                }
        }
 }
 
+/*
+ * Disabled until spa_thread() can be adapted for Linux.
+ */
+#undef HAVE_SPA_THREAD
+
 #if defined(_KERNEL) && defined(HAVE_SPA_THREAD)
 static void
 spa_thread(void *arg)
@@ -1121,6 +1203,9 @@ spa_activate(spa_t *spa, int mode)
                spa_create_zio_taskqs(spa);
        }
 
+       for (size_t i = 0; i < TXG_SIZE; i++)
+               spa->spa_txg_zio[i] = zio_root(spa, NULL, NULL, 0);
+
        list_create(&spa->spa_config_dirty_list, sizeof (vdev_t),
            offsetof(vdev_t, vdev_config_dirty_node));
        list_create(&spa->spa_evicting_os_list, sizeof (objset_t),
@@ -1128,7 +1213,7 @@ spa_activate(spa_t *spa, int mode)
        list_create(&spa->spa_state_dirty_list, sizeof (vdev_t),
            offsetof(vdev_t, vdev_state_dirty_node));
 
-       txg_list_create(&spa->spa_vdev_txg_list,
+       txg_list_create(&spa->spa_vdev_txg_list, spa,
            offsetof(struct vdev, vdev_txg_node));
 
        avl_create(&spa->spa_errlist_scrub,
@@ -1138,6 +1223,8 @@ spa_activate(spa_t *spa, int mode)
            spa_error_entry_compare, sizeof (spa_error_entry_t),
            offsetof(spa_error_entry_t, se_avl));
 
+       spa_keystore_init(&spa->spa_keystore);
+
        /*
         * This taskq is used to perform zvol-minor-related tasks
         * asynchronously. This has several advantages, including easy
@@ -1155,6 +1242,21 @@ spa_activate(spa_t *spa, int mode)
         */
        spa->spa_zvol_taskq = taskq_create("z_zvol", 1, defclsyspri,
            1, INT_MAX, 0);
+
+       /*
+        * Taskq dedicated to prefetcher threads: this is used to prevent the
+        * pool traverse code from monopolizing the global (and limited)
+        * system_taskq by inappropriately scheduling long running tasks on it.
+        */
+       spa->spa_prefetch_taskq = taskq_create("z_prefetch", boot_ncpus,
+           defclsyspri, 1, INT_MAX, TASKQ_DYNAMIC);
+
+       /*
+        * The taskq to upgrade datasets in this pool. Currently used by
+        * feature SPA_FEATURE_USEROBJ_ACCOUNTING/SPA_FEATURE_PROJECT_QUOTA.
+        */
+       spa->spa_upgrade_taskq = taskq_create("z_upgrade", boot_ncpus,
+           defclsyspri, 1, INT_MAX, TASKQ_DYNAMIC);
 }
 
 /*
@@ -1163,8 +1265,6 @@ spa_activate(spa_t *spa, int mode)
 static void
 spa_deactivate(spa_t *spa)
 {
-       int t, q;
-
        ASSERT(spa->spa_sync_on == B_FALSE);
        ASSERT(spa->spa_dsl_pool == NULL);
        ASSERT(spa->spa_root_vdev == NULL);
@@ -1178,20 +1278,36 @@ spa_deactivate(spa_t *spa)
                spa->spa_zvol_taskq = NULL;
        }
 
+       if (spa->spa_prefetch_taskq) {
+               taskq_destroy(spa->spa_prefetch_taskq);
+               spa->spa_prefetch_taskq = NULL;
+       }
+
+       if (spa->spa_upgrade_taskq) {
+               taskq_destroy(spa->spa_upgrade_taskq);
+               spa->spa_upgrade_taskq = NULL;
+       }
+
        txg_list_destroy(&spa->spa_vdev_txg_list);
 
        list_destroy(&spa->spa_config_dirty_list);
        list_destroy(&spa->spa_evicting_os_list);
        list_destroy(&spa->spa_state_dirty_list);
 
-       taskq_cancel_id(system_taskq, spa->spa_deadman_tqid);
+       taskq_cancel_id(system_delay_taskq, spa->spa_deadman_tqid);
 
-       for (t = 0; t < ZIO_TYPES; t++) {
-               for (q = 0; q < ZIO_TASKQ_TYPES; q++) {
+       for (int t = 0; t < ZIO_TYPES; t++) {
+               for (int q = 0; q < ZIO_TASKQ_TYPES; q++) {
                        spa_taskqs_fini(spa, t, q);
                }
        }
 
+       for (size_t i = 0; i < TXG_SIZE; i++) {
+               ASSERT3P(spa->spa_txg_zio[i], !=, NULL);
+               VERIFY0(zio_wait(spa->spa_txg_zio[i]));
+               spa->spa_txg_zio[i] = NULL;
+       }
+
        metaslab_class_destroy(spa->spa_normal_class);
        spa->spa_normal_class = NULL;
 
@@ -1203,10 +1319,11 @@ spa_deactivate(spa_t *spa)
         * still have errors left in the queues.  Empty them just in case.
         */
        spa_errlog_drain(spa);
-
        avl_destroy(&spa->spa_errlist_scrub);
        avl_destroy(&spa->spa_errlist_last);
 
+       spa_keystore_fini(&spa->spa_keystore);
+
        spa->spa_state = POOL_STATE_UNINITIALIZED;
 
        mutex_enter(&spa->spa_proc_lock);
@@ -1248,7 +1365,6 @@ spa_config_parse(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent,
        nvlist_t **child;
        uint_t children;
        int error;
-       int c;
 
        if ((error = vdev_alloc(spa, vdp, nv, parent, id, atype)) != 0)
                return (error);
@@ -1268,7 +1384,7 @@ spa_config_parse(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent,
                return (SET_ERROR(EINVAL));
        }
 
-       for (c = 0; c < children; c++) {
+       for (int c = 0; c < children; c++) {
                vdev_t *vd;
                if ((error = spa_config_parse(spa, &vd, child[c], *vdp, c,
                    atype)) != 0) {
@@ -1293,6 +1409,8 @@ spa_unload(spa_t *spa)
 
        ASSERT(MUTEX_HELD(&spa_namespace_lock));
 
+       spa_load_note(spa, "UNLOADING");
+
        /*
         * Stop async tasks.
         */
@@ -1306,16 +1424,45 @@ spa_unload(spa_t *spa)
                spa->spa_sync_on = B_FALSE;
        }
 
+       /*
+        * Even though vdev_free() also calls vdev_metaslab_fini, we need
+        * to call it earlier, before we wait for async i/o to complete.
+        * This ensures that there is no async metaslab prefetching, by
+        * calling taskq_wait(mg_taskq).
+        */
+       if (spa->spa_root_vdev != NULL) {
+               spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
+               for (int c = 0; c < spa->spa_root_vdev->vdev_children; c++)
+                       vdev_metaslab_fini(spa->spa_root_vdev->vdev_child[c]);
+               spa_config_exit(spa, SCL_ALL, FTAG);
+       }
+
+       if (spa->spa_mmp.mmp_thread)
+               mmp_thread_stop(spa);
+
        /*
         * Wait for any outstanding async I/O to complete.
         */
        if (spa->spa_async_zio_root != NULL) {
-               for (i = 0; i < max_ncpus; i++)
+               for (int i = 0; i < max_ncpus; i++)
                        (void) zio_wait(spa->spa_async_zio_root[i]);
                kmem_free(spa->spa_async_zio_root, max_ncpus * sizeof (void *));
                spa->spa_async_zio_root = NULL;
        }
 
+       if (spa->spa_vdev_removal != NULL) {
+               spa_vdev_removal_destroy(spa->spa_vdev_removal);
+               spa->spa_vdev_removal = NULL;
+       }
+
+       if (spa->spa_condense_zthr != NULL) {
+               ASSERT(!zthr_isrunning(spa->spa_condense_zthr));
+               zthr_destroy(spa->spa_condense_zthr);
+               spa->spa_condense_zthr = NULL;
+       }
+
+       spa_condense_fini(spa);
+
        bpobj_close(&spa->spa_deferred_bpobj);
 
        spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
@@ -1338,7 +1485,6 @@ spa_unload(spa_t *spa)
 
        ddt_unload(spa);
 
-
        /*
         * Drop and purge level 2 cache
         */
@@ -1374,6 +1520,8 @@ spa_unload(spa_t *spa)
 
        spa->spa_async_suspended = 0;
 
+       spa->spa_indirect_vdevs_loaded = B_FALSE;
+
        if (spa->spa_comment != NULL) {
                spa_strfree(spa->spa_comment);
                spa->spa_comment = NULL;
@@ -1388,7 +1536,7 @@ spa_unload(spa_t *spa)
  * 'spa_spares.sav_config'.  We parse this into vdevs, try to open them, and
  * then re-generate a more complete list including status information.
  */
-static void
+void
 spa_load_spares(spa_t *spa)
 {
        nvlist_t **spares;
@@ -1505,10 +1653,10 @@ spa_load_spares(spa_t *spa)
  * Devices which are already active have their details maintained, and are
  * not re-opened.
  */
-static void
+void
 spa_load_l2cache(spa_t *spa)
 {
-       nvlist_t **l2cache;
+       nvlist_t **l2cache = NULL;
        uint_t nl2cache;
        int i, j, oldnvdevs;
        uint64_t guid;
@@ -1517,20 +1665,21 @@ spa_load_l2cache(spa_t *spa)
 
        ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL);
 
-       if (sav->sav_config != NULL) {
-               VERIFY(nvlist_lookup_nvlist_array(sav->sav_config,
-                   ZPOOL_CONFIG_L2CACHE, &l2cache, &nl2cache) == 0);
-               newvdevs = kmem_alloc(nl2cache * sizeof (void *), KM_SLEEP);
-       } else {
-               nl2cache = 0;
-               newvdevs = NULL;
-       }
-
        oldvdevs = sav->sav_vdevs;
        oldnvdevs = sav->sav_count;
        sav->sav_vdevs = NULL;
        sav->sav_count = 0;
 
+       if (sav->sav_config == NULL) {
+               nl2cache = 0;
+               newvdevs = NULL;
+               goto out;
+       }
+
+       VERIFY(nvlist_lookup_nvlist_array(sav->sav_config,
+           ZPOOL_CONFIG_L2CACHE, &l2cache, &nl2cache) == 0);
+       newvdevs = kmem_alloc(nl2cache * sizeof (void *), KM_SLEEP);
+
        /*
         * Process new nvlist of vdevs.
         */
@@ -1581,6 +1730,26 @@ spa_load_l2cache(spa_t *spa)
                }
        }
 
+       sav->sav_vdevs = newvdevs;
+       sav->sav_count = (int)nl2cache;
+
+       /*
+        * Recompute the stashed list of l2cache devices, with status
+        * information this time.
+        */
+       VERIFY(nvlist_remove(sav->sav_config, ZPOOL_CONFIG_L2CACHE,
+           DATA_TYPE_NVLIST_ARRAY) == 0);
+
+       if (sav->sav_count > 0)
+               l2cache = kmem_alloc(sav->sav_count * sizeof (void *),
+                   KM_SLEEP);
+       for (i = 0; i < sav->sav_count; i++)
+               l2cache[i] = vdev_config_generate(spa,
+                   sav->sav_vdevs[i], B_TRUE, VDEV_CONFIG_L2CACHE);
+       VERIFY(nvlist_add_nvlist_array(sav->sav_config,
+           ZPOOL_CONFIG_L2CACHE, l2cache, sav->sav_count) == 0);
+
+out:
        /*
         * Purge vdevs that were dropped
         */
@@ -1602,26 +1771,6 @@ spa_load_l2cache(spa_t *spa)
        if (oldvdevs)
                kmem_free(oldvdevs, oldnvdevs * sizeof (void *));
 
-       if (sav->sav_config == NULL)
-               goto out;
-
-       sav->sav_vdevs = newvdevs;
-       sav->sav_count = (int)nl2cache;
-
-       /*
-        * Recompute the stashed list of l2cache devices, with status
-        * information this time.
-        */
-       VERIFY(nvlist_remove(sav->sav_config, ZPOOL_CONFIG_L2CACHE,
-           DATA_TYPE_NVLIST_ARRAY) == 0);
-
-       l2cache = kmem_alloc(sav->sav_count * sizeof (void *), KM_SLEEP);
-       for (i = 0; i < sav->sav_count; i++)
-               l2cache[i] = vdev_config_generate(spa,
-                   sav->sav_vdevs[i], B_TRUE, VDEV_CONFIG_L2CACHE);
-       VERIFY(nvlist_add_nvlist_array(sav->sav_config,
-           ZPOOL_CONFIG_L2CACHE, l2cache, sav->sav_count) == 0);
-out:
        for (i = 0; i < sav->sav_count; i++)
                nvlist_free(l2cache[i]);
        if (sav->sav_count)
@@ -1655,170 +1804,107 @@ load_nvlist(spa_t *spa, uint64_t obj, nvlist_t **value)
 }
 
 /*
- * Checks to see if the given vdev could not be opened, in which case we post a
- * sysevent to notify the autoreplace code that the device has been removed.
+ * Concrete top-level vdevs that are not missing and are not logs. At every
+ * spa_sync we write new uberblocks to at least SPA_SYNC_MIN_VDEVS core tvds.
  */
-static void
-spa_check_removed(vdev_t *vd)
+static uint64_t
+spa_healthy_core_tvds(spa_t *spa)
 {
-       int c;
-
-       for (c = 0; c < vd->vdev_children; c++)
-               spa_check_removed(vd->vdev_child[c]);
+       vdev_t *rvd = spa->spa_root_vdev;
+       uint64_t tvds = 0;
 
-       if (vd->vdev_ops->vdev_op_leaf && vdev_is_dead(vd) &&
-           !vd->vdev_ishole) {
-               zfs_ereport_post(FM_EREPORT_RESOURCE_AUTOREPLACE,
-                   vd->vdev_spa, vd, NULL, 0, 0);
-               spa_event_notify(vd->vdev_spa, vd, FM_EREPORT_ZFS_DEVICE_CHECK);
+       for (uint64_t i = 0; i < rvd->vdev_children; i++) {
+               vdev_t *vd = rvd->vdev_child[i];
+               if (vd->vdev_islog)
+                       continue;
+               if (vdev_is_concrete(vd) && !vdev_is_dead(vd))
+                       tvds++;
        }
+
+       return (tvds);
 }
 
+/*
+ * Checks to see if the given vdev could not be opened, in which case we post a
+ * sysevent to notify the autoreplace code that the device has been removed.
+ */
 static void
-spa_config_valid_zaps(vdev_t *vd, vdev_t *mvd)
+spa_check_removed(vdev_t *vd)
 {
-       uint64_t i;
-
-       ASSERT3U(vd->vdev_children, ==, mvd->vdev_children);
-
-       vd->vdev_top_zap = mvd->vdev_top_zap;
-       vd->vdev_leaf_zap = mvd->vdev_leaf_zap;
+       for (uint64_t c = 0; c < vd->vdev_children; c++)
+               spa_check_removed(vd->vdev_child[c]);
 
-       for (i = 0; i < vd->vdev_children; i++) {
-               spa_config_valid_zaps(vd->vdev_child[i], mvd->vdev_child[i]);
+       if (vd->vdev_ops->vdev_op_leaf && vdev_is_dead(vd) &&
+           vdev_is_concrete(vd)) {
+               zfs_post_autoreplace(vd->vdev_spa, vd);
+               spa_event_notify(vd->vdev_spa, vd, NULL, ESC_ZFS_VDEV_CHECK);
        }
 }
 
-/*
- * Validate the current config against the MOS config
- */
-static boolean_t
-spa_config_valid(spa_t *spa, nvlist_t *config)
+static int
+spa_check_for_missing_logs(spa_t *spa)
 {
-       vdev_t *mrvd, *rvd = spa->spa_root_vdev;
-       nvlist_t *nv;
-       int c, i;
-
-       VERIFY(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nv) == 0);
-
-       spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
-       VERIFY(spa_config_parse(spa, &mrvd, nv, NULL, 0, VDEV_ALLOC_LOAD) == 0);
-
-       ASSERT3U(rvd->vdev_children, ==, mrvd->vdev_children);
+       vdev_t *rvd = spa->spa_root_vdev;
 
        /*
         * If we're doing a normal import, then build up any additional
-        * diagnostic information about missing devices in this config.
+        * diagnostic information about missing log devices.
         * We'll pass this up to the user for further processing.
         */
        if (!(spa->spa_import_flags & ZFS_IMPORT_MISSING_LOG)) {
                nvlist_t **child, *nv;
                uint64_t idx = 0;
 
-               child = kmem_alloc(rvd->vdev_children * sizeof (nvlist_t **),
+               child = kmem_alloc(rvd->vdev_children * sizeof (nvlist_t *),
                    KM_SLEEP);
                VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0);
 
-               for (c = 0; c < rvd->vdev_children; c++) {
+               for (uint64_t c = 0; c < rvd->vdev_children; c++) {
                        vdev_t *tvd = rvd->vdev_child[c];
-                       vdev_t *mtvd  = mrvd->vdev_child[c];
 
-                       if (tvd->vdev_ops == &vdev_missing_ops &&
-                           mtvd->vdev_ops != &vdev_missing_ops &&
-                           mtvd->vdev_islog)
-                               child[idx++] = vdev_config_generate(spa, mtvd,
-                                   B_FALSE, 0);
+                       /*
+                        * We consider a device as missing only if it failed
+                        * to open (i.e. offline or faulted is not considered
+                        * as missing).
+                        */
+                       if (tvd->vdev_islog &&
+                           tvd->vdev_state == VDEV_STATE_CANT_OPEN) {
+                               child[idx++] = vdev_config_generate(spa, tvd,
+                                   B_FALSE, VDEV_CONFIG_MISSING);
+                       }
                }
 
-               if (idx) {
-                       VERIFY(nvlist_add_nvlist_array(nv,
-                           ZPOOL_CONFIG_CHILDREN, child, idx) == 0);
-                       VERIFY(nvlist_add_nvlist(spa->spa_load_info,
-                           ZPOOL_CONFIG_MISSING_DEVICES, nv) == 0);
+               if (idx > 0) {
+                       fnvlist_add_nvlist_array(nv,
+                           ZPOOL_CONFIG_CHILDREN, child, idx);
+                       fnvlist_add_nvlist(spa->spa_load_info,
+                           ZPOOL_CONFIG_MISSING_DEVICES, nv);
 
-                       for (i = 0; i < idx; i++)
+                       for (uint64_t i = 0; i < idx; i++)
                                nvlist_free(child[i]);
                }
                nvlist_free(nv);
                kmem_free(child, rvd->vdev_children * sizeof (char **));
-       }
-
-       /*
-        * Compare the root vdev tree with the information we have
-        * from the MOS config (mrvd). Check each top-level vdev
-        * with the corresponding MOS config top-level (mtvd).
-        */
-       for (c = 0; c < rvd->vdev_children; c++) {
-               vdev_t *tvd = rvd->vdev_child[c];
-               vdev_t *mtvd  = mrvd->vdev_child[c];
-
-               /*
-                * Resolve any "missing" vdevs in the current configuration.
-                * If we find that the MOS config has more accurate information
-                * about the top-level vdev then use that vdev instead.
-                */
-               if (tvd->vdev_ops == &vdev_missing_ops &&
-                   mtvd->vdev_ops != &vdev_missing_ops) {
 
-                       if (!(spa->spa_import_flags & ZFS_IMPORT_MISSING_LOG))
-                               continue;
+               if (idx > 0) {
+                       spa_load_failed(spa, "some log devices are missing");
+                       return (SET_ERROR(ENXIO));
+               }
+       } else {
+               for (uint64_t c = 0; c < rvd->vdev_children; c++) {
+                       vdev_t *tvd = rvd->vdev_child[c];
 
-                       /*
-                        * Device specific actions.
-                        */
-                       if (mtvd->vdev_islog) {
+                       if (tvd->vdev_islog &&
+                           tvd->vdev_state == VDEV_STATE_CANT_OPEN) {
                                spa_set_log_state(spa, SPA_LOG_CLEAR);
-                       } else {
-                               /*
-                                * XXX - once we have 'readonly' pool
-                                * support we should be able to handle
-                                * missing data devices by transitioning
-                                * the pool to readonly.
-                                */
-                               continue;
-                       }
-
-                       /*
-                        * Swap the missing vdev with the data we were
-                        * able to obtain from the MOS config.
-                        */
-                       vdev_remove_child(rvd, tvd);
-                       vdev_remove_child(mrvd, mtvd);
-
-                       vdev_add_child(rvd, mtvd);
-                       vdev_add_child(mrvd, tvd);
-
-                       spa_config_exit(spa, SCL_ALL, FTAG);
-                       vdev_load(mtvd);
-                       spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
-
-                       vdev_reopen(rvd);
-               } else {
-                       if (mtvd->vdev_islog) {
-                               /*
-                                * Load the slog device's state from the MOS
-                                * config since it's possible that the label
-                                * does not contain the most up-to-date
-                                * information.
-                                */
-                               vdev_load_log_state(tvd, mtvd);
-                               vdev_reopen(tvd);
+                               spa_load_note(spa, "some log devices are "
+                                   "missing, ZIL is dropped.");
+                               break;
                        }
-
-                       /*
-                        * Per-vdev ZAP info is stored exclusively in the MOS.
-                        */
-                       spa_config_valid_zaps(tvd, mtvd);
                }
        }
 
-       vdev_free(mrvd);
-       spa_config_exit(spa, SCL_ALL, FTAG);
-
-       /*
-        * Ensure we were able to validate the config.
-        */
-       return (rvd->vdev_guid_sum == spa->spa_uberblock.ub_guid_sum);
+       return (0);
 }
 
 /*
@@ -1850,14 +1936,13 @@ spa_passivate_log(spa_t *spa)
 {
        vdev_t *rvd = spa->spa_root_vdev;
        boolean_t slog_found = B_FALSE;
-       int c;
 
        ASSERT(spa_config_held(spa, SCL_ALLOC, RW_WRITER));
 
        if (!spa_has_slogs(spa))
                return (B_FALSE);
 
-       for (c = 0; c < rvd->vdev_children; c++) {
+       for (int c = 0; c < rvd->vdev_children; c++) {
                vdev_t *tvd = rvd->vdev_child[c];
                metaslab_group_t *mg = tvd->vdev_mg;
 
@@ -1874,11 +1959,10 @@ static void
 spa_activate_log(spa_t *spa)
 {
        vdev_t *rvd = spa->spa_root_vdev;
-       int c;
 
        ASSERT(spa_config_held(spa, SCL_ALLOC, RW_WRITER));
 
-       for (c = 0; c < rvd->vdev_children; c++) {
+       for (int c = 0; c < rvd->vdev_children; c++) {
                vdev_t *tvd = rvd->vdev_child[c];
                metaslab_group_t *mg = tvd->vdev_mg;
 
@@ -1888,11 +1972,11 @@ spa_activate_log(spa_t *spa)
 }
 
 int
-spa_offline_log(spa_t *spa)
+spa_reset_logs(spa_t *spa)
 {
        int error;
 
-       error = dmu_objset_find(spa_name(spa), zil_vdev_offline,
+       error = dmu_objset_find(spa_name(spa), zil_reset,
            NULL, DS_FIND_CHILDREN);
        if (error == 0) {
                /*
@@ -1908,9 +1992,7 @@ spa_offline_log(spa_t *spa)
 static void
 spa_aux_check_removed(spa_aux_vdev_t *sav)
 {
-       int i;
-
-       for (i = 0; i < sav->sav_count; i++)
+       for (int i = 0; i < sav->sav_count; i++)
                spa_check_removed(sav->sav_vdevs[i]);
 }
 
@@ -1942,6 +2024,7 @@ spa_load_verify_done(zio_t *zio)
        int error = zio->io_error;
        spa_t *spa = zio->io_spa;
 
+       abd_free(zio->io_abd);
        if (error) {
                if ((BP_GET_LEVEL(bp) != 0 || DMU_OT_IS_METADATA(type)) &&
                    type != DMU_OT_INTENT_LOG)
@@ -1949,10 +2032,9 @@ spa_load_verify_done(zio_t *zio)
                else
                        atomic_inc_64(&sle->sle_data_count);
        }
-       zio_data_buf_free(zio->io_data, zio->io_size);
 
        mutex_enter(&spa->spa_scrub_lock);
-       spa->spa_scrub_inflight--;
+       spa->spa_load_verify_ios--;
        cv_broadcast(&spa->spa_scrub_io_cv);
        mutex_exit(&spa->spa_scrub_lock);
 }
@@ -1970,10 +2052,6 @@ static int
 spa_load_verify_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
     const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg)
 {
-       zio_t *rio;
-       size_t size;
-       void *data;
-
        if (bp == NULL || BP_IS_HOLE(bp) || BP_IS_EMBEDDED(bp))
                return (0);
        /*
@@ -1983,26 +2061,35 @@ spa_load_verify_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
         */
        if (!spa_load_verify_metadata)
                return (0);
-       if (BP_GET_BUFC_TYPE(bp) == ARC_BUFC_DATA && !spa_load_verify_data)
+       if (!BP_IS_METADATA(bp) && !spa_load_verify_data)
                return (0);
 
-       rio = arg;
-       size = BP_GET_PSIZE(bp);
-       data = zio_data_buf_alloc(size);
+       zio_t *rio = arg;
+       size_t size = BP_GET_PSIZE(bp);
 
        mutex_enter(&spa->spa_scrub_lock);
-       while (spa->spa_scrub_inflight >= spa_load_verify_maxinflight)
+       while (spa->spa_load_verify_ios >= spa_load_verify_maxinflight)
                cv_wait(&spa->spa_scrub_io_cv, &spa->spa_scrub_lock);
-       spa->spa_scrub_inflight++;
+       spa->spa_load_verify_ios++;
        mutex_exit(&spa->spa_scrub_lock);
 
-       zio_nowait(zio_read(rio, spa, bp, data, size,
+       zio_nowait(zio_read(rio, spa, bp, abd_alloc_for_io(size, B_FALSE), size,
            spa_load_verify_done, rio->io_private, ZIO_PRIORITY_SCRUB,
            ZIO_FLAG_SPECULATIVE | ZIO_FLAG_CANFAIL |
            ZIO_FLAG_SCRUB | ZIO_FLAG_RAW, zb));
        return (0);
 }
 
+/* ARGSUSED */
+int
+verify_dataset_name_len(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg)
+{
+       if (dsl_dataset_namelen(ds) >= ZFS_MAX_DATASET_NAME_LEN)
+               return (SET_ERROR(ENAMETOOLONG));
+
+       return (0);
+}
+
 static int
 spa_load_verify(spa_t *spa)
 {
@@ -2017,13 +2104,28 @@ spa_load_verify(spa_t *spa)
        if (policy.zrp_request & ZPOOL_NEVER_REWIND)
                return (0);
 
+       dsl_pool_config_enter(spa->spa_dsl_pool, FTAG);
+       error = dmu_objset_find_dp(spa->spa_dsl_pool,
+           spa->spa_dsl_pool->dp_root_dir_obj, verify_dataset_name_len, NULL,
+           DS_FIND_CHILDREN);
+       dsl_pool_config_exit(spa->spa_dsl_pool, FTAG);
+       if (error != 0)
+               return (error);
+
        rio = zio_root(spa, NULL, &sle,
            ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE);
 
        if (spa_load_verify_metadata) {
+               if (spa->spa_extreme_rewind) {
+                       spa_load_note(spa, "performing a complete scan of the "
+                           "pool since extreme rewind is on. This may take "
+                           "a very long time.\n  (spa_load_verify_data=%u, "
+                           "spa_load_verify_metadata=%u)",
+                           spa_load_verify_data, spa_load_verify_metadata);
+               }
                error = traverse_pool(spa, spa->spa_verify_min_txg,
-                   TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA,
-                   spa_load_verify_cb, rio);
+                   TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA |
+                   TRAVERSE_NO_DECRYPT, spa_load_verify_cb, rio);
        }
 
        (void) zio_wait(rio);
@@ -2031,8 +2133,15 @@ spa_load_verify(spa_t *spa)
        spa->spa_load_meta_errors = sle.sle_meta_count;
        spa->spa_load_data_errors = sle.sle_data_count;
 
-       if (!error && sle.sle_meta_count <= policy.zrp_maxmeta &&
-           sle.sle_data_count <= policy.zrp_maxdata) {
+       if (sle.sle_meta_count != 0 || sle.sle_data_count != 0) {
+               spa_load_note(spa, "spa_load_verify found %llu metadata errors "
+                   "and %llu data errors", (u_longlong_t)sle.sle_meta_count,
+                   (u_longlong_t)sle.sle_data_count);
+       }
+
+       if (spa_load_verify_dryrun ||
+           (!error && sle.sle_meta_count <= policy.zrp_maxmeta &&
+           sle.sle_data_count <= policy.zrp_maxdata)) {
                int64_t loss = 0;
 
                verify_ok = B_TRUE;
@@ -2050,6 +2159,9 @@ spa_load_verify(spa_t *spa)
                spa->spa_load_max_txg = spa->spa_uberblock.ub_txg;
        }
 
+       if (spa_load_verify_dryrun)
+               return (0);
+
        if (error) {
                if (error != ENXIO && error != EIO)
                        error = SET_ERROR(EIO);
@@ -2073,17 +2185,34 @@ spa_prop_find(spa_t *spa, zpool_prop_t prop, uint64_t *val)
  * Find a value in the pool directory object.
  */
 static int
-spa_dir_prop(spa_t *spa, const char *name, uint64_t *val)
+spa_dir_prop(spa_t *spa, const char *name, uint64_t *val, boolean_t log_enoent)
 {
-       return (zap_lookup(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
-           name, sizeof (uint64_t), 1, val));
+       int error = zap_lookup(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
+           name, sizeof (uint64_t), 1, val);
+
+       if (error != 0 && (error != ENOENT || log_enoent)) {
+               spa_load_failed(spa, "couldn't get '%s' value in MOS directory "
+                   "[error=%d]", name, error);
+       }
+
+       return (error);
 }
 
 static int
 spa_vdev_err(vdev_t *vdev, vdev_aux_t aux, int err)
 {
        vdev_set_state(vdev, B_TRUE, VDEV_STATE_CANT_OPEN, aux);
-       return (err);
+       return (SET_ERROR(err));
+}
+
+static void
+spa_spawn_aux_threads(spa_t *spa)
+{
+       ASSERT(spa_writeable(spa));
+
+       ASSERT(MUTEX_HELD(&spa_namespace_lock));
+
+       spa_start_indirect_condensing_thread(spa);
 }
 
 /*
@@ -2169,57 +2298,19 @@ spa_try_repair(spa_t *spa, nvlist_t *config)
 }
 
 static int
-spa_load(spa_t *spa, spa_load_state_t state, spa_import_type_t type,
-    boolean_t mosconfig)
+spa_load(spa_t *spa, spa_load_state_t state, spa_import_type_t type)
 {
-       nvlist_t *config = spa->spa_config;
        char *ereport = FM_EREPORT_ZFS_POOL;
-       char *comment;
        int error;
-       uint64_t pool_guid;
-       nvlist_t *nvl;
 
-       if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &pool_guid))
-               return (SET_ERROR(EINVAL));
+       spa->spa_load_state = state;
 
-       ASSERT(spa->spa_comment == NULL);
-       if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
-               spa->spa_comment = spa_strdup(comment);
+       gethrestime(&spa->spa_loaded_ts);
+       error = spa_load_impl(spa, type, &ereport, B_FALSE);
 
        /*
-        * Versioning wasn't explicitly added to the label until later, so if
-        * it's not present treat it as the initial version.
-        */
-       if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
-           &spa->spa_ubsync.ub_version) != 0)
-               spa->spa_ubsync.ub_version = SPA_VERSION_INITIAL;
-
-       (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG,
-           &spa->spa_config_txg);
-
-       if ((state == SPA_LOAD_IMPORT || state == SPA_LOAD_TRYIMPORT) &&
-           spa_guid_exists(pool_guid, 0)) {
-               error = SET_ERROR(EEXIST);
-       } else {
-               spa->spa_config_guid = pool_guid;
-
-               if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_SPLIT,
-                   &nvl) == 0) {
-                       VERIFY(nvlist_dup(nvl, &spa->spa_config_splitting,
-                           KM_SLEEP) == 0);
-               }
-
-               nvlist_free(spa->spa_load_info);
-               spa->spa_load_info = fnvlist_alloc();
-
-               gethrestime(&spa->spa_loaded_ts);
-               error = spa_load_impl(spa, pool_guid, config, state, type,
-                   mosconfig, &ereport);
-       }
-
-       /*
-        * Don't count references from objsets that are already closed
-        * and are making their way through the eviction process.
+        * Don't count references from objsets that are already closed
+        * and are making their way through the eviction process.
         */
        spa_evicting_os_wait(spa);
        spa->spa_minref = refcount_count(&spa->spa_refcount);
@@ -2229,7 +2320,7 @@ spa_load(spa_t *spa, spa_load_state_t state, spa_import_type_t type,
                        spa->spa_loaded_ts.tv_nsec = 0;
                }
                if (error != EBADF) {
-                       zfs_ereport_post(ereport, spa, NULL, NULL, 0, 0);
+                       zfs_ereport_post(ereport, spa, NULL, NULL, NULL, 0, 0);
                }
        }
        spa->spa_load_state = error ? SPA_LOAD_ERROR : SPA_LOAD_NONE;
@@ -2249,7 +2340,6 @@ vdev_count_verify_zaps(vdev_t *vd)
 {
        spa_t *spa = vd->vdev_spa;
        uint64_t total = 0;
-       uint64_t i;
 
        if (vd->vdev_top_zap != 0) {
                total++;
@@ -2262,7 +2352,7 @@ vdev_count_verify_zaps(vdev_t *vd)
                    spa->spa_all_vdev_zaps, vd->vdev_leaf_zap));
        }
 
-       for (i = 0; i < vd->vdev_children; i++) {
+       for (uint64_t i = 0; i < vd->vdev_children; i++) {
                total += vdev_count_verify_zaps(vd->vdev_child[i]);
        }
 
@@ -2271,50 +2361,292 @@ vdev_count_verify_zaps(vdev_t *vd)
 #endif
 
 /*
- * Load an existing storage pool, using the pool's builtin spa_config as a
- * source of configuration information.
+ * Determine whether the activity check is required.
  */
-__attribute__((always_inline))
-static inline int
-spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
-    spa_load_state_t state, spa_import_type_t type, boolean_t mosconfig,
-    char **ereport)
+static boolean_t
+spa_activity_check_required(spa_t *spa, uberblock_t *ub, nvlist_t *label,
+    nvlist_t *config)
 {
+       uint64_t state = 0;
+       uint64_t hostid = 0;
+       uint64_t tryconfig_txg = 0;
+       uint64_t tryconfig_timestamp = 0;
+       nvlist_t *nvinfo;
+
+       if (nvlist_exists(config, ZPOOL_CONFIG_LOAD_INFO)) {
+               nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
+               (void) nvlist_lookup_uint64(nvinfo, ZPOOL_CONFIG_MMP_TXG,
+                   &tryconfig_txg);
+               (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_TIMESTAMP,
+                   &tryconfig_timestamp);
+       }
+
+       (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, &state);
+
+       /*
+        * Disable the MMP activity check - This is used by zdb which
+        * is intended to be used on potentially active pools.
+        */
+       if (spa->spa_import_flags & ZFS_IMPORT_SKIP_MMP)
+               return (B_FALSE);
+
+       /*
+        * Skip the activity check when the MMP feature is disabled.
+        */
+       if (ub->ub_mmp_magic == MMP_MAGIC && ub->ub_mmp_delay == 0)
+               return (B_FALSE);
+       /*
+        * If the tryconfig_* values are nonzero, they are the results of an
+        * earlier tryimport.  If they match the uberblock we just found, then
+        * the pool has not changed and we return false so we do not test a
+        * second time.
+        */
+       if (tryconfig_txg && tryconfig_txg == ub->ub_txg &&
+           tryconfig_timestamp && tryconfig_timestamp == ub->ub_timestamp)
+               return (B_FALSE);
+
+       /*
+        * Allow the activity check to be skipped when importing the pool
+        * on the same host which last imported it.  Since the hostid from
+        * configuration may be stale use the one read from the label.
+        */
+       if (nvlist_exists(label, ZPOOL_CONFIG_HOSTID))
+               hostid = fnvlist_lookup_uint64(label, ZPOOL_CONFIG_HOSTID);
+
+       if (hostid == spa_get_hostid())
+               return (B_FALSE);
+
+       /*
+        * Skip the activity test when the pool was cleanly exported.
+        */
+       if (state != POOL_STATE_ACTIVE)
+               return (B_FALSE);
+
+       return (B_TRUE);
+}
+
+/*
+ * Perform the import activity check.  If the user canceled the import or
+ * we detected activity then fail.
+ */
+static int
+spa_activity_check(spa_t *spa, uberblock_t *ub, nvlist_t *config)
+{
+       uint64_t import_intervals = MAX(zfs_multihost_import_intervals, 1);
+       uint64_t txg = ub->ub_txg;
+       uint64_t timestamp = ub->ub_timestamp;
+       uint64_t import_delay = NANOSEC;
+       hrtime_t import_expire;
+       nvlist_t *mmp_label = NULL;
+       vdev_t *rvd = spa->spa_root_vdev;
+       kcondvar_t cv;
+       kmutex_t mtx;
        int error = 0;
-       nvlist_t *nvroot = NULL;
-       nvlist_t *label;
-       vdev_t *rvd;
-       uberblock_t *ub = &spa->spa_uberblock;
-       uint64_t children, config_cache_txg = spa->spa_config_txg;
-       int orig_mode = spa->spa_mode;
-       int parse, i;
-       uint64_t obj;
-       boolean_t missing_feat_write = B_FALSE;
-       nvlist_t *mos_config;
+
+       cv_init(&cv, NULL, CV_DEFAULT, NULL);
+       mutex_init(&mtx, NULL, MUTEX_DEFAULT, NULL);
+       mutex_enter(&mtx);
 
        /*
-        * If this is an untrusted config, access the pool in read-only mode.
-        * This prevents things like resilvering recently removed devices.
+        * If ZPOOL_CONFIG_MMP_TXG is present an activity check was performed
+        * during the earlier tryimport.  If the txg recorded there is 0 then
+        * the pool is known to be active on another host.
+        *
+        * Otherwise, the pool might be in use on another node.  Check for
+        * changes in the uberblocks on disk if necessary.
         */
-       if (!mosconfig)
-               spa->spa_mode = FREAD;
+       if (nvlist_exists(config, ZPOOL_CONFIG_LOAD_INFO)) {
+               nvlist_t *nvinfo = fnvlist_lookup_nvlist(config,
+                   ZPOOL_CONFIG_LOAD_INFO);
 
-       ASSERT(MUTEX_HELD(&spa_namespace_lock));
+               if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_TXG) &&
+                   fnvlist_lookup_uint64(nvinfo, ZPOOL_CONFIG_MMP_TXG) == 0) {
+                       vdev_uberblock_load(rvd, ub, &mmp_label);
+                       error = SET_ERROR(EREMOTEIO);
+                       goto out;
+               }
+       }
 
-       spa->spa_load_state = state;
+       /*
+        * Preferentially use the zfs_multihost_interval from the node which
+        * last imported the pool.  This value is stored in an MMP uberblock as.
+        *
+        * ub_mmp_delay * vdev_count_leaves() == zfs_multihost_interval
+        */
+       if (ub->ub_mmp_magic == MMP_MAGIC && ub->ub_mmp_delay)
+               import_delay = MAX(import_delay, import_intervals *
+                   ub->ub_mmp_delay * MAX(vdev_count_leaves(spa), 1));
+
+       /* Apply a floor using the local default values. */
+       import_delay = MAX(import_delay, import_intervals *
+           MSEC2NSEC(MAX(zfs_multihost_interval, MMP_MIN_INTERVAL)));
+
+       zfs_dbgmsg("import_delay=%llu ub_mmp_delay=%llu import_intervals=%u "
+           "leaves=%u", import_delay, ub->ub_mmp_delay, import_intervals,
+           vdev_count_leaves(spa));
+
+       /* Add a small random factor in case of simultaneous imports (0-25%) */
+       import_expire = gethrtime() + import_delay +
+           (import_delay * spa_get_random(250) / 1000);
+
+       while (gethrtime() < import_expire) {
+               vdev_uberblock_load(rvd, ub, &mmp_label);
+
+               if (txg != ub->ub_txg || timestamp != ub->ub_timestamp) {
+                       error = SET_ERROR(EREMOTEIO);
+                       break;
+               }
+
+               if (mmp_label) {
+                       nvlist_free(mmp_label);
+                       mmp_label = NULL;
+               }
+
+               error = cv_timedwait_sig(&cv, &mtx, ddi_get_lbolt() + hz);
+               if (error != -1) {
+                       error = SET_ERROR(EINTR);
+                       break;
+               }
+               error = 0;
+       }
+
+out:
+       mutex_exit(&mtx);
+       mutex_destroy(&mtx);
+       cv_destroy(&cv);
+
+       /*
+        * If the pool is determined to be active store the status in the
+        * spa->spa_load_info nvlist.  If the remote hostname or hostid are
+        * available from configuration read from disk store them as well.
+        * This allows 'zpool import' to generate a more useful message.
+        *
+        * ZPOOL_CONFIG_MMP_STATE    - observed pool status (mandatory)
+        * ZPOOL_CONFIG_MMP_HOSTNAME - hostname from the active pool
+        * ZPOOL_CONFIG_MMP_HOSTID   - hostid from the active pool
+        */
+       if (error == EREMOTEIO) {
+               char *hostname = "<unknown>";
+               uint64_t hostid = 0;
+
+               if (mmp_label) {
+                       if (nvlist_exists(mmp_label, ZPOOL_CONFIG_HOSTNAME)) {
+                               hostname = fnvlist_lookup_string(mmp_label,
+                                   ZPOOL_CONFIG_HOSTNAME);
+                               fnvlist_add_string(spa->spa_load_info,
+                                   ZPOOL_CONFIG_MMP_HOSTNAME, hostname);
+                       }
+
+                       if (nvlist_exists(mmp_label, ZPOOL_CONFIG_HOSTID)) {
+                               hostid = fnvlist_lookup_uint64(mmp_label,
+                                   ZPOOL_CONFIG_HOSTID);
+                               fnvlist_add_uint64(spa->spa_load_info,
+                                   ZPOOL_CONFIG_MMP_HOSTID, hostid);
+                       }
+               }
+
+               fnvlist_add_uint64(spa->spa_load_info,
+                   ZPOOL_CONFIG_MMP_STATE, MMP_STATE_ACTIVE);
+               fnvlist_add_uint64(spa->spa_load_info,
+                   ZPOOL_CONFIG_MMP_TXG, 0);
+
+               error = spa_vdev_err(rvd, VDEV_AUX_ACTIVE, EREMOTEIO);
+       }
+
+       if (mmp_label)
+               nvlist_free(mmp_label);
+
+       return (error);
+}
 
-       if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvroot))
+static int
+spa_verify_host(spa_t *spa, nvlist_t *mos_config)
+{
+       uint64_t hostid;
+       char *hostname;
+       uint64_t myhostid = 0;
+
+       if (!spa_is_root(spa) && nvlist_lookup_uint64(mos_config,
+           ZPOOL_CONFIG_HOSTID, &hostid) == 0) {
+               hostname = fnvlist_lookup_string(mos_config,
+                   ZPOOL_CONFIG_HOSTNAME);
+
+               myhostid = zone_get_hostid(NULL);
+
+               if (hostid != 0 && myhostid != 0 && hostid != myhostid) {
+                       cmn_err(CE_WARN, "pool '%s' could not be "
+                           "loaded as it was last accessed by "
+                           "another system (host: %s hostid: 0x%llx). "
+                           "See: http://illumos.org/msg/ZFS-8000-EY",
+                           spa_name(spa), hostname, (u_longlong_t)hostid);
+                       spa_load_failed(spa, "hostid verification failed: pool "
+                           "last accessed by host: %s (hostid: 0x%llx)",
+                           hostname, (u_longlong_t)hostid);
+                       return (SET_ERROR(EBADF));
+               }
+       }
+
+       return (0);
+}
+
+static int
+spa_ld_parse_config(spa_t *spa, spa_import_type_t type)
+{
+       int error = 0;
+       nvlist_t *nvtree, *nvl, *config = spa->spa_config;
+       int parse;
+       vdev_t *rvd;
+       uint64_t pool_guid;
+       char *comment;
+
+       /*
+        * Versioning wasn't explicitly added to the label until later, so if
+        * it's not present treat it as the initial version.
+        */
+       if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
+           &spa->spa_ubsync.ub_version) != 0)
+               spa->spa_ubsync.ub_version = SPA_VERSION_INITIAL;
+
+       if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &pool_guid)) {
+               spa_load_failed(spa, "invalid config provided: '%s' missing",
+                   ZPOOL_CONFIG_POOL_GUID);
                return (SET_ERROR(EINVAL));
+       }
 
-       parse = (type == SPA_IMPORT_EXISTING ?
-           VDEV_ALLOC_LOAD : VDEV_ALLOC_SPLIT);
+       if ((spa->spa_load_state == SPA_LOAD_IMPORT || spa->spa_load_state ==
+           SPA_LOAD_TRYIMPORT) && spa_guid_exists(pool_guid, 0)) {
+               spa_load_failed(spa, "a pool with guid %llu is already open",
+                   (u_longlong_t)pool_guid);
+               return (SET_ERROR(EEXIST));
+       }
+
+       spa->spa_config_guid = pool_guid;
+
+       nvlist_free(spa->spa_load_info);
+       spa->spa_load_info = fnvlist_alloc();
+
+       ASSERT(spa->spa_comment == NULL);
+       if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
+               spa->spa_comment = spa_strdup(comment);
+
+       (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG,
+           &spa->spa_config_txg);
+
+       if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_SPLIT, &nvl) == 0)
+               spa->spa_config_splitting = fnvlist_dup(nvl);
+
+       if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvtree)) {
+               spa_load_failed(spa, "invalid config provided: '%s' missing",
+                   ZPOOL_CONFIG_VDEV_TREE);
+               return (SET_ERROR(EINVAL));
+       }
 
        /*
         * Create "The Godfather" zio to hold all async IOs
         */
        spa->spa_async_zio_root = kmem_alloc(max_ncpus * sizeof (void *),
            KM_SLEEP);
-       for (i = 0; i < max_ncpus; i++) {
+       for (int i = 0; i < max_ncpus; i++) {
                spa->spa_async_zio_root[i] = zio_root(spa, NULL, NULL,
                    ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
                    ZIO_FLAG_GODFATHER);
@@ -2326,11 +2658,16 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
         * configuration requires knowing the version number.
         */
        spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
-       error = spa_config_parse(spa, &rvd, nvroot, NULL, 0, parse);
+       parse = (type == SPA_IMPORT_EXISTING ?
+           VDEV_ALLOC_LOAD : VDEV_ALLOC_SPLIT);
+       error = spa_config_parse(spa, &rvd, nvtree, NULL, 0, parse);
        spa_config_exit(spa, SCL_ALL, FTAG);
 
-       if (error != 0)
+       if (error != 0) {
+               spa_load_failed(spa, "unable to parse config [error=%d]",
+                   error);
                return (error);
+       }
 
        ASSERT(spa->spa_root_vdev == rvd);
        ASSERT3U(spa->spa_min_ashift, >=, SPA_MINBLOCKSHIFT);
@@ -2340,40 +2677,110 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
                ASSERT(spa_guid(spa) == pool_guid);
        }
 
+       return (0);
+}
+
+/*
+ * Recursively open all vdevs in the vdev tree. This function is called twice:
+ * first with the untrusted config, then with the trusted config.
+ */
+static int
+spa_ld_open_vdevs(spa_t *spa)
+{
+       int error = 0;
+
        /*
-        * Try to open all vdevs, loading each label in the process.
+        * spa_missing_tvds_allowed defines how many top-level vdevs can be
+        * missing/unopenable for the root vdev to be still considered openable.
         */
+       if (spa->spa_trust_config) {
+               spa->spa_missing_tvds_allowed = zfs_max_missing_tvds;
+       } else if (spa->spa_config_source == SPA_CONFIG_SRC_CACHEFILE) {
+               spa->spa_missing_tvds_allowed = zfs_max_missing_tvds_cachefile;
+       } else if (spa->spa_config_source == SPA_CONFIG_SRC_SCAN) {
+               spa->spa_missing_tvds_allowed = zfs_max_missing_tvds_scan;
+       } else {
+               spa->spa_missing_tvds_allowed = 0;
+       }
+
+       spa->spa_missing_tvds_allowed =
+           MAX(zfs_max_missing_tvds, spa->spa_missing_tvds_allowed);
+
        spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
-       error = vdev_open(rvd);
+       error = vdev_open(spa->spa_root_vdev);
        spa_config_exit(spa, SCL_ALL, FTAG);
-       if (error != 0)
-               return (error);
 
-       /*
-        * We need to validate the vdev labels against the configuration that
-        * we have in hand, which is dependent on the setting of mosconfig. If
-        * mosconfig is true then we're validating the vdev labels based on
-        * that config.  Otherwise, we're validating against the cached config
-        * (zpool.cache) that was read when we loaded the zfs module, and then
-        * later we will recursively call spa_load() and validate against
-        * the vdev config.
-        *
-        * If we're assembling a new pool that's been split off from an
-        * existing pool, the labels haven't yet been updated so we skip
-        * validation for now.
-        */
-       if (type != SPA_IMPORT_ASSEMBLE) {
-               spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
-               error = vdev_validate(rvd, mosconfig);
-               spa_config_exit(spa, SCL_ALL, FTAG);
+       if (spa->spa_missing_tvds != 0) {
+               spa_load_note(spa, "vdev tree has %lld missing top-level "
+                   "vdevs.", (u_longlong_t)spa->spa_missing_tvds);
+               if (spa->spa_trust_config && (spa->spa_mode & FWRITE)) {
+                       /*
+                        * Although theoretically we could allow users to open
+                        * incomplete pools in RW mode, we'd need to add a lot
+                        * of extra logic (e.g. adjust pool space to account
+                        * for missing vdevs).
+                        * This limitation also prevents users from accidentally
+                        * opening the pool in RW mode during data recovery and
+                        * damaging it further.
+                        */
+                       spa_load_note(spa, "pools with missing top-level "
+                           "vdevs can only be opened in read-only mode.");
+                       error = SET_ERROR(ENXIO);
+               } else {
+                       spa_load_note(spa, "current settings allow for maximum "
+                           "%lld missing top-level vdevs at this stage.",
+                           (u_longlong_t)spa->spa_missing_tvds_allowed);
+               }
+       }
+       if (error != 0) {
+               spa_load_failed(spa, "unable to open vdev tree [error=%d]",
+                   error);
+       }
+       if (spa->spa_missing_tvds != 0 || error != 0)
+               vdev_dbgmsg_print_tree(spa->spa_root_vdev, 2);
 
-               if (error != 0)
-                       return (error);
+       return (error);
+}
 
-               if (rvd->vdev_state <= VDEV_STATE_CANT_OPEN)
-                       return (SET_ERROR(ENXIO));
+/*
+ * We need to validate the vdev labels against the configuration that
+ * we have in hand. This function is called twice: first with an untrusted
+ * config, then with a trusted config. The validation is more strict when the
+ * config is trusted.
+ */
+static int
+spa_ld_validate_vdevs(spa_t *spa)
+{
+       int error = 0;
+       vdev_t *rvd = spa->spa_root_vdev;
+
+       spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
+       error = vdev_validate(rvd);
+       spa_config_exit(spa, SCL_ALL, FTAG);
+
+       if (error != 0) {
+               spa_load_failed(spa, "vdev_validate failed [error=%d]", error);
+               return (error);
+       }
+
+       if (rvd->vdev_state <= VDEV_STATE_CANT_OPEN) {
+               spa_load_failed(spa, "cannot open vdev tree after invalidating "
+                   "some vdevs");
+               vdev_dbgmsg_print_tree(rvd, 2);
+               return (SET_ERROR(ENXIO));
        }
 
+       return (0);
+}
+
+static int
+spa_ld_select_uberblock(spa_t *spa, spa_import_type_t type)
+{
+       vdev_t *rvd = spa->spa_root_vdev;
+       nvlist_t *label;
+       uberblock_t *ub = &spa->spa_uberblock;
+       boolean_t activity_check = B_FALSE;
+
        /*
         * Find the best uberblock.
         */
@@ -2384,14 +2791,49 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
         */
        if (ub->ub_txg == 0) {
                nvlist_free(label);
+               spa_load_failed(spa, "no valid uberblock found");
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, ENXIO));
        }
 
+       spa_load_note(spa, "using uberblock with txg=%llu",
+           (u_longlong_t)ub->ub_txg);
+
+
+       /*
+        * For pools which have the multihost property on determine if the
+        * pool is truly inactive and can be safely imported.  Prevent
+        * hosts which don't have a hostid set from importing the pool.
+        */
+       activity_check = spa_activity_check_required(spa, ub, label,
+           spa->spa_config);
+       if (activity_check) {
+               if (ub->ub_mmp_magic == MMP_MAGIC && ub->ub_mmp_delay &&
+                   spa_get_hostid() == 0) {
+                       nvlist_free(label);
+                       fnvlist_add_uint64(spa->spa_load_info,
+                           ZPOOL_CONFIG_MMP_STATE, MMP_STATE_NO_HOSTID);
+                       return (spa_vdev_err(rvd, VDEV_AUX_ACTIVE, EREMOTEIO));
+               }
+
+               int error = spa_activity_check(spa, ub, spa->spa_config);
+               if (error) {
+                       nvlist_free(label);
+                       return (error);
+               }
+
+               fnvlist_add_uint64(spa->spa_load_info,
+                   ZPOOL_CONFIG_MMP_STATE, MMP_STATE_INACTIVE);
+               fnvlist_add_uint64(spa->spa_load_info,
+                   ZPOOL_CONFIG_MMP_TXG, ub->ub_txg);
+       }
+
        /*
         * If the pool has an unsupported version we can't open it.
         */
        if (!SPA_VERSION_IS_SUPPORTED(ub->ub_version)) {
                nvlist_free(label);
+               spa_load_failed(spa, "version %llu is not supported",
+                   (u_longlong_t)ub->ub_version);
                return (spa_vdev_err(rvd, VDEV_AUX_VERSION_NEWER, ENOTSUP));
        }
 
@@ -2402,9 +2844,17 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
                 * If we weren't able to find what's necessary for reading the
                 * MOS in the label, return failure.
                 */
-               if (label == NULL || nvlist_lookup_nvlist(label,
-                   ZPOOL_CONFIG_FEATURES_FOR_READ, &features) != 0) {
+               if (label == NULL) {
+                       spa_load_failed(spa, "label config unavailable");
+                       return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA,
+                           ENXIO));
+               }
+
+               if (nvlist_lookup_nvlist(label, ZPOOL_CONFIG_FEATURES_FOR_READ,
+                   &features) != 0) {
                        nvlist_free(label);
+                       spa_load_failed(spa, "invalid label: '%s' missing",
+                           ZPOOL_CONFIG_FEATURES_FOR_READ);
                        return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA,
                            ENXIO));
                }
@@ -2426,13 +2876,12 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
         */
        if (ub->ub_version >= SPA_VERSION_FEATURES) {
                nvlist_t *unsup_feat;
-               nvpair_t *nvp;
 
                VERIFY(nvlist_alloc(&unsup_feat, NV_UNIQUE_NAME, KM_SLEEP) ==
                    0);
 
-               for (nvp = nvlist_next_nvpair(spa->spa_label_features, NULL);
-                   nvp != NULL;
+               for (nvpair_t *nvp = nvlist_next_nvpair(spa->spa_label_features,
+                   NULL); nvp != NULL;
                    nvp = nvlist_next_nvpair(spa->spa_label_features, nvp)) {
                        if (!zfeature_is_supported(nvpair_name(nvp))) {
                                VERIFY(nvlist_add_string(unsup_feat,
@@ -2444,6 +2893,7 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
                        VERIFY(nvlist_add_nvlist(spa->spa_load_info,
                            ZPOOL_CONFIG_UNSUP_FEAT, unsup_feat) == 0);
                        nvlist_free(unsup_feat);
+                       spa_load_failed(spa, "some features are unsupported");
                        return (spa_vdev_err(rvd, VDEV_AUX_UNSUP_FEAT,
                            ENOTSUP));
                }
@@ -2451,63 +2901,263 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
                nvlist_free(unsup_feat);
        }
 
-       /*
-        * If the vdev guid sum doesn't match the uberblock, we have an
-        * incomplete configuration.  We first check to see if the pool
-        * is aware of the complete config (i.e ZPOOL_CONFIG_VDEV_CHILDREN).
-        * If it is, defer the vdev_guid_sum check till later so we
-        * can handle missing vdevs.
-        */
-       if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_VDEV_CHILDREN,
-           &children) != 0 && mosconfig && type != SPA_IMPORT_ASSEMBLE &&
-           rvd->vdev_guid_sum != ub->ub_guid_sum)
-               return (spa_vdev_err(rvd, VDEV_AUX_BAD_GUID_SUM, ENXIO));
-
        if (type != SPA_IMPORT_ASSEMBLE && spa->spa_config_splitting) {
                spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
-               spa_try_repair(spa, config);
+               spa_try_repair(spa, spa->spa_config);
                spa_config_exit(spa, SCL_ALL, FTAG);
                nvlist_free(spa->spa_config_splitting);
                spa->spa_config_splitting = NULL;
        }
 
        /*
-        * Initialize internal SPA structures.
+        * Initialize internal SPA structures.
+        */
+       spa->spa_state = POOL_STATE_ACTIVE;
+       spa->spa_ubsync = spa->spa_uberblock;
+       spa->spa_verify_min_txg = spa->spa_extreme_rewind ?
+           TXG_INITIAL - 1 : spa_last_synced_txg(spa) - TXG_DEFER_SIZE - 1;
+       spa->spa_first_txg = spa->spa_last_ubsync_txg ?
+           spa->spa_last_ubsync_txg : spa_last_synced_txg(spa) + 1;
+       spa->spa_claim_max_txg = spa->spa_first_txg;
+       spa->spa_prev_software_version = ub->ub_software_version;
+
+       return (0);
+}
+
+static int
+spa_ld_open_rootbp(spa_t *spa)
+{
+       int error = 0;
+       vdev_t *rvd = spa->spa_root_vdev;
+
+       error = dsl_pool_init(spa, spa->spa_first_txg, &spa->spa_dsl_pool);
+       if (error != 0) {
+               spa_load_failed(spa, "unable to open rootbp in dsl_pool_init "
+                   "[error=%d]", error);
+               return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+       }
+       spa->spa_meta_objset = spa->spa_dsl_pool->dp_meta_objset;
+
+       return (0);
+}
+
+static int
+spa_ld_load_trusted_config(spa_t *spa, spa_import_type_t type,
+    boolean_t reloading)
+{
+       vdev_t *mrvd, *rvd = spa->spa_root_vdev;
+       nvlist_t *nv, *mos_config, *policy;
+       int error = 0, copy_error;
+       uint64_t healthy_tvds, healthy_tvds_mos;
+       uint64_t mos_config_txg;
+
+       if (spa_dir_prop(spa, DMU_POOL_CONFIG, &spa->spa_config_object, B_TRUE)
+           != 0)
+               return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+
+       /*
+        * If we're assembling a pool from a split, the config provided is
+        * already trusted so there is nothing to do.
+        */
+       if (type == SPA_IMPORT_ASSEMBLE)
+               return (0);
+
+       healthy_tvds = spa_healthy_core_tvds(spa);
+
+       if (load_nvlist(spa, spa->spa_config_object, &mos_config)
+           != 0) {
+               spa_load_failed(spa, "unable to retrieve MOS config");
+               return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+       }
+
+       /*
+        * If we are doing an open, pool owner wasn't verified yet, thus do
+        * the verification here.
+        */
+       if (spa->spa_load_state == SPA_LOAD_OPEN) {
+               error = spa_verify_host(spa, mos_config);
+               if (error != 0) {
+                       nvlist_free(mos_config);
+                       return (error);
+               }
+       }
+
+       nv = fnvlist_lookup_nvlist(mos_config, ZPOOL_CONFIG_VDEV_TREE);
+
+       spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
+
+       /*
+        * Build a new vdev tree from the trusted config
+        */
+       VERIFY(spa_config_parse(spa, &mrvd, nv, NULL, 0, VDEV_ALLOC_LOAD) == 0);
+
+       /*
+        * Vdev paths in the MOS may be obsolete. If the untrusted config was
+        * obtained by scanning /dev/dsk, then it will have the right vdev
+        * paths. We update the trusted MOS config with this information.
+        * We first try to copy the paths with vdev_copy_path_strict, which
+        * succeeds only when both configs have exactly the same vdev tree.
+        * If that fails, we fall back to a more flexible method that has a
+        * best effort policy.
+        */
+       copy_error = vdev_copy_path_strict(rvd, mrvd);
+       if (copy_error != 0 || spa_load_print_vdev_tree) {
+               spa_load_note(spa, "provided vdev tree:");
+               vdev_dbgmsg_print_tree(rvd, 2);
+               spa_load_note(spa, "MOS vdev tree:");
+               vdev_dbgmsg_print_tree(mrvd, 2);
+       }
+       if (copy_error != 0) {
+               spa_load_note(spa, "vdev_copy_path_strict failed, falling "
+                   "back to vdev_copy_path_relaxed");
+               vdev_copy_path_relaxed(rvd, mrvd);
+       }
+
+       vdev_close(rvd);
+       vdev_free(rvd);
+       spa->spa_root_vdev = mrvd;
+       rvd = mrvd;
+       spa_config_exit(spa, SCL_ALL, FTAG);
+
+       /*
+        * We will use spa_config if we decide to reload the spa or if spa_load
+        * fails and we rewind. We must thus regenerate the config using the
+        * MOS information with the updated paths. Rewind policy is an import
+        * setting and is not in the MOS. We copy it over to our new, trusted
+        * config.
+        */
+       mos_config_txg = fnvlist_lookup_uint64(mos_config,
+           ZPOOL_CONFIG_POOL_TXG);
+       nvlist_free(mos_config);
+       mos_config = spa_config_generate(spa, NULL, mos_config_txg, B_FALSE);
+       if (nvlist_lookup_nvlist(spa->spa_config, ZPOOL_REWIND_POLICY,
+           &policy) == 0)
+               fnvlist_add_nvlist(mos_config, ZPOOL_REWIND_POLICY, policy);
+       spa_config_set(spa, mos_config);
+       spa->spa_config_source = SPA_CONFIG_SRC_MOS;
+
+       /*
+        * Now that we got the config from the MOS, we should be more strict
+        * in checking blkptrs and can make assumptions about the consistency
+        * of the vdev tree. spa_trust_config must be set to true before opening
+        * vdevs in order for them to be writeable.
+        */
+       spa->spa_trust_config = B_TRUE;
+
+       /*
+        * Open and validate the new vdev tree
+        */
+       error = spa_ld_open_vdevs(spa);
+       if (error != 0)
+               return (error);
+
+       error = spa_ld_validate_vdevs(spa);
+       if (error != 0)
+               return (error);
+
+       if (copy_error != 0 || spa_load_print_vdev_tree) {
+               spa_load_note(spa, "final vdev tree:");
+               vdev_dbgmsg_print_tree(rvd, 2);
+       }
+
+       if (spa->spa_load_state != SPA_LOAD_TRYIMPORT &&
+           !spa->spa_extreme_rewind && zfs_max_missing_tvds == 0) {
+               /*
+                * Sanity check to make sure that we are indeed loading the
+                * latest uberblock. If we missed SPA_SYNC_MIN_VDEVS tvds
+                * in the config provided and they happened to be the only ones
+                * to have the latest uberblock, we could involuntarily perform
+                * an extreme rewind.
+                */
+               healthy_tvds_mos = spa_healthy_core_tvds(spa);
+               if (healthy_tvds_mos - healthy_tvds >=
+                   SPA_SYNC_MIN_VDEVS) {
+                       spa_load_note(spa, "config provided misses too many "
+                           "top-level vdevs compared to MOS (%lld vs %lld). ",
+                           (u_longlong_t)healthy_tvds,
+                           (u_longlong_t)healthy_tvds_mos);
+                       spa_load_note(spa, "vdev tree:");
+                       vdev_dbgmsg_print_tree(rvd, 2);
+                       if (reloading) {
+                               spa_load_failed(spa, "config was already "
+                                   "provided from MOS. Aborting.");
+                               return (spa_vdev_err(rvd,
+                                   VDEV_AUX_CORRUPT_DATA, EIO));
+                       }
+                       spa_load_note(spa, "spa must be reloaded using MOS "
+                           "config");
+                       return (SET_ERROR(EAGAIN));
+               }
+       }
+
+       error = spa_check_for_missing_logs(spa);
+       if (error != 0)
+               return (spa_vdev_err(rvd, VDEV_AUX_BAD_GUID_SUM, ENXIO));
+
+       if (rvd->vdev_guid_sum != spa->spa_uberblock.ub_guid_sum) {
+               spa_load_failed(spa, "uberblock guid sum doesn't match MOS "
+                   "guid sum (%llu != %llu)",
+                   (u_longlong_t)spa->spa_uberblock.ub_guid_sum,
+                   (u_longlong_t)rvd->vdev_guid_sum);
+               return (spa_vdev_err(rvd, VDEV_AUX_BAD_GUID_SUM,
+                   ENXIO));
+       }
+
+       return (0);
+}
+
+static int
+spa_ld_open_indirect_vdev_metadata(spa_t *spa)
+{
+       int error = 0;
+       vdev_t *rvd = spa->spa_root_vdev;
+
+       /*
+        * Everything that we read before spa_remove_init() must be stored
+        * on concreted vdevs.  Therefore we do this as early as possible.
+        */
+       error = spa_remove_init(spa);
+       if (error != 0) {
+               spa_load_failed(spa, "spa_remove_init failed [error=%d]",
+                   error);
+               return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+       }
+
+       /*
+        * Retrieve information needed to condense indirect vdev mappings.
         */
-       spa->spa_state = POOL_STATE_ACTIVE;
-       spa->spa_ubsync = spa->spa_uberblock;
-       spa->spa_verify_min_txg = spa->spa_extreme_rewind ?
-           TXG_INITIAL - 1 : spa_last_synced_txg(spa) - TXG_DEFER_SIZE - 1;
-       spa->spa_first_txg = spa->spa_last_ubsync_txg ?
-           spa->spa_last_ubsync_txg : spa_last_synced_txg(spa) + 1;
-       spa->spa_claim_max_txg = spa->spa_first_txg;
-       spa->spa_prev_software_version = ub->ub_software_version;
+       error = spa_condense_init(spa);
+       if (error != 0) {
+               spa_load_failed(spa, "spa_condense_init failed [error=%d]",
+                   error);
+               return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, error));
+       }
 
-       error = dsl_pool_init(spa, spa->spa_first_txg, &spa->spa_dsl_pool);
-       if (error)
-               return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
-       spa->spa_meta_objset = spa->spa_dsl_pool->dp_meta_objset;
+       return (0);
+}
 
-       if (spa_dir_prop(spa, DMU_POOL_CONFIG, &spa->spa_config_object) != 0)
-               return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+static int
+spa_ld_check_features(spa_t *spa, boolean_t *missing_feat_writep)
+{
+       int error = 0;
+       vdev_t *rvd = spa->spa_root_vdev;
 
        if (spa_version(spa) >= SPA_VERSION_FEATURES) {
                boolean_t missing_feat_read = B_FALSE;
                nvlist_t *unsup_feat, *enabled_feat;
-               spa_feature_t i;
 
                if (spa_dir_prop(spa, DMU_POOL_FEATURES_FOR_READ,
-                   &spa->spa_feat_for_read_obj) != 0) {
+                   &spa->spa_feat_for_read_obj, B_TRUE) != 0) {
                        return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
                }
 
                if (spa_dir_prop(spa, DMU_POOL_FEATURES_FOR_WRITE,
-                   &spa->spa_feat_for_write_obj) != 0) {
+                   &spa->spa_feat_for_write_obj, B_TRUE) != 0) {
                        return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
                }
 
                if (spa_dir_prop(spa, DMU_POOL_FEATURE_DESCRIPTIONS,
-                   &spa->spa_feat_desc_obj) != 0) {
+                   &spa->spa_feat_desc_obj, B_TRUE) != 0) {
                        return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
                }
 
@@ -2518,10 +3168,11 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
                    unsup_feat, enabled_feat))
                        missing_feat_read = B_TRUE;
 
-               if (spa_writeable(spa) || state == SPA_LOAD_TRYIMPORT) {
+               if (spa_writeable(spa) ||
+                   spa->spa_load_state == SPA_LOAD_TRYIMPORT) {
                        if (!spa_features_check(spa, B_TRUE,
                            unsup_feat, enabled_feat)) {
-                               missing_feat_write = B_TRUE;
+                               *missing_feat_writep = B_TRUE;
                        }
                }
 
@@ -2560,8 +3211,9 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
                 * userland in order to know whether to display the
                 * abovementioned note.
                 */
-               if (missing_feat_read || (missing_feat_write &&
+               if (missing_feat_read || (*missing_feat_writep &&
                    spa_writeable(spa))) {
+                       spa_load_failed(spa, "pool uses unsupported features");
                        return (spa_vdev_err(rvd, VDEV_AUX_UNSUP_FEAT,
                            ENOTSUP));
                }
@@ -2570,7 +3222,7 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
                 * Load refcounts for ZFS features from disk into an in-memory
                 * cache during SPA initialization.
                 */
-               for (i = 0; i < SPA_FEATURES; i++) {
+               for (spa_feature_t i = 0; i < SPA_FEATURES; i++) {
                        uint64_t refcount;
 
                        error = feature_get_refcount_from_disk(spa,
@@ -2581,6 +3233,9 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
                                spa->spa_feat_refcount_cache[i] =
                                    SPA_FEATURE_DISABLED;
                        } else {
+                               spa_load_failed(spa, "error getting refcount "
+                                   "for feature %s [error=%d]",
+                                   spa_feature_table[i].fi_guid, error);
                                return (spa_vdev_err(rvd,
                                    VDEV_AUX_CORRUPT_DATA, EIO));
                        }
@@ -2589,82 +3244,72 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
 
        if (spa_feature_is_active(spa, SPA_FEATURE_ENABLED_TXG)) {
                if (spa_dir_prop(spa, DMU_POOL_FEATURE_ENABLED_TXG,
-                   &spa->spa_feat_enabled_txg_obj) != 0)
+                   &spa->spa_feat_enabled_txg_obj, B_TRUE) != 0)
                        return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
        }
 
+       return (0);
+}
+
+static int
+spa_ld_load_special_directories(spa_t *spa)
+{
+       int error = 0;
+       vdev_t *rvd = spa->spa_root_vdev;
+
        spa->spa_is_initializing = B_TRUE;
        error = dsl_pool_open(spa->spa_dsl_pool);
        spa->spa_is_initializing = B_FALSE;
-       if (error != 0)
+       if (error != 0) {
+               spa_load_failed(spa, "dsl_pool_open failed [error=%d]", error);
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+       }
 
-       if (!mosconfig) {
-               uint64_t hostid;
-               nvlist_t *policy = NULL, *nvconfig;
-
-               if (load_nvlist(spa, spa->spa_config_object, &nvconfig) != 0)
-                       return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
-
-               if (!spa_is_root(spa) && nvlist_lookup_uint64(nvconfig,
-                   ZPOOL_CONFIG_HOSTID, &hostid) == 0) {
-                       char *hostname;
-                       unsigned long myhostid = 0;
-
-                       VERIFY(nvlist_lookup_string(nvconfig,
-                           ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
-
-#ifdef _KERNEL
-                       myhostid = zone_get_hostid(NULL);
-#else  /* _KERNEL */
-                       /*
-                        * We're emulating the system's hostid in userland, so
-                        * we can't use zone_get_hostid().
-                        */
-                       (void) ddi_strtoul(hw_serial, NULL, 10, &myhostid);
-#endif /* _KERNEL */
-                       if (hostid != 0 && myhostid != 0 &&
-                           hostid != myhostid) {
-                               nvlist_free(nvconfig);
-                               cmn_err(CE_WARN, "pool '%s' could not be "
-                                   "loaded as it was last accessed by another "
-                                   "system (host: %s hostid: 0x%lx). See: "
-                                   "http://zfsonlinux.org/msg/ZFS-8000-EY",
-                                   spa_name(spa), hostname,
-                                   (unsigned long)hostid);
-                               return (SET_ERROR(EBADF));
-                       }
-               }
-               if (nvlist_lookup_nvlist(spa->spa_config,
-                   ZPOOL_REWIND_POLICY, &policy) == 0)
-                       VERIFY(nvlist_add_nvlist(nvconfig,
-                           ZPOOL_REWIND_POLICY, policy) == 0);
+       return (0);
+}
 
-               spa_config_set(spa, nvconfig);
-               spa_unload(spa);
-               spa_deactivate(spa);
-               spa_activate(spa, orig_mode);
+static int
+spa_ld_get_props(spa_t *spa)
+{
+       int error = 0;
+       uint64_t obj;
+       vdev_t *rvd = spa->spa_root_vdev;
 
-               return (spa_load(spa, state, SPA_IMPORT_EXISTING, B_TRUE));
+       /* Grab the checksum salt from the MOS. */
+       error = zap_lookup(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
+           DMU_POOL_CHECKSUM_SALT, 1,
+           sizeof (spa->spa_cksum_salt.zcs_bytes),
+           spa->spa_cksum_salt.zcs_bytes);
+       if (error == ENOENT) {
+               /* Generate a new salt for subsequent use */
+               (void) random_get_pseudo_bytes(spa->spa_cksum_salt.zcs_bytes,
+                   sizeof (spa->spa_cksum_salt.zcs_bytes));
+       } else if (error != 0) {
+               spa_load_failed(spa, "unable to retrieve checksum salt from "
+                   "MOS [error=%d]", error);
+               return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
        }
 
-       if (spa_dir_prop(spa, DMU_POOL_SYNC_BPOBJ, &obj) != 0)
+       if (spa_dir_prop(spa, DMU_POOL_SYNC_BPOBJ, &obj, B_TRUE) != 0)
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
        error = bpobj_open(&spa->spa_deferred_bpobj, spa->spa_meta_objset, obj);
-       if (error != 0)
+       if (error != 0) {
+               spa_load_failed(spa, "error opening deferred-frees bpobj "
+                   "[error=%d]", error);
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+       }
 
        /*
         * Load the bit that tells us to use the new accounting function
         * (raid-z deflation).  If we have an older pool, this will not
         * be present.
         */
-       error = spa_dir_prop(spa, DMU_POOL_DEFLATE, &spa->spa_deflate);
+       error = spa_dir_prop(spa, DMU_POOL_DEFLATE, &spa->spa_deflate, B_FALSE);
        if (error != 0 && error != ENOENT)
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
 
        error = spa_dir_prop(spa, DMU_POOL_CREATION_VERSION,
-           &spa->spa_creation_version);
+           &spa->spa_creation_version, B_FALSE);
        if (error != 0 && error != ENOENT)
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
 
@@ -2672,12 +3317,13 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
         * Load the persistent error log.  If we have an older pool, this will
         * not be present.
         */
-       error = spa_dir_prop(spa, DMU_POOL_ERRLOG_LAST, &spa->spa_errlog_last);
+       error = spa_dir_prop(spa, DMU_POOL_ERRLOG_LAST, &spa->spa_errlog_last,
+           B_FALSE);
        if (error != 0 && error != ENOENT)
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
 
        error = spa_dir_prop(spa, DMU_POOL_ERRLOG_SCRUB,
-           &spa->spa_errlog_scrub);
+           &spa->spa_errlog_scrub, B_FALSE);
        if (error != 0 && error != ENOENT)
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
 
@@ -2685,7 +3331,7 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
         * Load the history object.  If we have an older pool, this
         * will not be present.
         */
-       error = spa_dir_prop(spa, DMU_POOL_HISTORY, &spa->spa_history);
+       error = spa_dir_prop(spa, DMU_POOL_HISTORY, &spa->spa_history, B_FALSE);
        if (error != 0 && error != ENOENT)
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
 
@@ -2697,16 +3343,23 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
         */
 
        /* The sentinel is only available in the MOS config. */
-       if (load_nvlist(spa, spa->spa_config_object, &mos_config) != 0)
+       nvlist_t *mos_config;
+       if (load_nvlist(spa, spa->spa_config_object, &mos_config) != 0) {
+               spa_load_failed(spa, "unable to retrieve MOS config");
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+       }
 
        error = spa_dir_prop(spa, DMU_POOL_VDEV_ZAP_MAP,
-           &spa->spa_all_vdev_zaps);
+           &spa->spa_all_vdev_zaps, B_FALSE);
 
-       if (error != ENOENT && error != 0) {
+       if (error == ENOENT) {
+               VERIFY(!nvlist_exists(mos_config,
+                   ZPOOL_CONFIG_HAS_PER_VDEV_ZAPS));
+               spa->spa_avz_action = AVZ_ACTION_INITIALIZE;
+               ASSERT0(vdev_count_verify_zaps(spa->spa_root_vdev));
+       } else if (error != 0) {
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
-       } else if (error == 0 && !nvlist_exists(mos_config,
-           ZPOOL_CONFIG_HAS_PER_VDEV_ZAPS)) {
+       } else if (!nvlist_exists(mos_config, ZPOOL_CONFIG_HAS_PER_VDEV_ZAPS)) {
                /*
                 * An older version of ZFS overwrote the sentinel value, so
                 * we have orphaned per-vdev ZAPs in the MOS. Defer their
@@ -2721,6 +3374,50 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
        }
        nvlist_free(mos_config);
 
+       spa->spa_delegation = zpool_prop_default_numeric(ZPOOL_PROP_DELEGATION);
+
+       error = spa_dir_prop(spa, DMU_POOL_PROPS, &spa->spa_pool_props_object,
+           B_FALSE);
+       if (error && error != ENOENT)
+               return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+
+       if (error == 0) {
+               uint64_t autoreplace;
+
+               spa_prop_find(spa, ZPOOL_PROP_BOOTFS, &spa->spa_bootfs);
+               spa_prop_find(spa, ZPOOL_PROP_AUTOREPLACE, &autoreplace);
+               spa_prop_find(spa, ZPOOL_PROP_DELEGATION, &spa->spa_delegation);
+               spa_prop_find(spa, ZPOOL_PROP_FAILUREMODE, &spa->spa_failmode);
+               spa_prop_find(spa, ZPOOL_PROP_AUTOEXPAND, &spa->spa_autoexpand);
+               spa_prop_find(spa, ZPOOL_PROP_MULTIHOST, &spa->spa_multihost);
+               spa_prop_find(spa, ZPOOL_PROP_DEDUPDITTO,
+                   &spa->spa_dedup_ditto);
+
+               spa->spa_autoreplace = (autoreplace != 0);
+       }
+
+       /*
+        * If we are importing a pool with missing top-level vdevs,
+        * we enforce that the pool doesn't panic or get suspended on
+        * error since the likelihood of missing data is extremely high.
+        */
+       if (spa->spa_missing_tvds > 0 &&
+           spa->spa_failmode != ZIO_FAILURE_MODE_CONTINUE &&
+           spa->spa_load_state != SPA_LOAD_TRYIMPORT) {
+               spa_load_note(spa, "forcing failmode to 'continue' "
+                   "as some top level vdevs are missing");
+               spa->spa_failmode = ZIO_FAILURE_MODE_CONTINUE;
+       }
+
+       return (0);
+}
+
+static int
+spa_ld_open_aux_vdevs(spa_t *spa, spa_import_type_t type)
+{
+       int error = 0;
+       vdev_t *rvd = spa->spa_root_vdev;
+
        /*
         * If we're assembling the pool from the split-off vdevs of
         * an existing pool, we don't want to attach the spares & cache
@@ -2730,14 +3427,17 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
        /*
         * Load any hot spares for this pool.
         */
-       error = spa_dir_prop(spa, DMU_POOL_SPARES, &spa->spa_spares.sav_object);
+       error = spa_dir_prop(spa, DMU_POOL_SPARES, &spa->spa_spares.sav_object,
+           B_FALSE);
        if (error != 0 && error != ENOENT)
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
        if (error == 0 && type != SPA_IMPORT_ASSEMBLE) {
                ASSERT(spa_version(spa) >= SPA_VERSION_SPARES);
                if (load_nvlist(spa, spa->spa_spares.sav_object,
-                   &spa->spa_spares.sav_config) != 0)
+                   &spa->spa_spares.sav_config) != 0) {
+                       spa_load_failed(spa, "error loading spares nvlist");
                        return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+               }
 
                spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
                spa_load_spares(spa);
@@ -2750,14 +3450,16 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
         * Load any level 2 ARC devices for this pool.
         */
        error = spa_dir_prop(spa, DMU_POOL_L2CACHE,
-           &spa->spa_l2cache.sav_object);
+           &spa->spa_l2cache.sav_object, B_FALSE);
        if (error != 0 && error != ENOENT)
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
        if (error == 0 && type != SPA_IMPORT_ASSEMBLE) {
                ASSERT(spa_version(spa) >= SPA_VERSION_L2CACHE);
                if (load_nvlist(spa, spa->spa_l2cache.sav_object,
-                   &spa->spa_l2cache.sav_config) != 0)
+                   &spa->spa_l2cache.sav_config) != 0) {
+                       spa_load_failed(spa, "error loading l2cache nvlist");
                        return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+               }
 
                spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
                spa_load_l2cache(spa);
@@ -2766,196 +3468,445 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
                spa->spa_l2cache.sav_sync = B_TRUE;
        }
 
-       spa->spa_delegation = zpool_prop_default_numeric(ZPOOL_PROP_DELEGATION);
+       return (0);
+}
 
-       error = spa_dir_prop(spa, DMU_POOL_PROPS, &spa->spa_pool_props_object);
-       if (error && error != ENOENT)
+static int
+spa_ld_load_vdev_metadata(spa_t *spa)
+{
+       int error = 0;
+       vdev_t *rvd = spa->spa_root_vdev;
+
+       /*
+        * If the 'multihost' property is set, then never allow a pool to
+        * be imported when the system hostid is zero.  The exception to
+        * this rule is zdb which is always allowed to access pools.
+        */
+       if (spa_multihost(spa) && spa_get_hostid() == 0 &&
+           (spa->spa_import_flags & ZFS_IMPORT_SKIP_MMP) == 0) {
+               fnvlist_add_uint64(spa->spa_load_info,
+                   ZPOOL_CONFIG_MMP_STATE, MMP_STATE_NO_HOSTID);
+               return (spa_vdev_err(rvd, VDEV_AUX_ACTIVE, EREMOTEIO));
+       }
+
+       /*
+        * If the 'autoreplace' property is set, then post a resource notifying
+        * the ZFS DE that it should not issue any faults for unopenable
+        * devices.  We also iterate over the vdevs, and post a sysevent for any
+        * unopenable vdevs so that the normal autoreplace handler can take
+        * over.
+        */
+       if (spa->spa_autoreplace && spa->spa_load_state != SPA_LOAD_TRYIMPORT) {
+               spa_check_removed(spa->spa_root_vdev);
+               /*
+                * For the import case, this is done in spa_import(), because
+                * at this point we're using the spare definitions from
+                * the MOS config, not necessarily from the userland config.
+                */
+               if (spa->spa_load_state != SPA_LOAD_IMPORT) {
+                       spa_aux_check_removed(&spa->spa_spares);
+                       spa_aux_check_removed(&spa->spa_l2cache);
+               }
+       }
+
+       /*
+        * Load the vdev metadata such as metaslabs, DTLs, spacemap object, etc.
+        */
+       error = vdev_load(rvd);
+       if (error != 0) {
+               spa_load_failed(spa, "vdev_load failed [error=%d]", error);
+               return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, error));
+       }
+
+       /*
+        * Propagate the leaf DTLs we just loaded all the way up the vdev tree.
+        */
+       spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
+       vdev_dtl_reassess(rvd, 0, 0, B_FALSE);
+       spa_config_exit(spa, SCL_ALL, FTAG);
+
+       return (0);
+}
+
+static int
+spa_ld_load_dedup_tables(spa_t *spa)
+{
+       int error = 0;
+       vdev_t *rvd = spa->spa_root_vdev;
+
+       error = ddt_load(spa);
+       if (error != 0) {
+               spa_load_failed(spa, "ddt_load failed [error=%d]", error);
                return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+       }
 
-       if (error == 0) {
-               uint64_t autoreplace = 0;
+       return (0);
+}
+
+static int
+spa_ld_verify_logs(spa_t *spa, spa_import_type_t type, char **ereport)
+{
+       vdev_t *rvd = spa->spa_root_vdev;
+
+       if (type != SPA_IMPORT_ASSEMBLE && spa_writeable(spa)) {
+               boolean_t missing = spa_check_logs(spa);
+               if (missing) {
+                       if (spa->spa_missing_tvds != 0) {
+                               spa_load_note(spa, "spa_check_logs failed "
+                                   "so dropping the logs");
+                       } else {
+                               *ereport = FM_EREPORT_ZFS_LOG_REPLAY;
+                               spa_load_failed(spa, "spa_check_logs failed");
+                               return (spa_vdev_err(rvd, VDEV_AUX_BAD_LOG,
+                                   ENXIO));
+                       }
+               }
+       }
+
+       return (0);
+}
+
+static int
+spa_ld_verify_pool_data(spa_t *spa)
+{
+       int error = 0;
+       vdev_t *rvd = spa->spa_root_vdev;
+
+       /*
+        * We've successfully opened the pool, verify that we're ready
+        * to start pushing transactions.
+        */
+       if (spa->spa_load_state != SPA_LOAD_TRYIMPORT) {
+               error = spa_load_verify(spa);
+               if (error != 0) {
+                       spa_load_failed(spa, "spa_load_verify failed "
+                           "[error=%d]", error);
+                       return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA,
+                           error));
+               }
+       }
+
+       return (0);
+}
+
+static void
+spa_ld_claim_log_blocks(spa_t *spa)
+{
+       dmu_tx_t *tx;
+       dsl_pool_t *dp = spa_get_dsl(spa);
+
+       /*
+        * Claim log blocks that haven't been committed yet.
+        * This must all happen in a single txg.
+        * Note: spa_claim_max_txg is updated by spa_claim_notify(),
+        * invoked from zil_claim_log_block()'s i/o done callback.
+        * Price of rollback is that we abandon the log.
+        */
+       spa->spa_claiming = B_TRUE;
+
+       tx = dmu_tx_create_assigned(dp, spa_first_txg(spa));
+       (void) dmu_objset_find_dp(dp, dp->dp_root_dir_obj,
+           zil_claim, tx, DS_FIND_CHILDREN);
+       dmu_tx_commit(tx);
+
+       spa->spa_claiming = B_FALSE;
+
+       spa_set_log_state(spa, SPA_LOG_GOOD);
+}
+
+static void
+spa_ld_check_for_config_update(spa_t *spa, uint64_t config_cache_txg,
+    boolean_t reloading)
+{
+       vdev_t *rvd = spa->spa_root_vdev;
+       int need_update = B_FALSE;
+
+       /*
+        * If the config cache is stale, or we have uninitialized
+        * metaslabs (see spa_vdev_add()), then update the config.
+        *
+        * If this is a verbatim import, trust the current
+        * in-core spa_config and update the disk labels.
+        */
+       if (reloading || config_cache_txg != spa->spa_config_txg ||
+           spa->spa_load_state == SPA_LOAD_IMPORT ||
+           spa->spa_load_state == SPA_LOAD_RECOVER ||
+           (spa->spa_import_flags & ZFS_IMPORT_VERBATIM))
+               need_update = B_TRUE;
+
+       for (int c = 0; c < rvd->vdev_children; c++)
+               if (rvd->vdev_child[c]->vdev_ms_array == 0)
+                       need_update = B_TRUE;
+
+       /*
+        * Update the config cache asychronously in case we're the
+        * root pool, in which case the config cache isn't writable yet.
+        */
+       if (need_update)
+               spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE);
+}
+
+static void
+spa_ld_prepare_for_reload(spa_t *spa)
+{
+       int mode = spa->spa_mode;
+       int async_suspended = spa->spa_async_suspended;
+
+       spa_unload(spa);
+       spa_deactivate(spa);
+       spa_activate(spa, mode);
+
+       /*
+        * We save the value of spa_async_suspended as it gets reset to 0 by
+        * spa_unload(). We want to restore it back to the original value before
+        * returning as we might be calling spa_async_resume() later.
+        */
+       spa->spa_async_suspended = async_suspended;
+}
+
+/*
+ * Load an existing storage pool, using the config provided. This config
+ * describes which vdevs are part of the pool and is later validated against
+ * partial configs present in each vdev's label and an entire copy of the
+ * config stored in the MOS.
+ */
+static int
+spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport,
+    boolean_t reloading)
+{
+       int error = 0;
+       boolean_t missing_feat_write = B_FALSE;
+
+       ASSERT(MUTEX_HELD(&spa_namespace_lock));
+       ASSERT(spa->spa_config_source != SPA_CONFIG_SRC_NONE);
+
+       /*
+        * Never trust the config that is provided unless we are assembling
+        * a pool following a split.
+        * This means don't trust blkptrs and the vdev tree in general. This
+        * also effectively puts the spa in read-only mode since
+        * spa_writeable() checks for spa_trust_config to be true.
+        * We will later load a trusted config from the MOS.
+        */
+       if (type != SPA_IMPORT_ASSEMBLE)
+               spa->spa_trust_config = B_FALSE;
+
+       if (reloading)
+               spa_load_note(spa, "RELOADING");
+       else
+               spa_load_note(spa, "LOADING");
+
+       /*
+        * Parse the config provided to create a vdev tree.
+        */
+       error = spa_ld_parse_config(spa, type);
+       if (error != 0)
+               return (error);
+
+       /*
+        * Now that we have the vdev tree, try to open each vdev. This involves
+        * opening the underlying physical device, retrieving its geometry and
+        * probing the vdev with a dummy I/O. The state of each vdev will be set
+        * based on the success of those operations. After this we'll be ready
+        * to read from the vdevs.
+        */
+       error = spa_ld_open_vdevs(spa);
+       if (error != 0)
+               return (error);
+
+       /*
+        * Read the label of each vdev and make sure that the GUIDs stored
+        * there match the GUIDs in the config provided.
+        * If we're assembling a new pool that's been split off from an
+        * existing pool, the labels haven't yet been updated so we skip
+        * validation for now.
+        */
+       if (type != SPA_IMPORT_ASSEMBLE) {
+               error = spa_ld_validate_vdevs(spa);
+               if (error != 0)
+                       return (error);
+       }
 
-               spa_prop_find(spa, ZPOOL_PROP_BOOTFS, &spa->spa_bootfs);
-               spa_prop_find(spa, ZPOOL_PROP_AUTOREPLACE, &autoreplace);
-               spa_prop_find(spa, ZPOOL_PROP_DELEGATION, &spa->spa_delegation);
-               spa_prop_find(spa, ZPOOL_PROP_FAILUREMODE, &spa->spa_failmode);
-               spa_prop_find(spa, ZPOOL_PROP_AUTOEXPAND, &spa->spa_autoexpand);
-               spa_prop_find(spa, ZPOOL_PROP_DEDUPDITTO,
-                   &spa->spa_dedup_ditto);
+       /*
+        * Read vdev labels to find the best uberblock (i.e. latest, unless
+        * spa_load_max_txg is set) and store it in spa_uberblock. We get the
+        * list of features required to read blkptrs in the MOS from the vdev
+        * label with the best uberblock and verify that our version of zfs
+        * supports them all.
+        */
+       error = spa_ld_select_uberblock(spa, type);
+       if (error != 0)
+               return (error);
 
-               spa->spa_autoreplace = (autoreplace != 0);
-       }
+       /*
+        * Pass that uberblock to the dsl_pool layer which will open the root
+        * blkptr. This blkptr points to the latest version of the MOS and will
+        * allow us to read its contents.
+        */
+       error = spa_ld_open_rootbp(spa);
+       if (error != 0)
+               return (error);
 
        /*
-        * If the 'autoreplace' property is set, then post a resource notifying
-        * the ZFS DE that it should not issue any faults for unopenable
-        * devices.  We also iterate over the vdevs, and post a sysevent for any
-        * unopenable vdevs so that the normal autoreplace handler can take
-        * over.
+        * Retrieve the trusted config stored in the MOS and use it to create
+        * a new, exact version of the vdev tree, then reopen all vdevs.
         */
-       if (spa->spa_autoreplace && state != SPA_LOAD_TRYIMPORT) {
-               spa_check_removed(spa->spa_root_vdev);
+       error = spa_ld_load_trusted_config(spa, type, reloading);
+       if (error == EAGAIN) {
+               VERIFY(!reloading);
                /*
-                * For the import case, this is done in spa_import(), because
-                * at this point we're using the spare definitions from
-                * the MOS config, not necessarily from the userland config.
+                * Redo the loading process with the trusted config if it is
+                * too different from the untrusted config.
                 */
-               if (state != SPA_LOAD_IMPORT) {
-                       spa_aux_check_removed(&spa->spa_spares);
-                       spa_aux_check_removed(&spa->spa_l2cache);
-               }
+               spa_ld_prepare_for_reload(spa);
+               return (spa_load_impl(spa, type, ereport, B_TRUE));
+       } else if (error != 0) {
+               return (error);
        }
 
        /*
-        * Load the vdev state for all toplevel vdevs.
+        * Retrieve the mapping of indirect vdevs. Those vdevs were removed
+        * from the pool and their contents were re-mapped to other vdevs. Note
+        * that everything that we read before this step must have been
+        * rewritten on concrete vdevs after the last device removal was
+        * initiated. Otherwise we could be reading from indirect vdevs before
+        * we have loaded their mappings.
         */
-       vdev_load(rvd);
+       error = spa_ld_open_indirect_vdev_metadata(spa);
+       if (error != 0)
+               return (error);
 
        /*
-        * Propagate the leaf DTLs we just loaded all the way up the tree.
+        * Retrieve the full list of active features from the MOS and check if
+        * they are all supported.
         */
-       spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
-       vdev_dtl_reassess(rvd, 0, 0, B_FALSE);
-       spa_config_exit(spa, SCL_ALL, FTAG);
+       error = spa_ld_check_features(spa, &missing_feat_write);
+       if (error != 0)
+               return (error);
 
        /*
-        * Load the DDTs (dedup tables).
+        * Load several special directories from the MOS needed by the dsl_pool
+        * layer.
         */
-       error = ddt_load(spa);
+       error = spa_ld_load_special_directories(spa);
        if (error != 0)
-               return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
-
-       spa_update_dspace(spa);
+               return (error);
 
        /*
-        * Validate the config, using the MOS config to fill in any
-        * information which might be missing.  If we fail to validate
-        * the config then declare the pool unfit for use. If we're
-        * assembling a pool from a split, the log is not transferred
-        * over.
+        * Retrieve pool properties from the MOS.
         */
-       if (type != SPA_IMPORT_ASSEMBLE) {
-               nvlist_t *nvconfig;
+       error = spa_ld_get_props(spa);
+       if (error != 0)
+               return (error);
 
-               if (load_nvlist(spa, spa->spa_config_object, &nvconfig) != 0)
-                       return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+       /*
+        * Retrieve the list of auxiliary devices - cache devices and spares -
+        * and open them.
+        */
+       error = spa_ld_open_aux_vdevs(spa, type);
+       if (error != 0)
+               return (error);
 
-               if (!spa_config_valid(spa, nvconfig)) {
-                       nvlist_free(nvconfig);
-                       return (spa_vdev_err(rvd, VDEV_AUX_BAD_GUID_SUM,
-                           ENXIO));
-               }
-               nvlist_free(nvconfig);
+       /*
+        * Load the metadata for all vdevs. Also check if unopenable devices
+        * should be autoreplaced.
+        */
+       error = spa_ld_load_vdev_metadata(spa);
+       if (error != 0)
+               return (error);
 
-               /*
-                * Now that we've validated the config, check the state of the
-                * root vdev.  If it can't be opened, it indicates one or
-                * more toplevel vdevs are faulted.
-                */
-               if (rvd->vdev_state <= VDEV_STATE_CANT_OPEN)
-                       return (SET_ERROR(ENXIO));
+       error = spa_ld_load_dedup_tables(spa);
+       if (error != 0)
+               return (error);
 
-               if (spa_writeable(spa) && spa_check_logs(spa)) {
-                       *ereport = FM_EREPORT_ZFS_LOG_REPLAY;
-                       return (spa_vdev_err(rvd, VDEV_AUX_BAD_LOG, ENXIO));
-               }
-       }
+       /*
+        * Verify the logs now to make sure we don't have any unexpected errors
+        * when we claim log blocks later.
+        */
+       error = spa_ld_verify_logs(spa, type, ereport);
+       if (error != 0)
+               return (error);
 
        if (missing_feat_write) {
-               ASSERT(state == SPA_LOAD_TRYIMPORT);
+               ASSERT(spa->spa_load_state == SPA_LOAD_TRYIMPORT);
 
                /*
                 * At this point, we know that we can open the pool in
                 * read-only mode but not read-write mode. We now have enough
                 * information and can return to userland.
                 */
-               return (spa_vdev_err(rvd, VDEV_AUX_UNSUP_FEAT, ENOTSUP));
+               return (spa_vdev_err(spa->spa_root_vdev, VDEV_AUX_UNSUP_FEAT,
+                   ENOTSUP));
        }
 
        /*
-        * We've successfully opened the pool, verify that we're ready
-        * to start pushing transactions.
+        * Traverse the last txgs to make sure the pool was left off in a safe
+        * state. When performing an extreme rewind, we verify the whole pool,
+        * which can take a very long time.
         */
-       if (state != SPA_LOAD_TRYIMPORT) {
-               if ((error = spa_load_verify(spa)))
-                       return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA,
-                           error));
-       }
+       error = spa_ld_verify_pool_data(spa);
+       if (error != 0)
+               return (error);
+
+       /*
+        * Calculate the deflated space for the pool. This must be done before
+        * we write anything to the pool because we'd need to update the space
+        * accounting using the deflated sizes.
+        */
+       spa_update_dspace(spa);
 
-       if (spa_writeable(spa) && (state == SPA_LOAD_RECOVER ||
+       /*
+        * We have now retrieved all the information we needed to open the
+        * pool. If we are importing the pool in read-write mode, a few
+        * additional steps must be performed to finish the import.
+        */
+       if (spa_writeable(spa) && (spa->spa_load_state == SPA_LOAD_RECOVER ||
            spa->spa_load_max_txg == UINT64_MAX)) {
-               dmu_tx_t *tx;
-               int need_update = B_FALSE;
-               dsl_pool_t *dp = spa_get_dsl(spa);
-               int c;
+               uint64_t config_cache_txg = spa->spa_config_txg;
 
-               ASSERT(state != SPA_LOAD_TRYIMPORT);
+               ASSERT(spa->spa_load_state != SPA_LOAD_TRYIMPORT);
 
                /*
-                * Claim log blocks that haven't been committed yet.
-                * This must all happen in a single txg.
-                * Note: spa_claim_max_txg is updated by spa_claim_notify(),
-                * invoked from zil_claim_log_block()'s i/o done callback.
-                * Price of rollback is that we abandon the log.
+                * Traverse the ZIL and claim all blocks.
                 */
-               spa->spa_claiming = B_TRUE;
-
-               tx = dmu_tx_create_assigned(dp, spa_first_txg(spa));
-               (void) dmu_objset_find_dp(dp, dp->dp_root_dir_obj,
-                   zil_claim, tx, DS_FIND_CHILDREN);
-               dmu_tx_commit(tx);
-
-               spa->spa_claiming = B_FALSE;
+               spa_ld_claim_log_blocks(spa);
 
-               spa_set_log_state(spa, SPA_LOG_GOOD);
+               /*
+                * Kick-off the syncing thread.
+                */
                spa->spa_sync_on = B_TRUE;
                txg_sync_start(spa->spa_dsl_pool);
+               mmp_thread_start(spa);
 
                /*
                 * Wait for all claims to sync.  We sync up to the highest
                 * claimed log block birth time so that claimed log blocks
                 * don't appear to be from the future.  spa_claim_max_txg
-                * will have been set for us by either zil_check_log_chain()
-                * (invoked from spa_check_logs()) or zil_claim() above.
+                * will have been set for us by ZIL traversal operations
+                * performed above.
                 */
                txg_wait_synced(spa->spa_dsl_pool, spa->spa_claim_max_txg);
 
                /*
-                * If the config cache is stale, or we have uninitialized
-                * metaslabs (see spa_vdev_add()), then update the config.
-                *
-                * If this is a verbatim import, trust the current
-                * in-core spa_config and update the disk labels.
-                */
-               if (config_cache_txg != spa->spa_config_txg ||
-                   state == SPA_LOAD_IMPORT ||
-                   state == SPA_LOAD_RECOVER ||
-                   (spa->spa_import_flags & ZFS_IMPORT_VERBATIM))
-                       need_update = B_TRUE;
-
-               for (c = 0; c < rvd->vdev_children; c++)
-                       if (rvd->vdev_child[c]->vdev_ms_array == 0)
-                               need_update = B_TRUE;
-
-               /*
-                * Update the config cache asychronously in case we're the
-                * root pool, in which case the config cache isn't writable yet.
+                * Check if we need to request an update of the config. On the
+                * next sync, we would update the config stored in vdev labels
+                * and the cachefile (by default /etc/zfs/zpool.cache).
                 */
-               if (need_update)
-                       spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE);
+               spa_ld_check_for_config_update(spa, config_cache_txg,
+                   reloading);
 
                /*
                 * Check all DTLs to see if anything needs resilvering.
                 */
                if (!dsl_scan_resilvering(spa->spa_dsl_pool) &&
-                   vdev_resilver_needed(rvd, NULL, NULL))
+                   vdev_resilver_needed(spa->spa_root_vdev, NULL, NULL))
                        spa_async_request(spa, SPA_ASYNC_RESILVER);
 
                /*
                 * Log the fact that we booted up (so that we can detect if
                 * we rebooted in the middle of an operation).
                 */
-               spa_history_log_version(spa, "open");
+               spa_history_log_version(spa, "open", NULL);
 
                /*
                 * Delete any inconsistent datasets.
@@ -2967,13 +3918,19 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
                 * Clean up any stale temporary dataset userrefs.
                 */
                dsl_pool_clean_tmp_userrefs(spa->spa_dsl_pool);
+
+               spa_restart_removal(spa);
+
+               spa_spawn_aux_threads(spa);
        }
 
+       spa_load_note(spa, "LOADED");
+
        return (0);
 }
 
 static int
-spa_load_retry(spa_t *spa, spa_load_state_t state, int mosconfig)
+spa_load_retry(spa_t *spa, spa_load_state_t state)
 {
        int mode = spa->spa_mode;
 
@@ -2985,7 +3942,10 @@ spa_load_retry(spa_t *spa, spa_load_state_t state, int mosconfig)
        spa_activate(spa, mode);
        spa_async_suspend(spa);
 
-       return (spa_load(spa, state, SPA_IMPORT_EXISTING, mosconfig));
+       spa_load_note(spa, "spa_load_retry: rewind, max txg: %llu",
+           (u_longlong_t)spa->spa_load_max_txg);
+
+       return (spa_load(spa, state, SPA_IMPORT_EXISTING));
 }
 
 /*
@@ -2996,8 +3956,8 @@ spa_load_retry(spa_t *spa, spa_load_state_t state, int mosconfig)
  * spa_load().
  */
 static int
-spa_load_best(spa_t *spa, spa_load_state_t state, int mosconfig,
-    uint64_t max_request, int rewind_flags)
+spa_load_best(spa_t *spa, spa_load_state_t state, uint64_t max_request,
+    int rewind_flags)
 {
        nvlist_t *loadinfo = NULL;
        nvlist_t *config = NULL;
@@ -3014,8 +3974,7 @@ spa_load_best(spa_t *spa, spa_load_state_t state, int mosconfig,
                        spa->spa_extreme_rewind = B_TRUE;
        }
 
-       load_error = rewind_error = spa_load(spa, state, SPA_IMPORT_EXISTING,
-           mosconfig);
+       load_error = rewind_error = spa_load(spa, state, SPA_IMPORT_EXISTING);
        if (load_error == 0)
                return (0);
 
@@ -3056,7 +4015,7 @@ spa_load_best(spa_t *spa, spa_load_state_t state, int mosconfig,
            spa->spa_uberblock.ub_txg <= spa->spa_load_max_txg) {
                if (spa->spa_load_max_txg < safe_rewind_txg)
                        spa->spa_extreme_rewind = B_TRUE;
-               rewind_error = spa_load_retry(spa, state, mosconfig);
+               rewind_error = spa_load_retry(spa, state);
        }
 
        spa->spa_extreme_rewind = B_FALSE;
@@ -3064,6 +4023,8 @@ spa_load_best(spa_t *spa, spa_load_state_t state, int mosconfig,
 
        if (config && (rewind_error || state != SPA_LOAD_RECOVER))
                spa_config_set(spa, config);
+       else
+               nvlist_free(config);
 
        if (state == SPA_LOAD_RECOVER) {
                ASSERT3P(loadinfo, ==, NULL);
@@ -3111,7 +4072,7 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy,
         * up calling spa_open() again.  The real fix is to figure out how to
         * avoid dsl_dir_open() calling this in the first place.
         */
-       if (mutex_owner(&spa_namespace_lock) != curthread) {
+       if (MUTEX_NOT_HELD(&spa_namespace_lock)) {
                mutex_enter(&spa_namespace_lock);
                locked = B_TRUE;
        }
@@ -3136,8 +4097,10 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy,
 
                if (state != SPA_LOAD_RECOVER)
                        spa->spa_last_ubsync_txg = spa->spa_load_txg = 0;
+               spa->spa_config_source = SPA_CONFIG_SRC_CACHEFILE;
 
-               error = spa_load_best(spa, state, B_FALSE, policy.zrp_txg,
+               zfs_dbgmsg("spa_open_common: opening %s", pool);
+               error = spa_load_best(spa, state, policy.zrp_txg,
                    policy.zrp_request);
 
                if (error == EBADF) {
@@ -3150,7 +4113,7 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy,
                         */
                        spa_unload(spa);
                        spa_deactivate(spa);
-                       spa_config_sync(spa, B_TRUE, B_TRUE);
+                       spa_write_cachefile(spa, B_TRUE, B_TRUE);
                        spa_remove(spa);
                        if (locked)
                                mutex_exit(&spa_namespace_lock);
@@ -3350,6 +4313,8 @@ spa_add_l2cache(spa_t *spa, nvlist_t *config)
                            ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &vsc)
                            == 0);
                        vdev_get_stats(vd, vs);
+                       vdev_config_generate_stats(vd, l2cache[i]);
+
                }
        }
 }
@@ -3468,10 +4433,14 @@ spa_get_stats(const char *name, nvlist_t **config,
                            ZPOOL_CONFIG_ERRCOUNT,
                            spa_get_errlog_size(spa)) == 0);
 
-                       if (spa_suspended(spa))
+                       if (spa_suspended(spa)) {
                                VERIFY(nvlist_add_uint64(*config,
                                    ZPOOL_CONFIG_SUSPENDED,
                                    spa->spa_failmode) == 0);
+                               VERIFY(nvlist_add_uint64(*config,
+                                   ZPOOL_CONFIG_SUSPENDED_REASON,
+                                   spa->spa_suspended) == 0);
+                       }
 
                        spa_add_spares(spa, *config);
                        spa_add_l2cache(spa, *config);
@@ -3558,18 +4527,6 @@ spa_validate_aux_devs(spa_t *spa, nvlist_t *nvroot, uint64_t crtxg, int mode,
                        goto out;
                }
 
-               /*
-                * The L2ARC currently only supports disk devices in
-                * kernel context.  For user-level testing, we allow it.
-                */
-#ifdef _KERNEL
-               if ((strcmp(config, ZPOOL_CONFIG_L2CACHE) == 0) &&
-                   strcmp(vd->vdev_ops->vdev_op_type, VDEV_TYPE_DISK) != 0) {
-                       error = SET_ERROR(ENOTBLK);
-                       vdev_free(vd);
-                       goto out;
-               }
-#endif
                vd->vdev_top = vd;
 
                if ((error = vdev_open(vd)) == 0 &&
@@ -3623,7 +4580,7 @@ spa_set_aux_vdevs(spa_aux_vdev_t *sav, nvlist_t **devs, int ndevs,
                nvlist_t **newdevs;
 
                /*
-                * Generate new dev list by concatentating with the
+                * Generate new dev list by concatenating with the
                 * current dev list.
                 */
                VERIFY(nvlist_lookup_nvlist_array(sav->sav_config, config,
@@ -3679,12 +4636,28 @@ spa_l2cache_drop(spa_t *spa)
        }
 }
 
+/*
+ * Verify encryption parameters for spa creation. If we are encrypting, we must
+ * have the encryption feature flag enabled.
+ */
+static int
+spa_create_check_encryption_params(dsl_crypto_params_t *dcp,
+    boolean_t has_encryption)
+{
+       if (dcp->cp_crypt != ZIO_CRYPT_OFF &&
+           dcp->cp_crypt != ZIO_CRYPT_INHERIT &&
+           !has_encryption)
+               return (SET_ERROR(ENOTSUP));
+
+       return (dmu_objset_create_crypt_check(NULL, dcp));
+}
+
 /*
  * Pool Creation
  */
 int
 spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
-    nvlist_t *zplprops)
+    nvlist_t *zplprops, dsl_crypto_params_t *dcp)
 {
        spa_t *spa;
        char *altroot = NULL;
@@ -3695,10 +4668,11 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
        uint64_t txg = TXG_INITIAL;
        nvlist_t **spares, **l2cache;
        uint_t nspares, nl2cache;
-       uint64_t version, obj;
+       uint64_t version, obj, root_dsobj = 0;
        boolean_t has_features;
-       nvpair_t *elem;
-       int c, i;
+       boolean_t has_encryption;
+       spa_feature_t feat;
+       char *feat_name;
        char *poolname;
        nvlist_t *nvl;
 
@@ -3739,10 +4713,28 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
                spa->spa_import_flags |= ZFS_IMPORT_TEMP_NAME;
 
        has_features = B_FALSE;
-       for (elem = nvlist_next_nvpair(props, NULL);
+       has_encryption = B_FALSE;
+       for (nvpair_t *elem = nvlist_next_nvpair(props, NULL);
            elem != NULL; elem = nvlist_next_nvpair(props, elem)) {
-               if (zpool_prop_feature(nvpair_name(elem)))
+               if (zpool_prop_feature(nvpair_name(elem))) {
                        has_features = B_TRUE;
+
+                       feat_name = strchr(nvpair_name(elem), '@') + 1;
+                       VERIFY0(zfeature_lookup_name(feat_name, &feat));
+                       if (feat == SPA_FEATURE_ENCRYPTION)
+                               has_encryption = B_TRUE;
+               }
+       }
+
+       /* verify encryption params, if they were provided */
+       if (dcp != NULL) {
+               error = spa_create_check_encryption_params(dcp, has_encryption);
+               if (error != 0) {
+                       spa_deactivate(spa);
+                       spa_remove(spa);
+                       mutex_exit(&spa_namespace_lock);
+                       return (error);
+               }
        }
 
        if (has_features || nvlist_lookup_uint64(props,
@@ -3755,13 +4747,17 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
        spa->spa_uberblock.ub_txg = txg - 1;
        spa->spa_uberblock.ub_version = version;
        spa->spa_ubsync = spa->spa_uberblock;
+       spa->spa_load_state = SPA_LOAD_CREATE;
+       spa->spa_removing_phys.sr_state = DSS_NONE;
+       spa->spa_removing_phys.sr_removing_vdev = -1;
+       spa->spa_removing_phys.sr_prev_indirect_vdev = -1;
 
        /*
         * Create "The Godfather" zio to hold all async IOs
         */
        spa->spa_async_zio_root = kmem_alloc(max_ncpus * sizeof (void *),
            KM_SLEEP);
-       for (i = 0; i < max_ncpus; i++) {
+       for (int i = 0; i < max_ncpus; i++) {
                spa->spa_async_zio_root[i] = zio_root(spa, NULL, NULL,
                    ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
                    ZIO_FLAG_GODFATHER);
@@ -3784,7 +4780,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
            (error = vdev_create(rvd, txg, B_FALSE)) == 0 &&
            (error = spa_validate_aux(spa, nvroot, txg,
            VDEV_ALLOC_ADD)) == 0) {
-               for (c = 0; c < rvd->vdev_children; c++) {
+               for (int c = 0; c < rvd->vdev_children; c++) {
                        vdev_metaslab_set_size(rvd->vdev_child[c]);
                        vdev_expand(rvd->vdev_child[c], txg);
                }
@@ -3831,8 +4827,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
        }
 
        spa->spa_is_initializing = B_TRUE;
-       spa->spa_dsl_pool = dp = dsl_pool_create(spa, zplprops, txg);
-       spa->spa_meta_objset = dp->dp_meta_objset;
+       spa->spa_dsl_pool = dp = dsl_pool_create(spa, zplprops, dcp, txg);
        spa->spa_is_initializing = B_FALSE;
 
        /*
@@ -3844,6 +4839,15 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
 
        tx = dmu_tx_create_assigned(dp, txg);
 
+       /*
+        * Create the pool's history object.
+        */
+       if (version >= SPA_VERSION_ZPOOL_HISTORY && !spa->spa_history)
+               spa_history_create_obj(spa, tx);
+
+       spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_CREATE);
+       spa_history_log_version(spa, "create", tx);
+
        /*
         * Create the pool config object.
         */
@@ -3857,9 +4861,6 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
                cmn_err(CE_PANIC, "failed to add pool config");
        }
 
-       if (spa_version(spa) >= SPA_VERSION_FEATURES)
-               spa_feature_create_zap_objects(spa, tx);
-
        if (zap_add(spa->spa_meta_objset,
            DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_CREATION_VERSION,
            sizeof (uint64_t), 1, &version, tx) != 0) {
@@ -3893,10 +4894,10 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
            spa->spa_meta_objset, obj));
 
        /*
-        * Create the pool's history object.
+        * Generate some random noise for salted checksums to operate on.
         */
-       if (version >= SPA_VERSION_ZPOOL_HISTORY)
-               spa_history_create_obj(spa, tx);
+       (void) random_get_pseudo_bytes(spa->spa_cksum_salt.zcs_bytes,
+           sizeof (spa->spa_cksum_salt.zcs_bytes));
 
        /*
         * Set pool properties.
@@ -3905,6 +4906,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
        spa->spa_delegation = zpool_prop_default_numeric(ZPOOL_PROP_DELEGATION);
        spa->spa_failmode = zpool_prop_default_numeric(ZPOOL_PROP_FAILUREMODE);
        spa->spa_autoexpand = zpool_prop_default_numeric(ZPOOL_PROP_AUTOEXPAND);
+       spa->spa_multihost = zpool_prop_default_numeric(ZPOOL_PROP_MULTIHOST);
 
        if (props != NULL) {
                spa_configfile_set(spa, props, B_FALSE);
@@ -3913,18 +4915,30 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
 
        dmu_tx_commit(tx);
 
-       spa->spa_sync_on = B_TRUE;
-       txg_sync_start(spa->spa_dsl_pool);
-
        /*
-        * We explicitly wait for the first transaction to complete so that our
-        * bean counters are appropriately updated.
+        * If the root dataset is encrypted we will need to create key mappings
+        * for the zio layer before we start to write any data to disk and hold
+        * them until after the first txg has been synced. Waiting for the first
+        * transaction to complete also ensures that our bean counters are
+        * appropriately updated.
         */
-       txg_wait_synced(spa->spa_dsl_pool, txg);
+       if (dp->dp_root_dir->dd_crypto_obj != 0) {
+               root_dsobj = dsl_dir_phys(dp->dp_root_dir)->dd_head_dataset_obj;
+               VERIFY0(spa_keystore_create_mapping_impl(spa, root_dsobj,
+                   dp->dp_root_dir, FTAG));
+       }
+
+       spa->spa_sync_on = B_TRUE;
+       txg_sync_start(dp);
+       mmp_thread_start(spa);
+       txg_wait_synced(dp, txg);
+
+       if (dp->dp_root_dir->dd_crypto_obj != 0)
+               VERIFY0(spa_keystore_remove_mapping(spa, root_dsobj, FTAG));
 
-       spa_config_sync(spa, B_FALSE, B_TRUE);
+       spa_spawn_aux_threads(spa);
 
-       spa_history_log_version(spa, "create");
+       spa_write_cachefile(spa, B_FALSE, B_TRUE);
 
        /*
         * Don't count references from objsets that are already closed
@@ -3932,217 +4946,13 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
         */
        spa_evicting_os_wait(spa);
        spa->spa_minref = refcount_count(&spa->spa_refcount);
+       spa->spa_load_state = SPA_LOAD_NONE;
 
        mutex_exit(&spa_namespace_lock);
 
        return (0);
 }
 
-#ifdef _KERNEL
-/*
- * Get the root pool information from the root disk, then import the root pool
- * during the system boot up time.
- */
-extern int vdev_disk_read_rootlabel(char *, char *, nvlist_t **);
-
-static nvlist_t *
-spa_generate_rootconf(char *devpath, char *devid, uint64_t *guid)
-{
-       nvlist_t *config;
-       nvlist_t *nvtop, *nvroot;
-       uint64_t pgid;
-
-       if (vdev_disk_read_rootlabel(devpath, devid, &config) != 0)
-               return (NULL);
-
-       /*
-        * Add this top-level vdev to the child array.
-        */
-       VERIFY(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
-           &nvtop) == 0);
-       VERIFY(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
-           &pgid) == 0);
-       VERIFY(nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID, guid) == 0);
-
-       /*
-        * Put this pool's top-level vdevs into a root vdev.
-        */
-       VERIFY(nvlist_alloc(&nvroot, NV_UNIQUE_NAME, KM_SLEEP) == 0);
-       VERIFY(nvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE,
-           VDEV_TYPE_ROOT) == 0);
-       VERIFY(nvlist_add_uint64(nvroot, ZPOOL_CONFIG_ID, 0ULL) == 0);
-       VERIFY(nvlist_add_uint64(nvroot, ZPOOL_CONFIG_GUID, pgid) == 0);
-       VERIFY(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
-           &nvtop, 1) == 0);
-
-       /*
-        * Replace the existing vdev_tree with the new root vdev in
-        * this pool's configuration (remove the old, add the new).
-        */
-       VERIFY(nvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, nvroot) == 0);
-       nvlist_free(nvroot);
-       return (config);
-}
-
-/*
- * Walk the vdev tree and see if we can find a device with "better"
- * configuration. A configuration is "better" if the label on that
- * device has a more recent txg.
- */
-static void
-spa_alt_rootvdev(vdev_t *vd, vdev_t **avd, uint64_t *txg)
-{
-       int c;
-
-       for (c = 0; c < vd->vdev_children; c++)
-               spa_alt_rootvdev(vd->vdev_child[c], avd, txg);
-
-       if (vd->vdev_ops->vdev_op_leaf) {
-               nvlist_t *label;
-               uint64_t label_txg;
-
-               if (vdev_disk_read_rootlabel(vd->vdev_physpath, vd->vdev_devid,
-                   &label) != 0)
-                       return;
-
-               VERIFY(nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_TXG,
-                   &label_txg) == 0);
-
-               /*
-                * Do we have a better boot device?
-                */
-               if (label_txg > *txg) {
-                       *txg = label_txg;
-                       *avd = vd;
-               }
-               nvlist_free(label);
-       }
-}
-
-/*
- * Import a root pool.
- *
- * For x86. devpath_list will consist of devid and/or physpath name of
- * the vdev (e.g. "id1,sd@SSEAGATE..." or "/pci@1f,0/ide@d/disk@0,0:a").
- * The GRUB "findroot" command will return the vdev we should boot.
- *
- * For Sparc, devpath_list consists the physpath name of the booting device
- * no matter the rootpool is a single device pool or a mirrored pool.
- * e.g.
- *     "/pci@1f,0/ide@d/disk@0,0:a"
- */
-int
-spa_import_rootpool(char *devpath, char *devid)
-{
-       spa_t *spa;
-       vdev_t *rvd, *bvd, *avd = NULL;
-       nvlist_t *config, *nvtop;
-       uint64_t guid, txg;
-       char *pname;
-       int error;
-
-       /*
-        * Read the label from the boot device and generate a configuration.
-        */
-       config = spa_generate_rootconf(devpath, devid, &guid);
-#if defined(_OBP) && defined(_KERNEL)
-       if (config == NULL) {
-               if (strstr(devpath, "/iscsi/ssd") != NULL) {
-                       /* iscsi boot */
-                       get_iscsi_bootpath_phy(devpath);
-                       config = spa_generate_rootconf(devpath, devid, &guid);
-               }
-       }
-#endif
-       if (config == NULL) {
-               cmn_err(CE_NOTE, "Cannot read the pool label from '%s'",
-                   devpath);
-               return (SET_ERROR(EIO));
-       }
-
-       VERIFY(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
-           &pname) == 0);
-       VERIFY(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG, &txg) == 0);
-
-       mutex_enter(&spa_namespace_lock);
-       if ((spa = spa_lookup(pname)) != NULL) {
-               /*
-                * Remove the existing root pool from the namespace so that we
-                * can replace it with the correct config we just read in.
-                */
-               spa_remove(spa);
-       }
-
-       spa = spa_add(pname, config, NULL);
-       spa->spa_is_root = B_TRUE;
-       spa->spa_import_flags = ZFS_IMPORT_VERBATIM;
-
-       /*
-        * Build up a vdev tree based on the boot device's label config.
-        */
-       VERIFY(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
-           &nvtop) == 0);
-       spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
-       error = spa_config_parse(spa, &rvd, nvtop, NULL, 0,
-           VDEV_ALLOC_ROOTPOOL);
-       spa_config_exit(spa, SCL_ALL, FTAG);
-       if (error) {
-               mutex_exit(&spa_namespace_lock);
-               nvlist_free(config);
-               cmn_err(CE_NOTE, "Can not parse the config for pool '%s'",
-                   pname);
-               return (error);
-       }
-
-       /*
-        * Get the boot vdev.
-        */
-       if ((bvd = vdev_lookup_by_guid(rvd, guid)) == NULL) {
-               cmn_err(CE_NOTE, "Can not find the boot vdev for guid %llu",
-                   (u_longlong_t)guid);
-               error = SET_ERROR(ENOENT);
-               goto out;
-       }
-
-       /*
-        * Determine if there is a better boot device.
-        */
-       avd = bvd;
-       spa_alt_rootvdev(rvd, &avd, &txg);
-       if (avd != bvd) {
-               cmn_err(CE_NOTE, "The boot device is 'degraded'. Please "
-                   "try booting from '%s'", avd->vdev_path);
-               error = SET_ERROR(EINVAL);
-               goto out;
-       }
-
-       /*
-        * If the boot device is part of a spare vdev then ensure that
-        * we're booting off the active spare.
-        */
-       if (bvd->vdev_parent->vdev_ops == &vdev_spare_ops &&
-           !bvd->vdev_isspare) {
-               cmn_err(CE_NOTE, "The boot device is currently spared. Please "
-                   "try booting from '%s'",
-                   bvd->vdev_parent->
-                   vdev_child[bvd->vdev_parent->vdev_children - 1]->vdev_path);
-               error = SET_ERROR(EINVAL);
-               goto out;
-       }
-
-       error = 0;
-out:
-       spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
-       vdev_free(rvd);
-       spa_config_exit(spa, SCL_ALL, FTAG);
-       mutex_exit(&spa_namespace_lock);
-
-       nvlist_free(config);
-       return (error);
-}
-
-#endif
-
 /*
  * Import a non-root pool into the system.
  */
@@ -4189,8 +4999,9 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags)
                if (props != NULL)
                        spa_configfile_set(spa, props, B_FALSE);
 
-               spa_config_sync(spa, B_FALSE, B_TRUE);
-
+               spa_write_cachefile(spa, B_FALSE, B_TRUE);
+               spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_IMPORT);
+               zfs_dbgmsg("spa_import: verbatim import of %s", pool);
                mutex_exit(&spa_namespace_lock);
                return (0);
        }
@@ -4206,16 +5017,16 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags)
        if (policy.zrp_request & ZPOOL_DO_REWIND)
                state = SPA_LOAD_RECOVER;
 
-       /*
-        * Pass off the heavy lifting to spa_load().  Pass TRUE for mosconfig
-        * because the user-supplied config is actually the one to trust when
-        * doing an import.
-        */
-       if (state != SPA_LOAD_RECOVER)
-               spa->spa_last_ubsync_txg = spa->spa_load_txg = 0;
+       spa->spa_config_source = SPA_CONFIG_SRC_TRYIMPORT;
 
-       error = spa_load_best(spa, state, B_TRUE, policy.zrp_txg,
-           policy.zrp_request);
+       if (state != SPA_LOAD_RECOVER) {
+               spa->spa_last_ubsync_txg = spa->spa_load_txg = 0;
+               zfs_dbgmsg("spa_import: importing %s", pool);
+       } else {
+               zfs_dbgmsg("spa_import: importing %s, max_txg=%lld "
+                   "(RECOVERY MODE)", pool, (longlong_t)policy.zrp_txg);
+       }
+       error = spa_load_best(spa, state, policy.zrp_txg, policy.zrp_request);
 
        /*
         * Propagate anything learned while loading the pool and pass it
@@ -4242,12 +5053,6 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags)
 
        VERIFY(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
            &nvroot) == 0);
-       if (error == 0)
-               error = spa_validate_aux(spa, nvroot, -1ULL,
-                   VDEV_ALLOC_SPARE);
-       if (error == 0)
-               error = spa_validate_aux(spa, nvroot, -1ULL,
-                   VDEV_ALLOC_L2CACHE);
        spa_config_exit(spa, SCL_ALL, FTAG);
 
        if (props != NULL)
@@ -4320,10 +5125,14 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags)
         */
        spa_async_request(spa, SPA_ASYNC_AUTOEXPAND);
 
-       mutex_exit(&spa_namespace_lock);
-       spa_history_log_version(spa, "import");
+       spa_history_log_version(spa, "import", NULL);
+
+       spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_IMPORT);
+
        zvol_create_minors(spa, pool, B_TRUE);
 
+       mutex_exit(&spa_namespace_lock);
+
        return (0);
 }
 
@@ -4331,10 +5140,11 @@ nvlist_t *
 spa_tryimport(nvlist_t *tryconfig)
 {
        nvlist_t *config = NULL;
-       char *poolname;
+       char *poolname, *cachefile;
        spa_t *spa;
        uint64_t state;
        int error;
+       zpool_rewind_policy_t policy;
 
        if (nvlist_lookup_string(tryconfig, ZPOOL_CONFIG_POOL_NAME, &poolname))
                return (NULL);
@@ -4350,11 +5160,29 @@ spa_tryimport(nvlist_t *tryconfig)
        spa_activate(spa, FREAD);
 
        /*
-        * Pass off the heavy lifting to spa_load().
-        * Pass TRUE for mosconfig because the user-supplied config
-        * is actually the one to trust when doing an import.
+        * Rewind pool if a max txg was provided. Note that even though we
+        * retrieve the complete rewind policy, only the rewind txg is relevant
+        * for tryimport.
         */
-       error = spa_load(spa, SPA_LOAD_TRYIMPORT, SPA_IMPORT_EXISTING, B_TRUE);
+       zpool_get_rewind_policy(spa->spa_config, &policy);
+       if (policy.zrp_txg != UINT64_MAX) {
+               spa->spa_load_max_txg = policy.zrp_txg;
+               spa->spa_extreme_rewind = B_TRUE;
+               zfs_dbgmsg("spa_tryimport: importing %s, max_txg=%lld",
+                   poolname, (longlong_t)policy.zrp_txg);
+       } else {
+               zfs_dbgmsg("spa_tryimport: importing %s", poolname);
+       }
+
+       if (nvlist_lookup_string(tryconfig, ZPOOL_CONFIG_CACHEFILE, &cachefile)
+           == 0) {
+               zfs_dbgmsg("spa_tryimport: using cachefile '%s'", cachefile);
+               spa->spa_config_source = SPA_CONFIG_SRC_CACHEFILE;
+       } else {
+               spa->spa_config_source = SPA_CONFIG_SRC_SCAN;
+       }
+
+       error = spa_load(spa, SPA_LOAD_TRYIMPORT, SPA_IMPORT_EXISTING);
 
        /*
         * If 'tryconfig' was at least parsable, return the current config.
@@ -4519,7 +5347,10 @@ spa_export_common(char *pool, int new_state, nvlist_t **oldconfig,
        }
 
 export_spa:
-       spa_event_notify(spa, NULL, FM_EREPORT_ZFS_POOL_DESTROY);
+       if (new_state == POOL_STATE_DESTROYED)
+               spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_DESTROY);
+       else if (new_state == POOL_STATE_EXPORTED)
+               spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_EXPORT);
 
        if (spa->spa_state != POOL_STATE_UNINITIALIZED) {
                spa_unload(spa);
@@ -4531,7 +5362,7 @@ export_spa:
 
        if (new_state != POOL_STATE_UNINITIALIZED) {
                if (!hardforce)
-                       spa_config_sync(spa, B_TRUE, B_TRUE);
+                       spa_write_cachefile(spa, B_TRUE, B_TRUE);
                spa_remove(spa);
        }
        mutex_exit(&spa_namespace_lock);
@@ -4589,7 +5420,6 @@ spa_vdev_add(spa_t *spa, nvlist_t *nvroot)
        vdev_t *vd, *tvd;
        nvlist_t **spares, **l2cache;
        uint_t nspares, nl2cache;
-       int c;
 
        ASSERT(spa_writeable(spa));
 
@@ -4624,9 +5454,41 @@ spa_vdev_add(spa_t *spa, nvlist_t *nvroot)
                return (spa_vdev_exit(spa, vd, txg, error));
 
        /*
-        * Transfer each new top-level vdev from vd to rvd.
+        * If we are in the middle of a device removal, we can only add
+        * devices which match the existing devices in the pool.
+        * If we are in the middle of a removal, or have some indirect
+        * vdevs, we can not add raidz toplevels.
         */
-       for (c = 0; c < vd->vdev_children; c++) {
+       if (spa->spa_vdev_removal != NULL ||
+           spa->spa_removing_phys.sr_prev_indirect_vdev != -1) {
+               for (int c = 0; c < vd->vdev_children; c++) {
+                       tvd = vd->vdev_child[c];
+                       if (spa->spa_vdev_removal != NULL &&
+                           tvd->vdev_ashift != spa->spa_max_ashift) {
+                               return (spa_vdev_exit(spa, vd, txg, EINVAL));
+                       }
+                       /* Fail if top level vdev is raidz */
+                       if (tvd->vdev_ops == &vdev_raidz_ops) {
+                               return (spa_vdev_exit(spa, vd, txg, EINVAL));
+                       }
+                       /*
+                        * Need the top level mirror to be
+                        * a mirror of leaf vdevs only
+                        */
+                       if (tvd->vdev_ops == &vdev_mirror_ops) {
+                               for (uint64_t cid = 0;
+                                   cid < tvd->vdev_children; cid++) {
+                                       vdev_t *cvd = tvd->vdev_child[cid];
+                                       if (!cvd->vdev_ops->vdev_op_leaf) {
+                                               return (spa_vdev_exit(spa, vd,
+                                                   txg, EINVAL));
+                                       }
+                               }
+                       }
+               }
+       }
+
+       for (int c = 0; c < vd->vdev_children; c++) {
 
                /*
                 * Set the vdev id to the first hole, if one exists.
@@ -4675,6 +5537,7 @@ spa_vdev_add(spa_t *spa, nvlist_t *nvroot)
 
        mutex_enter(&spa_namespace_lock);
        spa_config_update(spa, SPA_CONFIG_UPDATE_POOL);
+       spa_event_notify(spa, NULL, NULL, ESC_ZFS_VDEV_ADD);
        mutex_exit(&spa_namespace_lock);
 
        return (0);
@@ -4697,12 +5560,12 @@ int
 spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing)
 {
        uint64_t txg, dtl_max_txg;
+       ASSERTV(vdev_t *rvd = spa->spa_root_vdev);
        vdev_t *oldvd, *newvd, *newrootvd, *pvd, *tvd;
        vdev_ops_t *pvops;
        char *oldvdpath, *newvdpath;
        int newvd_isspare;
        int error;
-       ASSERTV(vdev_t *rvd = spa->spa_root_vdev);
 
        ASSERT(spa_writeable(spa));
 
@@ -4710,6 +5573,9 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing)
 
        oldvd = spa_lookup_by_guid(spa, guid, B_FALSE);
 
+       if (spa->spa_vdev_removal != NULL)
+               return (spa_vdev_exit(spa, NULL, txg, EBUSY));
+
        if (oldvd == NULL)
                return (spa_vdev_exit(spa, NULL, txg, ENODEV));
 
@@ -4832,6 +5698,11 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing)
        newvd->vdev_crtxg = oldvd->vdev_crtxg;
        vdev_add_child(pvd, newvd);
 
+       /*
+        * Reevaluate the parent vdev state.
+        */
+       vdev_propagate_state(pvd);
+
        tvd = newvd->vdev_top;
        ASSERT(pvd->vdev_top == tvd);
        ASSERT(tvd->vdev_parent == rvd);
@@ -4850,7 +5721,7 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing)
 
        if (newvd->vdev_isspare) {
                spa_spare_activate(newvd);
-               spa_event_notify(spa, newvd, FM_EREPORT_ZFS_DEVICE_SPARE);
+               spa_event_notify(spa, newvd, NULL, ESC_ZFS_VDEV_SPARE);
        }
 
        oldvdpath = spa_strdup(oldvd->vdev_path);
@@ -4869,6 +5740,11 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing)
         */
        dsl_resilver_restart(spa->spa_dsl_pool, dtl_max_txg);
 
+       if (spa->spa_bootfs)
+               spa_event_notify(spa, newvd, NULL, ESC_ZFS_BOOTFS_VDEV_ATTACH);
+
+       spa_event_notify(spa, newvd, NULL, ESC_ZFS_VDEV_ATTACH);
+
        /*
         * Commit the config
         */
@@ -4883,9 +5759,6 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing)
        spa_strfree(oldvdpath);
        spa_strfree(newvdpath);
 
-       if (spa->spa_bootfs)
-               spa_event_notify(spa, newvd, FM_EREPORT_ZFS_BOOTFS_VDEV_ATTACH);
-
        return (0);
 }
 
@@ -4900,12 +5773,12 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done)
 {
        uint64_t txg;
        int error;
+       ASSERTV(vdev_t *rvd = spa->spa_root_vdev);
        vdev_t *vd, *pvd, *cvd, *tvd;
        boolean_t unspare = B_FALSE;
        uint64_t unspare_guid = 0;
        char *vdpath;
-       int c, t;
-       ASSERTV(vdev_t *rvd = spa->spa_root_vdev);
+
        ASSERT(spa_writeable(spa));
 
        txg = spa_vdev_enter(spa);
@@ -4972,7 +5845,7 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done)
            vd->vdev_path != NULL) {
                size_t len = strlen(vd->vdev_path);
 
-               for (c = 0; c < pvd->vdev_children; c++) {
+               for (int c = 0; c < pvd->vdev_children; c++) {
                        cvd = pvd->vdev_child[c];
 
                        if (cvd == vd || cvd->vdev_path == NULL)
@@ -5078,13 +5951,13 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done)
         * But first make sure we're not on any *other* txg's DTL list, to
         * prevent vd from being accessed after it's freed.
         */
-       vdpath = spa_strdup(vd->vdev_path);
-       for (t = 0; t < TXG_SIZE; t++)
+       vdpath = spa_strdup(vd->vdev_path ? vd->vdev_path : "none");
+       for (int t = 0; t < TXG_SIZE; t++)
                (void) txg_list_remove_this(&tvd->vdev_dtl_list, vd, t);
        vd->vdev_detached = B_TRUE;
        vdev_dirty(tvd, VDD_DTL, vd, txg);
 
-       spa_event_notify(spa, vd, FM_EREPORT_ZFS_DEVICE_REMOVE);
+       spa_event_notify(spa, vd, NULL, ESC_ZFS_VDEV_REMOVE);
 
        /* hang on to the spa before we release the lock */
        spa_open_ref(spa, FTAG);
@@ -5153,7 +6026,7 @@ spa_vdev_split_mirror(spa_t *spa, char *newname, nvlist_t *config,
        /* clear the log and flush everything up to now */
        activate_slog = spa_passivate_log(spa);
        (void) spa_vdev_config_exit(spa, NULL, txg, 0, FTAG);
-       error = spa_offline_log(spa);
+       error = spa_reset_logs(spa);
        txg = spa_vdev_config_enter(spa);
 
        if (activate_slog)
@@ -5181,7 +6054,7 @@ spa_vdev_split_mirror(spa_t *spa, char *newname, nvlist_t *config,
                vdev_t *vd = rvd->vdev_child[c];
 
                /* don't count the holes & logs as children */
-               if (vd->vdev_islog || vd->vdev_ishole) {
+               if (vd->vdev_islog || !vdev_is_concrete(vd)) {
                        if (lastlog == 0)
                                lastlog = c;
                        continue;
@@ -5234,7 +6107,7 @@ spa_vdev_split_mirror(spa_t *spa, char *newname, nvlist_t *config,
                /* make sure there's nothing stopping the split */
                if (vml[c]->vdev_parent->vdev_ops != &vdev_mirror_ops ||
                    vml[c]->vdev_islog ||
-                   vml[c]->vdev_ishole ||
+                   !vdev_is_concrete(vml[c]) ||
                    vml[c]->vdev_isspare ||
                    vml[c]->vdev_isl2cache ||
                    !vdev_writeable(vml[c]) ||
@@ -5329,8 +6202,10 @@ spa_vdev_split_mirror(spa_t *spa, char *newname, nvlist_t *config,
        spa_activate(newspa, spa_mode_global);
        spa_async_suspend(newspa);
 
+       newspa->spa_config_source = SPA_CONFIG_SRC_SPLIT;
+
        /* create the new pool from the disks of the original pool */
-       error = spa_load(newspa, SPA_LOAD_IMPORT, SPA_IMPORT_ASSEMBLE, B_TRUE);
+       error = spa_load(newspa, SPA_LOAD_IMPORT, SPA_IMPORT_ASSEMBLE);
        if (error)
                goto out;
 
@@ -5424,249 +6299,6 @@ out:
        return (error);
 }
 
-static nvlist_t *
-spa_nvlist_lookup_by_guid(nvlist_t **nvpp, int count, uint64_t target_guid)
-{
-       int i;
-
-       for (i = 0; i < count; i++) {
-               uint64_t guid;
-
-               VERIFY(nvlist_lookup_uint64(nvpp[i], ZPOOL_CONFIG_GUID,
-                   &guid) == 0);
-
-               if (guid == target_guid)
-                       return (nvpp[i]);
-       }
-
-       return (NULL);
-}
-
-static void
-spa_vdev_remove_aux(nvlist_t *config, char *name, nvlist_t **dev, int count,
-       nvlist_t *dev_to_remove)
-{
-       nvlist_t **newdev = NULL;
-       int i, j;
-
-       if (count > 1)
-               newdev = kmem_alloc((count - 1) * sizeof (void *), KM_SLEEP);
-
-       for (i = 0, j = 0; i < count; i++) {
-               if (dev[i] == dev_to_remove)
-                       continue;
-               VERIFY(nvlist_dup(dev[i], &newdev[j++], KM_SLEEP) == 0);
-       }
-
-       VERIFY(nvlist_remove(config, name, DATA_TYPE_NVLIST_ARRAY) == 0);
-       VERIFY(nvlist_add_nvlist_array(config, name, newdev, count - 1) == 0);
-
-       for (i = 0; i < count - 1; i++)
-               nvlist_free(newdev[i]);
-
-       if (count > 1)
-               kmem_free(newdev, (count - 1) * sizeof (void *));
-}
-
-/*
- * Evacuate the device.
- */
-static int
-spa_vdev_remove_evacuate(spa_t *spa, vdev_t *vd)
-{
-       uint64_t txg;
-       int error = 0;
-
-       ASSERT(MUTEX_HELD(&spa_namespace_lock));
-       ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == 0);
-       ASSERT(vd == vd->vdev_top);
-
-       /*
-        * Evacuate the device.  We don't hold the config lock as writer
-        * since we need to do I/O but we do keep the
-        * spa_namespace_lock held.  Once this completes the device
-        * should no longer have any blocks allocated on it.
-        */
-       if (vd->vdev_islog) {
-               if (vd->vdev_stat.vs_alloc != 0)
-                       error = spa_offline_log(spa);
-       } else {
-               error = SET_ERROR(ENOTSUP);
-       }
-
-       if (error)
-               return (error);
-
-       /*
-        * The evacuation succeeded.  Remove any remaining MOS metadata
-        * associated with this vdev, and wait for these changes to sync.
-        */
-       ASSERT0(vd->vdev_stat.vs_alloc);
-       txg = spa_vdev_config_enter(spa);
-       vd->vdev_removing = B_TRUE;
-       vdev_dirty_leaves(vd, VDD_DTL, txg);
-       vdev_config_dirty(vd);
-       spa_vdev_config_exit(spa, NULL, txg, 0, FTAG);
-
-       return (0);
-}
-
-/*
- * Complete the removal by cleaning up the namespace.
- */
-static void
-spa_vdev_remove_from_namespace(spa_t *spa, vdev_t *vd)
-{
-       vdev_t *rvd = spa->spa_root_vdev;
-       uint64_t id = vd->vdev_id;
-       boolean_t last_vdev = (id == (rvd->vdev_children - 1));
-
-       ASSERT(MUTEX_HELD(&spa_namespace_lock));
-       ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL);
-       ASSERT(vd == vd->vdev_top);
-
-       /*
-        * Only remove any devices which are empty.
-        */
-       if (vd->vdev_stat.vs_alloc != 0)
-               return;
-
-       (void) vdev_label_init(vd, 0, VDEV_LABEL_REMOVE);
-
-       if (list_link_active(&vd->vdev_state_dirty_node))
-               vdev_state_clean(vd);
-       if (list_link_active(&vd->vdev_config_dirty_node))
-               vdev_config_clean(vd);
-
-       vdev_free(vd);
-
-       if (last_vdev) {
-               vdev_compact_children(rvd);
-       } else {
-               vd = vdev_alloc_common(spa, id, 0, &vdev_hole_ops);
-               vdev_add_child(rvd, vd);
-       }
-       vdev_config_dirty(rvd);
-
-       /*
-        * Reassess the health of our root vdev.
-        */
-       vdev_reopen(rvd);
-}
-
-/*
- * Remove a device from the pool -
- *
- * Removing a device from the vdev namespace requires several steps
- * and can take a significant amount of time.  As a result we use
- * the spa_vdev_config_[enter/exit] functions which allow us to
- * grab and release the spa_config_lock while still holding the namespace
- * lock.  During each step the configuration is synced out.
- *
- * Currently, this supports removing only hot spares, slogs, and level 2 ARC
- * devices.
- */
-int
-spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare)
-{
-       vdev_t *vd;
-       metaslab_group_t *mg;
-       nvlist_t **spares, **l2cache, *nv;
-       uint64_t txg = 0;
-       uint_t nspares, nl2cache;
-       int error = 0;
-       boolean_t locked = MUTEX_HELD(&spa_namespace_lock);
-
-       ASSERT(spa_writeable(spa));
-
-       if (!locked)
-               txg = spa_vdev_enter(spa);
-
-       vd = spa_lookup_by_guid(spa, guid, B_FALSE);
-
-       if (spa->spa_spares.sav_vdevs != NULL &&
-           nvlist_lookup_nvlist_array(spa->spa_spares.sav_config,
-           ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0 &&
-           (nv = spa_nvlist_lookup_by_guid(spares, nspares, guid)) != NULL) {
-               /*
-                * Only remove the hot spare if it's not currently in use
-                * in this pool.
-                */
-               if (vd == NULL || unspare) {
-                       spa_vdev_remove_aux(spa->spa_spares.sav_config,
-                           ZPOOL_CONFIG_SPARES, spares, nspares, nv);
-                       spa_load_spares(spa);
-                       spa->spa_spares.sav_sync = B_TRUE;
-               } else {
-                       error = SET_ERROR(EBUSY);
-               }
-       } else if (spa->spa_l2cache.sav_vdevs != NULL &&
-           nvlist_lookup_nvlist_array(spa->spa_l2cache.sav_config,
-           ZPOOL_CONFIG_L2CACHE, &l2cache, &nl2cache) == 0 &&
-           (nv = spa_nvlist_lookup_by_guid(l2cache, nl2cache, guid)) != NULL) {
-               /*
-                * Cache devices can always be removed.
-                */
-               spa_vdev_remove_aux(spa->spa_l2cache.sav_config,
-                   ZPOOL_CONFIG_L2CACHE, l2cache, nl2cache, nv);
-               spa_load_l2cache(spa);
-               spa->spa_l2cache.sav_sync = B_TRUE;
-       } else if (vd != NULL && vd->vdev_islog) {
-               ASSERT(!locked);
-               ASSERT(vd == vd->vdev_top);
-
-               mg = vd->vdev_mg;
-
-               /*
-                * Stop allocating from this vdev.
-                */
-               metaslab_group_passivate(mg);
-
-               /*
-                * Wait for the youngest allocations and frees to sync,
-                * and then wait for the deferral of those frees to finish.
-                */
-               spa_vdev_config_exit(spa, NULL,
-                   txg + TXG_CONCURRENT_STATES + TXG_DEFER_SIZE, 0, FTAG);
-
-               /*
-                * Attempt to evacuate the vdev.
-                */
-               error = spa_vdev_remove_evacuate(spa, vd);
-
-               txg = spa_vdev_config_enter(spa);
-
-               /*
-                * If we couldn't evacuate the vdev, unwind.
-                */
-               if (error) {
-                       metaslab_group_activate(mg);
-                       return (spa_vdev_exit(spa, NULL, txg, error));
-               }
-
-               /*
-                * Clean up the vdev namespace.
-                */
-               spa_vdev_remove_from_namespace(spa, vd);
-
-       } else if (vd != NULL) {
-               /*
-                * Normal vdevs cannot be removed (yet).
-                */
-               error = SET_ERROR(ENOTSUP);
-       } else {
-               /*
-                * There is no vdev of any kind with the specified guid.
-                */
-               error = SET_ERROR(ENOENT);
-       }
-
-       if (!locked)
-               return (spa_vdev_exit(spa, NULL, txg, error));
-
-       return (error);
-}
-
 /*
  * Find any device that's done replacing, or a vdev marked 'unspare' that's
  * currently spared, so we can detach it.
@@ -5675,9 +6307,8 @@ static vdev_t *
 spa_vdev_resilver_done_hunt(vdev_t *vd)
 {
        vdev_t *newvd, *oldvd;
-       int c;
 
-       for (c = 0; c < vd->vdev_children; c++) {
+       for (int c = 0; c < vd->vdev_children; c++) {
                oldvd = spa_vdev_resilver_done_hunt(vd->vdev_child[c]);
                if (oldvd != NULL)
                        return (oldvd);
@@ -5842,6 +6473,16 @@ spa_vdev_setfru(spa_t *spa, uint64_t guid, const char *newfru)
  * SPA Scanning
  * ==========================================================================
  */
+int
+spa_scrub_pause_resume(spa_t *spa, pool_scrub_cmd_t cmd)
+{
+       ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == 0);
+
+       if (dsl_scan_resilvering(spa->spa_dsl_pool))
+               return (SET_ERROR(EBUSY));
+
+       return (dsl_scrub_set_pause_resume(spa->spa_dsl_pool, cmd));
+}
 
 int
 spa_scan_stop(spa_t *spa)
@@ -5882,8 +6523,6 @@ spa_scan(spa_t *spa, pool_scan_func_t func)
 static void
 spa_async_remove(spa_t *spa, vdev_t *vd)
 {
-       int c;
-
        if (vd->vdev_remove_wanted) {
                vd->vdev_remove_wanted = B_FALSE;
                vd->vdev_delayed_close = B_FALSE;
@@ -5902,33 +6541,29 @@ spa_async_remove(spa_t *spa, vdev_t *vd)
                vdev_state_dirty(vd->vdev_top);
        }
 
-       for (c = 0; c < vd->vdev_children; c++)
+       for (int c = 0; c < vd->vdev_children; c++)
                spa_async_remove(spa, vd->vdev_child[c]);
 }
 
 static void
 spa_async_probe(spa_t *spa, vdev_t *vd)
 {
-       int c;
-
        if (vd->vdev_probe_wanted) {
                vd->vdev_probe_wanted = B_FALSE;
                vdev_reopen(vd);        /* vdev_open() does the actual probe */
        }
 
-       for (c = 0; c < vd->vdev_children; c++)
+       for (int c = 0; c < vd->vdev_children; c++)
                spa_async_probe(spa, vd->vdev_child[c]);
 }
 
 static void
 spa_async_autoexpand(spa_t *spa, vdev_t *vd)
 {
-       int c;
-
        if (!spa->spa_autoexpand)
                return;
 
-       for (c = 0; c < vd->vdev_children; c++) {
+       for (int c = 0; c < vd->vdev_children; c++) {
                vdev_t *cvd = vd->vdev_child[c];
                spa_async_autoexpand(spa, cvd);
        }
@@ -5936,13 +6571,14 @@ spa_async_autoexpand(spa_t *spa, vdev_t *vd)
        if (!vd->vdev_ops->vdev_op_leaf || vd->vdev_physpath == NULL)
                return;
 
-       spa_event_notify(vd->vdev_spa, vd, FM_EREPORT_ZFS_DEVICE_AUTOEXPAND);
+       spa_event_notify(vd->vdev_spa, vd, NULL, ESC_ZFS_VDEV_AUTOEXPAND);
 }
 
 static void
-spa_async_thread(spa_t *spa)
+spa_async_thread(void *arg)
 {
-       int tasks, i;
+       spa_t *spa = (spa_t *)arg;
+       int tasks;
 
        ASSERT(spa->spa_sync_on);
 
@@ -5980,9 +6616,9 @@ spa_async_thread(spa_t *spa)
        if (tasks & SPA_ASYNC_REMOVE) {
                spa_vdev_state_enter(spa, SCL_NONE);
                spa_async_remove(spa, spa->spa_root_vdev);
-               for (i = 0; i < spa->spa_l2cache.sav_count; i++)
+               for (int i = 0; i < spa->spa_l2cache.sav_count; i++)
                        spa_async_remove(spa, spa->spa_l2cache.sav_vdevs[i]);
-               for (i = 0; i < spa->spa_spares.sav_count; i++)
+               for (int i = 0; i < spa->spa_spares.sav_count; i++)
                        spa_async_remove(spa, spa->spa_spares.sav_vdevs[i]);
                (void) spa_vdev_state_exit(spa, NULL, 0);
        }
@@ -6032,6 +6668,12 @@ spa_async_suspend(spa_t *spa)
        while (spa->spa_async_thread != NULL)
                cv_wait(&spa->spa_async_cv, &spa->spa_async_lock);
        mutex_exit(&spa->spa_async_lock);
+
+       spa_vdev_remove_suspend(spa);
+
+       zthr_t *condense_thread = spa->spa_condense_zthr;
+       if (condense_thread != NULL && zthr_isrunning(condense_thread))
+               VERIFY0(zthr_cancel(condense_thread));
 }
 
 void
@@ -6041,6 +6683,11 @@ spa_async_resume(spa_t *spa)
        ASSERT(spa->spa_async_suspended != 0);
        spa->spa_async_suspended--;
        mutex_exit(&spa->spa_async_lock);
+       spa_restart_removal(spa);
+
+       zthr_t *condense_thread = spa->spa_condense_zthr;
+       if (condense_thread != NULL && !zthr_isrunning(condense_thread))
+               zthr_resume(condense_thread);
 }
 
 static boolean_t
@@ -6057,7 +6704,7 @@ spa_async_tasks_pending(spa_t *spa)
        } else {
                config_task_suspended =
                    (gethrtime() - spa->spa_ccw_fail_time) <
-                   (zfs_ccw_retry_interval * NANOSEC);
+                   ((hrtime_t)zfs_ccw_retry_interval * NANOSEC);
        }
 
        return (non_config_tasks || (config_task && !config_task_suspended));
@@ -6220,7 +6867,6 @@ static void
 spa_avz_build(vdev_t *vd, uint64_t avz, dmu_tx_t *tx)
 {
        spa_t *spa = vd->vdev_spa;
-       uint64_t i;
 
        if (vd->vdev_top_zap != 0) {
                VERIFY0(zap_add_int(spa->spa_meta_objset, avz,
@@ -6230,7 +6876,7 @@ spa_avz_build(vdev_t *vd, uint64_t avz, dmu_tx_t *tx)
                VERIFY0(zap_add_int(spa->spa_meta_objset, avz,
                    vd->vdev_leaf_zap, tx));
        }
-       for (i = 0; i < vd->vdev_children; i++) {
+       for (uint64_t i = 0; i < vd->vdev_children; i++) {
                spa_avz_build(vd->vdev_child[i], avz, tx);
        }
 }
@@ -6253,18 +6899,19 @@ spa_sync_config_object(spa_t *spa, dmu_tx_t *tx)
        spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
 
        ASSERT(spa->spa_avz_action == AVZ_ACTION_NONE ||
+           spa->spa_avz_action == AVZ_ACTION_INITIALIZE ||
            spa->spa_all_vdev_zaps != 0);
 
        if (spa->spa_avz_action == AVZ_ACTION_REBUILD) {
-               zap_cursor_t zc;
-               zap_attribute_t za;
-
                /* Make and build the new AVZ */
                uint64_t new_avz = zap_create(spa->spa_meta_objset,
                    DMU_OTN_ZAP_METADATA, DMU_OT_NONE, 0, tx);
                spa_avz_build(spa->spa_root_vdev, new_avz, tx);
 
                /* Diff old AVZ with new one */
+               zap_cursor_t zc;
+               zap_attribute_t za;
+
                for (zap_cursor_init(&zc, spa->spa_meta_objset,
                    spa->spa_all_vdev_zaps);
                    zap_cursor_retrieve(&zc, &za) == 0;
@@ -6386,9 +7033,8 @@ spa_sync_props(void *arg, dmu_tx_t *tx)
                zprop_type_t proptype;
                spa_feature_t fid;
 
-               prop = zpool_name_to_prop(nvpair_name(elem));
-               switch ((int)prop) {
-               case ZPROP_INVAL:
+               switch (prop = zpool_name_to_prop(nvpair_name(elem))) {
+               case ZPOOL_PROP_INVAL:
                        /*
                         * We checked this earlier in spa_prop_validate().
                         */
@@ -6405,7 +7051,7 @@ spa_sync_props(void *arg, dmu_tx_t *tx)
                case ZPOOL_PROP_VERSION:
                        intval = fnvpair_value_uint64(elem);
                        /*
-                        * The version is synced seperatly before other
+                        * The version is synced separately before other
                         * properties and should be correct by now.
                         */
                        ASSERT3U(spa_version(spa), >=, intval);
@@ -6435,7 +7081,7 @@ spa_sync_props(void *arg, dmu_tx_t *tx)
                         * We need to dirty the configuration on all the vdevs
                         * so that their labels get updated.  It's unnecessary
                         * to do this for pool creation since the vdev's
-                        * configuratoin has already been dirtied.
+                        * configuration has already been dirtied.
                         */
                        if (tx->tx_txg != TXG_INITIAL)
                                vdev_config_dirty(spa->spa_root_vdev);
@@ -6498,6 +7144,9 @@ spa_sync_props(void *arg, dmu_tx_t *tx)
                                        spa_async_request(spa,
                                            SPA_ASYNC_AUTOEXPAND);
                                break;
+                       case ZPOOL_PROP_MULTIHOST:
+                               spa->spa_multihost = intval;
+                               break;
                        case ZPOOL_PROP_DEDUPDITTO:
                                spa->spa_dedup_ditto = intval;
                                break;
@@ -6568,9 +7217,56 @@ spa_sync_upgrades(spa_t *spa, dmu_tx_t *tx)
                if (lz4_en && !lz4_ac)
                        spa_feature_incr(spa, SPA_FEATURE_LZ4_COMPRESS, tx);
        }
+
+       /*
+        * If we haven't written the salt, do so now.  Note that the
+        * feature may not be activated yet, but that's fine since
+        * the presence of this ZAP entry is backwards compatible.
+        */
+       if (zap_contains(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
+           DMU_POOL_CHECKSUM_SALT) == ENOENT) {
+               VERIFY0(zap_add(spa->spa_meta_objset,
+                   DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_CHECKSUM_SALT, 1,
+                   sizeof (spa->spa_cksum_salt.zcs_bytes),
+                   spa->spa_cksum_salt.zcs_bytes, tx));
+       }
+
        rrw_exit(&dp->dp_config_rwlock, FTAG);
 }
 
+static void
+vdev_indirect_state_sync_verify(vdev_t *vd)
+{
+       ASSERTV(vdev_indirect_mapping_t *vim = vd->vdev_indirect_mapping);
+       ASSERTV(vdev_indirect_births_t *vib = vd->vdev_indirect_births);
+
+       if (vd->vdev_ops == &vdev_indirect_ops) {
+               ASSERT(vim != NULL);
+               ASSERT(vib != NULL);
+       }
+
+       if (vdev_obsolete_sm_object(vd) != 0) {
+               ASSERT(vd->vdev_obsolete_sm != NULL);
+               ASSERT(vd->vdev_removing ||
+                   vd->vdev_ops == &vdev_indirect_ops);
+               ASSERT(vdev_indirect_mapping_num_entries(vim) > 0);
+               ASSERT(vdev_indirect_mapping_bytes_mapped(vim) > 0);
+
+               ASSERT3U(vdev_obsolete_sm_object(vd), ==,
+                   space_map_object(vd->vdev_obsolete_sm));
+               ASSERT3U(vdev_indirect_mapping_bytes_mapped(vim), >=,
+                   space_map_allocated(vd->vdev_obsolete_sm));
+       }
+       ASSERT(vd->vdev_obsolete_segments != NULL);
+
+       /*
+        * Since frees / remaps to an indirect vdev can only
+        * happen in syncing context, the obsolete segments
+        * tree must be empty when we start syncing.
+        */
+       ASSERT0(range_tree_space(vd->vdev_obsolete_segments));
+}
+
 /*
  * Sync the specified transaction group.  New blocks may be dirtied as
  * part of the process, so we iterate until it converges.
@@ -6585,10 +7281,18 @@ spa_sync(spa_t *spa, uint64_t txg)
        vdev_t *vd;
        dmu_tx_t *tx;
        int error;
-       int c;
+       uint32_t max_queue_depth = zfs_vdev_async_write_max_active *
+           zfs_vdev_queue_depth_pct / 100;
 
        VERIFY(spa_writeable(spa));
 
+       /*
+        * Wait for i/os issued in open context that need to complete
+        * before this txg syncs.
+        */
+       VERIFY0(zio_wait(spa->spa_txg_zio[txg & TXG_MASK]));
+       spa->spa_txg_zio[txg & TXG_MASK] = zio_root(spa, NULL, NULL, 0);
+
        /*
         * Lock out configuration changes.
         */
@@ -6597,6 +7301,10 @@ spa_sync(spa_t *spa, uint64_t txg)
        spa->spa_syncing_txg = txg;
        spa->spa_sync_pass = 0;
 
+       mutex_enter(&spa->spa_alloc_lock);
+       VERIFY0(avl_numnodes(&spa->spa_alloc_tree));
+       mutex_exit(&spa->spa_alloc_lock);
+
        /*
         * If there are any pending vdev state changes, convert them
         * into config changes that go out with this transaction group.
@@ -6624,8 +7332,8 @@ spa_sync(spa_t *spa, uint64_t txg)
        tx = dmu_tx_create_assigned(dp, txg);
 
        spa->spa_sync_starttime = gethrtime();
-       taskq_cancel_id(system_taskq, spa->spa_deadman_tqid);
-       spa->spa_deadman_tqid = taskq_dispatch_delay(system_taskq,
+       taskq_cancel_id(system_delay_taskq, spa->spa_deadman_tqid);
+       spa->spa_deadman_tqid = taskq_dispatch_delay(system_delay_taskq,
            spa_deadman, spa, TQ_SLEEP, ddi_get_lbolt() +
            NSEC_TO_TICK(spa->spa_deadman_synctime));
 
@@ -6650,6 +7358,48 @@ spa_sync(spa_t *spa, uint64_t txg)
                }
        }
 
+       /*
+        * Set the top-level vdev's max queue depth. Evaluate each
+        * top-level's async write queue depth in case it changed.
+        * The max queue depth will not change in the middle of syncing
+        * out this txg.
+        */
+       uint64_t queue_depth_total = 0;
+       for (int c = 0; c < rvd->vdev_children; c++) {
+               vdev_t *tvd = rvd->vdev_child[c];
+               metaslab_group_t *mg = tvd->vdev_mg;
+
+               if (mg == NULL || mg->mg_class != spa_normal_class(spa) ||
+                   !metaslab_group_initialized(mg))
+                       continue;
+
+               /*
+                * It is safe to do a lock-free check here because only async
+                * allocations look at mg_max_alloc_queue_depth, and async
+                * allocations all happen from spa_sync().
+                */
+               ASSERT0(refcount_count(&mg->mg_alloc_queue_depth));
+               mg->mg_max_alloc_queue_depth = max_queue_depth;
+               queue_depth_total += mg->mg_max_alloc_queue_depth;
+       }
+       metaslab_class_t *mc = spa_normal_class(spa);
+       ASSERT0(refcount_count(&mc->mc_alloc_slots));
+       mc->mc_alloc_max_slots = queue_depth_total;
+       mc->mc_alloc_throttle_enabled = zio_dva_throttle_enabled;
+
+       ASSERT3U(mc->mc_alloc_max_slots, <=,
+           max_queue_depth * rvd->vdev_children);
+
+       for (int c = 0; c < rvd->vdev_children; c++) {
+               vdev_t *vd = rvd->vdev_child[c];
+               vdev_indirect_state_sync_verify(vd);
+
+               if (vdev_indirect_should_condense(vd)) {
+                       spa_condense_indirect_start_sync(vd, tx);
+                       break;
+               }
+       }
+
        /*
         * Iterate to convergence.
         */
@@ -6679,7 +7429,11 @@ spa_sync(spa_t *spa, uint64_t txg)
                ddt_sync(spa, txg);
                dsl_scan_sync(dp, tx);
 
-               while ((vd = txg_list_remove(&spa->spa_vdev_txg_list, txg)))
+               if (spa->spa_vdev_removal != NULL)
+                       svr_sync(spa, tx);
+
+               while ((vd = txg_list_remove(&spa->spa_vdev_txg_list, txg))
+                   != NULL)
                        vdev_sync(vd, txg);
 
                if (pass == 1) {
@@ -6733,6 +7487,10 @@ spa_sync(spa_t *spa, uint64_t txg)
        }
 #endif
 
+       if (spa->spa_vdev_removal != NULL) {
+               ASSERT0(spa->spa_vdev_removal->svr_bytes_done[txg & TXG_MASK]);
+       }
+
        /*
         * Rewrite the vdev configuration (which includes the uberblock)
         * to commit the transaction group.
@@ -6750,17 +7508,18 @@ spa_sync(spa_t *spa, uint64_t txg)
                spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
 
                if (list_is_empty(&spa->spa_config_dirty_list)) {
-                       vdev_t *svd[SPA_DVAS_PER_BP];
+                       vdev_t *svd[SPA_SYNC_MIN_VDEVS];
                        int svdcount = 0;
                        int children = rvd->vdev_children;
                        int c0 = spa_get_random(children);
 
-                       for (c = 0; c < children; c++) {
+                       for (int c = 0; c < children; c++) {
                                vd = rvd->vdev_child[(c0 + c) % children];
-                               if (vd->vdev_ms_array == 0 || vd->vdev_islog)
+                               if (vd->vdev_ms_array == 0 || vd->vdev_islog ||
+                                   !vdev_is_concrete(vd))
                                        continue;
                                svd[svdcount++] = vd;
-                               if (svdcount == SPA_DVAS_PER_BP)
+                               if (svdcount == SPA_SYNC_MIN_VDEVS)
                                        break;
                        }
                        error = vdev_config_sync(svd, svdcount, txg);
@@ -6776,12 +7535,12 @@ spa_sync(spa_t *spa, uint64_t txg)
 
                if (error == 0)
                        break;
-               zio_suspend(spa, NULL);
+               zio_suspend(spa, NULL, ZIO_SUSPEND_IOERR);
                zio_resume_wait(spa);
        }
        dmu_tx_commit(tx);
 
-       taskq_cancel_id(system_taskq, spa->spa_deadman_tqid);
+       taskq_cancel_id(system_delay_taskq, spa->spa_deadman_tqid);
        spa->spa_deadman_tqid = 0;
 
        /*
@@ -6800,10 +7559,12 @@ spa_sync(spa_t *spa, uint64_t txg)
                spa->spa_config_syncing = NULL;
        }
 
-       spa->spa_ubsync = spa->spa_uberblock;
-
        dsl_pool_sync_done(dp, txg);
 
+       mutex_enter(&spa->spa_alloc_lock);
+       VERIFY0(avl_numnodes(&spa->spa_alloc_tree));
+       mutex_exit(&spa->spa_alloc_lock);
+
        /*
         * Update usable space statistics.
         */
@@ -6822,6 +7583,13 @@ spa_sync(spa_t *spa, uint64_t txg)
 
        spa->spa_sync_pass = 0;
 
+       /*
+        * Update the last synced uberblock here. We want to do this at
+        * the end of spa_sync() so that consumers of spa_last_synced_txg()
+        * will be guaranteed that all the processing associated with
+        * that txg has been completed.
+        */
+       spa->spa_ubsync = spa->spa_uberblock;
        spa_config_exit(spa, SCL_CONFIG, FTAG);
 
        spa_handle_ignored_writes(spa);
@@ -6985,18 +7753,44 @@ spa_has_active_shared_spare(spa_t *spa)
        return (B_FALSE);
 }
 
+sysevent_t *
+spa_event_create(spa_t *spa, vdev_t *vd, nvlist_t *hist_nvl, const char *name)
+{
+       sysevent_t *ev = NULL;
+#ifdef _KERNEL
+       nvlist_t *resource;
+
+       resource = zfs_event_create(spa, vd, FM_SYSEVENT_CLASS, name, hist_nvl);
+       if (resource) {
+               ev = kmem_alloc(sizeof (sysevent_t), KM_SLEEP);
+               ev->resource = resource;
+       }
+#endif
+       return (ev);
+}
+
+void
+spa_event_post(sysevent_t *ev)
+{
+#ifdef _KERNEL
+       if (ev) {
+               zfs_zevent_post(ev->resource, NULL, zfs_zevent_post_cb);
+               kmem_free(ev, sizeof (*ev));
+       }
+#endif
+}
+
 /*
- * Post a FM_EREPORT_ZFS_* event from sys/fm/fs/zfs.h.  The payload will be
+ * Post a zevent corresponding to the given sysevent.   The 'name' must be one
+ * of the event definitions in sys/sysevent/eventdefs.h.  The payload will be
  * filled in from the spa and (optionally) the vdev.  This doesn't do anything
  * in the userland libzpool, as we don't want consumers to misinterpret ztest
  * or zdb as real changes.
  */
 void
-spa_event_notify(spa_t *spa, vdev_t *vd, const char *name)
+spa_event_notify(spa_t *spa, vdev_t *vd, nvlist_t *hist_nvl, const char *name)
 {
-#ifdef _KERNEL
-       zfs_ereport_post(name, spa, vd, NULL, 0, 0);
-#endif
+       spa_event_post(spa_event_create(spa, vd, hist_nvl, name));
 }
 
 #if defined(_KERNEL) && defined(HAVE_SPL)
@@ -7005,7 +7799,6 @@ EXPORT_SYMBOL(spa_open);
 EXPORT_SYMBOL(spa_open_rewind);
 EXPORT_SYMBOL(spa_get_stats);
 EXPORT_SYMBOL(spa_create);
-EXPORT_SYMBOL(spa_import_rootpool);
 EXPORT_SYMBOL(spa_import);
 EXPORT_SYMBOL(spa_tryimport);
 EXPORT_SYMBOL(spa_destroy);
@@ -7023,7 +7816,6 @@ EXPORT_SYMBOL(spa_scan_get_stats);
 EXPORT_SYMBOL(spa_vdev_add);
 EXPORT_SYMBOL(spa_vdev_attach);
 EXPORT_SYMBOL(spa_vdev_detach);
-EXPORT_SYMBOL(spa_vdev_remove);
 EXPORT_SYMBOL(spa_vdev_setpath);
 EXPORT_SYMBOL(spa_vdev_setfru);
 EXPORT_SYMBOL(spa_vdev_split_mirror);
@@ -7071,8 +7863,20 @@ module_param(spa_load_verify_data, int, 0644);
 MODULE_PARM_DESC(spa_load_verify_data,
        "Set to traverse data on pool import");
 
+module_param(spa_load_print_vdev_tree, int, 0644);
+MODULE_PARM_DESC(spa_load_print_vdev_tree,
+       "Print vdev tree to zfs_dbgmsg during pool import");
+
+/* CSTYLED */
 module_param(zio_taskq_batch_pct, uint, 0444);
 MODULE_PARM_DESC(zio_taskq_batch_pct,
        "Percentage of CPUs to run an IO worker thread");
 
+/* BEGIN CSTYLED */
+module_param(zfs_max_missing_tvds, ulong, 0644);
+MODULE_PARM_DESC(zfs_max_missing_tvds,
+       "Allow importing pool with up to this number of missing top-level vdevs"
+       " (in read-only mode)");
+/* END CSTYLED */
+
 #endif