Co-developed-by: Paolo Bonzini <pbonz...@redhat.com> Signed-off-by: Emanuele Giuseppe Esposito <eespo...@redhat.com> --- block/blkdebug.c | 53 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 13 deletions(-)
diff --git a/block/blkdebug.c b/block/blkdebug.c index dffd869b32..cf8b088ce7 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -54,6 +54,7 @@ typedef struct BDRVBlkdebugState { /* For blkdebug_refresh_filename() */ char *config_file; + QemuMutex lock; QLIST_HEAD(, BlkdebugRule) rules[BLKDBG__MAX]; QSIMPLEQ_HEAD(, BlkdebugRule) active_rules; QLIST_HEAD(, BlkdebugSuspendedReq) suspended_reqs; @@ -245,7 +246,9 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp) }; /* Add the rule */ + qemu_mutex_lock(&s->lock); QLIST_INSERT_HEAD(&s->rules[event], rule, next); + qemu_mutex_unlock(&s->lock); return 0; } @@ -468,6 +471,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, int ret; uint64_t align; + qemu_mutex_init(&s->lock); opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; @@ -568,6 +572,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, ret = 0; out: if (ret < 0) { + qemu_mutex_destroy(&s->lock); g_free(s->config_file); } qemu_opts_del(opts); @@ -582,6 +587,7 @@ static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes, int error; bool immediately; + qemu_mutex_lock(&s->lock); QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) { uint64_t inject_offset = rule->options.inject.offset; @@ -595,6 +601,7 @@ static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes, } if (!rule || !rule->options.inject.error) { + qemu_mutex_unlock(&s->lock); return 0; } @@ -606,6 +613,7 @@ static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes, remove_rule(rule); } + qemu_mutex_unlock(&s->lock); if (!immediately) { aio_co_schedule(qemu_get_current_aio_context(), qemu_coroutine_self()); qemu_coroutine_yield(); @@ -771,8 +779,10 @@ static void blkdebug_close(BlockDriverState *bs) } g_free(s->config_file); + qemu_mutex_destroy(&s->lock); } +/* Called with lock held. */ static void suspend_request(BlockDriverState *bs, BlkdebugRule *rule) { BDRVBlkdebugState *s = bs->opaque; @@ -791,6 +801,7 @@ static void suspend_request(BlockDriverState *bs, BlkdebugRule *rule) } } +/* Called with lock held. */ static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule, int *action_count) { @@ -829,9 +840,11 @@ static void blkdebug_debug_event(BlockDriverState *bs, BlkdebugEvent event) assert((int)event >= 0 && event < BLKDBG__MAX); - s->new_state = s->state; - QLIST_FOREACH_SAFE(rule, &s->rules[event], next, next) { - process_rule(bs, rule, actions_count); + WITH_QEMU_LOCK_GUARD(&s->lock) { + s->new_state = s->state; + QLIST_FOREACH_SAFE(rule, &s->rules[event], next, next) { + process_rule(bs, rule, actions_count); + } } while (actions_count[ACTION_SUSPEND] > 0) { @@ -839,7 +852,9 @@ static void blkdebug_debug_event(BlockDriverState *bs, BlkdebugEvent event) actions_count[ACTION_SUSPEND]--; } + qemu_mutex_lock(&s->lock); s->state = s->new_state; + qemu_mutex_unlock(&s->lock); } static int blkdebug_debug_breakpoint(BlockDriverState *bs, const char *event, @@ -862,11 +877,14 @@ static int blkdebug_debug_breakpoint(BlockDriverState *bs, const char *event, .options.suspend.tag = g_strdup(tag), }; + qemu_mutex_lock(&s->lock); QLIST_INSERT_HEAD(&s->rules[blkdebug_event], rule, next); + qemu_mutex_unlock(&s->lock); return 0; } +/* Called with lock held. */ static int resume_req_by_tag(BDRVBlkdebugState *s, const char *tag, bool all) { BlkdebugSuspendedReq *r; @@ -884,7 +902,9 @@ retry: g_free(r->tag); g_free(r); + qemu_mutex_unlock(&s->lock); qemu_coroutine_enter(co); + qemu_mutex_lock(&s->lock); if (all) { goto retry; @@ -898,8 +918,12 @@ retry: static int blkdebug_debug_resume(BlockDriverState *bs, const char *tag) { BDRVBlkdebugState *s = bs->opaque; + int rc; - return resume_req_by_tag(s, tag, false); + qemu_mutex_lock(&s->lock); + rc = resume_req_by_tag(s, tag, false); + qemu_mutex_unlock(&s->lock); + return rc; } static int blkdebug_debug_remove_breakpoint(BlockDriverState *bs, @@ -909,17 +933,19 @@ static int blkdebug_debug_remove_breakpoint(BlockDriverState *bs, BlkdebugRule *rule, *next; int i, ret = -ENOENT; - for (i = 0; i < BLKDBG__MAX; i++) { - QLIST_FOREACH_SAFE(rule, &s->rules[i], next, next) { - if (rule->action == ACTION_SUSPEND && - !strcmp(rule->options.suspend.tag, tag)) { - remove_rule(rule); - ret = 0; + WITH_QEMU_LOCK_GUARD(&s->lock) { + for (i = 0; i < BLKDBG__MAX; i++) { + QLIST_FOREACH_SAFE(rule, &s->rules[i], next, next) { + if (rule->action == ACTION_SUSPEND && + !strcmp(rule->options.suspend.tag, tag)) { + remove_rule(rule); + ret = 0; + } } } - } - if (resume_req_by_tag(s, tag, true) == 0) { - ret = 0; + if (resume_req_by_tag(s, tag, true) == 0) { + ret = 0; + } } return ret; } @@ -929,6 +955,7 @@ static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag) BDRVBlkdebugState *s = bs->opaque; BlkdebugSuspendedReq *r; + QEMU_LOCK_GUARD(&s->lock); QLIST_FOREACH(r, &s->suspended_reqs, next) { if (!strcmp(r->tag, tag)) { return true; -- 2.30.2