Update zio.c
[zfs.git] / module / zfs / zio.c
index a669ad6..0bc19a7 100644 (file)
@@ -19,8 +19,9 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
  */
 
 #include <sys/zfs_context.h>
@@ -32,6 +33,9 @@
 #include <sys/zio_impl.h>
 #include <sys/zio_compress.h>
 #include <sys/zio_checksum.h>
+#include <sys/dmu_objset.h>
+#include <sys/arc.h>
+#include <sys/ddt.h>
 
 /*
  * ==========================================================================
@@ -42,13 +46,15 @@ uint8_t zio_priority_table[ZIO_PRIORITY_TABLE_SIZE] = {
        0,      /* ZIO_PRIORITY_NOW             */
        0,      /* ZIO_PRIORITY_SYNC_READ       */
        0,      /* ZIO_PRIORITY_SYNC_WRITE      */
-       6,      /* ZIO_PRIORITY_ASYNC_READ      */
-       4,      /* ZIO_PRIORITY_ASYNC_WRITE     */
-       4,      /* ZIO_PRIORITY_FREE            */
-       0,      /* ZIO_PRIORITY_CACHE_FILL      */
        0,      /* ZIO_PRIORITY_LOG_WRITE       */
+       1,      /* ZIO_PRIORITY_CACHE_FILL      */
+       1,      /* ZIO_PRIORITY_AGG             */
+       4,      /* ZIO_PRIORITY_FREE            */
+       4,      /* ZIO_PRIORITY_ASYNC_WRITE     */
+       6,      /* ZIO_PRIORITY_ASYNC_READ      */
        10,     /* ZIO_PRIORITY_RESILVER        */
        20,     /* ZIO_PRIORITY_SCRUB           */
+       2,      /* ZIO_PRIORITY_DDT_PREFETCH    */
 };
 
 /*
@@ -57,11 +63,8 @@ uint8_t zio_priority_table[ZIO_PRIORITY_TABLE_SIZE] = {
  * ==========================================================================
  */
 char *zio_type_name[ZIO_TYPES] = {
-       "null", "read", "write", "free", "claim", "ioctl" };
-
-#define        SYNC_PASS_DEFERRED_FREE 1       /* defer frees after this pass */
-#define        SYNC_PASS_DONT_COMPRESS 4       /* don't compress after this pass */
-#define        SYNC_PASS_REWRITE       1       /* rewrite new bps after this pass */
+       "z_null", "z_rd", "z_wr", "z_fr", "z_cl", "z_ioctl"
+};
 
 /*
  * ==========================================================================
@@ -70,19 +73,77 @@ char *zio_type_name[ZIO_TYPES] = {
  */
 kmem_cache_t *zio_cache;
 kmem_cache_t *zio_link_cache;
+kmem_cache_t *zio_vdev_cache;
 kmem_cache_t *zio_buf_cache[SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT];
 kmem_cache_t *zio_data_buf_cache[SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT];
+int zio_bulk_flags = 0;
+int zio_delay_max = ZIO_DELAY_MAX;
 
 #ifdef _KERNEL
 extern vmem_t *zio_alloc_arena;
 #endif
+extern int zfs_mg_alloc_failures;
+
+/*
+ * The following actions directly effect the spa's sync-to-convergence logic.
+ * The values below define the sync pass when we start performing the action.
+ * Care should be taken when changing these values as they directly impact
+ * spa_sync() performance. Tuning these values may introduce subtle performance
+ * pathologies and should only be done in the context of performance analysis.
+ * These tunables will eventually be removed and replaced with #defines once
+ * enough analysis has been done to determine optimal values.
+ *
+ * The 'zfs_sync_pass_deferred_free' pass must be greater than 1 to ensure that
+ * regular blocks are not deferred.
+ */
+int zfs_sync_pass_deferred_free = 2; /* defer frees starting in this pass */
+int zfs_sync_pass_dont_compress = 5; /* don't compress starting in this pass */
+int zfs_sync_pass_rewrite = 2; /* rewrite new bps starting in this pass */
 
 /*
  * An allocating zio is one that either currently has the DVA allocate
  * stage set or will have it later in its lifetime.
  */
-#define        IO_IS_ALLOCATING(zio) \
-       ((zio)->io_orig_pipeline & (1U << ZIO_STAGE_DVA_ALLOCATE))
+#define        IO_IS_ALLOCATING(zio) ((zio)->io_orig_pipeline & ZIO_STAGE_DVA_ALLOCATE)
+
+int zio_requeue_io_start_cut_in_line = 1;
+
+#ifdef ZFS_DEBUG
+int zio_buf_debug_limit = 16384;
+#else
+int zio_buf_debug_limit = 0;
+#endif
+
+static inline void __zio_execute(zio_t *zio);
+
+static int
+zio_cons(void *arg, void *unused, int kmflag)
+{
+       zio_t *zio = arg;
+
+       bzero(zio, sizeof (zio_t));
+
+       mutex_init(&zio->io_lock, NULL, MUTEX_DEFAULT, NULL);
+       cv_init(&zio->io_cv, NULL, CV_DEFAULT, NULL);
+
+       list_create(&zio->io_parent_list, sizeof (zio_link_t),
+           offsetof(zio_link_t, zl_parent_node));
+       list_create(&zio->io_child_list, sizeof (zio_link_t),
+           offsetof(zio_link_t, zl_child_node));
+
+       return (0);
+}
+
+static void
+zio_dest(void *arg, void *unused)
+{
+       zio_t *zio = arg;
+
+       mutex_destroy(&zio->io_lock);
+       cv_destroy(&zio->io_cv);
+       list_destroy(&zio->io_parent_list);
+       list_destroy(&zio->io_child_list);
+}
 
 void
 zio_init(void)
@@ -93,10 +154,12 @@ zio_init(void)
 #ifdef _KERNEL
        data_alloc_arena = zio_alloc_arena;
 #endif
-       zio_cache = kmem_cache_create("zio_cache",
-           sizeof (zio_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
+       zio_cache = kmem_cache_create("zio_cache", sizeof (zio_t), 0,
+           zio_cons, zio_dest, NULL, NULL, NULL, KMC_KMEM);
        zio_link_cache = kmem_cache_create("zio_link_cache",
-           sizeof (zio_link_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
+           sizeof (zio_link_t), 0, NULL, NULL, NULL, NULL, NULL, KMC_KMEM);
+       zio_vdev_cache = kmem_cache_create("zio_vdev_cache", sizeof(vdev_io_t),
+           PAGESIZE, NULL, NULL, NULL, NULL, NULL, KMC_VMEM);
 
        /*
         * For small buffers, we want a cache for each multiple of
@@ -122,14 +185,27 @@ zio_init(void)
 
                if (align != 0) {
                        char name[36];
+                       int flags = zio_bulk_flags;
+
+                       /*
+                        * The smallest buffers (512b) are heavily used and
+                        * experience a lot of churn.  The slabs allocated
+                        * for them are also relatively small (32K).  Thus
+                        * in over to avoid expensive calls to vmalloc() we
+                        * make an exception to the usual slab allocation
+                        * policy and force these buffers to be kmem backed.
+                        */
+                       if (size == (1 << SPA_MINBLOCKSHIFT))
+                               flags |= KMC_KMEM;
+
                        (void) sprintf(name, "zio_buf_%lu", (ulong_t)size);
                        zio_buf_cache[c] = kmem_cache_create(name, size,
-                           align, NULL, NULL, NULL, NULL, NULL, KMC_NODEBUG);
+                           align, NULL, NULL, NULL, NULL, NULL, flags);
 
                        (void) sprintf(name, "zio_data_buf_%lu", (ulong_t)size);
                        zio_data_buf_cache[c] = kmem_cache_create(name, size,
-                           align, NULL, NULL, NULL, NULL, data_alloc_arena,
-                           KMC_NODEBUG);
+                           align, NULL, NULL, NULL, NULL,
+                           data_alloc_arena, flags);
                }
        }
 
@@ -143,7 +219,15 @@ zio_init(void)
                        zio_data_buf_cache[c - 1] = zio_data_buf_cache[c];
        }
 
+       /*
+        * The zio write taskqs have 1 thread per cpu, allow 1/2 of the taskqs
+        * to fail 3 times per txg or 8 failures, whichever is greater.
+        */
+       zfs_mg_alloc_failures = MAX((3 * max_ncpus / 2), 8);
+
        zio_inject_init();
+
+       lz4_init();
 }
 
 void
@@ -167,10 +251,13 @@ zio_fini(void)
                zio_data_buf_cache[c] = NULL;
        }
 
+       kmem_cache_destroy(zio_vdev_cache);
        kmem_cache_destroy(zio_link_cache);
        kmem_cache_destroy(zio_cache);
 
        zio_inject_fini();
+
+       lz4_fini();
 }
 
 /*
@@ -192,7 +279,7 @@ zio_buf_alloc(size_t size)
 
        ASSERT(c < SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT);
 
-       return (kmem_cache_alloc(zio_buf_cache[c], KM_PUSHPAGE));
+       return (kmem_cache_alloc(zio_buf_cache[c], KM_PUSHPAGE | KM_NODEBUG));
 }
 
 /*
@@ -208,7 +295,8 @@ zio_data_buf_alloc(size_t size)
 
        ASSERT(c < SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT);
 
-       return (kmem_cache_alloc(zio_data_buf_cache[c], KM_PUSHPAGE));
+       return (kmem_cache_alloc(zio_data_buf_cache[c],
+           KM_PUSHPAGE | KM_NODEBUG));
 }
 
 void
@@ -232,6 +320,24 @@ zio_data_buf_free(void *buf, size_t size)
 }
 
 /*
+ * Dedicated I/O buffers to ensure that memory fragmentation never prevents
+ * or significantly delays the issuing of a zio.   These buffers are used
+ * to aggregate I/O and could be used for raidz stripes.
+ */
+void *
+zio_vdev_alloc(void)
+{
+       return (kmem_cache_alloc(zio_vdev_cache, KM_PUSHPAGE));
+}
+
+void
+zio_vdev_free(void *buf)
+{
+       kmem_cache_free(zio_vdev_cache, buf);
+
+}
+
+/*
  * ==========================================================================
  * Push and pop I/O transform buffers
  * ==========================================================================
@@ -240,7 +346,7 @@ static void
 zio_push_transform(zio_t *zio, void *data, uint64_t size, uint64_t bufsize,
        zio_transform_func_t *transform)
 {
-       zio_transform_t *zt = kmem_alloc(sizeof (zio_transform_t), KM_SLEEP);
+       zio_transform_t *zt = kmem_alloc(sizeof (zio_transform_t), KM_PUSHPAGE);
 
        zt->zt_orig_data = zio->io_data;
        zt->zt_orig_size = zio->io_size;
@@ -264,7 +370,8 @@ zio_pop_transforms(zio_t *zio)
                        zt->zt_transform(zio,
                            zt->zt_orig_data, zt->zt_orig_size);
 
-               zio_buf_free(zio->io_data, zt->zt_bufsize);
+               if (zt->zt_bufsize != 0)
+                       zio_buf_free(zio->io_data, zt->zt_bufsize);
 
                zio->io_data = zt->zt_orig_data;
                zio->io_size = zt->zt_orig_size;
@@ -293,7 +400,7 @@ zio_decompress(zio_t *zio, void *data, uint64_t size)
 {
        if (zio->io_error == 0 &&
            zio_decompress_data(BP_GET_COMPRESS(zio->io_bp),
-           zio->io_data, zio->io_size, data, size) != 0)
+           zio->io_data, data, zio->io_size, size) != 0)
                zio->io_error = EIO;
 }
 
@@ -354,7 +461,8 @@ zio_unique_parent(zio_t *cio)
 void
 zio_add_child(zio_t *pio, zio_t *cio)
 {
-       zio_link_t *zl = kmem_cache_alloc(zio_link_cache, KM_SLEEP);
+       zio_link_t *zl = kmem_cache_alloc(zio_link_cache, KM_PUSHPAGE);
+       int w;
 
        /*
         * Logical I/Os can have logical, gang, or vdev children.
@@ -372,12 +480,15 @@ zio_add_child(zio_t *pio, zio_t *cio)
 
        ASSERT(pio->io_state[ZIO_WAIT_DONE] == 0);
 
-       for (int w = 0; w < ZIO_WAIT_TYPES; w++)
+       for (w = 0; w < ZIO_WAIT_TYPES; w++)
                pio->io_children[cio->io_child_type][w] += !cio->io_state[w];
 
        list_insert_head(&pio->io_child_list, zl);
        list_insert_head(&cio->io_parent_list, zl);
 
+       pio->io_child_count++;
+       cio->io_parent_count++;
+
        mutex_exit(&pio->io_lock);
        mutex_exit(&cio->io_lock);
 }
@@ -394,6 +505,9 @@ zio_remove_child(zio_t *pio, zio_t *cio, zio_link_t *zl)
        list_remove(&pio->io_child_list, zl);
        list_remove(&cio->io_parent_list, zl);
 
+       pio->io_child_count--;
+       cio->io_parent_count--;
+
        mutex_exit(&pio->io_lock);
        mutex_exit(&cio->io_lock);
 
@@ -409,7 +523,7 @@ zio_wait_for_children(zio_t *zio, enum zio_child child, enum zio_wait_type wait)
        mutex_enter(&zio->io_lock);
        ASSERT(zio->io_stall == NULL);
        if (*countp != 0) {
-               zio->io_stage--;
+               zio->io_stage >>= 1;
                zio->io_stall = countp;
                waiting = B_TRUE;
        }
@@ -418,7 +532,8 @@ zio_wait_for_children(zio_t *zio, enum zio_child child, enum zio_wait_type wait)
        return (waiting);
 }
 
-static void
+__attribute__((always_inline))
+static inline void
 zio_notify_parent(zio_t *pio, zio_t *zio, enum zio_wait_type wait)
 {
        uint64_t *countp = &pio->io_children[zio->io_child_type][wait];
@@ -432,7 +547,7 @@ zio_notify_parent(zio_t *pio, zio_t *zio, enum zio_wait_type wait)
        if (--*countp == 0 && pio->io_stall == countp) {
                pio->io_stall = NULL;
                mutex_exit(&pio->io_lock);
-               zio_execute(pio);
+               __zio_execute(pio);
        } else {
                mutex_exit(&pio->io_lock);
        }
@@ -451,10 +566,11 @@ zio_inherit_child_errors(zio_t *zio, enum zio_child c)
  * ==========================================================================
  */
 static zio_t *
-zio_create(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
+zio_create(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
     void *data, uint64_t size, zio_done_func_t *done, void *private,
-    zio_type_t type, int priority, int flags, vdev_t *vd, uint64_t offset,
-    const zbookmark_t *zb, uint8_t stage, uint32_t pipeline)
+    zio_type_t type, int priority, enum zio_flag flags,
+    vdev_t *vd, uint64_t offset, const zbookmark_t *zb,
+    enum zio_stage stage, enum zio_stage pipeline)
 {
        zio_t *zio;
 
@@ -466,50 +582,77 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
        ASSERT(!bp || !(flags & ZIO_FLAG_CONFIG_WRITER));
        ASSERT(vd || stage == ZIO_STAGE_OPEN);
 
-       zio = kmem_cache_alloc(zio_cache, KM_SLEEP);
-       bzero(zio, sizeof (zio_t));
-
-       mutex_init(&zio->io_lock, NULL, MUTEX_DEFAULT, NULL);
-       cv_init(&zio->io_cv, NULL, CV_DEFAULT, NULL);
-
-       list_create(&zio->io_parent_list, sizeof (zio_link_t),
-           offsetof(zio_link_t, zl_parent_node));
-       list_create(&zio->io_child_list, sizeof (zio_link_t),
-           offsetof(zio_link_t, zl_child_node));
+       zio = kmem_cache_alloc(zio_cache, KM_PUSHPAGE);
 
        if (vd != NULL)
                zio->io_child_type = ZIO_CHILD_VDEV;
        else if (flags & ZIO_FLAG_GANG_CHILD)
                zio->io_child_type = ZIO_CHILD_GANG;
+       else if (flags & ZIO_FLAG_DDT_CHILD)
+               zio->io_child_type = ZIO_CHILD_DDT;
        else
                zio->io_child_type = ZIO_CHILD_LOGICAL;
 
        if (bp != NULL) {
-               zio->io_bp = bp;
+               zio->io_logical = NULL;
+               zio->io_bp = (blkptr_t *)bp;
                zio->io_bp_copy = *bp;
                zio->io_bp_orig = *bp;
-               if (type != ZIO_TYPE_WRITE)
+               if (type != ZIO_TYPE_WRITE ||
+                   zio->io_child_type == ZIO_CHILD_DDT)
                        zio->io_bp = &zio->io_bp_copy;  /* so caller can free */
-               if (zio->io_child_type == ZIO_CHILD_LOGICAL) {
-                       if (BP_IS_GANG(bp))
-                               pipeline |= ZIO_GANG_STAGES;
+               if (zio->io_child_type == ZIO_CHILD_LOGICAL)
                        zio->io_logical = zio;
-               }
+               if (zio->io_child_type > ZIO_CHILD_GANG && BP_IS_GANG(bp))
+                       pipeline |= ZIO_GANG_STAGES;
+       } else {
+               zio->io_logical = NULL;
+               zio->io_bp = NULL;
+               bzero(&zio->io_bp_copy, sizeof (blkptr_t));
+               bzero(&zio->io_bp_orig, sizeof (blkptr_t));
        }
 
        zio->io_spa = spa;
        zio->io_txg = txg;
-       zio->io_data = data;
-       zio->io_size = size;
+       zio->io_ready = NULL;
        zio->io_done = done;
        zio->io_private = private;
+       zio->io_prev_space_delta = 0;
        zio->io_type = type;
        zio->io_priority = priority;
        zio->io_vd = vd;
+       zio->io_vsd = NULL;
+       zio->io_vsd_ops = NULL;
        zio->io_offset = offset;
+       zio->io_deadline = 0;
+       zio->io_timestamp = 0;
+       zio->io_delta = 0;
+       zio->io_delay = 0;
+       zio->io_orig_data = zio->io_data = data;
+       zio->io_orig_size = zio->io_size = size;
        zio->io_orig_flags = zio->io_flags = flags;
        zio->io_orig_stage = zio->io_stage = stage;
        zio->io_orig_pipeline = zio->io_pipeline = pipeline;
+       bzero(&zio->io_prop, sizeof (zio_prop_t));
+       zio->io_cmd = 0;
+       zio->io_reexecute = 0;
+       zio->io_bp_override = NULL;
+       zio->io_walk_link = NULL;
+       zio->io_transform_stack = NULL;
+       zio->io_error = 0;
+       zio->io_child_count = 0;
+       zio->io_parent_count = 0;
+       zio->io_stall = NULL;
+       zio->io_gang_leader = NULL;
+       zio->io_gang_tree = NULL;
+       zio->io_executor = NULL;
+       zio->io_waiter = NULL;
+       zio->io_cksum_report = NULL;
+       zio->io_ena = 0;
+       bzero(zio->io_child_error, sizeof (int) * ZIO_CHILD_TYPES);
+       bzero(zio->io_children,
+           sizeof (uint64_t) * ZIO_CHILD_TYPES * ZIO_WAIT_TYPES);
+       bzero(&zio->io_bookmark, sizeof (zbookmark_t));
 
        zio->io_state[ZIO_WAIT_READY] = (stage >= ZIO_STAGE_READY);
        zio->io_state[ZIO_WAIT_DONE] = (stage >= ZIO_STAGE_DONE);
@@ -520,35 +663,25 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
        if (pio != NULL) {
                if (zio->io_logical == NULL)
                        zio->io_logical = pio->io_logical;
+               if (zio->io_child_type == ZIO_CHILD_GANG)
+                       zio->io_gang_leader = pio->io_gang_leader;
                zio_add_child(pio, zio);
        }
 
+       taskq_init_ent(&zio->io_tqent);
+
        return (zio);
 }
 
 static void
 zio_destroy(zio_t *zio)
 {
-       spa_t *spa = zio->io_spa;
-       uint8_t async_root = zio->io_async_root;
-
-       list_destroy(&zio->io_parent_list);
-       list_destroy(&zio->io_child_list);
-       mutex_destroy(&zio->io_lock);
-       cv_destroy(&zio->io_cv);
        kmem_cache_free(zio_cache, zio);
-
-       if (async_root) {
-               mutex_enter(&spa->spa_async_root_lock);
-               if (--spa->spa_async_root_count == 0)
-                       cv_broadcast(&spa->spa_async_root_cv);
-               mutex_exit(&spa->spa_async_root_lock);
-       }
 }
 
 zio_t *
 zio_null(zio_t *pio, spa_t *spa, vdev_t *vd, zio_done_func_t *done,
-    void *private, int flags)
+    void *private, enum zio_flag flags)
 {
        zio_t *zio;
 
@@ -560,7 +693,7 @@ zio_null(zio_t *pio, spa_t *spa, vdev_t *vd, zio_done_func_t *done,
 }
 
 zio_t *
-zio_root(spa_t *spa, zio_done_func_t *done, void *private, int flags)
+zio_root(spa_t *spa, zio_done_func_t *done, void *private, enum zio_flag flags)
 {
        return (zio_null(NULL, spa, NULL, done, private, flags));
 }
@@ -568,33 +701,24 @@ zio_root(spa_t *spa, zio_done_func_t *done, void *private, int flags)
 zio_t *
 zio_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
     void *data, uint64_t size, zio_done_func_t *done, void *private,
-    int priority, int flags, const zbookmark_t *zb)
+    int priority, enum zio_flag flags, const zbookmark_t *zb)
 {
        zio_t *zio;
 
-       zio = zio_create(pio, spa, bp->blk_birth, (blkptr_t *)bp,
+       zio = zio_create(pio, spa, BP_PHYSICAL_BIRTH(bp), bp,
            data, size, done, private,
            ZIO_TYPE_READ, priority, flags, NULL, 0, zb,
-           ZIO_STAGE_OPEN, ZIO_READ_PIPELINE);
+           ZIO_STAGE_OPEN, (flags & ZIO_FLAG_DDT_CHILD) ?
+           ZIO_DDT_CHILD_READ_PIPELINE : ZIO_READ_PIPELINE);
 
        return (zio);
 }
 
-void
-zio_skip_write(zio_t *zio)
-{
-       ASSERT(zio->io_type == ZIO_TYPE_WRITE);
-       ASSERT(zio->io_stage == ZIO_STAGE_READY);
-       ASSERT(!BP_IS_GANG(zio->io_bp));
-
-       zio->io_pipeline &= ~ZIO_VDEV_IO_STAGES;
-}
-
 zio_t *
 zio_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
-    void *data, uint64_t size, zio_prop_t *zp,
+    void *data, uint64_t size, const zio_prop_t *zp,
     zio_done_func_t *ready, zio_done_func_t *done, void *private,
-    int priority, int flags, const zbookmark_t *zb)
+    int priority, enum zio_flag flags, const zbookmark_t *zb)
 {
        zio_t *zio;
 
@@ -602,15 +726,17 @@ zio_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
            zp->zp_checksum < ZIO_CHECKSUM_FUNCTIONS &&
            zp->zp_compress >= ZIO_COMPRESS_OFF &&
            zp->zp_compress < ZIO_COMPRESS_FUNCTIONS &&
-           zp->zp_type < DMU_OT_NUMTYPES &&
+           DMU_OT_IS_VALID(zp->zp_type) &&
            zp->zp_level < 32 &&
-           zp->zp_ndvas > 0 &&
-           zp->zp_ndvas <= spa_max_replication(spa));
-       ASSERT(ready != NULL);
+           zp->zp_copies > 0 &&
+           zp->zp_copies <= spa_max_replication(spa) &&
+           zp->zp_dedup <= 1 &&
+           zp->zp_dedup_verify <= 1);
 
        zio = zio_create(pio, spa, txg, bp, data, size, done, private,
            ZIO_TYPE_WRITE, priority, flags, NULL, 0, zb,
-           ZIO_STAGE_OPEN, ZIO_WRITE_PIPELINE);
+           ZIO_STAGE_OPEN, (flags & ZIO_FLAG_DDT_CHILD) ?
+           ZIO_DDT_CHILD_WRITE_PIPELINE : ZIO_WRITE_PIPELINE);
 
        zio->io_ready = ready;
        zio->io_prop = *zp;
@@ -621,7 +747,7 @@ zio_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
 zio_t *
 zio_rewrite(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp, void *data,
     uint64_t size, zio_done_func_t *done, void *private, int priority,
-    int flags, zbookmark_t *zb)
+    enum zio_flag flags, zbookmark_t *zb)
 {
        zio_t *zio;
 
@@ -632,33 +758,49 @@ zio_rewrite(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp, void *data,
        return (zio);
 }
 
+void
+zio_write_override(zio_t *zio, blkptr_t *bp, int copies)
+{
+       ASSERT(zio->io_type == ZIO_TYPE_WRITE);
+       ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL);
+       ASSERT(zio->io_stage == ZIO_STAGE_OPEN);
+       ASSERT(zio->io_txg == spa_syncing_txg(zio->io_spa));
+
+       zio->io_prop.zp_copies = copies;
+       zio->io_bp_override = bp;
+}
+
+void
+zio_free(spa_t *spa, uint64_t txg, const blkptr_t *bp)
+{
+       bplist_append(&spa->spa_free_bplist[txg & TXG_MASK], bp);
+}
+
 zio_t *
-zio_free(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
-    zio_done_func_t *done, void *private, int flags)
+zio_free_sync(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
+    enum zio_flag flags)
 {
        zio_t *zio;
 
+       dprintf_bp(bp, "freeing in txg %llu, pass %u",
+           (longlong_t)txg, spa->spa_sync_pass);
+
        ASSERT(!BP_IS_HOLE(bp));
+       ASSERT(spa_syncing_txg(spa) == txg);
+       ASSERT(spa_sync_pass(spa) < zfs_sync_pass_deferred_free);
 
-       if (bp->blk_fill == BLK_FILL_ALREADY_FREED)
-               return (zio_null(pio, spa, NULL, NULL, NULL, flags));
-
-       if (txg == spa->spa_syncing_txg &&
-           spa_sync_pass(spa) > SYNC_PASS_DEFERRED_FREE) {
-               bplist_enqueue_deferred(&spa->spa_sync_bplist, bp);
-               return (zio_null(pio, spa, NULL, NULL, NULL, flags));
-       }
+       arc_freed(spa, bp);
 
        zio = zio_create(pio, spa, txg, bp, NULL, BP_GET_PSIZE(bp),
-           done, private, ZIO_TYPE_FREE, ZIO_PRIORITY_FREE, flags,
+           NULL, NULL, ZIO_TYPE_FREE, ZIO_PRIORITY_FREE, flags,
            NULL, 0, NULL, ZIO_STAGE_OPEN, ZIO_FREE_PIPELINE);
 
        return (zio);
 }
 
 zio_t *
-zio_claim(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
-    zio_done_func_t *done, void *private, int flags)
+zio_claim(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
+    zio_done_func_t *done, void *private, enum zio_flag flags)
 {
        zio_t *zio;
 
@@ -672,9 +814,11 @@ zio_claim(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
         *
         * All claims *must* be resolved in the first txg -- before the SPA
         * starts allocating blocks -- so that nothing is allocated twice.
+        * If txg == 0 we just verify that the block is claimable.
         */
        ASSERT3U(spa->spa_uberblock.ub_rootbp.blk_birth, <, spa_first_txg(spa));
-       ASSERT3U(spa_first_txg(spa), <=, txg);
+       ASSERT(txg == spa_first_txg(spa) || txg == 0);
+       ASSERT(!BP_GET_DEDUP(bp) || !spa_writeable(spa));       /* zdb(1M) */
 
        zio = zio_create(pio, spa, txg, bp, NULL, BP_GET_PSIZE(bp),
            done, private, ZIO_TYPE_CLAIM, ZIO_PRIORITY_NOW, flags,
@@ -685,7 +829,7 @@ zio_claim(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
 
 zio_t *
 zio_ioctl(zio_t *pio, spa_t *spa, vdev_t *vd, int cmd,
-    zio_done_func_t *done, void *private, int priority, int flags)
+    zio_done_func_t *done, void *private, int priority, enum zio_flag flags)
 {
        zio_t *zio;
        int c;
@@ -710,7 +854,7 @@ zio_ioctl(zio_t *pio, spa_t *spa, vdev_t *vd, int cmd,
 zio_t *
 zio_read_phys(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size,
     void *data, int checksum, zio_done_func_t *done, void *private,
-    int priority, int flags, boolean_t labels)
+    int priority, enum zio_flag flags, boolean_t labels)
 {
        zio_t *zio;
 
@@ -731,7 +875,7 @@ zio_read_phys(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size,
 zio_t *
 zio_write_phys(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size,
     void *data, int checksum, zio_done_func_t *done, void *private,
-    int priority, int flags, boolean_t labels)
+    int priority, enum zio_flag flags, boolean_t labels)
 {
        zio_t *zio;
 
@@ -746,9 +890,9 @@ zio_write_phys(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size,
 
        zio->io_prop.zp_checksum = checksum;
 
-       if (zio_checksum_table[checksum].ci_zbt) {
+       if (zio_checksum_table[checksum].ci_eck) {
                /*
-                * zbt checksums are necessarily destructive -- they modify
+                * zec checksums are necessarily destructive -- they modify
                 * the end of the write buffer to hold the verifier/checksum.
                 * Therefore, we must make a local copy in case the data is
                 * being written to multiple places in parallel.
@@ -766,10 +910,10 @@ zio_write_phys(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size,
  */
 zio_t *
 zio_vdev_child_io(zio_t *pio, blkptr_t *bp, vdev_t *vd, uint64_t offset,
-       void *data, uint64_t size, int type, int priority, int flags,
+       void *data, uint64_t size, int type, int priority, enum zio_flag flags,
        zio_done_func_t *done, void *private)
 {
-       uint32_t pipeline = ZIO_VDEV_CHILD_PIPELINE;
+       enum zio_stage pipeline = ZIO_VDEV_CHILD_PIPELINE;
        zio_t *zio;
 
        ASSERT(vd->vdev_parent ==
@@ -782,26 +926,33 @@ zio_vdev_child_io(zio_t *pio, blkptr_t *bp, vdev_t *vd, uint64_t offset,
                 * detection as close to the leaves as possible and
                 * eliminates redundant checksums in the interior nodes.
                 */
-               pipeline |= 1U << ZIO_STAGE_CHECKSUM_VERIFY;
-               pio->io_pipeline &= ~(1U << ZIO_STAGE_CHECKSUM_VERIFY);
+               pipeline |= ZIO_STAGE_CHECKSUM_VERIFY;
+               pio->io_pipeline &= ~ZIO_STAGE_CHECKSUM_VERIFY;
        }
 
        if (vd->vdev_children == 0)
                offset += VDEV_LABEL_START_SIZE;
 
+       flags |= ZIO_VDEV_CHILD_FLAGS(pio) | ZIO_FLAG_DONT_PROPAGATE;
+
+       /*
+        * If we've decided to do a repair, the write is not speculative --
+        * even if the original read was.
+        */
+       if (flags & ZIO_FLAG_IO_REPAIR)
+               flags &= ~ZIO_FLAG_SPECULATIVE;
+
        zio = zio_create(pio, pio->io_spa, pio->io_txg, bp, data, size,
-           done, private, type, priority,
-           (pio->io_flags & ZIO_FLAG_VDEV_INHERIT) |
-           ZIO_FLAG_CANFAIL | ZIO_FLAG_DONT_PROPAGATE | flags,
-           vd, offset, &pio->io_bookmark,
-           ZIO_STAGE_VDEV_IO_START - 1, pipeline);
+           done, private, type, priority, flags, vd, offset, &pio->io_bookmark,
+           ZIO_STAGE_VDEV_IO_START >> 1, pipeline);
 
        return (zio);
 }
 
 zio_t *
 zio_vdev_delegated_io(vdev_t *vd, uint64_t offset, void *data, uint64_t size,
-       int type, int priority, int flags, zio_done_func_t *done, void *private)
+       int type, int priority, enum zio_flag flags,
+       zio_done_func_t *done, void *private)
 {
        zio_t *zio;
 
@@ -811,7 +962,7 @@ zio_vdev_delegated_io(vdev_t *vd, uint64_t offset, void *data, uint64_t size,
            data, size, done, private, type, priority,
            flags | ZIO_FLAG_CANFAIL | ZIO_FLAG_DONT_RETRY,
            vd, offset, NULL,
-           ZIO_STAGE_VDEV_IO_START - 1, ZIO_VDEV_CHILD_PIPELINE);
+           ZIO_STAGE_VDEV_IO_START >> 1, ZIO_VDEV_CHILD_PIPELINE);
 
        return (zio);
 }
@@ -824,6 +975,23 @@ zio_flush(zio_t *zio, vdev_t *vd)
            ZIO_FLAG_CANFAIL | ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY));
 }
 
+void
+zio_shrink(zio_t *zio, uint64_t size)
+{
+       ASSERT(zio->io_executor == NULL);
+       ASSERT(zio->io_orig_size == zio->io_size);
+       ASSERT(size <= zio->io_size);
+
+       /*
+        * We don't shrink for raidz because of problems with the
+        * reconstruction when reading back less than the block size.
+        * Note, BP_IS_RAIDZ() assumes no compression.
+        */
+       ASSERT(BP_GET_COMPRESS(zio->io_bp) == ZIO_COMPRESS_OFF);
+       if (!BP_IS_RAIDZ(zio->io_bp))
+               zio->io_orig_size = zio->io_size = size;
+}
+
 /*
  * ==========================================================================
  * Prepare to read and write logical blocks
@@ -836,29 +1004,35 @@ zio_read_bp_init(zio_t *zio)
        blkptr_t *bp = zio->io_bp;
 
        if (BP_GET_COMPRESS(bp) != ZIO_COMPRESS_OFF &&
-           zio->io_logical == zio && !(zio->io_flags & ZIO_FLAG_RAW)) {
-               uint64_t csize = BP_GET_PSIZE(bp);
-               void *cbuf = zio_buf_alloc(csize);
+           zio->io_child_type == ZIO_CHILD_LOGICAL &&
+           !(zio->io_flags & ZIO_FLAG_RAW)) {
+               uint64_t psize = BP_GET_PSIZE(bp);
+               void *cbuf = zio_buf_alloc(psize);
 
-               zio_push_transform(zio, cbuf, csize, csize, zio_decompress);
+               zio_push_transform(zio, cbuf, psize, psize, zio_decompress);
        }
 
-       if (!dmu_ot[BP_GET_TYPE(bp)].ot_metadata && BP_GET_LEVEL(bp) == 0)
+       if (!DMU_OT_IS_METADATA(BP_GET_TYPE(bp)) && BP_GET_LEVEL(bp) == 0)
                zio->io_flags |= ZIO_FLAG_DONT_CACHE;
 
+       if (BP_GET_TYPE(bp) == DMU_OT_DDT_ZAP)
+               zio->io_flags |= ZIO_FLAG_DONT_CACHE;
+
+       if (BP_GET_DEDUP(bp) && zio->io_child_type == ZIO_CHILD_LOGICAL)
+               zio->io_pipeline = ZIO_DDT_READ_PIPELINE;
+
        return (ZIO_PIPELINE_CONTINUE);
 }
 
 static int
 zio_write_bp_init(zio_t *zio)
 {
+       spa_t *spa = zio->io_spa;
        zio_prop_t *zp = &zio->io_prop;
-       int compress = zp->zp_compress;
+       enum zio_compress compress = zp->zp_compress;
        blkptr_t *bp = zio->io_bp;
-       void *cbuf;
        uint64_t lsize = zio->io_size;
-       uint64_t csize = lsize;
-       uint64_t cbufsize = 0;
+       uint64_t psize = lsize;
        int pass = 1;
 
        /*
@@ -872,7 +1046,29 @@ zio_write_bp_init(zio_t *zio)
        if (!IO_IS_ALLOCATING(zio))
                return (ZIO_PIPELINE_CONTINUE);
 
-       ASSERT(compress != ZIO_COMPRESS_INHERIT);
+       ASSERT(zio->io_child_type != ZIO_CHILD_DDT);
+
+       if (zio->io_bp_override) {
+               ASSERT(bp->blk_birth != zio->io_txg);
+               ASSERT(BP_GET_DEDUP(zio->io_bp_override) == 0);
+
+               *bp = *zio->io_bp_override;
+               zio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
+
+               if (BP_IS_HOLE(bp) || !zp->zp_dedup)
+                       return (ZIO_PIPELINE_CONTINUE);
+
+               ASSERT(zio_checksum_table[zp->zp_checksum].ci_dedup ||
+                   zp->zp_dedup_verify);
+
+               if (BP_GET_CHECKSUM(bp) == zp->zp_checksum) {
+                       BP_SET_DEDUP(bp, 1);
+                       zio->io_pipeline |= ZIO_STAGE_DDT_WRITE;
+                       return (ZIO_PIPELINE_CONTINUE);
+               }
+               zio->io_bp_override = NULL;
+               BP_ZERO(bp);
+       }
 
        if (bp->blk_birth == zio->io_txg) {
                /*
@@ -884,28 +1080,29 @@ zio_write_bp_init(zio_t *zio)
                 * convergence take longer.  Therefore, after the first
                 * few passes, stop compressing to ensure convergence.
                 */
-               pass = spa_sync_pass(zio->io_spa);
-               ASSERT(pass > 1);
+               pass = spa_sync_pass(spa);
 
-               if (pass > SYNC_PASS_DONT_COMPRESS)
-                       compress = ZIO_COMPRESS_OFF;
+               ASSERT(zio->io_txg == spa_syncing_txg(spa));
+               ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL);
+               ASSERT(!BP_GET_DEDUP(bp));
 
-               /*
-                * Only MOS (objset 0) data should need to be rewritten.
-                */
-               ASSERT(zio->io_logical->io_bookmark.zb_objset == 0);
+               if (pass >= zfs_sync_pass_dont_compress)
+                       compress = ZIO_COMPRESS_OFF;
 
                /* Make sure someone doesn't change their mind on overwrites */
-               ASSERT(MIN(zp->zp_ndvas + BP_IS_GANG(bp),
-                   spa_max_replication(zio->io_spa)) == BP_GET_NDVAS(bp));
+               ASSERT(MIN(zp->zp_copies + BP_IS_GANG(bp),
+                   spa_max_replication(spa)) == BP_GET_NDVAS(bp));
        }
 
        if (compress != ZIO_COMPRESS_OFF) {
-               if (!zio_compress_data(compress, zio->io_data, zio->io_size,
-                   &cbuf, &csize, &cbufsize)) {
+               void *cbuf = zio_buf_alloc(lsize);
+               psize = zio_compress_data(compress, zio->io_data, cbuf, lsize);
+               if (psize == 0 || psize == lsize) {
                        compress = ZIO_COMPRESS_OFF;
-               } else if (csize != 0) {
-                       zio_push_transform(zio, cbuf, csize, cbufsize, NULL);
+                       zio_buf_free(cbuf, lsize);
+               } else {
+                       ASSERT(psize < lsize);
+                       zio_push_transform(zio, cbuf, psize, lsize, NULL);
                }
        }
 
@@ -917,10 +1114,10 @@ zio_write_bp_init(zio_t *zio)
         * spa_sync() to allocate new blocks, but force rewrites after that.
         * There should only be a handful of blocks after pass 1 in any case.
         */
-       if (bp->blk_birth == zio->io_txg && BP_GET_PSIZE(bp) == csize &&
-           pass > SYNC_PASS_REWRITE) {
-               ASSERT(csize != 0);
-               uint32_t gang_stages = zio->io_pipeline & ZIO_GANG_STAGES;
+       if (bp->blk_birth == zio->io_txg && BP_GET_PSIZE(bp) == psize &&
+           pass >= zfs_sync_pass_rewrite) {
+               enum zio_stage gang_stages = zio->io_pipeline & ZIO_GANG_STAGES;
+               ASSERT(psize != 0);
                zio->io_pipeline = ZIO_REWRITE_PIPELINE | gang_stages;
                zio->io_flags |= ZIO_FLAG_IO_REWRITE;
        } else {
@@ -928,17 +1125,36 @@ zio_write_bp_init(zio_t *zio)
                zio->io_pipeline = ZIO_WRITE_PIPELINE;
        }
 
-       if (csize == 0) {
+       if (psize == 0) {
                zio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
        } else {
                ASSERT(zp->zp_checksum != ZIO_CHECKSUM_GANG_HEADER);
                BP_SET_LSIZE(bp, lsize);
-               BP_SET_PSIZE(bp, csize);
+               BP_SET_PSIZE(bp, psize);
                BP_SET_COMPRESS(bp, compress);
                BP_SET_CHECKSUM(bp, zp->zp_checksum);
                BP_SET_TYPE(bp, zp->zp_type);
                BP_SET_LEVEL(bp, zp->zp_level);
+               BP_SET_DEDUP(bp, zp->zp_dedup);
                BP_SET_BYTEORDER(bp, ZFS_HOST_BYTEORDER);
+               if (zp->zp_dedup) {
+                       ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL);
+                       ASSERT(!(zio->io_flags & ZIO_FLAG_IO_REWRITE));
+                       zio->io_pipeline = ZIO_DDT_WRITE_PIPELINE;
+               }
+       }
+
+       return (ZIO_PIPELINE_CONTINUE);
+}
+
+static int
+zio_free_bp_init(zio_t *zio)
+{
+       blkptr_t *bp = zio->io_bp;
+
+       if (zio->io_child_type == ZIO_CHILD_LOGICAL) {
+               if (BP_GET_DEDUP(bp))
+                       zio->io_pipeline = ZIO_DDT_FREE_PIPELINE;
        }
 
        return (ZIO_PIPELINE_CONTINUE);
@@ -951,16 +1167,18 @@ zio_write_bp_init(zio_t *zio)
  */
 
 static void
-zio_taskq_dispatch(zio_t *zio, enum zio_taskq_type q)
+zio_taskq_dispatch(zio_t *zio, zio_taskq_type_t q, boolean_t cutinline)
 {
+       spa_t *spa = zio->io_spa;
        zio_type_t t = zio->io_type;
+       int flags = (cutinline ? TQ_FRONT : 0);
 
        /*
-        * If we're a config writer, the normal issue and interrupt threads
-        * may all be blocked waiting for the config lock.  In this case,
-        * select the otherwise-unused taskq for ZIO_TYPE_NULL.
+        * If we're a config writer or a probe, the normal issue and
+        * interrupt threads may all be blocked waiting for the config lock.
+        * In this case, select the otherwise-unused taskq for ZIO_TYPE_NULL.
         */
-       if (zio->io_flags & ZIO_FLAG_CONFIG_WRITER)
+       if (zio->io_flags & (ZIO_FLAG_CONFIG_WRITER | ZIO_FLAG_PROBE))
                t = ZIO_TYPE_NULL;
 
        /*
@@ -969,19 +1187,41 @@ zio_taskq_dispatch(zio_t *zio, enum zio_taskq_type q)
        if (t == ZIO_TYPE_WRITE && zio->io_vd && zio->io_vd->vdev_aux)
                t = ZIO_TYPE_NULL;
 
-       (void) taskq_dispatch(zio->io_spa->spa_zio_taskq[t][q],
-           (task_func_t *)zio_execute, zio, TQ_SLEEP);
+       /*
+        * If this is a high priority I/O, then use the high priority taskq if
+        * available.
+        */
+       if (zio->io_priority == ZIO_PRIORITY_NOW &&
+           spa->spa_zio_taskq[t][q + 1].stqs_count != 0)
+               q++;
+
+       ASSERT3U(q, <, ZIO_TASKQ_TYPES);
+
+       /*
+        * NB: We are assuming that the zio can only be dispatched
+        * to a single taskq at a time.  It would be a grievous error
+        * to dispatch the zio to another taskq at the same time.
+        */
+       ASSERT(taskq_empty_ent(&zio->io_tqent));
+       spa_taskq_dispatch_ent(spa, t, q, (task_func_t *)zio_execute, zio,
+           flags, &zio->io_tqent);
 }
 
 static boolean_t
-zio_taskq_member(zio_t *zio, enum zio_taskq_type q)
+zio_taskq_member(zio_t *zio, zio_taskq_type_t q)
 {
        kthread_t *executor = zio->io_executor;
        spa_t *spa = zio->io_spa;
-
-       for (zio_type_t t = 0; t < ZIO_TYPES; t++)
-               if (taskq_member(spa->spa_zio_taskq[t][q], executor))
-                       return (B_TRUE);
+       zio_type_t t;
+
+       for (t = 0; t < ZIO_TYPES; t++) {
+               spa_taskqs_t *tqs = &spa->spa_zio_taskq[t][q];
+               uint_t i;
+               for (i = 0; i < tqs->stqs_count; i++) {
+                       if (taskq_member(tqs->stqs_taskq[i], executor))
+                               return (B_TRUE);
+               }
+       }
 
        return (B_FALSE);
 }
@@ -989,7 +1229,7 @@ zio_taskq_member(zio_t *zio, enum zio_taskq_type q)
 static int
 zio_issue_async(zio_t *zio)
 {
-       zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE);
+       zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE, B_FALSE);
 
        return (ZIO_PIPELINE_STOP);
 }
@@ -997,7 +1237,7 @@ zio_issue_async(zio_t *zio)
 void
 zio_interrupt(zio_t *zio)
 {
-       zio_taskq_dispatch(zio, ZIO_TASKQ_INTERRUPT);
+       zio_taskq_dispatch(zio, ZIO_TASKQ_INTERRUPT, B_FALSE);
 }
 
 /*
@@ -1008,45 +1248,86 @@ zio_interrupt(zio_t *zio)
  * vdev-level caching or aggregation; (5) the I/O is deferred
  * due to vdev-level queueing; (6) the I/O is handed off to
  * another thread.  In all cases, the pipeline stops whenever
- * there's no CPU work; it never burns a thread in cv_wait().
+ * there's no CPU work; it never burns a thread in cv_wait_io().
  *
  * There's no locking on io_stage because there's no legitimate way
  * for multiple threads to be attempting to process the same I/O.
  */
-static zio_pipe_stage_t *zio_pipeline[ZIO_STAGES];
+static zio_pipe_stage_t *zio_pipeline[];
 
+/*
+ * zio_execute() is a wrapper around the static function
+ * __zio_execute() so that we can force  __zio_execute() to be
+ * inlined.  This reduces stack overhead which is important
+ * because __zio_execute() is called recursively in several zio
+ * code paths.  zio_execute() itself cannot be inlined because
+ * it is externally visible.
+ */
 void
 zio_execute(zio_t *zio)
 {
+       __zio_execute(zio);
+}
+
+__attribute__((always_inline))
+static inline void
+__zio_execute(zio_t *zio)
+{
        zio->io_executor = curthread;
 
        while (zio->io_stage < ZIO_STAGE_DONE) {
-               uint32_t pipeline = zio->io_pipeline;
-               zio_stage_t stage = zio->io_stage;
+               enum zio_stage pipeline = zio->io_pipeline;
+               enum zio_stage stage = zio->io_stage;
+               dsl_pool_t *dp;
+               boolean_t cut;
                int rv;
 
                ASSERT(!MUTEX_HELD(&zio->io_lock));
+               ASSERT(ISP2(stage));
+               ASSERT(zio->io_stall == NULL);
 
-               while (((1U << ++stage) & pipeline) == 0)
-                       continue;
+               do {
+                       stage <<= 1;
+               } while ((stage & pipeline) == 0);
 
                ASSERT(stage <= ZIO_STAGE_DONE);
-               ASSERT(zio->io_stall == NULL);
+
+               dp = spa_get_dsl(zio->io_spa);
+               cut = (stage == ZIO_STAGE_VDEV_IO_START) ?
+                   zio_requeue_io_start_cut_in_line : B_FALSE;
 
                /*
                 * If we are in interrupt context and this pipeline stage
                 * will grab a config lock that is held across I/O,
-                * issue async to avoid deadlock.
+                * or may wait for an I/O that needs an interrupt thread
+                * to complete, issue async to avoid deadlock.
+                *
+                * For VDEV_IO_START, we cut in line so that the io will
+                * be sent to disk promptly.
                 */
-               if (((1U << stage) & ZIO_CONFIG_LOCK_BLOCKING_STAGES) &&
-                   zio->io_vd == NULL &&
+               if ((stage & ZIO_BLOCKING_STAGES) && zio->io_vd == NULL &&
                    zio_taskq_member(zio, ZIO_TASKQ_INTERRUPT)) {
-                       zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE);
+                       zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE, cut);
+                       return;
+               }
+
+#ifdef _KERNEL
+               /*
+                * If we executing in the context of the tx_sync_thread,
+                * or we are performing pool initialization outside of a
+                * zio_taskq[ZIO_TASKQ_ISSUE] context.  Then issue the zio
+                * async to minimize stack usage for these deep call paths.
+                */
+               if ((dp && curthread == dp->dp_tx.tx_sync_thread) ||
+                   (dp && spa_is_initializing(dp->dp_spa) &&
+                   !zio_taskq_member(zio, ZIO_TASKQ_ISSUE))) {
+                       zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE, cut);
                        return;
                }
+#endif
 
                zio->io_stage = stage;
-               rv = zio_pipeline[stage](zio);
+               rv = zio_pipeline[highbit(stage) - 1](zio);
 
                if (rv == ZIO_PIPELINE_STOP)
                        return;
@@ -1055,6 +1336,7 @@ zio_execute(zio_t *zio)
        }
 }
 
+
 /*
  * ==========================================================================
  * Initiate I/O, either sync or async
@@ -1070,11 +1352,11 @@ zio_wait(zio_t *zio)
 
        zio->io_waiter = curthread;
 
-       zio_execute(zio);
+       __zio_execute(zio);
 
        mutex_enter(&zio->io_lock);
        while (zio->io_executor != NULL)
-               cv_wait(&zio->io_cv, &zio->io_lock);
+               cv_wait_io(&zio->io_cv, &zio->io_lock);
        mutex_exit(&zio->io_lock);
 
        error = zio->io_error;
@@ -1092,17 +1374,15 @@ zio_nowait(zio_t *zio)
            zio_unique_parent(zio) == NULL) {
                /*
                 * This is a logical async I/O with no parent to wait for it.
-                * Track how many outstanding I/Os of this type exist so
-                * that spa_unload() knows when they are all done.
+                * We add it to the spa_async_root_zio "Godfather" I/O which
+                * will ensure they complete prior to unloading the pool.
                 */
                spa_t *spa = zio->io_spa;
-               zio->io_async_root = B_TRUE;
-               mutex_enter(&spa->spa_async_root_lock);
-               spa->spa_async_root_count++;
-               mutex_exit(&spa->spa_async_root_lock);
+
+               zio_add_child(spa->spa_async_zio_root, zio);
        }
 
-       zio_execute(zio);
+       __zio_execute(zio);
 }
 
 /*
@@ -1115,33 +1395,25 @@ static void
 zio_reexecute(zio_t *pio)
 {
        zio_t *cio, *cio_next;
+       int c, w;
 
        ASSERT(pio->io_child_type == ZIO_CHILD_LOGICAL);
        ASSERT(pio->io_orig_stage == ZIO_STAGE_OPEN);
+       ASSERT(pio->io_gang_leader == NULL);
+       ASSERT(pio->io_gang_tree == NULL);
 
        pio->io_flags = pio->io_orig_flags;
        pio->io_stage = pio->io_orig_stage;
        pio->io_pipeline = pio->io_orig_pipeline;
        pio->io_reexecute = 0;
        pio->io_error = 0;
-       for (int w = 0; w < ZIO_WAIT_TYPES; w++)
+       for (w = 0; w < ZIO_WAIT_TYPES; w++)
                pio->io_state[w] = 0;
-       for (int c = 0; c < ZIO_CHILD_TYPES; c++)
+       for (c = 0; c < ZIO_CHILD_TYPES; c++)
                pio->io_child_error[c] = 0;
 
-       if (IO_IS_ALLOCATING(pio)) {
-               /*
-                * Remember the failed bp so that the io_ready() callback
-                * can update its accounting upon reexecution.  The block
-                * was already freed in zio_done(); we indicate this with
-                * a fill count of -1 so that zio_free() knows to skip it.
-                */
-               blkptr_t *bp = pio->io_bp;
-               ASSERT(bp->blk_birth == 0 || bp->blk_birth == pio->io_txg);
-               bp->blk_fill = BLK_FILL_ALREADY_FREED;
-               pio->io_bp_orig = *bp;
-               BP_ZERO(bp);
-       }
+       if (IO_IS_ALLOCATING(pio))
+               BP_ZERO(pio->io_bp);
 
        /*
         * As we reexecute pio's children, new children could be created.
@@ -1153,7 +1425,7 @@ zio_reexecute(zio_t *pio)
        for (cio = zio_walk_children(pio); cio != NULL; cio = cio_next) {
                cio_next = zio_walk_children(pio);
                mutex_enter(&pio->io_lock);
-               for (int w = 0; w < ZIO_WAIT_TYPES; w++)
+               for (w = 0; w < ZIO_WAIT_TYPES; w++)
                        pio->io_children[cio->io_child_type][w]++;
                mutex_exit(&pio->io_lock);
                zio_reexecute(cio);
@@ -1161,8 +1433,11 @@ zio_reexecute(zio_t *pio)
 
        /*
         * Now that all children have been reexecuted, execute the parent.
+        * We don't reexecute "The Godfather" I/O here as it's the
+        * responsibility of the caller to wait on him.
         */
-       zio_execute(pio);
+       if (!(pio->io_flags & ZIO_FLAG_GODFATHER))
+               __zio_execute(pio);
 }
 
 void
@@ -1178,11 +1453,14 @@ zio_suspend(spa_t *spa, zio_t *zio)
        mutex_enter(&spa->spa_suspend_lock);
 
        if (spa->spa_suspend_zio_root == NULL)
-               spa->spa_suspend_zio_root = zio_root(spa, NULL, NULL, 0);
+               spa->spa_suspend_zio_root = zio_root(spa, NULL, NULL,
+                   ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
+                   ZIO_FLAG_GODFATHER);
 
        spa->spa_suspended = B_TRUE;
 
        if (zio != NULL) {
+               ASSERT(!(zio->io_flags & ZIO_FLAG_GODFATHER));
                ASSERT(zio != spa->spa_suspend_zio_root);
                ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL);
                ASSERT(zio_unique_parent(zio) == NULL);
@@ -1193,10 +1471,10 @@ zio_suspend(spa_t *spa, zio_t *zio)
        mutex_exit(&spa->spa_suspend_lock);
 }
 
-void
+int
 zio_resume(spa_t *spa)
 {
-       zio_t *pio, *cio, *cio_next;
+       zio_t *pio;
 
        /*
         * Reexecute all previously suspended i/o.
@@ -1209,18 +1487,10 @@ zio_resume(spa_t *spa)
        mutex_exit(&spa->spa_suspend_lock);
 
        if (pio == NULL)
-               return;
+               return (0);
 
-       for (cio = zio_walk_children(pio); cio != NULL; cio = cio_next) {
-               zio_link_t *zl = pio->io_walk_link;
-               cio_next = zio_walk_children(pio);
-               zio_remove_child(pio, cio, zl);
-               zio_reexecute(cio);
-       }
-
-       ASSERT(pio->io_children[ZIO_CHILD_LOGICAL][ZIO_WAIT_DONE] == 0);
-
-       (void) zio_wait(pio);
+       zio_reexecute(pio);
+       return (zio_wait(pio));
 }
 
 void
@@ -1327,10 +1597,16 @@ zio_rewrite_gang(zio_t *pio, blkptr_t *bp, zio_gang_node_t *gn, void *data)
                 * (Presently, nothing actually uses interior data checksums;
                 * this is just good hygiene.)
                 */
-               if (gn != pio->io_logical->io_gang_tree) {
+               if (gn != pio->io_gang_leader->io_gang_tree) {
                        zio_checksum_compute(zio, BP_GET_CHECKSUM(bp),
                            data, BP_GET_PSIZE(bp));
                }
+               /*
+                * If we are here to damage data for testing purposes,
+                * leave the GBH alone so that we can detect the damage.
+                */
+               if (pio->io_gang_leader->io_flags & ZIO_FLAG_INDUCE_DAMAGE)
+                       zio->io_pipeline &= ~ZIO_VDEV_IO_STAGES;
        } else {
                zio = zio_rewrite(pio, pio->io_spa, pio->io_txg, bp,
                    data, BP_GET_PSIZE(bp), NULL, NULL, pio->io_priority,
@@ -1344,8 +1620,8 @@ zio_rewrite_gang(zio_t *pio, blkptr_t *bp, zio_gang_node_t *gn, void *data)
 zio_t *
 zio_free_gang(zio_t *pio, blkptr_t *bp, zio_gang_node_t *gn, void *data)
 {
-       return (zio_free(pio, pio->io_spa, pio->io_txg, bp,
-           NULL, NULL, ZIO_GANG_CHILD_FLAGS(pio)));
+       return (zio_free_sync(pio, pio->io_spa, pio->io_txg, bp,
+           ZIO_GANG_CHILD_FLAGS(pio)));
 }
 
 /* ARGSUSED */
@@ -1374,7 +1650,7 @@ zio_gang_node_alloc(zio_gang_node_t **gnpp)
 
        ASSERT(*gnpp == NULL);
 
-       gn = kmem_zalloc(sizeof (*gn), KM_SLEEP);
+       gn = kmem_zalloc(sizeof (*gn), KM_PUSHPAGE);
        gn->gn_gbh = zio_buf_alloc(SPA_GANGBLOCKSIZE);
        *gnpp = gn;
 
@@ -1385,8 +1661,9 @@ static void
 zio_gang_node_free(zio_gang_node_t **gnpp)
 {
        zio_gang_node_t *gn = *gnpp;
+       int g;
 
-       for (int g = 0; g < SPA_GBH_NBLKPTRS; g++)
+       for (g = 0; g < SPA_GBH_NBLKPTRS; g++)
                ASSERT(gn->gn_child[g] == NULL);
 
        zio_buf_free(gn->gn_gbh, SPA_GANGBLOCKSIZE);
@@ -1398,39 +1675,40 @@ static void
 zio_gang_tree_free(zio_gang_node_t **gnpp)
 {
        zio_gang_node_t *gn = *gnpp;
+       int g;
 
        if (gn == NULL)
                return;
 
-       for (int g = 0; g < SPA_GBH_NBLKPTRS; g++)
+       for (g = 0; g < SPA_GBH_NBLKPTRS; g++)
                zio_gang_tree_free(&gn->gn_child[g]);
 
        zio_gang_node_free(gnpp);
 }
 
 static void
-zio_gang_tree_assemble(zio_t *lio, blkptr_t *bp, zio_gang_node_t **gnpp)
+zio_gang_tree_assemble(zio_t *gio, blkptr_t *bp, zio_gang_node_t **gnpp)
 {
        zio_gang_node_t *gn = zio_gang_node_alloc(gnpp);
 
-       ASSERT(lio->io_logical == lio);
+       ASSERT(gio->io_gang_leader == gio);
        ASSERT(BP_IS_GANG(bp));
 
-       zio_nowait(zio_read(lio, lio->io_spa, bp, gn->gn_gbh,
+       zio_nowait(zio_read(gio, gio->io_spa, bp, gn->gn_gbh,
            SPA_GANGBLOCKSIZE, zio_gang_tree_assemble_done, gn,
-           lio->io_priority, ZIO_GANG_CHILD_FLAGS(lio), &lio->io_bookmark));
+           gio->io_priority, ZIO_GANG_CHILD_FLAGS(gio), &gio->io_bookmark));
 }
 
 static void
 zio_gang_tree_assemble_done(zio_t *zio)
 {
-       zio_t *lio = zio->io_logical;
+       zio_t *gio = zio->io_gang_leader;
        zio_gang_node_t *gn = zio->io_private;
        blkptr_t *bp = zio->io_bp;
-       zio_t *pio = zio_unique_parent(zio);
+       int g;
 
-       ASSERT(pio == lio);
-       ASSERT(zio_walk_children(zio) == NULL);
+       ASSERT(gio == zio_unique_parent(zio));
+       ASSERT(zio->io_child_count == 0);
 
        if (zio->io_error)
                return;
@@ -1440,36 +1718,37 @@ zio_gang_tree_assemble_done(zio_t *zio)
 
        ASSERT(zio->io_data == gn->gn_gbh);
        ASSERT(zio->io_size == SPA_GANGBLOCKSIZE);
-       ASSERT(gn->gn_gbh->zg_tail.zbt_magic == ZBT_MAGIC);
+       ASSERT(gn->gn_gbh->zg_tail.zec_magic == ZEC_MAGIC);
 
-       for (int g = 0; g < SPA_GBH_NBLKPTRS; g++) {
+       for (g = 0; g < SPA_GBH_NBLKPTRS; g++) {
                blkptr_t *gbp = &gn->gn_gbh->zg_blkptr[g];
                if (!BP_IS_GANG(gbp))
                        continue;
-               zio_gang_tree_assemble(lio, gbp, &gn->gn_child[g]);
+               zio_gang_tree_assemble(gio, gbp, &gn->gn_child[g]);
        }
 }
 
 static void
 zio_gang_tree_issue(zio_t *pio, zio_gang_node_t *gn, blkptr_t *bp, void *data)
 {
-       zio_t *lio = pio->io_logical;
+       zio_t *gio = pio->io_gang_leader;
        zio_t *zio;
+       int g;
 
        ASSERT(BP_IS_GANG(bp) == !!gn);
-       ASSERT(BP_GET_CHECKSUM(bp) == BP_GET_CHECKSUM(lio->io_bp));
-       ASSERT(BP_GET_LSIZE(bp) == BP_GET_PSIZE(bp) || gn == lio->io_gang_tree);
+       ASSERT(BP_GET_CHECKSUM(bp) == BP_GET_CHECKSUM(gio->io_bp));
+       ASSERT(BP_GET_LSIZE(bp) == BP_GET_PSIZE(bp) || gn == gio->io_gang_tree);
 
        /*
         * If you're a gang header, your data is in gn->gn_gbh.
         * If you're a gang member, your data is in 'data' and gn == NULL.
         */
-       zio = zio_gang_issue_func[lio->io_type](pio, bp, gn, data);
+       zio = zio_gang_issue_func[gio->io_type](pio, bp, gn, data);
 
        if (gn != NULL) {
-               ASSERT(gn->gn_gbh->zg_tail.zbt_magic == ZBT_MAGIC);
+               ASSERT(gn->gn_gbh->zg_tail.zec_magic == ZEC_MAGIC);
 
-               for (int g = 0; g < SPA_GBH_NBLKPTRS; g++) {
+               for (g = 0; g < SPA_GBH_NBLKPTRS; g++) {
                        blkptr_t *gbp = &gn->gn_gbh->zg_blkptr[g];
                        if (BP_IS_HOLE(gbp))
                                continue;
@@ -1478,8 +1757,8 @@ zio_gang_tree_issue(zio_t *pio, zio_gang_node_t *gn, blkptr_t *bp, void *data)
                }
        }
 
-       if (gn == lio->io_gang_tree)
-               ASSERT3P((char *)lio->io_data + lio->io_size, ==, data);
+       if (gn == gio->io_gang_tree)
+               ASSERT3P((char *)gio->io_data + gio->io_size, ==, data);
 
        if (zio != pio)
                zio_nowait(zio);
@@ -1490,7 +1769,10 @@ zio_gang_assemble(zio_t *zio)
 {
        blkptr_t *bp = zio->io_bp;
 
-       ASSERT(BP_IS_GANG(bp) && zio == zio->io_logical);
+       ASSERT(BP_IS_GANG(bp) && zio->io_gang_leader == NULL);
+       ASSERT(zio->io_child_type > ZIO_CHILD_GANG);
+
+       zio->io_gang_leader = zio;
 
        zio_gang_tree_assemble(zio, bp, &zio->io_gang_tree);
 
@@ -1500,18 +1782,18 @@ zio_gang_assemble(zio_t *zio)
 static int
 zio_gang_issue(zio_t *zio)
 {
-       zio_t *lio = zio->io_logical;
        blkptr_t *bp = zio->io_bp;
 
        if (zio_wait_for_children(zio, ZIO_CHILD_GANG, ZIO_WAIT_DONE))
                return (ZIO_PIPELINE_STOP);
 
-       ASSERT(BP_IS_GANG(bp) && zio == lio);
+       ASSERT(BP_IS_GANG(bp) && zio->io_gang_leader == zio);
+       ASSERT(zio->io_child_type > ZIO_CHILD_GANG);
 
        if (zio->io_child_error[ZIO_CHILD_GANG] == 0)
-               zio_gang_tree_issue(lio, lio->io_gang_tree, bp, lio->io_data);
+               zio_gang_tree_issue(zio, zio->io_gang_tree, bp, zio->io_data);
        else
-               zio_gang_tree_free(&lio->io_gang_tree);
+               zio_gang_tree_free(&zio->io_gang_tree);
 
        zio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
 
@@ -1522,10 +1804,11 @@ static void
 zio_write_gang_member_ready(zio_t *zio)
 {
        zio_t *pio = zio_unique_parent(zio);
-       zio_t *lio = zio->io_logical;
+       ASSERTV(zio_t *gio = zio->io_gang_leader;)
        dva_t *cdva = zio->io_bp->blk_dva;
        dva_t *pdva = pio->io_bp->blk_dva;
        uint64_t asize;
+       int d;
 
        if (BP_IS_HOLE(zio->io_bp))
                return;
@@ -1533,13 +1816,13 @@ zio_write_gang_member_ready(zio_t *zio)
        ASSERT(BP_IS_HOLE(&zio->io_bp_orig));
 
        ASSERT(zio->io_child_type == ZIO_CHILD_GANG);
-       ASSERT3U(zio->io_prop.zp_ndvas, ==, lio->io_prop.zp_ndvas);
-       ASSERT3U(zio->io_prop.zp_ndvas, <=, BP_GET_NDVAS(zio->io_bp));
-       ASSERT3U(pio->io_prop.zp_ndvas, <=, BP_GET_NDVAS(pio->io_bp));
+       ASSERT3U(zio->io_prop.zp_copies, ==, gio->io_prop.zp_copies);
+       ASSERT3U(zio->io_prop.zp_copies, <=, BP_GET_NDVAS(zio->io_bp));
+       ASSERT3U(pio->io_prop.zp_copies, <=, BP_GET_NDVAS(pio->io_bp));
        ASSERT3U(BP_GET_NDVAS(zio->io_bp), <=, BP_GET_NDVAS(pio->io_bp));
 
        mutex_enter(&pio->io_lock);
-       for (int d = 0; d < BP_GET_NDVAS(zio->io_bp); d++) {
+       for (d = 0; d < BP_GET_NDVAS(zio->io_bp); d++) {
                ASSERT(DVA_GET_GANG(&pdva[d]));
                asize = DVA_GET_ASIZE(&pdva[d]);
                asize += DVA_GET_ASIZE(&cdva[d]);
@@ -1553,28 +1836,28 @@ zio_write_gang_block(zio_t *pio)
 {
        spa_t *spa = pio->io_spa;
        blkptr_t *bp = pio->io_bp;
-       zio_t *lio = pio->io_logical;
+       zio_t *gio = pio->io_gang_leader;
        zio_t *zio;
        zio_gang_node_t *gn, **gnpp;
        zio_gbh_phys_t *gbh;
        uint64_t txg = pio->io_txg;
        uint64_t resid = pio->io_size;
        uint64_t lsize;
-       int ndvas = lio->io_prop.zp_ndvas;
-       int gbh_ndvas = MIN(ndvas + 1, spa_max_replication(spa));
+       int copies = gio->io_prop.zp_copies;
+       int gbh_copies = MIN(copies + 1, spa_max_replication(spa));
        zio_prop_t zp;
-       int error;
+       int g, error;
 
-       error = metaslab_alloc(spa, spa->spa_normal_class, SPA_GANGBLOCKSIZE,
-           bp, gbh_ndvas, txg, pio == lio ? NULL : lio->io_bp,
+       error = metaslab_alloc(spa, spa_normal_class(spa), SPA_GANGBLOCKSIZE,
+           bp, gbh_copies, txg, pio == gio ? NULL : gio->io_bp,
            METASLAB_HINTBP_FAVOR | METASLAB_GANG_HEADER);
        if (error) {
                pio->io_error = error;
                return (ZIO_PIPELINE_CONTINUE);
        }
 
-       if (pio == lio) {
-               gnpp = &lio->io_gang_tree;
+       if (pio == gio) {
+               gnpp = &gio->io_gang_tree;
        } else {
                gnpp = pio->io_private;
                ASSERT(pio->io_ready == zio_write_gang_member_ready);
@@ -1593,16 +1876,18 @@ zio_write_gang_block(zio_t *pio)
        /*
         * Create and nowait the gang children.
         */
-       for (int g = 0; resid != 0; resid -= lsize, g++) {
+       for (g = 0; resid != 0; resid -= lsize, g++) {
                lsize = P2ROUNDUP(resid / (SPA_GBH_NBLKPTRS - g),
                    SPA_MINBLOCKSIZE);
                ASSERT(lsize >= SPA_MINBLOCKSIZE && lsize <= resid);
 
-               zp.zp_checksum = lio->io_prop.zp_checksum;
+               zp.zp_checksum = gio->io_prop.zp_checksum;
                zp.zp_compress = ZIO_COMPRESS_OFF;
                zp.zp_type = DMU_OT_NONE;
                zp.zp_level = 0;
-               zp.zp_ndvas = lio->io_prop.zp_ndvas;
+               zp.zp_copies = gio->io_prop.zp_copies;
+               zp.zp_dedup = 0;
+               zp.zp_dedup_verify = 0;
 
                zio_nowait(zio_write(zio, spa, txg, &gbh->zg_blkptr[g],
                    (char *)pio->io_data + (pio->io_size - resid), lsize, &zp,
@@ -1616,6 +1901,11 @@ zio_write_gang_block(zio_t *pio)
         */
        pio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
 
+       /*
+        * We didn't allocate this bp, so make sure it doesn't get unmarked.
+        */
+       pio->io_flags &= ~ZIO_FLAG_FASTWRITE;
+
        zio_nowait(zio);
 
        return (ZIO_PIPELINE_CONTINUE);
@@ -1623,28 +1913,419 @@ zio_write_gang_block(zio_t *pio)
 
 /*
  * ==========================================================================
- * Allocate and free blocks
+ * Dedup
  * ==========================================================================
  */
+static void
+zio_ddt_child_read_done(zio_t *zio)
+{
+       blkptr_t *bp = zio->io_bp;
+       ddt_entry_t *dde = zio->io_private;
+       ddt_phys_t *ddp;
+       zio_t *pio = zio_unique_parent(zio);
+
+       mutex_enter(&pio->io_lock);
+       ddp = ddt_phys_select(dde, bp);
+       if (zio->io_error == 0)
+               ddt_phys_clear(ddp);    /* this ddp doesn't need repair */
+       if (zio->io_error == 0 && dde->dde_repair_data == NULL)
+               dde->dde_repair_data = zio->io_data;
+       else
+               zio_buf_free(zio->io_data, zio->io_size);
+       mutex_exit(&pio->io_lock);
+}
+
+static int
+zio_ddt_read_start(zio_t *zio)
+{
+       blkptr_t *bp = zio->io_bp;
+       int p;
+
+       ASSERT(BP_GET_DEDUP(bp));
+       ASSERT(BP_GET_PSIZE(bp) == zio->io_size);
+       ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL);
+
+       if (zio->io_child_error[ZIO_CHILD_DDT]) {
+               ddt_t *ddt = ddt_select(zio->io_spa, bp);
+               ddt_entry_t *dde = ddt_repair_start(ddt, bp);
+               ddt_phys_t *ddp = dde->dde_phys;
+               ddt_phys_t *ddp_self = ddt_phys_select(dde, bp);
+               blkptr_t blk;
+
+               ASSERT(zio->io_vsd == NULL);
+               zio->io_vsd = dde;
+
+               if (ddp_self == NULL)
+                       return (ZIO_PIPELINE_CONTINUE);
+
+               for (p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
+                       if (ddp->ddp_phys_birth == 0 || ddp == ddp_self)
+                               continue;
+                       ddt_bp_create(ddt->ddt_checksum, &dde->dde_key, ddp,
+                           &blk);
+                       zio_nowait(zio_read(zio, zio->io_spa, &blk,
+                           zio_buf_alloc(zio->io_size), zio->io_size,
+                           zio_ddt_child_read_done, dde, zio->io_priority,
+                           ZIO_DDT_CHILD_FLAGS(zio) | ZIO_FLAG_DONT_PROPAGATE,
+                           &zio->io_bookmark));
+               }
+               return (ZIO_PIPELINE_CONTINUE);
+       }
+
+       zio_nowait(zio_read(zio, zio->io_spa, bp,
+           zio->io_data, zio->io_size, NULL, NULL, zio->io_priority,
+           ZIO_DDT_CHILD_FLAGS(zio), &zio->io_bookmark));
+
+       return (ZIO_PIPELINE_CONTINUE);
+}
+
+static int
+zio_ddt_read_done(zio_t *zio)
+{
+       blkptr_t *bp = zio->io_bp;
+
+       if (zio_wait_for_children(zio, ZIO_CHILD_DDT, ZIO_WAIT_DONE))
+               return (ZIO_PIPELINE_STOP);
+
+       ASSERT(BP_GET_DEDUP(bp));
+       ASSERT(BP_GET_PSIZE(bp) == zio->io_size);
+       ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL);
+
+       if (zio->io_child_error[ZIO_CHILD_DDT]) {
+               ddt_t *ddt = ddt_select(zio->io_spa, bp);
+               ddt_entry_t *dde = zio->io_vsd;
+               if (ddt == NULL) {
+                       ASSERT(spa_load_state(zio->io_spa) != SPA_LOAD_NONE);
+                       return (ZIO_PIPELINE_CONTINUE);
+               }
+               if (dde == NULL) {
+                       zio->io_stage = ZIO_STAGE_DDT_READ_START >> 1;
+                       zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE, B_FALSE);
+                       return (ZIO_PIPELINE_STOP);
+               }
+               if (dde->dde_repair_data != NULL) {
+                       bcopy(dde->dde_repair_data, zio->io_data, zio->io_size);
+                       zio->io_child_error[ZIO_CHILD_DDT] = 0;
+               }
+               ddt_repair_done(ddt, dde);
+               zio->io_vsd = NULL;
+       }
+
+       ASSERT(zio->io_vsd == NULL);
+
+       return (ZIO_PIPELINE_CONTINUE);
+}
+
+static boolean_t
+zio_ddt_collision(zio_t *zio, ddt_t *ddt, ddt_entry_t *dde)
+{
+       spa_t *spa = zio->io_spa;
+       int p;
+
+       /*
+        * Note: we compare the original data, not the transformed data,
+        * because when zio->io_bp is an override bp, we will not have
+        * pushed the I/O transforms.  That's an important optimization
+        * because otherwise we'd compress/encrypt all dmu_sync() data twice.
+        */
+       for (p = DDT_PHYS_SINGLE; p <= DDT_PHYS_TRIPLE; p++) {
+               zio_t *lio = dde->dde_lead_zio[p];
+
+               if (lio != NULL) {
+                       return (lio->io_orig_size != zio->io_orig_size ||
+                           bcmp(zio->io_orig_data, lio->io_orig_data,
+                           zio->io_orig_size) != 0);
+               }
+       }
+
+       for (p = DDT_PHYS_SINGLE; p <= DDT_PHYS_TRIPLE; p++) {
+               ddt_phys_t *ddp = &dde->dde_phys[p];
+
+               if (ddp->ddp_phys_birth != 0) {
+                       arc_buf_t *abuf = NULL;
+                       uint32_t aflags = ARC_WAIT;
+                       blkptr_t blk = *zio->io_bp;
+                       int error;
+
+                       ddt_bp_fill(ddp, &blk, ddp->ddp_phys_birth);
+
+                       ddt_exit(ddt);
+
+                       error = arc_read(NULL, spa, &blk,
+                           arc_getbuf_func, &abuf, ZIO_PRIORITY_SYNC_READ,
+                           ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE,
+                           &aflags, &zio->io_bookmark);
+
+                       if (error == 0) {
+                               if (arc_buf_size(abuf) != zio->io_orig_size ||
+                                   bcmp(abuf->b_data, zio->io_orig_data,
+                                   zio->io_orig_size) != 0)
+                                       error = EEXIST;
+                               VERIFY(arc_buf_remove_ref(abuf, &abuf) == 1);
+                       }
+
+                       ddt_enter(ddt);
+                       return (error != 0);
+               }
+       }
+
+       return (B_FALSE);
+}
+
+static void
+zio_ddt_child_write_ready(zio_t *zio)
+{
+       int p = zio->io_prop.zp_copies;
+       ddt_t *ddt = ddt_select(zio->io_spa, zio->io_bp);
+       ddt_entry_t *dde = zio->io_private;
+       ddt_phys_t *ddp = &dde->dde_phys[p];
+       zio_t *pio;
+
+       if (zio->io_error)
+               return;
+
+       ddt_enter(ddt);
+
+       ASSERT(dde->dde_lead_zio[p] == zio);
+
+       ddt_phys_fill(ddp, zio->io_bp);
+
+       while ((pio = zio_walk_parents(zio)) != NULL)
+               ddt_bp_fill(ddp, pio->io_bp, zio->io_txg);
+
+       ddt_exit(ddt);
+}
+
+static void
+zio_ddt_child_write_done(zio_t *zio)
+{
+       int p = zio->io_prop.zp_copies;
+       ddt_t *ddt = ddt_select(zio->io_spa, zio->io_bp);
+       ddt_entry_t *dde = zio->io_private;
+       ddt_phys_t *ddp = &dde->dde_phys[p];
+
+       ddt_enter(ddt);
+
+       ASSERT(ddp->ddp_refcnt == 0);
+       ASSERT(dde->dde_lead_zio[p] == zio);
+       dde->dde_lead_zio[p] = NULL;
+
+       if (zio->io_error == 0) {
+               while (zio_walk_parents(zio) != NULL)
+                       ddt_phys_addref(ddp);
+       } else {
+               ddt_phys_clear(ddp);
+       }
+
+       ddt_exit(ddt);
+}
+
+static void
+zio_ddt_ditto_write_done(zio_t *zio)
+{
+       int p = DDT_PHYS_DITTO;
+       blkptr_t *bp = zio->io_bp;
+       ddt_t *ddt = ddt_select(zio->io_spa, bp);
+       ddt_entry_t *dde = zio->io_private;
+       ddt_phys_t *ddp = &dde->dde_phys[p];
+       ddt_key_t *ddk = &dde->dde_key;
+       ASSERTV(zio_prop_t *zp = &zio->io_prop);
+
+       ddt_enter(ddt);
+
+       ASSERT(ddp->ddp_refcnt == 0);
+       ASSERT(dde->dde_lead_zio[p] == zio);
+       dde->dde_lead_zio[p] = NULL;
+
+       if (zio->io_error == 0) {
+               ASSERT(ZIO_CHECKSUM_EQUAL(bp->blk_cksum, ddk->ddk_cksum));
+               ASSERT(zp->zp_copies < SPA_DVAS_PER_BP);
+               ASSERT(zp->zp_copies == BP_GET_NDVAS(bp) - BP_IS_GANG(bp));
+               if (ddp->ddp_phys_birth != 0)
+                       ddt_phys_free(ddt, ddk, ddp, zio->io_txg);
+               ddt_phys_fill(ddp, bp);
+       }
+
+       ddt_exit(ddt);
+}
+
+static int
+zio_ddt_write(zio_t *zio)
+{
+       spa_t *spa = zio->io_spa;
+       blkptr_t *bp = zio->io_bp;
+       uint64_t txg = zio->io_txg;
+       zio_prop_t *zp = &zio->io_prop;
+       int p = zp->zp_copies;
+       int ditto_copies;
+       zio_t *cio = NULL;
+       zio_t *dio = NULL;
+       ddt_t *ddt = ddt_select(spa, bp);
+       ddt_entry_t *dde;
+       ddt_phys_t *ddp;
+
+       ASSERT(BP_GET_DEDUP(bp));
+       ASSERT(BP_GET_CHECKSUM(bp) == zp->zp_checksum);
+       ASSERT(BP_IS_HOLE(bp) || zio->io_bp_override);
+
+       ddt_enter(ddt);
+       dde = ddt_lookup(ddt, bp, B_TRUE);
+       ddp = &dde->dde_phys[p];
+
+       if (zp->zp_dedup_verify && zio_ddt_collision(zio, ddt, dde)) {
+               /*
+                * If we're using a weak checksum, upgrade to a strong checksum
+                * and try again.  If we're already using a strong checksum,
+                * we can't resolve it, so just convert to an ordinary write.
+                * (And automatically e-mail a paper to Nature?)
+                */
+               if (!zio_checksum_table[zp->zp_checksum].ci_dedup) {
+                       zp->zp_checksum = spa_dedup_checksum(spa);
+                       zio_pop_transforms(zio);
+                       zio->io_stage = ZIO_STAGE_OPEN;
+                       BP_ZERO(bp);
+               } else {
+                       zp->zp_dedup = 0;
+               }
+               zio->io_pipeline = ZIO_WRITE_PIPELINE;
+               ddt_exit(ddt);
+               return (ZIO_PIPELINE_CONTINUE);
+       }
+
+       ditto_copies = ddt_ditto_copies_needed(ddt, dde, ddp);
+       ASSERT(ditto_copies < SPA_DVAS_PER_BP);
+
+       if (ditto_copies > ddt_ditto_copies_present(dde) &&
+           dde->dde_lead_zio[DDT_PHYS_DITTO] == NULL) {
+               zio_prop_t czp = *zp;
+
+               czp.zp_copies = ditto_copies;
+
+               /*
+                * If we arrived here with an override bp, we won't have run
+                * the transform stack, so we won't have the data we need to
+                * generate a child i/o.  So, toss the override bp and restart.
+                * This is safe, because using the override bp is just an
+                * optimization; and it's rare, so the cost doesn't matter.
+                */
+               if (zio->io_bp_override) {
+                       zio_pop_transforms(zio);
+                       zio->io_stage = ZIO_STAGE_OPEN;
+                       zio->io_pipeline = ZIO_WRITE_PIPELINE;
+                       zio->io_bp_override = NULL;
+                       BP_ZERO(bp);
+                       ddt_exit(ddt);
+                       return (ZIO_PIPELINE_CONTINUE);
+               }
+
+               dio = zio_write(zio, spa, txg, bp, zio->io_orig_data,
+                   zio->io_orig_size, &czp, NULL,
+                   zio_ddt_ditto_write_done, dde, zio->io_priority,
+                   ZIO_DDT_CHILD_FLAGS(zio), &zio->io_bookmark);
+
+               zio_push_transform(dio, zio->io_data, zio->io_size, 0, NULL);
+               dde->dde_lead_zio[DDT_PHYS_DITTO] = dio;
+       }
+
+       if (ddp->ddp_phys_birth != 0 || dde->dde_lead_zio[p] != NULL) {
+               if (ddp->ddp_phys_birth != 0)
+                       ddt_bp_fill(ddp, bp, txg);
+               if (dde->dde_lead_zio[p] != NULL)
+                       zio_add_child(zio, dde->dde_lead_zio[p]);
+               else
+                       ddt_phys_addref(ddp);
+       } else if (zio->io_bp_override) {
+               ASSERT(bp->blk_birth == txg);
+               ASSERT(BP_EQUAL(bp, zio->io_bp_override));
+               ddt_phys_fill(ddp, bp);
+               ddt_phys_addref(ddp);
+       } else {
+               cio = zio_write(zio, spa, txg, bp, zio->io_orig_data,
+                   zio->io_orig_size, zp, zio_ddt_child_write_ready,
+                   zio_ddt_child_write_done, dde, zio->io_priority,
+                   ZIO_DDT_CHILD_FLAGS(zio), &zio->io_bookmark);
+
+               zio_push_transform(cio, zio->io_data, zio->io_size, 0, NULL);
+               dde->dde_lead_zio[p] = cio;
+       }
+
+       ddt_exit(ddt);
+
+       if (cio)
+               zio_nowait(cio);
+       if (dio)
+               zio_nowait(dio);
+
+       return (ZIO_PIPELINE_CONTINUE);
+}
+
+ddt_entry_t *freedde; /* for debugging */
+
+static int
+zio_ddt_free(zio_t *zio)
+{
+       spa_t *spa = zio->io_spa;
+       blkptr_t *bp = zio->io_bp;
+       ddt_t *ddt = ddt_select(spa, bp);
+       ddt_entry_t *dde;
+       ddt_phys_t *ddp;
+
+       ASSERT(BP_GET_DEDUP(bp));
+       ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL);
+
+       ddt_enter(ddt);
+       freedde = dde = ddt_lookup(ddt, bp, B_TRUE);
+       if (dde) {
+               ddp = ddt_phys_select(dde, bp);
+               if (ddp)
+                       ddt_phys_decref(ddp);
+       }
+       ddt_exit(ddt);
+
+       return (ZIO_PIPELINE_CONTINUE);
+}
 
+/*
+ * ==========================================================================
+ * Allocate and free blocks
+ * ==========================================================================
+ */
 static int
 zio_dva_allocate(zio_t *zio)
 {
        spa_t *spa = zio->io_spa;
-       metaslab_class_t *mc = spa->spa_normal_class;
+       metaslab_class_t *mc = spa_normal_class(spa);
        blkptr_t *bp = zio->io_bp;
        int error;
+       int flags = 0;
+
+       if (zio->io_gang_leader == NULL) {
+               ASSERT(zio->io_child_type > ZIO_CHILD_GANG);
+               zio->io_gang_leader = zio;
+       }
 
        ASSERT(BP_IS_HOLE(bp));
-       ASSERT3U(BP_GET_NDVAS(bp), ==, 0);
-       ASSERT3U(zio->io_prop.zp_ndvas, >, 0);
-       ASSERT3U(zio->io_prop.zp_ndvas, <=, spa_max_replication(spa));
+       ASSERT0(BP_GET_NDVAS(bp));
+       ASSERT3U(zio->io_prop.zp_copies, >, 0);
+       ASSERT3U(zio->io_prop.zp_copies, <=, spa_max_replication(spa));
        ASSERT3U(zio->io_size, ==, BP_GET_PSIZE(bp));
 
+       /*
+        * The dump device does not support gang blocks so allocation on
+        * behalf of the dump device (i.e. ZIO_FLAG_NODATA) must avoid
+        * the "fast" gang feature.
+        */
+       flags |= (zio->io_flags & ZIO_FLAG_NODATA) ? METASLAB_GANG_AVOID : 0;
+       flags |= (zio->io_flags & ZIO_FLAG_GANG_CHILD) ?
+           METASLAB_GANG_CHILD : 0;
+       flags |= (zio->io_flags & ZIO_FLAG_FASTWRITE) ? METASLAB_FASTWRITE : 0;
        error = metaslab_alloc(spa, mc, zio->io_size, bp,
-           zio->io_prop.zp_ndvas, zio->io_txg, NULL, 0);
+           zio->io_prop.zp_copies, zio->io_txg, NULL, flags);
 
        if (error) {
+               spa_dbgmsg(spa, "%s: metaslab allocation failure: zio %p, "
+                   "size %llu, error %d", spa_name(spa), zio, zio->io_size,
+                   error);
                if (error == ENOSPC && zio->io_size > SPA_MINBLOCKSIZE)
                        return (zio_write_gang_block(zio));
                zio->io_error = error;
@@ -1681,39 +2362,16 @@ zio_dva_claim(zio_t *zio)
 static void
 zio_dva_unallocate(zio_t *zio, zio_gang_node_t *gn, blkptr_t *bp)
 {
-       spa_t *spa = zio->io_spa;
-       boolean_t now = !(zio->io_flags & ZIO_FLAG_IO_REWRITE);
+       int g;
 
        ASSERT(bp->blk_birth == zio->io_txg || BP_IS_HOLE(bp));
-
-       if (zio->io_bp == bp && !now) {
-               /*
-                * This is a rewrite for sync-to-convergence.
-                * We can't do a metaslab_free(NOW) because bp wasn't allocated
-                * during this sync pass, which means that metaslab_sync()
-                * already committed the allocation.
-                */
-               ASSERT(DVA_EQUAL(BP_IDENTITY(bp),
-                   BP_IDENTITY(&zio->io_bp_orig)));
-               ASSERT(spa_sync_pass(spa) > 1);
-
-               if (BP_IS_GANG(bp) && gn == NULL) {
-                       /*
-                        * This is a gang leader whose gang header(s) we
-                        * couldn't read now, so defer the free until later.
-                        * The block should still be intact because without
-                        * the headers, we'd never even start the rewrite.
-                        */
-                       bplist_enqueue_deferred(&spa->spa_sync_bplist, bp);
-                       return;
-               }
-       }
+       ASSERT(zio->io_bp_override == NULL);
 
        if (!BP_IS_HOLE(bp))
-               metaslab_free(spa, bp, bp->blk_birth, now);
+               metaslab_free(zio->io_spa, bp, bp->blk_birth, B_TRUE);
 
        if (gn != NULL) {
-               for (int g = 0; g < SPA_GBH_NBLKPTRS; g++) {
+               for (g = 0; g < SPA_GBH_NBLKPTRS; g++) {
                        zio_dva_unallocate(zio, gn->gn_child[g],
                            &gn->gn_gbh->zg_blkptr[g]);
                }
@@ -1724,25 +2382,40 @@ zio_dva_unallocate(zio_t *zio, zio_gang_node_t *gn, blkptr_t *bp)
  * Try to allocate an intent log block.  Return 0 on success, errno on failure.
  */
 int
-zio_alloc_blk(spa_t *spa, uint64_t size, blkptr_t *new_bp, blkptr_t *old_bp,
-    uint64_t txg)
+zio_alloc_zil(spa_t *spa, uint64_t txg, blkptr_t *new_bp, uint64_t size,
+    boolean_t use_slog)
 {
-       int error;
+       int error = 1;
 
-       error = metaslab_alloc(spa, spa->spa_log_class, size,
-           new_bp, 1, txg, old_bp, METASLAB_HINTBP_AVOID);
+       ASSERT(txg > spa_syncing_txg(spa));
 
-       if (error)
-               error = metaslab_alloc(spa, spa->spa_normal_class, size,
-                   new_bp, 1, txg, old_bp, METASLAB_HINTBP_AVOID);
+       /*
+        * ZIL blocks are always contiguous (i.e. not gang blocks) so we
+        * set the METASLAB_GANG_AVOID flag so that they don't "fast gang"
+        * when allocating them.
+        */
+       if (use_slog) {
+               error = metaslab_alloc(spa, spa_log_class(spa), size,
+                   new_bp, 1, txg, NULL,
+                   METASLAB_FASTWRITE | METASLAB_GANG_AVOID);
+       }
+
+       if (error) {
+               error = metaslab_alloc(spa, spa_normal_class(spa), size,
+                   new_bp, 1, txg, NULL,
+                   METASLAB_FASTWRITE | METASLAB_GANG_AVOID);
+       }
 
        if (error == 0) {
                BP_SET_LSIZE(new_bp, size);
                BP_SET_PSIZE(new_bp, size);
                BP_SET_COMPRESS(new_bp, ZIO_COMPRESS_OFF);
-               BP_SET_CHECKSUM(new_bp, ZIO_CHECKSUM_ZILOG);
+               BP_SET_CHECKSUM(new_bp,
+                   spa_version(spa) >= SPA_VERSION_SLIM_ZIL
+                   ? ZIO_CHECKSUM_ZILOG2 : ZIO_CHECKSUM_ZILOG);
                BP_SET_TYPE(new_bp, DMU_OT_INTENT_LOG);
                BP_SET_LEVEL(new_bp, 0);
+               BP_SET_DEDUP(new_bp, 0);
                BP_SET_BYTEORDER(new_bp, ZFS_HOST_BYTEORDER);
        }
 
@@ -1750,15 +2423,15 @@ zio_alloc_blk(spa_t *spa, uint64_t size, blkptr_t *new_bp, blkptr_t *old_bp,
 }
 
 /*
- * Free an intent log block.  We know it can't be a gang block, so there's
- * nothing to do except metaslab_free() it.
+ * Free an intent log block.
  */
 void
-zio_free_blk(spa_t *spa, blkptr_t *bp, uint64_t txg)
+zio_free_zil(spa_t *spa, uint64_t txg, blkptr_t *bp)
 {
+       ASSERT(BP_GET_TYPE(bp) == DMU_OT_INTENT_LOG);
        ASSERT(!BP_IS_GANG(bp));
 
-       metaslab_free(spa, bp, txg, B_FALSE);
+       zio_free(spa, txg, bp);
 }
 
 /*
@@ -1786,6 +2459,26 @@ zio_vdev_io_start(zio_t *zio)
                return (vdev_mirror_ops.vdev_op_io_start(zio));
        }
 
+       /*
+        * We keep track of time-sensitive I/Os so that the scan thread
+        * can quickly react to certain workloads.  In particular, we care
+        * about non-scrubbing, top-level reads and writes with the following
+        * characteristics:
+        *      - synchronous writes of user data to non-slog devices
+        *      - any reads of user data
+        * When these conditions are met, adjust the timestamp of spa_last_io
+        * which allows the scan thread to adjust its workload accordingly.
+        */
+       if (!(zio->io_flags & ZIO_FLAG_SCAN_THREAD) && zio->io_bp != NULL &&
+           vd == vd->vdev_top && !vd->vdev_islog &&
+           zio->io_bookmark.zb_objset != DMU_META_OBJSET &&
+           zio->io_txg != spa_syncing_txg(spa)) {
+               uint64_t old = spa->spa_last_io;
+               uint64_t new = ddi_get_lbolt64();
+               if (old != new)
+                       (void) atomic_cas_64(&spa->spa_last_io, old, new);
+       }
+
        align = 1ULL << vd->vdev_top->vdev_ashift;
 
        if (P2PHASE(zio->io_size, align) != 0) {
@@ -1801,7 +2494,7 @@ zio_vdev_io_start(zio_t *zio)
 
        ASSERT(P2PHASE(zio->io_offset, align) == 0);
        ASSERT(P2PHASE(zio->io_size, align) == 0);
-       ASSERT(zio->io_type != ZIO_TYPE_WRITE || spa_writeable(spa));
+       VERIFY(zio->io_type != ZIO_TYPE_WRITE || spa_writeable(spa));
 
        /*
         * If this is a repair I/O, and there's no self-healing involved --
@@ -1864,7 +2557,8 @@ zio_vdev_io_done(zio_t *zio)
                        vdev_cache_write(zio);
 
                if (zio_injection_enabled && zio->io_error == 0)
-                       zio->io_error = zio_handle_device_injection(vd, EIO);
+                       zio->io_error = zio_handle_device_injection(vd,
+                           zio, EIO);
 
                if (zio_injection_enabled && zio->io_error == 0)
                        zio->io_error = zio_handle_label_injection(zio, EIO);
@@ -1886,6 +2580,32 @@ zio_vdev_io_done(zio_t *zio)
        return (ZIO_PIPELINE_CONTINUE);
 }
 
+/*
+ * For non-raidz ZIOs, we can just copy aside the bad data read from the
+ * disk, and use that to finish the checksum ereport later.
+ */
+static void
+zio_vsd_default_cksum_finish(zio_cksum_report_t *zcr,
+    const void *good_buf)
+{
+       /* no processing needed */
+       zfs_ereport_finish_checksum(zcr, good_buf, zcr->zcr_cbdata, B_FALSE);
+}
+
+/*ARGSUSED*/
+void
+zio_vsd_default_cksum_report(zio_t *zio, zio_cksum_report_t *zcr, void *ignored)
+{
+       void *buf = zio_buf_alloc(zio->io_size);
+
+       bcopy(zio->io_data, buf, zio->io_size);
+
+       zcr->zcr_cbinfo = zio->io_size;
+       zcr->zcr_cbdata = buf;
+       zcr->zcr_finish = zio_vsd_default_cksum_finish;
+       zcr->zcr_free = zio_buf_free;
+}
+
 static int
 zio_vdev_io_assess(zio_t *zio)
 {
@@ -1898,7 +2618,7 @@ zio_vdev_io_assess(zio_t *zio)
                spa_config_exit(zio->io_spa, SCL_ZIO, zio);
 
        if (zio->io_vsd != NULL) {
-               zio->io_vsd_free(zio);
+               zio->io_vsd_ops->vsd_free(zio);
                zio->io_vsd = NULL;
        }
 
@@ -1907,6 +2627,9 @@ zio_vdev_io_assess(zio_t *zio)
 
        /*
         * If the I/O failed, determine whether we should attempt to retry it.
+        *
+        * On retry, we cut in line in the issue queue, since we don't want
+        * compression/checksumming/etc. work to prevent our (cheap) IO reissue.
         */
        if (zio->io_error && vd == NULL &&
            !(zio->io_flags & (ZIO_FLAG_DONT_RETRY | ZIO_FLAG_IO_RETRY))) {
@@ -1915,8 +2638,9 @@ zio_vdev_io_assess(zio_t *zio)
                zio->io_error = 0;
                zio->io_flags |= ZIO_FLAG_IO_RETRY |
                    ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_AGGREGATE;
-               zio->io_stage = ZIO_STAGE_VDEV_IO_START - 1;
-               zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE);
+               zio->io_stage = ZIO_STAGE_VDEV_IO_START >> 1;
+               zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE,
+                   zio_requeue_io_start_cut_in_line);
                return (ZIO_PIPELINE_STOP);
        }
 
@@ -1948,7 +2672,7 @@ zio_vdev_io_reissue(zio_t *zio)
        ASSERT(zio->io_stage == ZIO_STAGE_VDEV_IO_START);
        ASSERT(zio->io_error == 0);
 
-       zio->io_stage--;
+       zio->io_stage >>= 1;
 }
 
 void
@@ -1956,7 +2680,7 @@ zio_vdev_io_redone(zio_t *zio)
 {
        ASSERT(zio->io_stage == ZIO_STAGE_VDEV_IO_DONE);
 
-       zio->io_stage--;
+       zio->io_stage >>= 1;
 }
 
 void
@@ -1966,7 +2690,7 @@ zio_vdev_io_bypass(zio_t *zio)
        ASSERT(zio->io_error == 0);
 
        zio->io_flags |= ZIO_FLAG_IO_BYPASS;
-       zio->io_stage = ZIO_STAGE_VDEV_IO_ASSESS - 1;
+       zio->io_stage = ZIO_STAGE_VDEV_IO_ASSESS >> 1;
 }
 
 /*
@@ -2008,9 +2732,12 @@ zio_checksum_generate(zio_t *zio)
 static int
 zio_checksum_verify(zio_t *zio)
 {
+       zio_bad_cksum_t info;
        blkptr_t *bp = zio->io_bp;
        int error;
 
+       ASSERT(zio->io_vd != NULL);
+
        if (bp == NULL) {
                /*
                 * This is zio_read_phys().
@@ -2022,11 +2749,12 @@ zio_checksum_verify(zio_t *zio)
                ASSERT(zio->io_prop.zp_checksum == ZIO_CHECKSUM_LABEL);
        }
 
-       if ((error = zio_checksum_error(zio)) != 0) {
+       if ((error = zio_checksum_error(zio, &info)) != 0) {
                zio->io_error = error;
                if (!(zio->io_flags & ZIO_FLAG_SPECULATIVE)) {
-                       zfs_ereport_post(FM_EREPORT_ZFS_CHECKSUM,
-                           zio->io_spa, zio->io_vd, zio, 0, 0);
+                       zfs_ereport_start_checksum(zio->io_spa,
+                           zio->io_vd, zio, zio->io_offset,
+                           zio->io_size, NULL, &info);
                }
        }
 
@@ -2039,7 +2767,7 @@ zio_checksum_verify(zio_t *zio)
 void
 zio_checksum_verified(zio_t *zio)
 {
-       zio->io_pipeline &= ~(1U << ZIO_STAGE_CHECKSUM_VERIFY);
+       zio->io_pipeline &= ~ZIO_STAGE_CHECKSUM_VERIFY;
 }
 
 /*
@@ -2079,11 +2807,11 @@ zio_ready(zio_t *zio)
        blkptr_t *bp = zio->io_bp;
        zio_t *pio, *pio_next;
 
-       if (zio->io_ready) {
-               if (BP_IS_GANG(bp) &&
-                   zio_wait_for_children(zio, ZIO_CHILD_GANG, ZIO_WAIT_READY))
-                       return (ZIO_PIPELINE_STOP);
+       if (zio_wait_for_children(zio, ZIO_CHILD_GANG, ZIO_WAIT_READY) ||
+           zio_wait_for_children(zio, ZIO_CHILD_DDT, ZIO_WAIT_READY))
+               return (ZIO_PIPELINE_STOP);
 
+       if (zio->io_ready) {
                ASSERT(IO_IS_ALLOCATING(zio));
                ASSERT(bp->blk_birth == zio->io_txg || BP_IS_HOLE(bp));
                ASSERT(zio->io_children[ZIO_CHILD_GANG][ZIO_WAIT_READY] == 0);
@@ -2114,56 +2842,105 @@ zio_ready(zio_t *zio)
                zio_notify_parent(pio, zio, ZIO_WAIT_READY);
        }
 
+       if (zio->io_flags & ZIO_FLAG_NODATA) {
+               if (BP_IS_GANG(bp)) {
+                       zio->io_flags &= ~ZIO_FLAG_NODATA;
+               } else {
+                       ASSERT((uintptr_t)zio->io_data < SPA_MAXBLOCKSIZE);
+                       zio->io_pipeline &= ~ZIO_VDEV_IO_STAGES;
+               }
+       }
+
+       if (zio_injection_enabled &&
+           zio->io_spa->spa_syncing_txg == zio->io_txg)
+               zio_handle_ignored_writes(zio);
+
        return (ZIO_PIPELINE_CONTINUE);
 }
 
 static int
 zio_done(zio_t *zio)
 {
-       spa_t *spa = zio->io_spa;
-       zio_t *lio = zio->io_logical;
-       blkptr_t *bp = zio->io_bp;
-       vdev_t *vd = zio->io_vd;
-       uint64_t psize = zio->io_size;
        zio_t *pio, *pio_next;
+       int c, w;
 
        /*
-        * If our of children haven't all completed,
+        * If our children haven't all completed,
         * wait for them and then repeat this pipeline stage.
         */
        if (zio_wait_for_children(zio, ZIO_CHILD_VDEV, ZIO_WAIT_DONE) ||
            zio_wait_for_children(zio, ZIO_CHILD_GANG, ZIO_WAIT_DONE) ||
+           zio_wait_for_children(zio, ZIO_CHILD_DDT, ZIO_WAIT_DONE) ||
            zio_wait_for_children(zio, ZIO_CHILD_LOGICAL, ZIO_WAIT_DONE))
                return (ZIO_PIPELINE_STOP);
 
-       for (int c = 0; c < ZIO_CHILD_TYPES; c++)
-               for (int w = 0; w < ZIO_WAIT_TYPES; w++)
+       for (c = 0; c < ZIO_CHILD_TYPES; c++)
+               for (w = 0; w < ZIO_WAIT_TYPES; w++)
                        ASSERT(zio->io_children[c][w] == 0);
 
-       if (bp != NULL) {
-               ASSERT(bp->blk_pad[0] == 0);
-               ASSERT(bp->blk_pad[1] == 0);
-               ASSERT(bp->blk_pad[2] == 0);
-               ASSERT(bcmp(bp, &zio->io_bp_copy, sizeof (blkptr_t)) == 0 ||
-                   (bp == zio_unique_parent(zio)->io_bp));
-               if (zio->io_type == ZIO_TYPE_WRITE && !BP_IS_HOLE(bp) &&
+       if (zio->io_bp != NULL) {
+               ASSERT(zio->io_bp->blk_pad[0] == 0);
+               ASSERT(zio->io_bp->blk_pad[1] == 0);
+               ASSERT(bcmp(zio->io_bp, &zio->io_bp_copy, sizeof (blkptr_t)) == 0 ||
+                   (zio->io_bp == zio_unique_parent(zio)->io_bp));
+               if (zio->io_type == ZIO_TYPE_WRITE && !BP_IS_HOLE(zio->io_bp) &&
+                   zio->io_bp_override == NULL &&
                    !(zio->io_flags & ZIO_FLAG_IO_REPAIR)) {
-                       ASSERT(!BP_SHOULD_BYTESWAP(bp));
-                       ASSERT3U(zio->io_prop.zp_ndvas, <=, BP_GET_NDVAS(bp));
-                       ASSERT(BP_COUNT_GANG(bp) == 0 ||
-                           (BP_COUNT_GANG(bp) == BP_GET_NDVAS(bp)));
+                       ASSERT(!BP_SHOULD_BYTESWAP(zio->io_bp));
+                       ASSERT3U(zio->io_prop.zp_copies, <=, BP_GET_NDVAS(zio->io_bp));
+                       ASSERT(BP_COUNT_GANG(zio->io_bp) == 0 ||
+                           (BP_COUNT_GANG(zio->io_bp) == BP_GET_NDVAS(zio->io_bp)));
                }
        }
 
        /*
-        * If there were child vdev or gang errors, they apply to us now.
+        * If there were child vdev/gang/ddt errors, they apply to us now.
         */
        zio_inherit_child_errors(zio, ZIO_CHILD_VDEV);
        zio_inherit_child_errors(zio, ZIO_CHILD_GANG);
+       zio_inherit_child_errors(zio, ZIO_CHILD_DDT);
+
+       /*
+        * If the I/O on the transformed data was successful, generate any
+        * checksum reports now while we still have the transformed data.
+        */
+       if (zio->io_error == 0) {
+               while (zio->io_cksum_report != NULL) {
+                       zio_cksum_report_t *zcr = zio->io_cksum_report;
+                       uint64_t align = zcr->zcr_align;
+                       uint64_t asize = P2ROUNDUP(zio->io_size, align);
+                       char *abuf = zio->io_data;
+
+                       if (asize != zio->io_size) {
+                               abuf = zio_buf_alloc(asize);
+                               bcopy(zio->io_data, abuf, zio->io_size);
+                               bzero(abuf + zio->io_size, asize - zio->io_size);
+                       }
+
+                       zio->io_cksum_report = zcr->zcr_next;
+                       zcr->zcr_next = NULL;
+                       zcr->zcr_finish(zcr, abuf);
+                       zfs_ereport_free_checksum(zcr);
+
+                       if (asize != zio->io_size)
+                               zio_buf_free(abuf, asize);
+               }
+       }
 
        zio_pop_transforms(zio);        /* note: may set zio->io_error */
 
-       vdev_stat_update(zio, psize);
+       vdev_stat_update(zio, zio->io_size);
+
+       /*
+        * If this I/O is attached to a particular vdev is slow, exceeding
+        * 30 seconds to complete, post an error described the I/O delay.
+        * We ignore these errors if the device is currently unavailable.
+        */
+       if (zio->io_delay >= MSEC_TO_TICK(zio_delay_max)) {
+               if (zio->io_vd != NULL && !vdev_is_dead(zio->io_vd))
+                       zfs_ereport_post(FM_EREPORT_ZFS_DELAY, zio->io_spa,
+                                         zio->io_vd, zio, 0, 0);
+       }
 
        if (zio->io_error) {
                /*
@@ -2172,43 +2949,58 @@ zio_done(zio_t *zio)
                 * at the block level.  We ignore these errors if the
                 * device is currently unavailable.
                 */
-               if (zio->io_error != ECKSUM && vd != NULL && !vdev_is_dead(vd))
-                       zfs_ereport_post(FM_EREPORT_ZFS_IO, spa, vd, zio, 0, 0);
-
-               if ((zio->io_error == EIO ||
-                   !(zio->io_flags & ZIO_FLAG_SPECULATIVE)) && zio == lio) {
+               if (zio->io_error != ECKSUM && zio->io_vd != NULL &&
+                       !vdev_is_dead(zio->io_vd))
+                       zfs_ereport_post(FM_EREPORT_ZFS_IO, zio->io_spa,
+                                               zio->io_vd, zio, 0, 0);
+
+               if ((zio->io_error == EIO || !(zio->io_flags &
+                   (ZIO_FLAG_SPECULATIVE | ZIO_FLAG_DONT_PROPAGATE))) &&
+                   zio == zio->io_logical) {
                        /*
                         * For logical I/O requests, tell the SPA to log the
                         * error and generate a logical data ereport.
                         */
-                       spa_log_error(spa, zio);
-                       zfs_ereport_post(FM_EREPORT_ZFS_DATA, spa, NULL, zio,
+                       spa_log_error(zio->io_spa, zio);
+                       zfs_ereport_post(FM_EREPORT_ZFS_DATA, zio->io_spa, NULL, zio,
                            0, 0);
                }
        }
 
-       if (zio->io_error && zio == lio) {
+       if (zio->io_error && zio == zio->io_logical) {
                /*
                 * Determine whether zio should be reexecuted.  This will
                 * propagate all the way to the root via zio_notify_parent().
                 */
-               ASSERT(vd == NULL && bp != NULL);
+               ASSERT(zio->io_vd == NULL && zio->io_bp != NULL);
+               ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL);
 
-               if (IO_IS_ALLOCATING(zio))
+               if (IO_IS_ALLOCATING(zio) &&
+                   !(zio->io_flags & ZIO_FLAG_CANFAIL)) {
                        if (zio->io_error != ENOSPC)
                                zio->io_reexecute |= ZIO_REEXECUTE_NOW;
                        else
                                zio->io_reexecute |= ZIO_REEXECUTE_SUSPEND;
+               }
 
                if ((zio->io_type == ZIO_TYPE_READ ||
                    zio->io_type == ZIO_TYPE_FREE) &&
+                   !(zio->io_flags & ZIO_FLAG_SCAN_THREAD) &&
                    zio->io_error == ENXIO &&
-                   spa->spa_load_state == SPA_LOAD_NONE &&
-                   spa_get_failmode(spa) != ZIO_FAILURE_MODE_CONTINUE)
+                   spa_load_state(zio->io_spa) == SPA_LOAD_NONE &&
+                   spa_get_failmode(zio->io_spa) != ZIO_FAILURE_MODE_CONTINUE)
                        zio->io_reexecute |= ZIO_REEXECUTE_SUSPEND;
 
                if (!(zio->io_flags & ZIO_FLAG_CANFAIL) && !zio->io_reexecute)
                        zio->io_reexecute |= ZIO_REEXECUTE_SUSPEND;
+
+               /*
+                * Here is a possibly good place to attempt to do
+                * either combinatorial reconstruction or error correction
+                * based on checksums.  It also might be a good place
+                * to send out preliminary ereports before we suspend
+                * processing.
+                */
        }
 
        /*
@@ -2219,6 +3011,20 @@ zio_done(zio_t *zio)
         */
        zio_inherit_child_errors(zio, ZIO_CHILD_LOGICAL);
 
+       if ((zio->io_error || zio->io_reexecute) &&
+           IO_IS_ALLOCATING(zio) && zio->io_gang_leader == zio &&
+           !(zio->io_flags & ZIO_FLAG_IO_REWRITE))
+               zio_dva_unallocate(zio, zio->io_gang_tree, zio->io_bp);
+
+       zio_gang_tree_free(&zio->io_gang_tree);
+
+       /*
+        * Godfather I/Os should never suspend.
+        */
+       if ((zio->io_flags & ZIO_FLAG_GODFATHER) &&
+           (zio->io_reexecute & ZIO_REEXECUTE_SUSPEND))
+               zio->io_reexecute = 0;
+
        if (zio->io_reexecute) {
                /*
                 * This is a logical I/O that wants to reexecute.
@@ -2235,21 +3041,37 @@ zio_done(zio_t *zio)
                 */
                ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL);
 
-               if (IO_IS_ALLOCATING(zio))
-                       zio_dva_unallocate(zio, zio->io_gang_tree, bp);
-
-               zio_gang_tree_free(&zio->io_gang_tree);
+               zio->io_gang_leader = NULL;
 
                mutex_enter(&zio->io_lock);
                zio->io_state[ZIO_WAIT_DONE] = 1;
                mutex_exit(&zio->io_lock);
 
+               /*
+                * "The Godfather" I/O monitors its children but is
+                * not a true parent to them. It will track them through
+                * the pipeline but severs its ties whenever they get into
+                * trouble (e.g. suspended). This allows "The Godfather"
+                * I/O to return status without blocking.
+                */
+               for (pio = zio_walk_parents(zio); pio != NULL; pio = pio_next) {
+                       zio_link_t *zl = zio->io_walk_link;
+                       pio_next = zio_walk_parents(zio);
+
+                       if ((pio->io_flags & ZIO_FLAG_GODFATHER) &&
+                           (zio->io_reexecute & ZIO_REEXECUTE_SUSPEND)) {
+                               zio_remove_child(pio, zio, zl);
+                               zio_notify_parent(pio, zio, ZIO_WAIT_DONE);
+                       }
+               }
+
                if ((pio = zio_unique_parent(zio)) != NULL) {
                        /*
                         * We're not a root i/o, so there's nothing to do
                         * but notify our parent.  Don't propagate errors
                         * upward since we haven't permanently failed yet.
                         */
+                       ASSERT(!(zio->io_flags & ZIO_FLAG_GODFATHER));
                        zio->io_flags |= ZIO_FLAG_DONT_PROPAGATE;
                        zio_notify_parent(pio, zio, ZIO_WAIT_DONE);
                } else if (zio->io_reexecute & ZIO_REEXECUTE_SUSPEND) {
@@ -2257,24 +3079,42 @@ zio_done(zio_t *zio)
                         * We'd fail again if we reexecuted now, so suspend
                         * until conditions improve (e.g. device comes online).
                         */
-                       zio_suspend(spa, zio);
+                       zio_suspend(zio->io_spa, zio);
                } else {
                        /*
                         * Reexecution is potentially a huge amount of work.
                         * Hand it off to the otherwise-unused claim taskq.
                         */
-                       (void) taskq_dispatch(
-                           spa->spa_zio_taskq[ZIO_TYPE_CLAIM][ZIO_TASKQ_ISSUE],
-                           (task_func_t *)zio_reexecute, zio, TQ_SLEEP);
+                       ASSERT(taskq_empty_ent(&zio->io_tqent));
+                       spa_taskq_dispatch_ent(zio->io_spa,
+                           ZIO_TYPE_CLAIM, ZIO_TASKQ_ISSUE,
+                           (task_func_t *)zio_reexecute, zio, 0,
+                           &zio->io_tqent);
                }
                return (ZIO_PIPELINE_STOP);
        }
 
-       ASSERT(zio_walk_children(zio) == NULL);
+       ASSERT(zio->io_child_count == 0);
        ASSERT(zio->io_reexecute == 0);
        ASSERT(zio->io_error == 0 || (zio->io_flags & ZIO_FLAG_CANFAIL));
 
        /*
+        * Report any checksum errors, since the I/O is complete.
+        */
+       while (zio->io_cksum_report != NULL) {
+               zio_cksum_report_t *zcr = zio->io_cksum_report;
+               zio->io_cksum_report = zcr->zcr_next;
+               zcr->zcr_next = NULL;
+               zcr->zcr_finish(zcr, NULL);
+               zfs_ereport_free_checksum(zcr);
+       }
+
+       if (zio->io_flags & ZIO_FLAG_FASTWRITE && zio->io_bp &&
+           !BP_IS_HOLE(zio->io_bp)) {
+               metaslab_fastwrite_unmark(zio->io_spa, zio->io_bp);
+       }
+
+       /*
         * It is the responsibility of the done callback to ensure that this
         * particular zio is no longer discoverable for adoption, and as
         * such, cannot acquire any new parents.
@@ -2282,8 +3122,6 @@ zio_done(zio_t *zio)
        if (zio->io_done)
                zio->io_done(zio);
 
-       zio_gang_tree_free(&zio->io_gang_tree);
-
        mutex_enter(&zio->io_lock);
        zio->io_state[ZIO_WAIT_DONE] = 1;
        mutex_exit(&zio->io_lock);
@@ -2312,12 +3150,17 @@ zio_done(zio_t *zio)
  * I/O pipeline definition
  * ==========================================================================
  */
-static zio_pipe_stage_t *zio_pipeline[ZIO_STAGES] = {
+static zio_pipe_stage_t *zio_pipeline[] = {
        NULL,
-       zio_issue_async,
        zio_read_bp_init,
+       zio_free_bp_init,
+       zio_issue_async,
        zio_write_bp_init,
        zio_checksum_generate,
+       zio_ddt_read_start,
+       zio_ddt_read_done,
+       zio_ddt_write,
+       zio_ddt_free,
        zio_gang_assemble,
        zio_gang_issue,
        zio_dva_allocate,
@@ -2330,3 +3173,79 @@ static zio_pipe_stage_t *zio_pipeline[ZIO_STAGES] = {
        zio_checksum_verify,
        zio_done
 };
+
+/* dnp is the dnode for zb1->zb_object */
+boolean_t
+zbookmark_is_before(const dnode_phys_t *dnp, const zbookmark_t *zb1,
+    const zbookmark_t *zb2)
+{
+       uint64_t zb1nextL0, zb2thisobj;
+
+       ASSERT(zb1->zb_objset == zb2->zb_objset);
+       ASSERT(zb2->zb_level == 0);
+
+       /*
+        * A bookmark in the deadlist is considered to be after
+        * everything else.
+        */
+       if (zb2->zb_object == DMU_DEADLIST_OBJECT)
+               return (B_TRUE);
+
+       /* The objset_phys_t isn't before anything. */
+       if (dnp == NULL)
+               return (B_FALSE);
+
+       zb1nextL0 = (zb1->zb_blkid + 1) <<
+           ((zb1->zb_level) * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT));
+
+       zb2thisobj = zb2->zb_object ? zb2->zb_object :
+           zb2->zb_blkid << (DNODE_BLOCK_SHIFT - DNODE_SHIFT);
+
+       if (zb1->zb_object == DMU_META_DNODE_OBJECT) {
+               uint64_t nextobj = zb1nextL0 *
+                   (dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT) >> DNODE_SHIFT;
+               return (nextobj <= zb2thisobj);
+       }
+
+       if (zb1->zb_object < zb2thisobj)
+               return (B_TRUE);
+       if (zb1->zb_object > zb2thisobj)
+               return (B_FALSE);
+       if (zb2->zb_object == DMU_META_DNODE_OBJECT)
+               return (B_FALSE);
+       return (zb1nextL0 <= zb2->zb_blkid);
+}
+
+#if defined(_KERNEL) && defined(HAVE_SPL)
+/* Fault injection */
+EXPORT_SYMBOL(zio_injection_enabled);
+EXPORT_SYMBOL(zio_inject_fault);
+EXPORT_SYMBOL(zio_inject_list_next);
+EXPORT_SYMBOL(zio_clear_fault);
+EXPORT_SYMBOL(zio_handle_fault_injection);
+EXPORT_SYMBOL(zio_handle_device_injection);
+EXPORT_SYMBOL(zio_handle_label_injection);
+EXPORT_SYMBOL(zio_priority_table);
+EXPORT_SYMBOL(zio_type_name);
+
+module_param(zio_bulk_flags, int, 0644);
+MODULE_PARM_DESC(zio_bulk_flags, "Additional flags to pass to bulk buffers");
+
+module_param(zio_delay_max, int, 0644);
+MODULE_PARM_DESC(zio_delay_max, "Max zio millisec delay before posting event");
+
+module_param(zio_requeue_io_start_cut_in_line, int, 0644);
+MODULE_PARM_DESC(zio_requeue_io_start_cut_in_line, "Prioritize requeued I/O");
+
+module_param(zfs_sync_pass_deferred_free, int, 0644);
+MODULE_PARM_DESC(zfs_sync_pass_deferred_free,
+    "defer frees starting in this pass");
+
+module_param(zfs_sync_pass_dont_compress, int, 0644);
+MODULE_PARM_DESC(zfs_sync_pass_dont_compress,
+    "don't compress starting in this pass");
+
+module_param(zfs_sync_pass_rewrite, int, 0644);
+MODULE_PARM_DESC(zfs_sync_pass_rewrite,
+    "rewrite new bps starting in this pass");
+#endif