Fix ZVOL rename minor devices
[zfs.git] / module / zfs / spa.c
index b6190e4..3599e61 100644 (file)
@@ -40,6 +40,7 @@
 #include <sys/zil.h>
 #include <sys/ddt.h>
 #include <sys/vdev_impl.h>
+#include <sys/vdev_disk.h>
 #include <sys/metaslab.h>
 #include <sys/metaslab_impl.h>
 #include <sys/uberblock_impl.h>
@@ -94,7 +95,7 @@ typedef struct zio_taskq_info {
 } zio_taskq_info_t;
 
 static const char *const zio_taskq_types[ZIO_TASKQ_TYPES] = {
-       "issue", "issue_high", "intr", "intr_high"
+       "iss", "iss_h", "int", "int_h"
 };
 
 /*
@@ -105,7 +106,7 @@ const zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = {
        /* ISSUE        ISSUE_HIGH      INTR            INTR_HIGH */
        { ZTI_ONE,      ZTI_NULL,       ZTI_ONE,        ZTI_NULL },
        { ZTI_FIX(8),   ZTI_NULL,       ZTI_BATCH,      ZTI_NULL },
-       { ZTI_BATCH,    ZTI_FIX(5),     ZTI_FIX(8),     ZTI_FIX(5) },
+       { ZTI_BATCH,    ZTI_FIX(5),     ZTI_FIX(16),    ZTI_FIX(5) },
        { ZTI_FIX(100), ZTI_NULL,       ZTI_ONE,        ZTI_NULL },
        { ZTI_ONE,      ZTI_NULL,       ZTI_ONE,        ZTI_NULL },
        { ZTI_ONE,      ZTI_NULL,       ZTI_ONE,        ZTI_NULL },
@@ -113,7 +114,7 @@ const zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = {
 
 static dsl_syncfunc_t spa_sync_props;
 static boolean_t spa_has_active_shared_spare(spa_t *spa);
-static int spa_load_impl(spa_t *spa, uint64_t, nvlist_t *config,
+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 void spa_vdev_resilver_done(spa_t *spa);
@@ -229,7 +230,9 @@ spa_prop_get(spa_t *spa, nvlist_t **nvp)
        zap_attribute_t za;
        int err;
 
-       VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
+       err = nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP);
+       if (err)
+               return err;
 
        mutex_enter(&spa->spa_props_lock);
 
@@ -241,7 +244,7 @@ spa_prop_get(spa_t *spa, nvlist_t **nvp)
        /* If no pool property object, no more prop to get. */
        if (mos == NULL || spa->spa_pool_props_object == 0) {
                mutex_exit(&spa->spa_props_lock);
-               return (0);
+               goto out;
        }
 
        /*
@@ -271,8 +274,8 @@ spa_prop_get(spa_t *spa, nvlist_t **nvp)
 
                                dp = spa_get_dsl(spa);
                                rw_enter(&dp->dp_config_rwlock, RW_READER);
-                               if (err = dsl_dataset_hold_obj(dp,
-                                   za.za_first_integer, FTAG, &ds)) {
+                               if ((err = dsl_dataset_hold_obj(dp,
+                                   za.za_first_integer, FTAG, &ds))) {
                                        rw_exit(&dp->dp_config_rwlock);
                                        break;
                                }
@@ -334,7 +337,7 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
 {
        nvpair_t *elem;
        int error = 0, reset_bootfs = 0;
-       uint64_t objnum;
+       uint64_t objnum = 0;
 
        elem = NULL;
        while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
@@ -398,7 +401,7 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
                                        break;
                                }
 
-                               if (error = dmu_objset_hold(strval, FTAG, &os))
+                               if ((error = dmu_objset_hold(strval,FTAG,&os)))
                                        break;
 
                                /* Must be ZPL and not gzip compressed. */
@@ -471,6 +474,9 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
                            intval != 0 && intval < ZIO_DEDUPDITTO_MIN)
                                error = EINVAL;
                        break;
+
+               default:
+                       break;
                }
 
                if (error)
@@ -653,8 +659,10 @@ spa_taskq_create(spa_t *spa, const char *name, enum zti_modes mode,
 static void
 spa_create_zio_taskqs(spa_t *spa)
 {
-       for (int t = 0; t < ZIO_TYPES; t++) {
-               for (int q = 0; q < ZIO_TASKQ_TYPES; q++) {
+       int t, q;
+
+       for (t = 0; t < ZIO_TYPES; t++) {
+               for (q = 0; q < ZIO_TASKQ_TYPES; q++) {
                        const zio_taskq_info_t *ztip = &zio_taskqs[t][q];
                        enum zti_modes mode = ztip->zti_mode;
                        uint_t value = ztip->zti_value;
@@ -669,7 +677,7 @@ spa_create_zio_taskqs(spa_t *spa)
        }
 }
 
-#ifdef _KERNEL
+#if defined(_KERNEL) && defined(HAVE_SPA_THREAD)
 static void
 spa_thread(void *arg)
 {
@@ -759,6 +767,7 @@ spa_activate(spa_t *spa, int mode)
        ASSERT(spa->spa_proc == &p0);
        spa->spa_did = 0;
 
+#ifdef HAVE_SPA_THREAD
        /* Only create a process if we're going to be around a while. */
        if (spa_create_process && strcmp(spa->spa_name, TRYIMPORT_NAME) != 0) {
                if (newproc(spa_thread, (caddr_t)spa, syscid, maxclsyspri,
@@ -779,6 +788,7 @@ spa_activate(spa_t *spa, int mode)
 #endif
                }
        }
+#endif /* HAVE_SPA_THREAD */
        mutex_exit(&spa->spa_proc_lock);
 
        /* If we didn't create a process, we need to create our taskqs. */
@@ -808,6 +818,8 @@ 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);
@@ -819,8 +831,8 @@ spa_deactivate(spa_t *spa)
        list_destroy(&spa->spa_config_dirty_list);
        list_destroy(&spa->spa_state_dirty_list);
 
-       for (int t = 0; t < ZIO_TYPES; t++) {
-               for (int q = 0; q < ZIO_TASKQ_TYPES; q++) {
+       for (t = 0; t < ZIO_TYPES; t++) {
+               for (q = 0; q < ZIO_TASKQ_TYPES; q++) {
                        if (spa->spa_zio_taskq[t][q] != NULL)
                                taskq_destroy(spa->spa_zio_taskq[t][q]);
                        spa->spa_zio_taskq[t][q] = NULL;
@@ -883,6 +895,7 @@ 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);
@@ -902,7 +915,7 @@ spa_config_parse(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent,
                return (EINVAL);
        }
 
-       for (int c = 0; c < children; c++) {
+       for (c = 0; c < children; c++) {
                vdev_t *vd;
                if ((error = spa_config_parse(spa, &vd, child[c], *vdp, c,
                    atype)) != 0) {
@@ -1136,7 +1149,7 @@ spa_load_l2cache(spa_t *spa)
        uint_t nl2cache;
        int i, j, oldnvdevs;
        uint64_t guid;
-       vdev_t *vd, **oldvdevs, **newvdevs;
+       vdev_t *vd, **oldvdevs, **newvdevs = NULL;
        spa_aux_vdev_t *sav = &spa->spa_l2cache;
 
        ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL);
@@ -1262,7 +1275,7 @@ load_nvlist(spa_t *spa, uint64_t obj, nvlist_t **value)
        nvsize = *(uint64_t *)db->db_data;
        dmu_buf_rele(db, FTAG);
 
-       packed = kmem_alloc(nvsize, KM_SLEEP);
+       packed = kmem_alloc(nvsize, KM_SLEEP | KM_NODEBUG);
        error = dmu_read(spa->spa_meta_objset, obj, 0, nvsize, packed,
            DMU_READ_PREFETCH);
        if (error == 0)
@@ -1279,12 +1292,15 @@ load_nvlist(spa_t *spa, uint64_t obj, nvlist_t **value)
 static void
 spa_check_removed(vdev_t *vd)
 {
-       for (int c = 0; c < vd->vdev_children; c++)
+       int c;
+
+       for (c = 0; c < vd->vdev_children; c++)
                spa_check_removed(vd->vdev_child[c]);
 
        if (vd->vdev_ops->vdev_op_leaf && vdev_is_dead(vd)) {
-               zfs_post_autoreplace(vd->vdev_spa, vd);
-               spa_event_notify(vd->vdev_spa, vd, ESC_ZFS_VDEV_CHECK);
+               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);
        }
 }
 
@@ -1296,6 +1312,7 @@ spa_config_valid(spa_t *spa, nvlist_t *config)
 {
        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);
 
@@ -1317,7 +1334,7 @@ spa_config_valid(spa_t *spa, nvlist_t *config)
                    KM_SLEEP);
                VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0);
 
-               for (int c = 0; c < rvd->vdev_children; c++) {
+               for (c = 0; c < rvd->vdev_children; c++) {
                        vdev_t *tvd = rvd->vdev_child[c];
                        vdev_t *mtvd  = mrvd->vdev_child[c];
 
@@ -1334,7 +1351,7 @@ spa_config_valid(spa_t *spa, nvlist_t *config)
                        VERIFY(nvlist_add_nvlist(spa->spa_load_info,
                            ZPOOL_CONFIG_MISSING_DEVICES, nv) == 0);
 
-                       for (int i = 0; i < idx; i++)
+                       for (i = 0; i < idx; i++)
                                nvlist_free(child[i]);
                }
                nvlist_free(nv);
@@ -1346,7 +1363,7 @@ spa_config_valid(spa_t *spa, nvlist_t *config)
         * from the MOS config (mrvd). Check each top-level vdev
         * with the corresponding MOS config top-level (mtvd).
         */
-       for (int c = 0; c < rvd->vdev_children; c++) {
+       for (c = 0; c < rvd->vdev_children; c++) {
                vdev_t *tvd = rvd->vdev_child[c];
                vdev_t *mtvd  = mrvd->vdev_child[c];
 
@@ -1417,6 +1434,8 @@ static int
 spa_check_logs(spa_t *spa)
 {
        switch (spa->spa_log_state) {
+       default:
+               break;
        case SPA_LOG_MISSING:
                /* need to recheck in case slog has been restored */
        case SPA_LOG_UNKNOWN:
@@ -1435,13 +1454,14 @@ 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 (int c = 0; c < rvd->vdev_children; c++) {
+       for (c = 0; c < rvd->vdev_children; c++) {
                vdev_t *tvd = rvd->vdev_child[c];
                metaslab_group_t *mg = tvd->vdev_mg;
 
@@ -1458,10 +1478,11 @@ 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 (int c = 0; c < rvd->vdev_children; c++) {
+       for (c = 0; c < rvd->vdev_children; c++) {
                vdev_t *tvd = rvd->vdev_child[c];
                metaslab_group_t *mg = tvd->vdev_mg;
 
@@ -1491,7 +1512,9 @@ spa_offline_log(spa_t *spa)
 static void
 spa_aux_check_removed(spa_aux_vdev_t *sav)
 {
-       for (int i = 0; i < sav->sav_count; i++)
+       int i;
+
+       for (i = 0; i < sav->sav_count; i++)
                spa_check_removed(sav->sav_vdevs[i]);
 }
 
@@ -1773,7 +1796,8 @@ spa_load(spa_t *spa, spa_load_state_t state, spa_import_type_t type,
  * Load an existing storage pool, using the pool's builtin spa_config as a
  * source of configuration information.
  */
-static int
+__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)
@@ -2154,7 +2178,7 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
         * to start pushing transactions.
         */
        if (state != SPA_LOAD_TRYIMPORT) {
-               if (error = spa_load_verify(spa))
+               if ((error = spa_load_verify(spa)))
                        return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA,
                            error));
        }
@@ -2163,6 +2187,7 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
            spa->spa_load_max_txg == UINT64_MAX)) {
                dmu_tx_t *tx;
                int need_update = B_FALSE;
+               int c;
 
                ASSERT(state != SPA_LOAD_TRYIMPORT);
 
@@ -2209,7 +2234,7 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
                    (spa->spa_import_flags & ZFS_IMPORT_VERBATIM))
                        need_update = B_TRUE;
 
-               for (int c = 0; c < rvd->vdev_children; c++)
+               for (c = 0; c < rvd->vdev_children; c++)
                        if (rvd->vdev_child[c]->vdev_ms_array == 0)
                                need_update = B_TRUE;
 
@@ -2845,6 +2870,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
        nvlist_t **spares, **l2cache;
        uint_t nspares, nl2cache;
        uint64_t version, obj;
+       int c;
 
        /*
         * If this pool already exists, return failure.
@@ -2903,7 +2929,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 (int c = 0; c < rvd->vdev_children; c++) {
+               for (c = 0; c < rvd->vdev_children; c++) {
                        vdev_metaslab_set_size(rvd->vdev_child[c]);
                        vdev_expand(rvd->vdev_child[c], txg);
                }
@@ -3103,7 +3129,9 @@ spa_generate_rootconf(char *devpath, char *devid, uint64_t *guid)
 static void
 spa_alt_rootvdev(vdev_t *vd, vdev_t **avd, uint64_t *txg)
 {
-       for (int c = 0; c < vd->vdev_children; c++)
+       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) {
@@ -3617,7 +3645,7 @@ spa_export_common(char *pool, int new_state, nvlist_t **oldconfig,
                }
        }
 
-       spa_event_notify(spa, NULL, ESC_ZFS_POOL_DESTROY);
+       spa_event_notify(spa, NULL, FM_EREPORT_ZFS_POOL_DESTROY);
 
        if (spa->spa_state != POOL_STATE_UNINITIALIZED) {
                spa_unload(spa);
@@ -3687,6 +3715,7 @@ 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));
 
@@ -3723,7 +3752,7 @@ spa_vdev_add(spa_t *spa, nvlist_t *nvroot)
        /*
         * Transfer each new top-level vdev from vd to rvd.
         */
-       for (int c = 0; c < vd->vdev_children; c++) {
+       for (c = 0; c < vd->vdev_children; c++) {
 
                /*
                 * Set the vdev id to the first hole, if one exists.
@@ -3794,7 +3823,7 @@ int
 spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing)
 {
        uint64_t txg, dtl_max_txg;
-       vdev_t *rvd = spa->spa_root_vdev;
+       ASSERTV(vdev_t *rvd = spa->spa_root_vdev;)
        vdev_t *oldvd, *newvd, *newrootvd, *pvd, *tvd;
        vdev_ops_t *pvops;
        char *oldvdpath, *newvdpath;
@@ -3947,7 +3976,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, ESC_ZFS_VDEV_SPARE);
+               spa_event_notify(spa, newvd, FM_EREPORT_ZFS_DEVICE_SPARE);
        }
 
        oldvdpath = spa_strdup(oldvd->vdev_path);
@@ -3979,7 +4008,7 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing)
        spa_strfree(newvdpath);
 
        if (spa->spa_bootfs)
-               spa_event_notify(spa, newvd, ESC_ZFS_BOOTFS_VDEV_ATTACH);
+               spa_event_notify(spa, newvd, FM_EREPORT_ZFS_BOOTFS_VDEV_ATTACH);
 
        return (0);
 }
@@ -3994,11 +4023,12 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done)
 {
        uint64_t txg;
        int error;
-       vdev_t *rvd = spa->spa_root_vdev;
+       ASSERTV(vdev_t *rvd = spa->spa_root_vdev;)
        vdev_t *vd, *pvd, *cvd, *tvd;
        boolean_t unspare = B_FALSE;
-       uint64_t unspare_guid;
+       uint64_t unspare_guid = 0;
        char *vdpath;
+       int c, t;
 
        ASSERT(spa_writeable(spa));
 
@@ -4066,7 +4096,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 (int c = 0; c < pvd->vdev_children; c++) {
+               for (c = 0; c < pvd->vdev_children; c++) {
                        cvd = pvd->vdev_child[c];
 
                        if (cvd == vd || cvd->vdev_path == NULL)
@@ -4174,12 +4204,12 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done)
         * prevent vd from being accessed after it's freed.
         */
        vdpath = spa_strdup(vd->vdev_path);
-       for (int t = 0; t < TXG_SIZE; t++)
+       for (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, ESC_ZFS_VDEV_REMOVE);
+       spa_event_notify(spa, vd, FM_EREPORT_ZFS_DEVICE_REMOVE);
 
        /* hang on to the spa before we release the lock */
        spa_open_ref(spa, FTAG);
@@ -4509,7 +4539,9 @@ out:
 static nvlist_t *
 spa_nvlist_lookup_by_guid(nvlist_t **nvpp, int count, uint64_t target_guid)
 {
-       for (int i = 0; i < count; i++) {
+       int i;
+
+       for (i = 0; i < count; i++) {
                uint64_t guid;
 
                VERIFY(nvlist_lookup_uint64(nvpp[i], ZPOOL_CONFIG_GUID,
@@ -4527,11 +4559,12 @@ 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 (int i = 0, j = 0; i < count; i++) {
+       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);
@@ -4540,7 +4573,7 @@ spa_vdev_remove_aux(nvlist_t *config, char *name, nvlist_t **dev, int count,
        VERIFY(nvlist_remove(config, name, DATA_TYPE_NVLIST_ARRAY) == 0);
        VERIFY(nvlist_add_nvlist_array(config, name, newdev, count - 1) == 0);
 
-       for (int i = 0; i < count - 1; i++)
+       for (i = 0; i < count - 1; i++)
                nvlist_free(newdev[i]);
 
        if (count > 1)
@@ -4761,8 +4794,9 @@ static vdev_t *
 spa_vdev_resilver_done_hunt(vdev_t *vd)
 {
        vdev_t *newvd, *oldvd;
+       int c;
 
-       for (int c = 0; c < vd->vdev_children; c++) {
+       for (c = 0; c < vd->vdev_children; c++) {
                oldvd = spa_vdev_resilver_done_hunt(vd->vdev_child[c]);
                if (oldvd != NULL)
                        return (oldvd);
@@ -4965,6 +4999,8 @@ 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;
@@ -4983,33 +5019,33 @@ spa_async_remove(spa_t *spa, vdev_t *vd)
                vdev_state_dirty(vd->vdev_top);
        }
 
-       for (int c = 0; c < vd->vdev_children; c++)
+       for (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 (int c = 0; c < vd->vdev_children; c++)
+       for (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)
 {
-       sysevent_id_t eid;
-       nvlist_t *attr;
-       char *physpath;
+       int c;
 
        if (!spa->spa_autoexpand)
                return;
 
-       for (int c = 0; c < vd->vdev_children; c++) {
+       for (c = 0; c < vd->vdev_children; c++) {
                vdev_t *cvd = vd->vdev_child[c];
                spa_async_autoexpand(spa, cvd);
        }
@@ -5017,23 +5053,13 @@ spa_async_autoexpand(spa_t *spa, vdev_t *vd)
        if (!vd->vdev_ops->vdev_op_leaf || vd->vdev_physpath == NULL)
                return;
 
-       physpath = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
-       (void) snprintf(physpath, MAXPATHLEN, "/devices%s", vd->vdev_physpath);
-
-       VERIFY(nvlist_alloc(&attr, NV_UNIQUE_NAME, KM_SLEEP) == 0);
-       VERIFY(nvlist_add_string(attr, DEV_PHYS_PATH, physpath) == 0);
-
-       (void) ddi_log_sysevent(zfs_dip, SUNW_VENDOR, EC_DEV_STATUS,
-           ESC_DEV_DLE, attr, &eid, DDI_SLEEP);
-
-       nvlist_free(attr);
-       kmem_free(physpath, MAXPATHLEN);
+       spa_event_notify(vd->vdev_spa, vd, FM_EREPORT_ZFS_DEVICE_AUTOEXPAND);
 }
 
 static void
 spa_async_thread(spa_t *spa)
 {
-       int tasks;
+       int tasks, i;
 
        ASSERT(spa->spa_sync_on);
 
@@ -5072,9 +5098,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 (int i = 0; i < spa->spa_l2cache.sav_count; i++)
+               for (i = 0; i < spa->spa_l2cache.sav_count; i++)
                        spa_async_remove(spa, spa->spa_l2cache.sav_vdevs[i]);
-               for (int i = 0; i < spa->spa_spares.sav_count; i++)
+               for (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);
        }
@@ -5196,7 +5222,7 @@ spa_sync_nvlist(spa_t *spa, uint64_t obj, nvlist_t *nv, dmu_tx_t *tx)
         * saves us a pre-read to get data we don't actually care about.
         */
        bufsize = P2ROUNDUP(nvsize, SPA_CONFIG_BLOCKSIZE);
-       packed = kmem_alloc(bufsize, KM_SLEEP);
+       packed = vmem_alloc(bufsize, KM_SLEEP);
 
        VERIFY(nvlist_pack(nv, &packed, &nvsize, NV_ENCODE_XDR,
            KM_SLEEP) == 0);
@@ -5204,7 +5230,7 @@ spa_sync_nvlist(spa_t *spa, uint64_t obj, nvlist_t *nv, dmu_tx_t *tx)
 
        dmu_write(spa->spa_meta_objset, obj, 0, bufsize, packed, tx);
 
-       kmem_free(packed, bufsize);
+       vmem_free(packed, bufsize);
 
        VERIFY(0 == dmu_bonus_hold(spa->spa_meta_objset, obj, FTAG, &db));
        dmu_buf_will_dirty(db, tx);
@@ -5460,6 +5486,7 @@ spa_sync(spa_t *spa, uint64_t txg)
        vdev_t *vd;
        dmu_tx_t *tx;
        int error;
+       int c;
 
        VERIFY(spa_writeable(spa));
 
@@ -5563,7 +5590,7 @@ 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))
+               while ((vd = txg_list_remove(&spa->spa_vdev_txg_list, txg)))
                        vdev_sync(vd, txg);
 
                if (pass == 1)
@@ -5593,7 +5620,7 @@ spa_sync(spa_t *spa, uint64_t txg)
                        int children = rvd->vdev_children;
                        int c0 = spa_get_random(children);
 
-                       for (int c = 0; c < children; c++) {
+                       for (c = 0; c < children; c++) {
                                vd = rvd->vdev_child[(c0 + c) % children];
                                if (vd->vdev_ms_array == 0 || vd->vdev_islog)
                                        continue;
@@ -5645,7 +5672,7 @@ spa_sync(spa_t *spa, uint64_t txg)
        /*
         * Update usable space statistics.
         */
-       while (vd = txg_list_remove(&spa->spa_vdev_txg_list, TXG_CLEAN(txg)))
+       while ((vd = txg_list_remove(&spa->spa_vdev_txg_list, TXG_CLEAN(txg))))
                vdev_sync_done(vd, txg);
 
        spa_update_dspace(spa);
@@ -5824,8 +5851,7 @@ spa_has_active_shared_spare(spa_t *spa)
 }
 
 /*
- * Post a sysevent corresponding to the given event.  The 'name' must be one of
- * the event definitions in sys/sysevent/eventdefs.h.  The payload will be
+ * Post a FM_EREPORT_ZFS_* event from sys/fm/fs/zfs.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.
@@ -5834,49 +5860,65 @@ void
 spa_event_notify(spa_t *spa, vdev_t *vd, const char *name)
 {
 #ifdef _KERNEL
-       sysevent_t              *ev;
-       sysevent_attr_list_t    *attr = NULL;
-       sysevent_value_t        value;
-       sysevent_id_t           eid;
-
-       ev = sysevent_alloc(EC_ZFS, (char *)name, SUNW_KERN_PUB "zfs",
-           SE_SLEEP);
-
-       value.value_type = SE_DATA_TYPE_STRING;
-       value.value.sv_string = spa_name(spa);
-       if (sysevent_add_attr(&attr, ZFS_EV_POOL_NAME, &value, SE_SLEEP) != 0)
-               goto done;
-
-       value.value_type = SE_DATA_TYPE_UINT64;
-       value.value.sv_uint64 = spa_guid(spa);
-       if (sysevent_add_attr(&attr, ZFS_EV_POOL_GUID, &value, SE_SLEEP) != 0)
-               goto done;
-
-       if (vd) {
-               value.value_type = SE_DATA_TYPE_UINT64;
-               value.value.sv_uint64 = vd->vdev_guid;
-               if (sysevent_add_attr(&attr, ZFS_EV_VDEV_GUID, &value,
-                   SE_SLEEP) != 0)
-                       goto done;
-
-               if (vd->vdev_path) {
-                       value.value_type = SE_DATA_TYPE_STRING;
-                       value.value.sv_string = vd->vdev_path;
-                       if (sysevent_add_attr(&attr, ZFS_EV_VDEV_PATH,
-                           &value, SE_SLEEP) != 0)
-                               goto done;
-               }
-       }
-
-       if (sysevent_attach_attributes(ev, attr) != 0)
-               goto done;
-       attr = NULL;
-
-       (void) log_sysevent(ev, SE_SLEEP, &eid);
-
-done:
-       if (attr)
-               sysevent_free_attr(attr);
-       sysevent_free(ev);
+       zfs_ereport_post(name, spa, vd, NULL, 0, 0);
 #endif
 }
+
+#if defined(_KERNEL) && defined(HAVE_SPL)
+/* state manipulation functions */
+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);
+EXPORT_SYMBOL(spa_export);
+EXPORT_SYMBOL(spa_reset);
+EXPORT_SYMBOL(spa_async_request);
+EXPORT_SYMBOL(spa_async_suspend);
+EXPORT_SYMBOL(spa_async_resume);
+EXPORT_SYMBOL(spa_inject_addref);
+EXPORT_SYMBOL(spa_inject_delref);
+EXPORT_SYMBOL(spa_scan_stat_init);
+EXPORT_SYMBOL(spa_scan_get_stats);
+
+/* device maniion */
+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);
+
+/* spare statech is global across all pools) */
+EXPORT_SYMBOL(spa_spare_add);
+EXPORT_SYMBOL(spa_spare_remove);
+EXPORT_SYMBOL(spa_spare_exists);
+EXPORT_SYMBOL(spa_spare_activate);
+
+/* L2ARC statech is global across all pools) */
+EXPORT_SYMBOL(spa_l2cache_add);
+EXPORT_SYMBOL(spa_l2cache_remove);
+EXPORT_SYMBOL(spa_l2cache_exists);
+EXPORT_SYMBOL(spa_l2cache_activate);
+EXPORT_SYMBOL(spa_l2cache_drop);
+
+/* scanning */
+EXPORT_SYMBOL(spa_scan);
+EXPORT_SYMBOL(spa_scan_stop);
+
+/* spa syncing */
+EXPORT_SYMBOL(spa_sync); /* only for DMU use */
+EXPORT_SYMBOL(spa_sync_allpools);
+
+/* properties */
+EXPORT_SYMBOL(spa_prop_set);
+EXPORT_SYMBOL(spa_prop_get);
+EXPORT_SYMBOL(spa_prop_clear_bootfs);
+
+/* asynchronous event notification */
+EXPORT_SYMBOL(spa_event_notify);
+#endif