Message ID | 20211012084906.2060507-9-eesposit@redhat.com |
---|---|
State | New |
Headers | show |
Series | block layer: split block APIs in global state and I/O | expand |
On 12/10/21 10:48, Emanuele Giuseppe Esposito wrote: > 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 <eesposit@redhat.com> > --- > block.c | 5 +++++ > block/io.c | 11 +++++++++++ > include/block/block_int-global-state.h | 10 +++++++++- > 3 files changed, 25 insertions(+), 1 deletion(-) > > diff --git a/block.c b/block.c > index 41c5883c5c..94bff5c757 100644 > --- a/block.c > +++ b/block.c > @@ -2734,12 +2734,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); > > /* > @@ -2940,6 +2942,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 > @@ -3140,6 +3143,7 @@ static void bdrv_unset_inherits_from(BlockDriverState *root, BdrvChild *child, > void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child) > { > assert(qemu_in_main_thread()); > + assert_bdrv_graph_writable(parent); > if (child == NULL) { > return; > } > @@ -4903,6 +4907,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 f271ab3684..1c71e354d6 100644 > --- a/block/io.c > +++ b/block/io.c > @@ -740,6 +740,17 @@ void bdrv_drain_all(void) > bdrv_drain_all_end(); > } > > +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()); > +} > + > /** > * 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 d08e80222c..6bd7746409 100644 > --- a/include/block/block_int-global-state.h > +++ b/include/block/block_int-global-state.h > @@ -316,4 +316,12 @@ 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 and BQL. The latter protects from concurrent writings > + * from the GS API, while the former prevents concurrent reads > + * from I/O. > + */ > +void assert_bdrv_graph_writable(BlockDriverState *bs); > + > +#endif /* BLOCK_INT_GLOBAL_STATE */ > Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
On Tue, Oct 12, 2021 at 04:48:49AM -0400, Emanuele Giuseppe Esposito wrote: > 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 <eesposit@redhat.com> > --- > block.c | 5 +++++ > block/io.c | 11 +++++++++++ > include/block/block_int-global-state.h | 10 +++++++++- > 3 files changed, 25 insertions(+), 1 deletion(-) Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
diff --git a/block.c b/block.c index 41c5883c5c..94bff5c757 100644 --- a/block.c +++ b/block.c @@ -2734,12 +2734,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); /* @@ -2940,6 +2942,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 @@ -3140,6 +3143,7 @@ static void bdrv_unset_inherits_from(BlockDriverState *root, BdrvChild *child, void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child) { assert(qemu_in_main_thread()); + assert_bdrv_graph_writable(parent); if (child == NULL) { return; } @@ -4903,6 +4907,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 f271ab3684..1c71e354d6 100644 --- a/block/io.c +++ b/block/io.c @@ -740,6 +740,17 @@ void bdrv_drain_all(void) bdrv_drain_all_end(); } +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()); +} + /** * 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 d08e80222c..6bd7746409 100644 --- a/include/block/block_int-global-state.h +++ b/include/block/block_int-global-state.h @@ -316,4 +316,12 @@ 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 and BQL. The latter protects from concurrent writings + * from the GS API, while the former prevents concurrent reads + * from I/O. + */ +void assert_bdrv_graph_writable(BlockDriverState *bs); + +#endif /* BLOCK_INT_GLOBAL_STATE */
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 <eesposit@redhat.com> --- block.c | 5 +++++ block/io.c | 11 +++++++++++ include/block/block_int-global-state.h | 10 +++++++++- 3 files changed, 25 insertions(+), 1 deletion(-)