From 696bf4c78c4640026c827c931a18385b687c66e8 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Thu, 3 Mar 2022 10:15:59 -0500 Subject: [PATCH] block: introduce assert_bdrv_graph_writable We want to be sure that the functions that write the child and parent list of a bs are under BQL and drain. BQL prevents from concurrent writings from the GS API, while drains protect from I/O. TODO: drains are missing in some functions using this assert. Therefore a proper assertion will fail. Because adding drains requires additional discussions, they will be added in future series. Signed-off-by: Emanuele Giuseppe Esposito Message-Id: <20220303151616.325444-15-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- block.c | 4 ++++ include/block/block_int-global-state.h | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/block.c b/block.c index f2a7350548..fe05df471a 100644 --- a/block.c +++ b/block.c @@ -1420,6 +1420,7 @@ static void bdrv_child_cb_attach(BdrvChild *child) { BlockDriverState *bs = child->opaque; + assert_bdrv_graph_writable(bs); QLIST_INSERT_HEAD(&bs->children, child, next); if (child->role & BDRV_CHILD_COW) { @@ -1439,6 +1440,7 @@ static void bdrv_child_cb_detach(BdrvChild *child) bdrv_unapply_subtree_drain(child, bs); + assert_bdrv_graph_writable(bs); QLIST_REMOVE(child, next); } @@ -2829,6 +2831,7 @@ static void bdrv_replace_child_noperm(BdrvChild **childp, if (child->klass->detach) { child->klass->detach(child); } + assert_bdrv_graph_writable(old_bs); QLIST_REMOVE(child, next_parent); } @@ -2838,6 +2841,7 @@ static void bdrv_replace_child_noperm(BdrvChild **childp, } if (new_bs) { + assert_bdrv_graph_writable(new_bs); QLIST_INSERT_HEAD(&new_bs->parents, child, next_parent); /* diff --git a/include/block/block_int-global-state.h b/include/block/block_int-global-state.h index 5078d6a6ea..0f21b0570b 100644 --- a/include/block/block_int-global-state.h +++ b/include/block/block_int-global-state.h @@ -309,4 +309,21 @@ void bdrv_remove_aio_context_notifier(BlockDriverState *bs, */ void bdrv_drain_all_end_quiesce(BlockDriverState *bs); +/** + * Make sure that the function is running under both drain and BQL. + * The latter protects from concurrent writings + * from the GS API, while the former prevents concurrent reads + * from I/O. + */ +static inline void assert_bdrv_graph_writable(BlockDriverState *bs) +{ + /* + * TODO: this function is incomplete. Because the users of this + * assert lack the necessary drains, check only for BQL. + * Once the necessary drains are added, + * assert also for qatomic_read(&bs->quiesce_counter) > 0 + */ + assert(qemu_in_main_thread()); +} + #endif /* BLOCK_INT_GLOBAL_STATE */ -- 2.11.0