Blame SOURCES/kvm-block-fix-QEMU-crash-with-scsi-hd-and-drive_del.patch

1bdc94
From 08e7b4d1dc3f71818fec2ebd5f189142011969a9 Mon Sep 17 00:00:00 2001
1bdc94
From: Kevin Wolf <kwolf@redhat.com>
1bdc94
Date: Thu, 12 Jul 2018 16:06:19 +0200
1bdc94
Subject: [PATCH 41/89] block: fix QEMU crash with scsi-hd and drive_del
1bdc94
1bdc94
RH-Author: Kevin Wolf <kwolf@redhat.com>
1bdc94
Message-id: <20180712160619.30712-2-kwolf@redhat.com>
1bdc94
Patchwork-id: 81334
1bdc94
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH 1/1] block: fix QEMU crash with scsi-hd and drive_del
1bdc94
Bugzilla: 1599515
1bdc94
RH-Acked-by: Fam Zheng <famz@redhat.com>
1bdc94
RH-Acked-by: Max Reitz <mreitz@redhat.com>
1bdc94
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
1bdc94
1bdc94
From: Greg Kurz <groug@kaod.org>
1bdc94
1bdc94
Removing a drive with drive_del while it is being used to run an I/O
1bdc94
intensive workload can cause QEMU to crash.
1bdc94
1bdc94
An AIO flush can yield at some point:
1bdc94
1bdc94
blk_aio_flush_entry()
1bdc94
 blk_co_flush(blk)
1bdc94
  bdrv_co_flush(blk->root->bs)
1bdc94
   ...
1bdc94
    qemu_coroutine_yield()
1bdc94
1bdc94
and let the HMP command to run, free blk->root and give control
1bdc94
back to the AIO flush:
1bdc94
1bdc94
    hmp_drive_del()
1bdc94
     blk_remove_bs()
1bdc94
      bdrv_root_unref_child(blk->root)
1bdc94
       child_bs = blk->root->bs
1bdc94
       bdrv_detach_child(blk->root)
1bdc94
        bdrv_replace_child(blk->root, NULL)
1bdc94
         blk->root->bs = NULL
1bdc94
        g_free(blk->root) <============== blk->root becomes stale
1bdc94
       bdrv_unref(child_bs)
1bdc94
        bdrv_delete(child_bs)
1bdc94
         bdrv_close()
1bdc94
          bdrv_drained_begin()
1bdc94
           bdrv_do_drained_begin()
1bdc94
            bdrv_drain_recurse()
1bdc94
             aio_poll()
1bdc94
              ...
1bdc94
              qemu_coroutine_switch()
1bdc94
1bdc94
and the AIO flush completion ends up dereferencing blk->root:
1bdc94
1bdc94
  blk_aio_complete()
1bdc94
   scsi_aio_complete()
1bdc94
    blk_get_aio_context(blk)
1bdc94
     bs = blk_bs(blk)
1bdc94
 ie, bs = blk->root ? blk->root->bs : NULL
1bdc94
            ^^^^^
1bdc94
            stale
1bdc94
1bdc94
The problem is that we should avoid making block driver graph
1bdc94
changes while we have in-flight requests. Let's drain all I/O
1bdc94
for this BB before calling bdrv_root_unref_child().
1bdc94
1bdc94
Signed-off-by: Greg Kurz <groug@kaod.org>
1bdc94
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1bdc94
(cherry picked from commit f45280cbf66d8e58224f6a253d0ae2aa72cc6280)
1bdc94
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1bdc94
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
1bdc94
---
1bdc94
 block/block-backend.c | 5 +++++
1bdc94
 1 file changed, 5 insertions(+)
1bdc94
1bdc94
diff --git a/block/block-backend.c b/block/block-backend.c
1bdc94
index 56ae535..a469fc6 100644
1bdc94
--- a/block/block-backend.c
1bdc94
+++ b/block/block-backend.c
1bdc94
@@ -768,6 +768,11 @@ void blk_remove_bs(BlockBackend *blk)
1bdc94
 
1bdc94
     blk_update_root_state(blk);
1bdc94
 
1bdc94
+    /* bdrv_root_unref_child() will cause blk->root to become stale and may
1bdc94
+     * switch to a completion coroutine later on. Let's drain all I/O here
1bdc94
+     * to avoid that and a potential QEMU crash.
1bdc94
+     */
1bdc94
+    blk_drain(blk);
1bdc94
     bdrv_root_unref_child(blk->root);
1bdc94
     blk->root = NULL;
1bdc94
 }
1bdc94
-- 
1bdc94
1.8.3.1
1bdc94