Blame SOURCES/kvm-block-Fix-AioContext-switch-for-bs-drv-NULL.patch

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