Blame SOURCES/kvm-blockdev-Return-bs-to-the-proper-context-on-snapshot.patch

ddf19c
From 24e5eca4218b294bd013e2d85a38345045506bec Mon Sep 17 00:00:00 2001
ddf19c
From: Sergio Lopez Pascual <slp@redhat.com>
ddf19c
Date: Fri, 7 Feb 2020 11:27:48 +0000
ddf19c
Subject: [PATCH 15/18] blockdev: Return bs to the proper context on snapshot
ddf19c
 abort
ddf19c
ddf19c
RH-Author: Sergio Lopez Pascual <slp@redhat.com>
ddf19c
Message-id: <20200207112749.25073-9-slp@redhat.com>
ddf19c
Patchwork-id: 93761
ddf19c
O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH v2 8/9] blockdev: Return bs to the proper context on snapshot abort
ddf19c
Bugzilla: 1745606 1746217 1773517 1779036 1782111 1782175 1783965
ddf19c
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
ddf19c
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
ddf19c
RH-Acked-by: Max Reitz <mreitz@redhat.com>
ddf19c
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
ddf19c
ddf19c
external_snapshot_abort() calls to bdrv_set_backing_hd(), which
ddf19c
returns state->old_bs to the main AioContext, as it's intended to be
ddf19c
used then the BDS is going to be released. As that's not the case when
ddf19c
aborting an external snapshot, return it to the AioContext it was
ddf19c
before the call.
ddf19c
ddf19c
This issue can be triggered by issuing a transaction with two actions,
ddf19c
a proper blockdev-snapshot-sync and a bogus one, so the second will
ddf19c
trigger a transaction abort. This results in a crash with an stack
ddf19c
trace like this one:
ddf19c
ddf19c
 #0  0x00007fa1048b28df in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
ddf19c
 #1  0x00007fa10489ccf5 in __GI_abort () at abort.c:79
ddf19c
 #2  0x00007fa10489cbc9 in __assert_fail_base
ddf19c
     (fmt=0x7fa104a03300 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x5572240b44d8 "bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs)", file=0x557224014d30 "block.c", line=2240, function=<optimized out>) at assert.c:92
ddf19c
 #3  0x00007fa1048aae96 in __GI___assert_fail
ddf19c
     (assertion=assertion@entry=0x5572240b44d8 "bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs)", file=file@entry=0x557224014d30 "block.c", line=line@entry=2240, function=function@entry=0x5572240b5d60 <__PRETTY_FUNCTION__.31620> "bdrv_replace_child_noperm") at assert.c:101
ddf19c
 #4  0x0000557223e631f8 in bdrv_replace_child_noperm (child=0x557225b9c980, new_bs=new_bs@entry=0x557225c42e40) at block.c:2240
ddf19c
 #5  0x0000557223e68be7 in bdrv_replace_node (from=0x557226951a60, to=0x557225c42e40, errp=0x5572247d6138 <error_abort>) at block.c:4196
ddf19c
 #6  0x0000557223d069c4 in external_snapshot_abort (common=0x557225d7e170) at blockdev.c:1731
ddf19c
 #7  0x0000557223d069c4 in external_snapshot_abort (common=0x557225d7e170) at blockdev.c:1717
ddf19c
 #8  0x0000557223d09013 in qmp_transaction (dev_list=<optimized out>, has_props=<optimized out>, props=0x557225cc7d70, errp=errp@entry=0x7ffe704c0c98) at blockdev.c:2360
ddf19c
 #9  0x0000557223e32085 in qmp_marshal_transaction (args=<optimized out>, ret=<optimized out>, errp=0x7ffe704c0d08) at qapi/qapi-commands-transaction.c:44
ddf19c
 #10 0x0000557223ee798c in do_qmp_dispatch (errp=0x7ffe704c0d00, allow_oob=<optimized out>, request=<optimized out>, cmds=0x5572247d3cc0 <qmp_commands>) at qapi/qmp-dispatch.c:132
ddf19c
 #11 0x0000557223ee798c in qmp_dispatch (cmds=0x5572247d3cc0 <qmp_commands>, request=<optimized out>, allow_oob=<optimized out>) at qapi/qmp-dispatch.c:175
ddf19c
 #12 0x0000557223e06141 in monitor_qmp_dispatch (mon=0x557225c69ff0, req=<optimized out>) at monitor/qmp.c:120
ddf19c
 #13 0x0000557223e0678a in monitor_qmp_bh_dispatcher (data=<optimized out>) at monitor/qmp.c:209
ddf19c
 #14 0x0000557223f2f366 in aio_bh_call (bh=0x557225b9dc60) at util/async.c:117
ddf19c
 #15 0x0000557223f2f366 in aio_bh_poll (ctx=ctx@entry=0x557225b9c840) at util/async.c:117
ddf19c
 #16 0x0000557223f32754 in aio_dispatch (ctx=0x557225b9c840) at util/aio-posix.c:459
ddf19c
 #17 0x0000557223f2f242 in aio_ctx_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at util/async.c:260
ddf19c
 #18 0x00007fa10913467d in g_main_dispatch (context=0x557225c28e80) at gmain.c:3176
ddf19c
 #19 0x00007fa10913467d in g_main_context_dispatch (context=context@entry=0x557225c28e80) at gmain.c:3829
ddf19c
 #20 0x0000557223f31808 in glib_pollfds_poll () at util/main-loop.c:219
ddf19c
 #21 0x0000557223f31808 in os_host_main_loop_wait (timeout=<optimized out>) at util/main-loop.c:242
ddf19c
 #22 0x0000557223f31808 in main_loop_wait (nonblocking=<optimized out>) at util/main-loop.c:518
ddf19c
 #23 0x0000557223d13201 in main_loop () at vl.c:1828
ddf19c
 #24 0x0000557223bbfb82 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4504
ddf19c
ddf19c
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1779036
ddf19c
Signed-off-by: Sergio Lopez <slp@redhat.com>
ddf19c
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ddf19c
(cherry picked from commit 377410f6fb4f6b0d26d4a028c20766fae05de17e)
ddf19c
Signed-off-by: Sergio Lopez <slp@redhat.com>
ddf19c
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
ddf19c
---
ddf19c
 blockdev.c | 21 +++++++++++++++++++++
ddf19c
 1 file changed, 21 insertions(+)
ddf19c
ddf19c
diff --git a/blockdev.c b/blockdev.c
ddf19c
index d4ef6cd..4cd9a58 100644
ddf19c
--- a/blockdev.c
ddf19c
+++ b/blockdev.c
ddf19c
@@ -1731,6 +1731,8 @@ static void external_snapshot_abort(BlkActionState *common)
ddf19c
     if (state->new_bs) {
ddf19c
         if (state->overlay_appended) {
ddf19c
             AioContext *aio_context;
ddf19c
+            AioContext *tmp_context;
ddf19c
+            int ret;
ddf19c
 
ddf19c
             aio_context = bdrv_get_aio_context(state->old_bs);
ddf19c
             aio_context_acquire(aio_context);
ddf19c
@@ -1738,6 +1740,25 @@ static void external_snapshot_abort(BlkActionState *common)
ddf19c
             bdrv_ref(state->old_bs);   /* we can't let bdrv_set_backind_hd()
ddf19c
                                           close state->old_bs; we need it */
ddf19c
             bdrv_set_backing_hd(state->new_bs, NULL, &error_abort);
ddf19c
+
ddf19c
+            /*
ddf19c
+             * The call to bdrv_set_backing_hd() above returns state->old_bs to
ddf19c
+             * the main AioContext. As we're still going to be using it, return
ddf19c
+             * it to the AioContext it was before.
ddf19c
+             */
ddf19c
+            tmp_context = bdrv_get_aio_context(state->old_bs);
ddf19c
+            if (aio_context != tmp_context) {
ddf19c
+                aio_context_release(aio_context);
ddf19c
+                aio_context_acquire(tmp_context);
ddf19c
+
ddf19c
+                ret = bdrv_try_set_aio_context(state->old_bs,
ddf19c
+                                               aio_context, NULL);
ddf19c
+                assert(ret == 0);
ddf19c
+
ddf19c
+                aio_context_release(tmp_context);
ddf19c
+                aio_context_acquire(aio_context);
ddf19c
+            }
ddf19c
+
ddf19c
             bdrv_replace_node(state->new_bs, state->old_bs, &error_abort);
ddf19c
             bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_bs */
ddf19c
 
ddf19c
-- 
ddf19c
1.8.3.1
ddf19c