diff mbox series

[06/26] blkdebug: add missing coroutine_fn annotations

Message ID 20220922084924.201610-7-pbonzini@redhat.com
State New
Headers show
Series block: fix coroutine_fn annotations | expand

Commit Message

Paolo Bonzini Sept. 22, 2022, 8:49 a.m. UTC
Callers of coroutine_fn must be coroutine_fn themselves, or the call
must be within "if (qemu_in_coroutine())".  Apply coroutine_fn to
functions where this holds.

Reviewed-by: Alberto Faria <afaria@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 block/blkdebug.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

Comments

Kevin Wolf Oct. 5, 2022, 10:32 a.m. UTC | #1
Am 22.09.2022 um 10:49 hat Paolo Bonzini geschrieben:
> Callers of coroutine_fn must be coroutine_fn themselves, or the call
> must be within "if (qemu_in_coroutine())".  Apply coroutine_fn to
> functions where this holds.
> 
> Reviewed-by: Alberto Faria <afaria@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Hm... blkdebug_debug_event() is called from bdrv_debug_event(), which is
not coroutine_fn. And I think that it's not coroutine_fn is correct:
For example, with 'qemu-img snapshot -c' you get img_snapshot() ->
bdrv_snapshot_create() -> qcow2_snapshot_create() ->
qcow2_alloc_clusters() -> BLKDBG_EVENT. I'm sure many other calls in
qcow2 can be reached from non-coroutine context as well.

It almost looks like your code analysis didn't consider calls through
function pointers?

Kevin
Paolo Bonzini Oct. 5, 2022, 9:11 p.m. UTC | #2
Il mer 5 ott 2022, 06:32 Kevin Wolf <kwolf@redhat.com> ha scritto:

> Hm... blkdebug_debug_event() is called from bdrv_debug_event(), which is
> not coroutine_fn. And I think that it's not coroutine_fn is correct:
> For example, with 'qemu-img snapshot -c' you get img_snapshot() ->
> bdrv_snapshot_create() -> qcow2_snapshot_create() ->
> qcow2_alloc_clusters() -> BLKDBG_EVENT. I'm sure many other calls in
> qcow2 can be reached from non-coroutine context as well.
>
> It almost looks like your code analysis didn't consider calls through
> function pointers?
>

No, that is not what happened. Rather it's that the analysis goes the other
way round: because SUSPEND rules call qemu_coroutine_yield(), clang wants
all the callers to be coroutine_fn too. It is technically incorrect that
bdrv_debug_events sometimes are placed outside coroutine context, and QEMU
would crash if those events were associated with a suspend rule.

I guess I (or you) can just drop this patch?

Paolo

>
Kevin Wolf Oct. 6, 2022, 8:45 a.m. UTC | #3
Am 05.10.2022 um 23:11 hat Paolo Bonzini geschrieben:
> Il mer 5 ott 2022, 06:32 Kevin Wolf <kwolf@redhat.com> ha scritto:
> 
> > Hm... blkdebug_debug_event() is called from bdrv_debug_event(), which is
> > not coroutine_fn. And I think that it's not coroutine_fn is correct:
> > For example, with 'qemu-img snapshot -c' you get img_snapshot() ->
> > bdrv_snapshot_create() -> qcow2_snapshot_create() ->
> > qcow2_alloc_clusters() -> BLKDBG_EVENT. I'm sure many other calls in
> > qcow2 can be reached from non-coroutine context as well.
> >
> > It almost looks like your code analysis didn't consider calls through
> > function pointers?
> >
> 
> No, that is not what happened. Rather it's that the analysis goes the
> other way round: because SUSPEND rules call qemu_coroutine_yield(),
> clang wants all the callers to be coroutine_fn too.

Ah, ok, makes sense. So checking the callers is indeed something that
requires manual review.

> It is technically incorrect that bdrv_debug_events sometimes are
> placed outside coroutine context, and QEMU would crash if those events
> were associated with a suspend rule.

Yes, looks like a bug. As long as it's only in blkdebug, we can probably
live with it (the easiest fix would probably be generating coroutine
wrappers for bdrv_debug_event(), too).

> I guess I (or you) can just drop this patch?

Yes, I can do that.

Kevin
diff mbox series

Patch

diff --git a/block/blkdebug.c b/block/blkdebug.c
index bbf2948703..a93ba61487 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -587,8 +587,8 @@  out:
     return ret;
 }
 
-static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
-                      BlkdebugIOType iotype)
+static int coroutine_fn rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
+                                   BlkdebugIOType iotype)
 {
     BDRVBlkdebugState *s = bs->opaque;
     BlkdebugRule *rule = NULL;
@@ -672,7 +672,7 @@  blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
     return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
 }
 
-static int blkdebug_co_flush(BlockDriverState *bs)
+static int coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
 {
     int err = rule_check(bs, 0, 0, BLKDEBUG_IO_TYPE_FLUSH);
 
@@ -791,7 +791,7 @@  static void blkdebug_close(BlockDriverState *bs)
 }
 
 /* Called with lock held.  */
-static void suspend_request(BlockDriverState *bs, BlkdebugRule *rule)
+static void coroutine_fn suspend_request(BlockDriverState *bs, BlkdebugRule *rule)
 {
     BDRVBlkdebugState *s = bs->opaque;
     BlkdebugSuspendedReq *r;
@@ -810,8 +810,8 @@  static void suspend_request(BlockDriverState *bs, BlkdebugRule *rule)
 }
 
 /* Called with lock held.  */
-static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
-                         int *action_count, int *new_state)
+static void coroutine_fn process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
+                                      int *action_count, int *new_state)
 {
     BDRVBlkdebugState *s = bs->opaque;
 
@@ -840,7 +840,7 @@  static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
     }
 }
 
-static void blkdebug_debug_event(BlockDriverState *bs, BlkdebugEvent event)
+static void coroutine_fn blkdebug_debug_event(BlockDriverState *bs, BlkdebugEvent event)
 {
     BDRVBlkdebugState *s = bs->opaque;
     struct BlkdebugRule *rule, *next;