We want to be sure that the functions that write the child and parent list of a bs are either under BQL or drain. If this guarantee holds, then we can read the list also in the I/O APIs.
Signed-off-by: Emanuele Giuseppe Esposito <eespo...@redhat.com> --- block.c | 5 +++++ block/io.c | 5 +++++ include/block/block_int-global-state.h | 8 +++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/block.c b/block.c index b912f517a4..7d1eb847a4 100644 --- a/block.c +++ b/block.c @@ -2711,12 +2711,14 @@ static void bdrv_replace_child_noperm(BdrvChild *child, if (child->klass->detach) { child->klass->detach(child); } + assert_bdrv_graph_writable(old_bs); QLIST_REMOVE(child, next_parent); } child->bs = new_bs; if (new_bs) { + assert_bdrv_graph_writable(new_bs); QLIST_INSERT_HEAD(&new_bs->parents, child, next_parent); /* @@ -2917,6 +2919,7 @@ static int bdrv_attach_child_noperm(BlockDriverState *parent_bs, return ret; } + assert_bdrv_graph_writable(parent_bs); QLIST_INSERT_HEAD(&parent_bs->children, *child, next); /* * child is removed in bdrv_attach_child_common_abort(), so don't care to @@ -3117,6 +3120,7 @@ static void bdrv_unset_inherits_from(BlockDriverState *root, BdrvChild *child, void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child) { g_assert(qemu_in_main_thread()); + assert_bdrv_graph_writable(parent); if (child == NULL) { return; } @@ -4878,6 +4882,7 @@ static void bdrv_remove_filter_or_cow_child_abort(void *opaque) BdrvRemoveFilterOrCowChild *s = opaque; BlockDriverState *parent_bs = s->child->opaque; + assert_bdrv_graph_writable(parent_bs); QLIST_INSERT_HEAD(&parent_bs->children, s->child, next); if (s->is_backing) { parent_bs->backing = s->child; diff --git a/block/io.c b/block/io.c index 21dcc5d962..d184183b07 100644 --- a/block/io.c +++ b/block/io.c @@ -739,6 +739,11 @@ void bdrv_drain_all(void) bdrv_drain_all_end(); } +void assert_bdrv_graph_writable(BlockDriverState *bs) +{ + g_assert(qatomic_read(&bs->quiesce_counter) > 0 || qemu_in_main_thread()); +} + /** * Remove an active request from the tracked requests list * diff --git a/include/block/block_int-global-state.h b/include/block/block_int-global-state.h index aad549cb85..a53ab146fc 100644 --- a/include/block/block_int-global-state.h +++ b/include/block/block_int-global-state.h @@ -343,4 +343,10 @@ void bdrv_remove_aio_context_notifier(BlockDriverState *bs, */ void bdrv_drain_all_end_quiesce(BlockDriverState *bs); -#endif /* BLOCK_INT_GLOBAL_STATE*/ +/** + * Make sure that the function is either running under + * drain, or under BQL. + */ +void assert_bdrv_graph_writable(BlockDriverState *bs); + +#endif /* BLOCK_INT_GLOBAL_STATE */ -- 2.27.0