Iotest 30 accidentally fails due to interleaving of mirror and stream graph-modifying procedures. Protect these things by global co-mutex.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> --- include/block/block.h | 2 ++ block.c | 2 ++ block/mirror.c | 4 ++++ block/stream.c | 4 ++++ 4 files changed, 12 insertions(+) diff --git a/include/block/block.h b/include/block/block.h index c9d7c58765..a92756cbfc 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -20,6 +20,8 @@ */ #define generated_co_wrapper +extern CoMutex graph_modify_mutex; + /* block.c */ typedef struct BlockDriver BlockDriver; typedef struct BdrvChild BdrvChild; diff --git a/block.c b/block.c index 5e8dd98cec..eb82b1ca1e 100644 --- a/block.c +++ b/block.c @@ -86,6 +86,8 @@ static int use_bdrv_whitelist; bool abort_on_set_to_true = false; +CoMutex graph_modify_mutex; + #ifdef _WIN32 static int is_windows_drive_prefix(const char *filename) { diff --git a/block/mirror.c b/block/mirror.c index 91e98b2349..16c3e0b0cb 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -628,6 +628,8 @@ static void coroutine_fn mirror_wait_for_all_io(MirrorBlockJob *s) */ int coroutine_fn mirror_co_exit_common(Job *job) { + QEMU_LOCK_GUARD(&graph_modify_mutex); + MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job); BlockJob *bjob = &s->common; MirrorBDSOpaque *bs_opaque; @@ -1106,6 +1108,8 @@ immediate_exit: void coroutine_fn mirror_co_complete(Job *job, Error **errp) { + QEMU_LOCK_GUARD(&graph_modify_mutex); + MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job); BlockDriverState *target; diff --git a/block/stream.c b/block/stream.c index 8a4b88b223..13eba00ce8 100644 --- a/block/stream.c +++ b/block/stream.c @@ -61,6 +61,8 @@ static void stream_abort(Job *job) int coroutine_fn stream_co_prepare(Job *job) { + QEMU_LOCK_GUARD(&graph_modify_mutex); + StreamBlockJob *s = container_of(job, StreamBlockJob, common.job); BlockJob *bjob = &s->common; BlockDriverState *bs = blk_bs(bjob->blk); @@ -93,6 +95,8 @@ int coroutine_fn stream_co_prepare(Job *job) void coroutine_fn stream_co_clean(Job *job) { + QEMU_LOCK_GUARD(&graph_modify_mutex); + StreamBlockJob *s = container_of(job, StreamBlockJob, common.job); BlockJob *bjob = &s->common; BlockDriverState *bs = blk_bs(bjob->blk); -- 2.21.3