|
|
7711c0 |
From b495f8e19a84ce58d711fd1ec34b2d8234e4b542 Mon Sep 17 00:00:00 2001
|
|
|
7711c0 |
From: Kevin Wolf <kwolf@redhat.com>
|
|
|
7711c0 |
Date: Thu, 9 May 2019 15:34:15 +0200
|
|
|
7711c0 |
Subject: [PATCH 12/12] block: Fix AioContext switch for bs->drv == NULL
|
|
|
7711c0 |
|
|
|
7711c0 |
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
|
7711c0 |
Message-id: <20190509153415.29673-2-kwolf@redhat.com>
|
|
|
7711c0 |
Patchwork-id: 87216
|
|
|
7711c0 |
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 1/1] block: Fix AioContext switch for bs->drv == NULL
|
|
|
7711c0 |
Bugzilla: 1631227
|
|
|
7711c0 |
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
|
7711c0 |
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
|
7711c0 |
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
7711c0 |
|
|
|
7711c0 |
Even for block nodes with bs->drv == NULL, we can't just ignore a
|
|
|
7711c0 |
bdrv_set_aio_context() call. Leaving the node in its old context can
|
|
|
7711c0 |
mean that it's still in an iothread context in bdrv_close_all() during
|
|
|
7711c0 |
shutdown, resulting in an attempted unlock of the AioContext lock which
|
|
|
7711c0 |
we don't hold.
|
|
|
7711c0 |
|
|
|
7711c0 |
This is an example stack trace of a related crash:
|
|
|
7711c0 |
|
|
|
7711c0 |
#0 0x00007ffff59da57f in raise () at /lib64/libc.so.6
|
|
|
7711c0 |
#1 0x00007ffff59c4895 in abort () at /lib64/libc.so.6
|
|
|
7711c0 |
#2 0x0000555555b97b1e in error_exit (err=<optimized out>, msg=msg@entry=0x555555d386d0 <__func__.19059> "qemu_mutex_unlock_impl") at util/qemu-thread-posix.c:36
|
|
|
7711c0 |
#3 0x0000555555b97f7f in qemu_mutex_unlock_impl (mutex=mutex@entry=0x5555568002f0, file=file@entry=0x555555d378df "util/async.c", line=line@entry=507) at util/qemu-thread-posix.c:97
|
|
|
7711c0 |
#4 0x0000555555b92f55 in aio_context_release (ctx=ctx@entry=0x555556800290) at util/async.c:507
|
|
|
7711c0 |
#5 0x0000555555b05cf8 in bdrv_prwv_co (child=child@entry=0x7fffc80012f0, offset=offset@entry=131072, qiov=qiov@entry=0x7fffffffd4f0, is_write=is_write@entry=true, flags=flags@entry=0)
|
|
|
7711c0 |
at block/io.c:833
|
|
|
7711c0 |
#6 0x0000555555b060a9 in bdrv_pwritev (qiov=0x7fffffffd4f0, offset=131072, child=0x7fffc80012f0) at block/io.c:990
|
|
|
7711c0 |
#7 0x0000555555b060a9 in bdrv_pwrite (child=0x7fffc80012f0, offset=131072, buf=<optimized out>, bytes=<optimized out>) at block/io.c:990
|
|
|
7711c0 |
#8 0x0000555555ae172b in qcow2_cache_entry_flush (bs=bs@entry=0x555556810680, c=c@entry=0x5555568cc740, i=i@entry=0) at block/qcow2-cache.c:51
|
|
|
7711c0 |
#9 0x0000555555ae18dd in qcow2_cache_write (bs=bs@entry=0x555556810680, c=0x5555568cc740) at block/qcow2-cache.c:248
|
|
|
7711c0 |
#10 0x0000555555ae15de in qcow2_cache_flush (bs=0x555556810680, c=<optimized out>) at block/qcow2-cache.c:259
|
|
|
7711c0 |
#11 0x0000555555ae16b1 in qcow2_cache_flush_dependency (c=0x5555568a1700, c=0x5555568a1700, bs=0x555556810680) at block/qcow2-cache.c:194
|
|
|
7711c0 |
#12 0x0000555555ae16b1 in qcow2_cache_entry_flush (bs=bs@entry=0x555556810680, c=c@entry=0x5555568a1700, i=i@entry=0) at block/qcow2-cache.c:194
|
|
|
7711c0 |
#13 0x0000555555ae18dd in qcow2_cache_write (bs=bs@entry=0x555556810680, c=0x5555568a1700) at block/qcow2-cache.c:248
|
|
|
7711c0 |
#14 0x0000555555ae15de in qcow2_cache_flush (bs=bs@entry=0x555556810680, c=<optimized out>) at block/qcow2-cache.c:259
|
|
|
7711c0 |
#15 0x0000555555ad242c in qcow2_inactivate (bs=bs@entry=0x555556810680) at block/qcow2.c:2124
|
|
|
7711c0 |
#16 0x0000555555ad2590 in qcow2_close (bs=0x555556810680) at block/qcow2.c:2153
|
|
|
7711c0 |
#17 0x0000555555ab0c62 in bdrv_close (bs=0x555556810680) at block.c:3358
|
|
|
7711c0 |
#18 0x0000555555ab0c62 in bdrv_delete (bs=0x555556810680) at block.c:3542
|
|
|
7711c0 |
#19 0x0000555555ab0c62 in bdrv_unref (bs=0x555556810680) at block.c:4598
|
|
|
7711c0 |
#20 0x0000555555af4d72 in blk_remove_bs (blk=blk@entry=0x5555568103d0) at block/block-backend.c:785
|
|
|
7711c0 |
#21 0x0000555555af4dbb in blk_remove_all_bs () at block/block-backend.c:483
|
|
|
7711c0 |
#22 0x0000555555aae02f in bdrv_close_all () at block.c:3412
|
|
|
7711c0 |
#23 0x00005555557f9796 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4776
|
|
|
7711c0 |
|
|
|
7711c0 |
The reproducer I used is a qcow2 image on gluster volume, where the
|
|
|
7711c0 |
virtual disk size (4 GB) is larger than the gluster volume size (64M),
|
|
|
7711c0 |
so we can easily trigger an ENOSPC. This backend is assigned to a
|
|
|
7711c0 |
virtio-blk device using an iothread, and then from the guest a
|
|
|
7711c0 |
'dd if=/dev/zero of=/dev/vda bs=1G count=1' causes the VM to stop
|
|
|
7711c0 |
because of an I/O error. qemu_gluster_co_flush_to_disk() sets
|
|
|
7711c0 |
bs->drv = NULL on error, so when virtio-blk stops the dataplane, the
|
|
|
7711c0 |
block nodes stay in the iothread AioContext. A 'quit' monitor command
|
|
|
7711c0 |
issued from this paused state crashes the process.
|
|
|
7711c0 |
|
|
|
7711c0 |
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1631227
|
|
|
7711c0 |
Cc: qemu-stable@nongnu.org
|
|
|
7711c0 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
7711c0 |
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
|
7711c0 |
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
|
7711c0 |
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
|
7711c0 |
(cherry picked from commit 1bffe1ae7a7b707c3a14ea2ccd00d3609d3ce4d8)
|
|
|
7711c0 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
7711c0 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
7711c0 |
---
|
|
|
7711c0 |
block.c | 12 ++----------
|
|
|
7711c0 |
1 file changed, 2 insertions(+), 10 deletions(-)
|
|
|
7711c0 |
|
|
|
7711c0 |
diff --git a/block.c b/block.c
|
|
|
7711c0 |
index e3e0e34..7061f9b 100644
|
|
|
7711c0 |
--- a/block.c
|
|
|
7711c0 |
+++ b/block.c
|
|
|
7711c0 |
@@ -4946,10 +4946,6 @@ void bdrv_detach_aio_context(BlockDriverState *bs)
|
|
|
7711c0 |
BdrvAioNotifier *baf, *baf_tmp;
|
|
|
7711c0 |
BdrvChild *child;
|
|
|
7711c0 |
|
|
|
7711c0 |
- if (!bs->drv) {
|
|
|
7711c0 |
- return;
|
|
|
7711c0 |
- }
|
|
|
7711c0 |
-
|
|
|
7711c0 |
assert(!bs->walking_aio_notifiers);
|
|
|
7711c0 |
bs->walking_aio_notifiers = true;
|
|
|
7711c0 |
QLIST_FOREACH_SAFE(baf, &bs->aio_notifiers, list, baf_tmp) {
|
|
|
7711c0 |
@@ -4964,7 +4960,7 @@ void bdrv_detach_aio_context(BlockDriverState *bs)
|
|
|
7711c0 |
*/
|
|
|
7711c0 |
bs->walking_aio_notifiers = false;
|
|
|
7711c0 |
|
|
|
7711c0 |
- if (bs->drv->bdrv_detach_aio_context) {
|
|
|
7711c0 |
+ if (bs->drv && bs->drv->bdrv_detach_aio_context) {
|
|
|
7711c0 |
bs->drv->bdrv_detach_aio_context(bs);
|
|
|
7711c0 |
}
|
|
|
7711c0 |
QLIST_FOREACH(child, &bs->children, next) {
|
|
|
7711c0 |
@@ -4983,10 +4979,6 @@ void bdrv_attach_aio_context(BlockDriverState *bs,
|
|
|
7711c0 |
BdrvAioNotifier *ban, *ban_tmp;
|
|
|
7711c0 |
BdrvChild *child;
|
|
|
7711c0 |
|
|
|
7711c0 |
- if (!bs->drv) {
|
|
|
7711c0 |
- return;
|
|
|
7711c0 |
- }
|
|
|
7711c0 |
-
|
|
|
7711c0 |
if (bs->quiesce_counter) {
|
|
|
7711c0 |
aio_disable_external(new_context);
|
|
|
7711c0 |
}
|
|
|
7711c0 |
@@ -4996,7 +4988,7 @@ void bdrv_attach_aio_context(BlockDriverState *bs,
|
|
|
7711c0 |
QLIST_FOREACH(child, &bs->children, next) {
|
|
|
7711c0 |
bdrv_attach_aio_context(child->bs, new_context);
|
|
|
7711c0 |
}
|
|
|
7711c0 |
- if (bs->drv->bdrv_attach_aio_context) {
|
|
|
7711c0 |
+ if (bs->drv && bs->drv->bdrv_attach_aio_context) {
|
|
|
7711c0 |
bs->drv->bdrv_attach_aio_context(bs, new_context);
|
|
|
7711c0 |
}
|
|
|
7711c0 |
|
|
|
7711c0 |
--
|
|
|
7711c0 |
1.8.3.1
|
|
|
7711c0 |
|