Blame SOURCES/kvm-block-don-t-keep-AioContext-acquired-after-external_.patch

9bac43
From 618ad78b4afa654623057234db339c8cbcfb7392 Mon Sep 17 00:00:00 2001
9bac43
From: Stefan Hajnoczi <stefanha@redhat.com>
9bac43
Date: Fri, 22 Dec 2017 11:08:50 +0100
9bac43
Subject: [PATCH 32/42] block: don't keep AioContext acquired after
9bac43
 external_snapshot_prepare()
9bac43
9bac43
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
9bac43
Message-id: <20171222110900.24813-11-stefanha@redhat.com>
9bac43
Patchwork-id: 78492
9bac43
O-Subject: [RHV7.5 qemu-kvm-rhev PATCH 10/20] block: don't keep AioContext acquired after external_snapshot_prepare()
9bac43
Bugzilla: 1519721
9bac43
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
9bac43
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
9bac43
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
9bac43
9bac43
It is not necessary to hold AioContext across transactions anymore since
9bac43
bdrv_drained_begin/end() is used to keep the nodes quiesced.  In fact,
9bac43
using the AioContext lock for this purpose was always buggy.
9bac43
9bac43
This patch reduces the scope of AioContext locked regions.  This is not
9bac43
just a cleanup but also fixes hangs that occur in BDRV_POLL_WHILE()
9bac43
because it is unware of recursive locking and does not release the
9bac43
AioContext the necessary number of times to allow progress to be made.
9bac43
9bac43
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9bac43
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9bac43
Reviewed-by: Eric Blake <eblake@redhat.com>
9bac43
Message-id: 20171206144550.22295-3-stefanha@redhat.com
9bac43
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9bac43
(cherry picked from commit 2d24b60b7747f7bf40fd00b0375b6bd988d4f0d9)
9bac43
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9bac43
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9bac43
---
9bac43
 blockdev.c | 71 ++++++++++++++++++++++++++++++++++++++++++--------------------
9bac43
 1 file changed, 48 insertions(+), 23 deletions(-)
9bac43
9bac43
diff --git a/blockdev.c b/blockdev.c
9bac43
index c6978a5..8bb23e9 100644
9bac43
--- a/blockdev.c
9bac43
+++ b/blockdev.c
9bac43
@@ -1649,7 +1649,6 @@ typedef struct ExternalSnapshotState {
9bac43
     BlkActionState common;
9bac43
     BlockDriverState *old_bs;
9bac43
     BlockDriverState *new_bs;
9bac43
-    AioContext *aio_context;
9bac43
     bool overlay_appended;
9bac43
 } ExternalSnapshotState;
9bac43
 
9bac43
@@ -1669,6 +1668,7 @@ static void external_snapshot_prepare(BlkActionState *common,
9bac43
     ExternalSnapshotState *state =
9bac43
                              DO_UPCAST(ExternalSnapshotState, common, common);
9bac43
     TransactionAction *action = common->action;
9bac43
+    AioContext *aio_context;
9bac43
 
9bac43
     /* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
9bac43
      * purpose but a different set of parameters */
9bac43
@@ -1705,31 +1705,32 @@ static void external_snapshot_prepare(BlkActionState *common,
9bac43
         return;
9bac43
     }
9bac43
 
9bac43
-    /* Acquire AioContext now so any threads operating on old_bs stop */
9bac43
-    state->aio_context = bdrv_get_aio_context(state->old_bs);
9bac43
-    aio_context_acquire(state->aio_context);
9bac43
+    aio_context = bdrv_get_aio_context(state->old_bs);
9bac43
+    aio_context_acquire(aio_context);
9bac43
+
9bac43
+    /* Paired with .clean() */
9bac43
     bdrv_drained_begin(state->old_bs);
9bac43
 
9bac43
     if (!bdrv_is_inserted(state->old_bs)) {
9bac43
         error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
9bac43
-        return;
9bac43
+        goto out;
9bac43
     }
9bac43
 
9bac43
     if (bdrv_op_is_blocked(state->old_bs,
9bac43
                            BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, errp)) {
9bac43
-        return;
9bac43
+        goto out;
9bac43
     }
9bac43
 
9bac43
     if (!bdrv_is_read_only(state->old_bs)) {
9bac43
         if (bdrv_flush(state->old_bs)) {
9bac43
             error_setg(errp, QERR_IO_ERROR);
9bac43
-            return;
9bac43
+            goto out;
9bac43
         }
9bac43
     }
9bac43
 
9bac43
     if (!bdrv_is_first_non_filter(state->old_bs)) {
9bac43
         error_setg(errp, QERR_FEATURE_DISABLED, "snapshot");
9bac43
-        return;
9bac43
+        goto out;
9bac43
     }
9bac43
 
9bac43
     if (action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC) {
9bac43
@@ -1741,13 +1742,13 @@ static void external_snapshot_prepare(BlkActionState *common,
9bac43
 
9bac43
         if (node_name && !snapshot_node_name) {
9bac43
             error_setg(errp, "New snapshot node name missing");
9bac43
-            return;
9bac43
+            goto out;
9bac43
         }
9bac43
 
9bac43
         if (snapshot_node_name &&
9bac43
             bdrv_lookup_bs(snapshot_node_name, snapshot_node_name, NULL)) {
9bac43
             error_setg(errp, "New snapshot node name already in use");
9bac43
-            return;
9bac43
+            goto out;
9bac43
         }
9bac43
 
9bac43
         flags = state->old_bs->open_flags;
9bac43
@@ -1760,7 +1761,7 @@ static void external_snapshot_prepare(BlkActionState *common,
9bac43
             int64_t size = bdrv_getlength(state->old_bs);
9bac43
             if (size < 0) {
9bac43
                 error_setg_errno(errp, -size, "bdrv_getlength failed");
9bac43
-                return;
9bac43
+                goto out;
9bac43
             }
9bac43
             bdrv_img_create(new_image_file, format,
9bac43
                             state->old_bs->filename,
9bac43
@@ -1768,7 +1769,7 @@ static void external_snapshot_prepare(BlkActionState *common,
9bac43
                             NULL, size, flags, false, &local_err);
9bac43
             if (local_err) {
9bac43
                 error_propagate(errp, local_err);
9bac43
-                return;
9bac43
+                goto out;
9bac43
             }
9bac43
         }
9bac43
 
9bac43
@@ -1783,30 +1784,30 @@ static void external_snapshot_prepare(BlkActionState *common,
9bac43
                               errp);
9bac43
     /* We will manually add the backing_hd field to the bs later */
9bac43
     if (!state->new_bs) {
9bac43
-        return;
9bac43
+        goto out;
9bac43
     }
9bac43
 
9bac43
     if (bdrv_has_blk(state->new_bs)) {
9bac43
         error_setg(errp, "The snapshot is already in use");
9bac43
-        return;
9bac43
+        goto out;
9bac43
     }
9bac43
 
9bac43
     if (bdrv_op_is_blocked(state->new_bs, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
9bac43
                            errp)) {
9bac43
-        return;
9bac43
+        goto out;
9bac43
     }
9bac43
 
9bac43
     if (state->new_bs->backing != NULL) {
9bac43
         error_setg(errp, "The snapshot already has a backing image");
9bac43
-        return;
9bac43
+        goto out;
9bac43
     }
9bac43
 
9bac43
     if (!state->new_bs->drv->supports_backing) {
9bac43
         error_setg(errp, "The snapshot does not support backing images");
9bac43
-        return;
9bac43
+        goto out;
9bac43
     }
9bac43
 
9bac43
-    bdrv_set_aio_context(state->new_bs, state->aio_context);
9bac43
+    bdrv_set_aio_context(state->new_bs, aio_context);
9bac43
 
9bac43
     /* This removes our old bs and adds the new bs. This is an operation that
9bac43
      * can fail, so we need to do it in .prepare; undoing it for abort is
9bac43
@@ -1815,15 +1816,22 @@ static void external_snapshot_prepare(BlkActionState *common,
9bac43
     bdrv_append(state->new_bs, state->old_bs, &local_err);
9bac43
     if (local_err) {
9bac43
         error_propagate(errp, local_err);
9bac43
-        return;
9bac43
+        goto out;
9bac43
     }
9bac43
     state->overlay_appended = true;
9bac43
+
9bac43
+out:
9bac43
+    aio_context_release(aio_context);
9bac43
 }
9bac43
 
9bac43
 static void external_snapshot_commit(BlkActionState *common)
9bac43
 {
9bac43
     ExternalSnapshotState *state =
9bac43
                              DO_UPCAST(ExternalSnapshotState, common, common);
9bac43
+    AioContext *aio_context;
9bac43
+
9bac43
+    aio_context = bdrv_get_aio_context(state->old_bs);
9bac43
+    aio_context_acquire(aio_context);
9bac43
 
9bac43
     /* We don't need (or want) to use the transactional
9bac43
      * bdrv_reopen_multiple() across all the entries at once, because we
9bac43
@@ -1832,6 +1840,8 @@ static void external_snapshot_commit(BlkActionState *common)
9bac43
         bdrv_reopen(state->old_bs, state->old_bs->open_flags & ~BDRV_O_RDWR,
9bac43
                     NULL);
9bac43
     }
9bac43
+
9bac43
+    aio_context_release(aio_context);
9bac43
 }
9bac43
 
9bac43
 static void external_snapshot_abort(BlkActionState *common)
9bac43
@@ -1840,11 +1850,18 @@ static void external_snapshot_abort(BlkActionState *common)
9bac43
                              DO_UPCAST(ExternalSnapshotState, common, common);
9bac43
     if (state->new_bs) {
9bac43
         if (state->overlay_appended) {
9bac43
+            AioContext *aio_context;
9bac43
+
9bac43
+            aio_context = bdrv_get_aio_context(state->old_bs);
9bac43
+            aio_context_acquire(aio_context);
9bac43
+
9bac43
             bdrv_ref(state->old_bs);   /* we can't let bdrv_set_backind_hd()
9bac43
                                           close state->old_bs; we need it */
9bac43
             bdrv_set_backing_hd(state->new_bs, NULL, &error_abort);
9bac43
             bdrv_replace_node(state->new_bs, state->old_bs, &error_abort);
9bac43
             bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_bs */
9bac43
+
9bac43
+            aio_context_release(aio_context);
9bac43
         }
9bac43
     }
9bac43
 }
9bac43
@@ -1853,11 +1870,19 @@ static void external_snapshot_clean(BlkActionState *common)
9bac43
 {
9bac43
     ExternalSnapshotState *state =
9bac43
                              DO_UPCAST(ExternalSnapshotState, common, common);
9bac43
-    if (state->aio_context) {
9bac43
-        bdrv_drained_end(state->old_bs);
9bac43
-        bdrv_unref(state->new_bs);
9bac43
-        aio_context_release(state->aio_context);
9bac43
+    AioContext *aio_context;
9bac43
+
9bac43
+    if (!state->old_bs) {
9bac43
+        return;
9bac43
     }
9bac43
+
9bac43
+    aio_context = bdrv_get_aio_context(state->old_bs);
9bac43
+    aio_context_acquire(aio_context);
9bac43
+
9bac43
+    bdrv_drained_end(state->old_bs);
9bac43
+    bdrv_unref(state->new_bs);
9bac43
+
9bac43
+    aio_context_release(aio_context);
9bac43
 }
9bac43
 
9bac43
 typedef struct DriveBackupState {
9bac43
-- 
9bac43
1.8.3.1
9bac43