From e8e602d987b01e7940f698d5fa2b00754609c74b Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Sat, 31 May 2025 11:18:10 +1000 Subject: [PATCH] zio_add_child: collapse into a single function The child locking difference is simple enough to handle with a boolean. The actual work is more involved, and it's easy to forget to change things in both places when experimenting. Just collapse them. Sponsored-by: Klara, Inc. Sponsored-by: Wasabi Technology, Inc. Reviewed-by: Brian Behlendorf Reviewed-by: Alexander Motin Signed-off-by: Rob Norris Closes #17382 --- include/sys/zio.h | 1 - module/zfs/zio.c | 52 ++++++++++++++++------------------------------- 2 files changed, 17 insertions(+), 36 deletions(-) diff --git a/include/sys/zio.h b/include/sys/zio.h index ea3809ce0..d91a4eb1e 100644 --- a/include/sys/zio.h +++ b/include/sys/zio.h @@ -621,7 +621,6 @@ extern zio_t *zio_walk_parents(zio_t *cio, zio_link_t **); extern zio_t *zio_walk_children(zio_t *pio, zio_link_t **); extern zio_t *zio_unique_parent(zio_t *cio); extern void zio_add_child(zio_t *pio, zio_t *cio); -extern void zio_add_child_first(zio_t *pio, zio_t *cio); extern void *zio_buf_alloc(size_t size); extern void zio_buf_free(void *buf, size_t size); diff --git a/module/zfs/zio.c b/module/zfs/zio.c index 2bbf5d50b..ca84f919e 100644 --- a/module/zfs/zio.c +++ b/module/zfs/zio.c @@ -744,8 +744,8 @@ zio_unique_parent(zio_t *cio) return (pio); } -void -zio_add_child(zio_t *pio, zio_t *cio) +static void +zio_add_child_impl(zio_t *pio, zio_t *cio, boolean_t first) { /* * Logical I/Os can have logical, gang, or vdev children. @@ -765,7 +765,11 @@ zio_add_child(zio_t *pio, zio_t *cio) zl->zl_child = cio; mutex_enter(&pio->io_lock); - mutex_enter(&cio->io_lock); + + if (first) + ASSERT(list_is_empty(&cio->io_parent_list)); + else + mutex_enter(&cio->io_lock); ASSERT(pio->io_state[ZIO_WAIT_DONE] == 0); @@ -776,44 +780,22 @@ zio_add_child(zio_t *pio, zio_t *cio) list_insert_head(&pio->io_child_list, zl); list_insert_head(&cio->io_parent_list, zl); - mutex_exit(&cio->io_lock); + if (!first) + mutex_exit(&cio->io_lock); + mutex_exit(&pio->io_lock); } void +zio_add_child(zio_t *pio, zio_t *cio) +{ + zio_add_child_impl(pio, cio, B_FALSE); +} + +static void zio_add_child_first(zio_t *pio, zio_t *cio) { - /* - * Logical I/Os can have logical, gang, or vdev children. - * Gang I/Os can have gang or vdev children. - * Vdev I/Os can only have vdev children. - * The following ASSERT captures all of these constraints. - */ - ASSERT3S(cio->io_child_type, <=, pio->io_child_type); - - /* Parent should not have READY stage if child doesn't have it. */ - IMPLY((cio->io_pipeline & ZIO_STAGE_READY) == 0 && - (cio->io_child_type != ZIO_CHILD_VDEV), - (pio->io_pipeline & ZIO_STAGE_READY) == 0); - - zio_link_t *zl = kmem_cache_alloc(zio_link_cache, KM_SLEEP); - zl->zl_parent = pio; - zl->zl_child = cio; - - ASSERT(list_is_empty(&cio->io_parent_list)); - list_insert_head(&cio->io_parent_list, zl); - - mutex_enter(&pio->io_lock); - - ASSERT(pio->io_state[ZIO_WAIT_DONE] == 0); - - uint64_t *countp = pio->io_children[cio->io_child_type]; - for (int w = 0; w < ZIO_WAIT_TYPES; w++) - countp[w] += !cio->io_state[w]; - - list_insert_head(&pio->io_child_list, zl); - - mutex_exit(&pio->io_lock); + zio_add_child_impl(pio, cio, B_TRUE); } static void