|
|
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 |
|