yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone

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

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