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

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