Export dbuf_* symbols
[zfs.git] / module / zfs / zio.c
index 6b03be6..206ed9a 100644 (file)
@@ -20,7 +20,8 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011 by Delphix. 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>
@@ -98,6 +99,35 @@ int zio_buf_debug_limit = 0;
 
 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)
 {
@@ -107,8 +137,8 @@ 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, KMC_KMEM);
+       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, KMC_KMEM);
 
@@ -510,15 +540,6 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
        ASSERT(vd || stage == ZIO_STAGE_OPEN);
 
        zio = kmem_cache_alloc(zio_cache, KM_PUSHPAGE);
-       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));
 
        if (vd != NULL)
                zio->io_child_type = ZIO_CHILD_VDEV;
@@ -530,6 +551,7 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
                zio->io_child_type = ZIO_CHILD_LOGICAL;
 
        if (bp != NULL) {
+               zio->io_logical = NULL;
                zio->io_bp = (blkptr_t *)bp;
                zio->io_bp_copy = *bp;
                zio->io_bp_orig = *bp;
@@ -540,21 +562,52 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
                        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_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_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_delay = 0;
+       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);
@@ -570,16 +623,14 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
                zio_add_child(pio, zio);
        }
 
+       taskq_init_ent(&zio->io_tqent);
+
        return (zio);
 }
 
 static void
 zio_destroy(zio_t *zio)
 {
-       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);
 }
 
@@ -1073,7 +1124,7 @@ zio_taskq_dispatch(zio_t *zio, enum zio_taskq_type q, boolean_t cutinline)
 {
        spa_t *spa = zio->io_spa;
        zio_type_t t = zio->io_type;
-       int flags = TQ_NOSLEEP | (cutinline ? TQ_FRONT : 0);
+       int flags = (cutinline ? TQ_FRONT : 0);
 
        /*
         * If we're a config writer or a probe, the normal issue and
@@ -1098,8 +1149,14 @@ zio_taskq_dispatch(zio_t *zio, enum zio_taskq_type q, boolean_t cutinline)
 
        ASSERT3U(q, <, ZIO_TASKQ_TYPES);
 
-       while (taskq_dispatch(spa->spa_zio_taskq[t][q],
-           (task_func_t *)zio_execute, zio, flags) == 0); /* do nothing */
+       /*
+        * 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));
+       taskq_dispatch_ent(spa->spa_zio_taskq[t][q],
+           (task_func_t *)zio_execute, zio, flags, &zio->io_tqent);
 }
 
 static boolean_t
@@ -2260,13 +2317,22 @@ zio_alloc_zil(spa_t *spa, uint64_t txg, blkptr_t *new_bp, blkptr_t *old_bp,
 
        ASSERT(txg > spa_syncing_txg(spa));
 
-       if (use_slog)
+       /*
+        * 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, old_bp, METASLAB_HINTBP_AVOID);
+                   new_bp, 1, txg, old_bp,
+                   METASLAB_HINTBP_AVOID | METASLAB_GANG_AVOID);
+       }
 
-       if (error)
+       if (error) {
                error = metaslab_alloc(spa, spa_normal_class(spa), size,
-                   new_bp, 1, txg, old_bp, METASLAB_HINTBP_AVOID);
+                   new_bp, 1, txg, old_bp,
+                   METASLAB_HINTBP_AVOID | METASLAB_GANG_AVOID);
+       }
 
        if (error == 0) {
                BP_SET_LSIZE(new_bp, size);
@@ -2947,9 +3013,11 @@ zio_done(zio_t *zio)
                         * Reexecution is potentially a huge amount of work.
                         * Hand it off to the otherwise-unused claim taskq.
                         */
-                       (void) taskq_dispatch(
+                       ASSERT(taskq_empty_ent(&zio->io_tqent));
+                       (void) taskq_dispatch_ent(
                            zio->io_spa->spa_zio_taskq[ZIO_TYPE_CLAIM][ZIO_TASKQ_ISSUE],
-                           (task_func_t *)zio_reexecute, zio, TQ_SLEEP);
+                           (task_func_t *)zio_reexecute, zio, 0,
+                           &zio->io_tqent);
                }
                return (ZIO_PIPELINE_STOP);
        }