Sometimes reproducing a problem for debugging involves slow I/O, so let's add something to blkdebug to make I/O slow when we need it. This can be used either together with an error so that the request fails after the delay, or with errno=0, which allows the request to succeed after the delay.
Signed-off-by: Kevin Wolf <[email protected]> Message-ID: <[email protected]> Signed-off-by: Kevin Wolf <[email protected]> --- qapi/block-core.json | 4 ++++ block/blkdebug.c | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 508b081ac16..0efd51787b4 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3919,6 +3919,9 @@ # # @errno: error identifier (errno) to be returned; defaults to EIO # +# @delay-ns: request delay before completion in nanoseconds +# (default: 0, since: 11.1) +# # @sector: specifies the sector index which has to be affected in # order to actually trigger the event; defaults to "any sector" # @@ -3934,6 +3937,7 @@ '*state': 'int', '*iotype': 'BlkdebugIOType', '*errno': 'int', + '*delay-ns': 'int', '*sector': 'int', '*once': 'bool', '*immediately': 'bool' } } diff --git a/block/blkdebug.c b/block/blkdebug.c index fdc96d1f45d..78cc03746f0 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -95,6 +95,7 @@ typedef struct BlkdebugRule { int immediately; int once; int64_t offset; + int64_t delay_ns; } inject; struct { int new_state; @@ -144,6 +145,10 @@ static QemuOptsList inject_error_opts = { .name = "immediately", .type = QEMU_OPT_BOOL, }, + { + .name = "delay-ns", + .type = QEMU_OPT_NUMBER, + }, { /* end of list */ } }, }; @@ -216,6 +221,8 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp) rule->options.inject.once = qemu_opt_get_bool(opts, "once", 0); rule->options.inject.immediately = qemu_opt_get_bool(opts, "immediately", 0); + rule->options.inject.delay_ns = + qemu_opt_get_number(opts, "delay-ns", 0); sector = qemu_opt_get_number(opts, "sector", -1); rule->options.inject.offset = sector == -1 ? -1 : sector * BDRV_SECTOR_SIZE; @@ -594,6 +601,7 @@ static int coroutine_fn rule_check(BlockDriverState *bs, uint64_t offset, BlkdebugRule *rule; int error; bool immediately; + int64_t delay_ns; qemu_mutex_lock(&s->lock); QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) { @@ -608,13 +616,14 @@ static int coroutine_fn rule_check(BlockDriverState *bs, uint64_t offset, } } - if (!rule || !rule->options.inject.error) { + if (!rule) { qemu_mutex_unlock(&s->lock); return 0; } immediately = rule->options.inject.immediately; error = rule->options.inject.error; + delay_ns = rule->options.inject.delay_ns; if (rule->options.inject.once) { QSIMPLEQ_REMOVE(&s->active_rules, rule, BlkdebugRule, active_next); @@ -622,6 +631,10 @@ static int coroutine_fn rule_check(BlockDriverState *bs, uint64_t offset, } qemu_mutex_unlock(&s->lock); + + if (delay_ns) { + qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, delay_ns); + } if (!immediately) { aio_co_schedule(qemu_get_current_aio_context(), qemu_coroutine_self()); qemu_coroutine_yield(); -- 2.54.0
