]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/zio.c
Improve ZFS objset sync parallelism
[mirror_zfs.git] / module / zfs / zio.c
index 4eb276352a23984b6377db83f7e0ae573b39381e..2f5b423ee72e52a246c84e5eb0060d0dacd45d1f 100644 (file)
@@ -899,6 +899,7 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
        zio->io_orig_stage = zio->io_stage = stage;
        zio->io_orig_pipeline = zio->io_pipeline = pipeline;
        zio->io_pipeline_trace = ZIO_STAGE_OPEN;
+       zio->io_allocator = ZIO_ALLOCATOR_NONE;
 
        zio->io_state[ZIO_WAIT_READY] = (stage >= ZIO_STAGE_READY) ||
            (pipeline & ZIO_STAGE_READY) == 0;
@@ -2007,7 +2008,7 @@ zio_taskq_dispatch(zio_t *zio, zio_taskq_type_t q, boolean_t cutinline)
         */
        ASSERT(taskq_empty_ent(&zio->io_tqent));
        spa_taskq_dispatch_ent(spa, t, q, zio_execute, zio, flags,
-           &zio->io_tqent);
+           &zio->io_tqent, zio);
 }
 
 static boolean_t
@@ -2032,8 +2033,8 @@ zio_taskq_member(zio_t *zio, zio_taskq_type_t q)
 static zio_t *
 zio_issue_async(zio_t *zio)
 {
+       ASSERT((zio->io_type != ZIO_TYPE_WRITE) || ZIO_HAS_ALLOCATOR(zio));
        zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE, B_FALSE);
-
        return (NULL);
 }
 
@@ -2347,6 +2348,9 @@ zio_wait(zio_t *zio)
        ASSERT0(zio->io_queued_timestamp);
        zio->io_queued_timestamp = gethrtime();
 
+       if (zio->io_type == ZIO_TYPE_WRITE) {
+               spa_select_allocator(zio);
+       }
        __zio_execute(zio);
 
        mutex_enter(&zio->io_lock);
@@ -2399,6 +2403,9 @@ zio_nowait(zio_t *zio)
 
        ASSERT0(zio->io_queued_timestamp);
        zio->io_queued_timestamp = gethrtime();
+       if (zio->io_type == ZIO_TYPE_WRITE) {
+               spa_select_allocator(zio);
+       }
        __zio_execute(zio);
 }
 
@@ -2863,6 +2870,13 @@ zio_gang_issue(zio_t *zio)
        return (zio);
 }
 
+static void
+zio_gang_inherit_allocator(zio_t *pio, zio_t *cio)
+{
+       cio->io_allocator = pio->io_allocator;
+       cio->io_wr_iss_tq = pio->io_wr_iss_tq;
+}
+
 static void
 zio_write_gang_member_ready(zio_t *zio)
 {
@@ -2934,6 +2948,7 @@ zio_write_gang_block(zio_t *pio, metaslab_class_t *mc)
                gbh_copies = MIN(2, spa_max_replication(spa));
        }
 
+       ASSERT(ZIO_HAS_ALLOCATOR(pio));
        int flags = METASLAB_HINTBP_FAVOR | METASLAB_GANG_HEADER;
        if (pio->io_flags & ZIO_FLAG_IO_ALLOCATING) {
                ASSERT(pio->io_priority == ZIO_PRIORITY_ASYNC_WRITE);
@@ -2997,6 +3012,8 @@ zio_write_gang_block(zio_t *pio, metaslab_class_t *mc)
            zio_write_gang_done, NULL, pio->io_priority,
            ZIO_GANG_CHILD_FLAGS(pio), &pio->io_bookmark);
 
+       zio_gang_inherit_allocator(pio, zio);
+
        /*
         * Create and nowait the gang children.
         */
@@ -3027,6 +3044,8 @@ zio_write_gang_block(zio_t *pio, metaslab_class_t *mc)
                    zio_write_gang_done, &gn->gn_child[g], pio->io_priority,
                    ZIO_GANG_CHILD_FLAGS(pio), &pio->io_bookmark);
 
+               zio_gang_inherit_allocator(zio, cio);
+
                if (pio->io_flags & ZIO_FLAG_IO_ALLOCATING) {
                        ASSERT(pio->io_priority == ZIO_PRIORITY_ASYNC_WRITE);
                        ASSERT(has_data);
@@ -3539,6 +3558,7 @@ zio_io_to_allocate(spa_t *spa, int allocator)
                return (NULL);
 
        ASSERT(IO_IS_ALLOCATING(zio));
+       ASSERT(ZIO_HAS_ALLOCATOR(zio));
 
        /*
         * Try to place a reservation for this zio. If we're unable to
@@ -3575,21 +3595,12 @@ zio_dva_throttle(zio_t *zio)
        }
 
        ASSERT(zio->io_type == ZIO_TYPE_WRITE);
+       ASSERT(ZIO_HAS_ALLOCATOR(zio));
        ASSERT(zio->io_child_type > ZIO_CHILD_GANG);
        ASSERT3U(zio->io_queued_timestamp, >, 0);
        ASSERT(zio->io_stage == ZIO_STAGE_DVA_THROTTLE);
 
-       zbookmark_phys_t *bm = &zio->io_bookmark;
-       /*
-        * We want to try to use as many allocators as possible to help improve
-        * performance, but we also want logically adjacent IOs to be physically
-        * adjacent to improve sequential read performance. We chunk each object
-        * into 2^20 block regions, and then hash based on the objset, object,
-        * level, and region to accomplish both of these goals.
-        */
-       int allocator = (uint_t)cityhash4(bm->zb_objset, bm->zb_object,
-           bm->zb_level, bm->zb_blkid >> 20) % spa->spa_alloc_count;
-       zio->io_allocator = allocator;
+       int allocator = zio->io_allocator;
        zio->io_metaslab_class = mc;
        mutex_enter(&spa->spa_allocs[allocator].spaa_lock);
        avl_add(&spa->spa_allocs[allocator].spaa_tree, zio);
@@ -3663,6 +3674,7 @@ zio_dva_allocate(zio_t *zio)
         * sync write performance.  If a log allocation fails, we will fall
         * back to spa_sync() which is abysmal for performance.
         */
+       ASSERT(ZIO_HAS_ALLOCATOR(zio));
        error = metaslab_alloc(spa, mc, zio->io_size, bp,
            zio->io_prop.zp_copies, zio->io_txg, NULL, flags,
            &zio->io_alloc_list, zio, zio->io_allocator);
@@ -4515,6 +4527,7 @@ zio_ready(zio_t *zio)
                        ASSERT(IO_IS_ALLOCATING(zio));
                        ASSERT(zio->io_priority == ZIO_PRIORITY_ASYNC_WRITE);
                        ASSERT(zio->io_metaslab_class != NULL);
+                       ASSERT(ZIO_HAS_ALLOCATOR(zio));
 
                        /*
                         * We were unable to allocate anything, unreserve and
@@ -4601,6 +4614,7 @@ zio_dva_throttle_done(zio_t *zio)
        }
 
        ASSERT(IO_IS_ALLOCATING(pio));
+       ASSERT(ZIO_HAS_ALLOCATOR(pio));
        ASSERT3P(zio, !=, zio->io_logical);
        ASSERT(zio->io_logical != NULL);
        ASSERT(!(zio->io_flags & ZIO_FLAG_IO_REPAIR));
@@ -4663,6 +4677,7 @@ zio_done(zio_t *zio)
                ASSERT(zio->io_type == ZIO_TYPE_WRITE);
                ASSERT(zio->io_priority == ZIO_PRIORITY_ASYNC_WRITE);
                ASSERT(zio->io_bp != NULL);
+               ASSERT(ZIO_HAS_ALLOCATOR(zio));
 
                metaslab_group_alloc_verify(zio->io_spa, zio->io_bp, zio,
                    zio->io_allocator);
@@ -4928,7 +4943,7 @@ zio_done(zio_t *zio)
                        ASSERT(taskq_empty_ent(&zio->io_tqent));
                        spa_taskq_dispatch_ent(zio->io_spa,
                            ZIO_TYPE_CLAIM, ZIO_TASKQ_ISSUE,
-                           zio_reexecute, zio, 0, &zio->io_tqent);
+                           zio_reexecute, zio, 0, &zio->io_tqent, NULL);
                }
                return (NULL);
        }