bdrv_co_get_self_request() does not take a lock around iterating through bs->tracked_requests. With multiqueue, it may thus iterate over a list that is in the process of being modified, producing an assertion failure:
../block/file-posix.c:3702: raw_do_pwrite_zeroes: Assertion `req' failed. [0] abort() at /lib64/libc.so.6 [1] __assert_fail_base.cold() at /lib64/libc.so.6 [2] raw_do_pwrite_zeroes() at ../block/file-posix.c:3702 [3] bdrv_co_do_pwrite_zeroes() at ../block/io.c:1910 [4] bdrv_aligned_pwritev() at ../block/io.c:2109 [5] bdrv_co_do_zero_pwritev() at ../block/io.c:2192 [6] bdrv_co_pwritev_part() at ../block/io.c:2292 [7] bdrv_co_pwritev() at ../block/io.c:2225 [8] handle_alloc_space() at ../block/qcow2.c:2573 [9] qcow2_co_pwritev_task() at ../block/qcow2.c:2625 Fix this by taking reqs_lock. Cc: [email protected] Signed-off-by: Hanna Czenczek <[email protected]> --- block/io.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/block/io.c b/block/io.c index 928c02d1ad..c4a4301321 100644 --- a/block/io.c +++ b/block/io.c @@ -718,11 +718,14 @@ BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs) Coroutine *self = qemu_coroutine_self(); IO_CODE(); + qemu_mutex_lock(&bs->reqs_lock); QLIST_FOREACH(req, &bs->tracked_requests, list) { if (req->co == self) { + qemu_mutex_unlock(&bs->reqs_lock); return req; } } + qemu_mutex_unlock(&bs->reqs_lock); return NULL; } -- 2.51.1
