Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h (revision 326843) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h (working copy) @@ -202,12 +202,13 @@ enum zio_flag { ZIO_FLAG_CANFAIL) enum zio_child { - ZIO_CHILD_VDEV = 0, - ZIO_CHILD_GANG, - ZIO_CHILD_DDT, - ZIO_CHILD_LOGICAL, - ZIO_CHILD_TYPES + ZIO_CHILD_VDEV = 1 << 0, + ZIO_CHILD_GANG = 1 << 1, + ZIO_CHILD_DDT = 1 << 2, + ZIO_CHILD_LOGICAL = 1 << 3 }; +#define ZIO_CHILD_TYPES 4 +#define zio_child(x) (highbit64(x) - 1) enum zio_wait_type { ZIO_WAIT_READY = 0, Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c (revision 326843) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c (working copy) @@ -477,8 +477,10 @@ 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++) - pio->io_children[cio->io_child_type][w] += !cio->io_state[w]; + for (int w = 0; w < ZIO_WAIT_TYPES; w++) { + int child = zio_child(cio->io_child_type); + pio->io_children[child][w] += !cio->io_state[w]; + } list_insert_head(&pio->io_child_list, zl); list_insert_head(&cio->io_parent_list, zl); @@ -512,18 +514,26 @@ zio_remove_child(zio_t *pio, zio_t *cio, zio_link_ } static boolean_t -zio_wait_for_children(zio_t *zio, enum zio_child child, enum zio_wait_type wait) +zio_wait_for_children(zio_t *zio, enum zio_child children, + enum zio_wait_type wait) { - uint64_t *countp = &zio->io_children[child][wait]; boolean_t waiting = B_FALSE; mutex_enter(&zio->io_lock); - ASSERT(zio->io_stall == NULL); - if (*countp != 0) { - zio->io_stage >>= 1; - ASSERT3U(zio->io_stage, !=, ZIO_STAGE_OPEN); - zio->io_stall = countp; - waiting = B_TRUE; + for (int child = 0; child < ZIO_CHILD_TYPES; child++) { + if (!(children & (1 << child))) + continue; + + uint64_t *countp = &zio->io_children[child][wait]; + + ASSERT(zio->io_stall == NULL); + if (*countp != 0) { + zio->io_stage >>= 1; + ASSERT3U(zio->io_stage, !=, ZIO_STAGE_OPEN); + zio->io_stall = countp; + waiting = B_TRUE; + break; + } } mutex_exit(&zio->io_lock); @@ -533,8 +543,10 @@ static boolean_t static 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]; - int *errorp = &pio->io_child_error[zio->io_child_type]; + int child = zio_child(zio->io_child_type); + uint64_t *countp = + &pio->io_children[child][wait]; + int *errorp = &pio->io_child_error[child]; mutex_enter(&pio->io_lock); if (zio->io_error && !(zio->io_flags & ZIO_FLAG_DONT_PROPAGATE)) @@ -565,8 +577,8 @@ zio_notify_parent(zio_t *pio, zio_t *zio, enum zio static void zio_inherit_child_errors(zio_t *zio, enum zio_child c) { - if (zio->io_child_error[c] != 0 && zio->io_error == 0) - zio->io_error = zio->io_child_error[c]; + if (zio->io_child_error[zio_child(c)] != 0 && zio->io_error == 0) + zio->io_error = zio->io_child_error[zio_child(c)]; } int @@ -1330,9 +1342,10 @@ zio_write_compress(zio_t *zio) * If our children haven't all reached the ready stage, * wait for them and then repeat this pipeline stage. */ - if (zio_wait_for_children(zio, ZIO_CHILD_GANG, ZIO_WAIT_READY) || - zio_wait_for_children(zio, ZIO_CHILD_LOGICAL, ZIO_WAIT_READY)) + if (zio_wait_for_children(zio, ZIO_CHILD_GANG | ZIO_CHILD_LOGICAL, + ZIO_WAIT_READY)) { return (ZIO_PIPELINE_STOP); + } if (!IO_IS_ALLOCATING(zio)) return (ZIO_PIPELINE_CONTINUE); @@ -1795,10 +1808,11 @@ zio_reexecute(zio_t *pio) */ zio_link_t *zl = NULL; for (cio = zio_walk_children(pio, &zl); cio != NULL; cio = cio_next) { + int child = zio_child(cio->io_child_type); cio_next = zio_walk_children(pio, &zl); mutex_enter(&pio->io_lock); for (int w = 0; w < ZIO_WAIT_TYPES; w++) - pio->io_children[cio->io_child_type][w]++; + pio->io_children[child][w]++; mutex_exit(&pio->io_lock); zio_reexecute(cio); } @@ -2200,7 +2214,7 @@ zio_gang_issue(zio_t *zio) 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) + if (zio->io_child_error[zio_child(ZIO_CHILD_GANG)] == 0) zio_gang_tree_issue(zio, zio->io_gang_tree, bp, zio->io_abd, 0); else @@ -2477,7 +2491,7 @@ zio_ddt_read_start(zio_t *zio) ASSERT(BP_GET_PSIZE(bp) == zio->io_size); ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL); - if (zio->io_child_error[ZIO_CHILD_DDT]) { + if (zio->io_child_error[zio_child(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; @@ -2523,7 +2537,7 @@ zio_ddt_read_done(zio_t *zio) ASSERT(BP_GET_PSIZE(bp) == zio->io_size); ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL); - if (zio->io_child_error[ZIO_CHILD_DDT]) { + if (zio->io_child_error[zio_child(ZIO_CHILD_DDT)]) { ddt_t *ddt = ddt_select(zio->io_spa, bp); ddt_entry_t *dde = zio->io_vsd; if (ddt == NULL) { @@ -2538,7 +2552,7 @@ zio_ddt_read_done(zio_t *zio) if (dde->dde_repair_abd != NULL) { abd_copy(zio->io_abd, dde->dde_repair_abd, zio->io_size); - zio->io_child_error[ZIO_CHILD_DDT] = 0; + zio->io_child_error[zio_child(ZIO_CHILD_DDT)] = 0; } ddt_repair_done(ddt, dde); zio->io_vsd = NULL; @@ -3107,7 +3121,7 @@ zio_vdev_io_start(zio_t *zio) int ret; ASSERT(zio->io_error == 0); - ASSERT(zio->io_child_error[ZIO_CHILD_VDEV] == 0); + ASSERT(zio->io_child_error[zio_child(ZIO_CHILD_VDEV)] == 0); if (vd == NULL) { if (!(zio->io_flags & ZIO_FLAG_CONFIG_WRITER)) @@ -3558,15 +3572,17 @@ zio_ready(zio_t *zio) zio_t *pio, *pio_next; zio_link_t *zl = NULL; - if (zio_wait_for_children(zio, ZIO_CHILD_GANG, ZIO_WAIT_READY) || - zio_wait_for_children(zio, ZIO_CHILD_DDT, ZIO_WAIT_READY)) + if (zio_wait_for_children(zio, ZIO_CHILD_GANG | 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) || (zio->io_flags & ZIO_FLAG_NOPWRITE)); - ASSERT(zio->io_children[ZIO_CHILD_GANG][ZIO_WAIT_READY] == 0); + ASSERT0(zio->io_children[zio_child( + ZIO_CHILD_GANG)][ZIO_WAIT_READY]); zio->io_ready(zio); } @@ -3700,11 +3716,10 @@ zio_done(zio_t *zio) * 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)) + if (zio_wait_for_children(zio, ZIO_CHILD_VDEV | ZIO_CHILD_GANG | + ZIO_CHILD_DDT | ZIO_CHILD_LOGICAL, ZIO_WAIT_DONE)) { return (ZIO_PIPELINE_STOP); + } /* * If the allocation throttle is enabled, then update the accounting. @@ -3730,9 +3745,9 @@ zio_done(zio_t *zio) VERIFY(refcount_not_held(&mc->mc_alloc_slots, zio)); } - for (int c = 0; c < ZIO_CHILD_TYPES; c++) + for (int child = 0; child < ZIO_CHILD_TYPES; child++) for (int w = 0; w < ZIO_WAIT_TYPES; w++) - ASSERT(zio->io_children[c][w] == 0); + ASSERT0(zio->io_children[child][w]); if (bp != NULL && !BP_IS_EMBEDDED(bp)) { ASSERT(bp->blk_pad[0] == 0);