Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h (revision 326914) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h (working copy) @@ -223,12 +223,13 @@ 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 326914) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c (working copy) @@ -465,8 +465,10 @@ 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); @@ -500,18 +502,26 @@ } 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; - 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); return (waiting); @@ -520,8 +530,10 @@ 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)) @@ -543,8 +555,8 @@ 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)]; } /* @@ -1176,9 +1188,10 @@ * 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); @@ -1593,10 +1606,11 @@ * cannot be affected by any side effects of reexecuting 'cio'. */ for (cio = zio_walk_children(pio); cio != NULL; cio = cio_next) { + int child = zio_child(cio->io_child_type); cio_next = zio_walk_children(pio); 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); } @@ -1957,7 +1971,7 @@ 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_data); else zio_gang_tree_free(&zio->io_gang_tree); @@ -2174,7 +2188,7 @@ 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; @@ -2220,7 +2234,7 @@ 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) { @@ -2234,7 +2248,7 @@ } 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; + zio->io_child_error[zio_child(ZIO_CHILD_DDT)] = 0; } ddt_repair_done(ddt, dde); zio->io_vsd = NULL; @@ -2671,7 +2685,7 @@ 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)) @@ -3109,15 +3123,17 @@ blkptr_t *bp = zio->io_bp; zio_t *pio, *pio_next; - 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); } @@ -3175,15 +3191,14 @@ * 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); + } - 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);