Add a handler to wait for the break to happen in coroutine context. It will be used in further commit.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> --- include/block/block.h | 1 + include/block/block_int.h | 1 + block.c | 11 +++++++++++ block/blkdebug.c | 16 ++++++++++++++++ 4 files changed, 29 insertions(+) diff --git a/include/block/block.h b/include/block/block.h index b3f6e509d4..e133adf54f 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -648,6 +648,7 @@ int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event, int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag); int bdrv_debug_resume(BlockDriverState *bs, const char *tag); bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag); +void coroutine_fn bdrv_debug_wait_break(BlockDriverState *bs, const char *tag); /** * bdrv_get_aio_context: diff --git a/include/block/block_int.h b/include/block/block_int.h index 50af58af75..89e6904fc7 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -502,6 +502,7 @@ struct BlockDriver { const char *tag); int (*bdrv_debug_resume)(BlockDriverState *bs, const char *tag); bool (*bdrv_debug_is_suspended)(BlockDriverState *bs, const char *tag); + void (*bdrv_debug_wait_break)(BlockDriverState *bs, const char *tag); void (*bdrv_refresh_limits)(BlockDriverState *bs, Error **errp); diff --git a/block.c b/block.c index 001453105e..3ea088b9fb 100644 --- a/block.c +++ b/block.c @@ -5702,6 +5702,17 @@ bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag) return false; } +void coroutine_fn bdrv_debug_wait_break(BlockDriverState *bs, const char *tag) +{ + while (bs && bs->drv && !bs->drv->bdrv_debug_wait_break) { + bs = bdrv_primary_bs(bs); + } + + if (bs && bs->drv && bs->drv->bdrv_debug_wait_break) { + bs->drv->bdrv_debug_wait_break(bs, tag); + } +} + /* backing_file can either be relative, or absolute, or a protocol. If it is * relative, it must be relative to the chain. So, passing in bs->filename * from a BDS as backing_file should not be done, as that may be relative to diff --git a/block/blkdebug.c b/block/blkdebug.c index 2c0b9b0ee8..10b7c38467 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -57,6 +57,7 @@ typedef struct BDRVBlkdebugState { QLIST_HEAD(, BlkdebugRule) rules[BLKDBG__MAX]; QSIMPLEQ_HEAD(, BlkdebugRule) active_rules; QLIST_HEAD(, BlkdebugSuspendedReq) suspended_reqs; + CoQueue break_waiters; } BDRVBlkdebugState; typedef struct BlkdebugAIOCB { @@ -467,6 +468,8 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, int ret; uint64_t align; + qemu_co_queue_init(&s->break_waiters); + opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; @@ -785,6 +788,8 @@ static void suspend_request(BlockDriverState *bs, BlkdebugRule *rule) remove_rule(rule); QLIST_INSERT_HEAD(&s->suspended_reqs, &r, next); + qemu_co_queue_restart_all(&s->break_waiters); + if (!qtest_enabled()) { printf("blkdebug: Suspended request '%s'\n", r.tag); } @@ -922,6 +927,16 @@ static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag) return false; } +static void coroutine_fn +blkdebug_debug_wait_break(BlockDriverState *bs, const char *tag) +{ + BDRVBlkdebugState *s = bs->opaque; + + while (!blkdebug_debug_is_suspended(bs, tag)) { + qemu_co_queue_wait(&s->break_waiters, NULL); + } +} + static int64_t blkdebug_getlength(BlockDriverState *bs) { return bdrv_getlength(bs->file->bs); @@ -1048,6 +1063,7 @@ static BlockDriver bdrv_blkdebug = { = blkdebug_debug_remove_breakpoint, .bdrv_debug_resume = blkdebug_debug_resume, .bdrv_debug_is_suspended = blkdebug_debug_is_suspended, + .bdrv_debug_wait_break = blkdebug_debug_wait_break, .strong_runtime_opts = blkdebug_strong_runtime_opts, }; -- 2.29.2