forked from rpms/qemu-kvm
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
897 lines
32 KiB
897 lines
32 KiB
From 79063522861cb2baf921b204bcdf4c3bfb5697f4 Mon Sep 17 00:00:00 2001
|
|
From: Kevin Wolf <kwolf@redhat.com>
|
|
Date: Fri, 18 Nov 2022 18:41:05 +0100
|
|
Subject: [PATCH 23/31] block: Remove subtree drains
|
|
|
|
RH-Author: Stefano Garzarella <sgarzare@redhat.com>
|
|
RH-MergeRequest: 135: block: Simplify drain to prevent QEMU from crashing during snapshot
|
|
RH-Bugzilla: 2155112
|
|
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
|
|
RH-Acked-by: Hanna Czenczek <hreitz@redhat.com>
|
|
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
|
RH-Commit: [11/16] d92f5041cceeeec49a65441b22d20f692c0f1c77 (sgarzarella/qemu-kvm-c-9-s)
|
|
|
|
Subtree drains are not used any more. Remove them.
|
|
|
|
After this, BdrvChildClass.attach/detach() don't poll any more.
|
|
|
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
|
|
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
|
|
Message-Id: <20221118174110.55183-11-kwolf@redhat.com>
|
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
(cherry picked from commit 299403aedaeb7f08d8e98aa8614b29d4e5546066)
|
|
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
---
|
|
block.c | 20 +--
|
|
block/io.c | 121 +++-----------
|
|
include/block/block-io.h | 18 +--
|
|
include/block/block_int-common.h | 1 -
|
|
include/block/block_int-io.h | 12 --
|
|
tests/unit/test-bdrv-drain.c | 261 ++-----------------------------
|
|
6 files changed, 44 insertions(+), 389 deletions(-)
|
|
|
|
diff --git a/block.c b/block.c
|
|
index 5330e89903..e0e3b21790 100644
|
|
--- a/block.c
|
|
+++ b/block.c
|
|
@@ -1232,7 +1232,7 @@ static void bdrv_child_cb_drained_begin(BdrvChild *child)
|
|
static bool bdrv_child_cb_drained_poll(BdrvChild *child)
|
|
{
|
|
BlockDriverState *bs = child->opaque;
|
|
- return bdrv_drain_poll(bs, false, NULL, false);
|
|
+ return bdrv_drain_poll(bs, NULL, false);
|
|
}
|
|
|
|
static void bdrv_child_cb_drained_end(BdrvChild *child)
|
|
@@ -1482,8 +1482,6 @@ static void bdrv_child_cb_attach(BdrvChild *child)
|
|
assert(!bs->file);
|
|
bs->file = child;
|
|
}
|
|
-
|
|
- bdrv_apply_subtree_drain(child, bs);
|
|
}
|
|
|
|
static void bdrv_child_cb_detach(BdrvChild *child)
|
|
@@ -1494,8 +1492,6 @@ static void bdrv_child_cb_detach(BdrvChild *child)
|
|
bdrv_backing_detach(child);
|
|
}
|
|
|
|
- bdrv_unapply_subtree_drain(child, bs);
|
|
-
|
|
assert_bdrv_graph_writable(bs);
|
|
QLIST_REMOVE(child, next);
|
|
if (child == bs->backing) {
|
|
@@ -2851,9 +2847,6 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
|
|
}
|
|
|
|
if (old_bs) {
|
|
- /* Detach first so that the recursive drain sections coming from @child
|
|
- * are already gone and we only end the drain sections that came from
|
|
- * elsewhere. */
|
|
if (child->klass->detach) {
|
|
child->klass->detach(child);
|
|
}
|
|
@@ -2868,17 +2861,14 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
|
|
QLIST_INSERT_HEAD(&new_bs->parents, child, next_parent);
|
|
|
|
/*
|
|
- * Detaching the old node may have led to the new node's
|
|
- * quiesce_counter having been decreased. Not a problem, we
|
|
- * just need to recognize this here and then invoke
|
|
- * drained_end appropriately more often.
|
|
+ * Polling in bdrv_parent_drained_begin_single() may have led to the new
|
|
+ * node's quiesce_counter having been decreased. Not a problem, we just
|
|
+ * need to recognize this here and then invoke drained_end appropriately
|
|
+ * more often.
|
|
*/
|
|
assert(new_bs->quiesce_counter <= new_bs_quiesce_counter);
|
|
drain_saldo += new_bs->quiesce_counter - new_bs_quiesce_counter;
|
|
|
|
- /* Attach only after starting new drained sections, so that recursive
|
|
- * drain sections coming from @child don't get an extra .drained_begin
|
|
- * callback. */
|
|
if (child->klass->attach) {
|
|
child->klass->attach(child);
|
|
}
|
|
diff --git a/block/io.c b/block/io.c
|
|
index a25103be6f..75224480d0 100644
|
|
--- a/block/io.c
|
|
+++ b/block/io.c
|
|
@@ -236,17 +236,15 @@ typedef struct {
|
|
BlockDriverState *bs;
|
|
bool done;
|
|
bool begin;
|
|
- bool recursive;
|
|
bool poll;
|
|
BdrvChild *parent;
|
|
bool ignore_bds_parents;
|
|
} BdrvCoDrainData;
|
|
|
|
/* Returns true if BDRV_POLL_WHILE() should go into a blocking aio_poll() */
|
|
-bool bdrv_drain_poll(BlockDriverState *bs, bool recursive,
|
|
- BdrvChild *ignore_parent, bool ignore_bds_parents)
|
|
+bool bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent,
|
|
+ bool ignore_bds_parents)
|
|
{
|
|
- BdrvChild *child, *next;
|
|
IO_OR_GS_CODE();
|
|
|
|
if (bdrv_parent_drained_poll(bs, ignore_parent, ignore_bds_parents)) {
|
|
@@ -257,29 +255,19 @@ bool bdrv_drain_poll(BlockDriverState *bs, bool recursive,
|
|
return true;
|
|
}
|
|
|
|
- if (recursive) {
|
|
- assert(!ignore_bds_parents);
|
|
- QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
|
|
- if (bdrv_drain_poll(child->bs, recursive, child, false)) {
|
|
- return true;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
return false;
|
|
}
|
|
|
|
-static bool bdrv_drain_poll_top_level(BlockDriverState *bs, bool recursive,
|
|
+static bool bdrv_drain_poll_top_level(BlockDriverState *bs,
|
|
BdrvChild *ignore_parent)
|
|
{
|
|
- return bdrv_drain_poll(bs, recursive, ignore_parent, false);
|
|
+ return bdrv_drain_poll(bs, ignore_parent, false);
|
|
}
|
|
|
|
-static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
|
|
- BdrvChild *parent, bool ignore_bds_parents,
|
|
- bool poll);
|
|
-static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
|
|
- BdrvChild *parent, bool ignore_bds_parents);
|
|
+static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent,
|
|
+ bool ignore_bds_parents, bool poll);
|
|
+static void bdrv_do_drained_end(BlockDriverState *bs, BdrvChild *parent,
|
|
+ bool ignore_bds_parents);
|
|
|
|
static void bdrv_co_drain_bh_cb(void *opaque)
|
|
{
|
|
@@ -292,12 +280,11 @@ static void bdrv_co_drain_bh_cb(void *opaque)
|
|
aio_context_acquire(ctx);
|
|
bdrv_dec_in_flight(bs);
|
|
if (data->begin) {
|
|
- bdrv_do_drained_begin(bs, data->recursive, data->parent,
|
|
- data->ignore_bds_parents, data->poll);
|
|
+ bdrv_do_drained_begin(bs, data->parent, data->ignore_bds_parents,
|
|
+ data->poll);
|
|
} else {
|
|
assert(!data->poll);
|
|
- bdrv_do_drained_end(bs, data->recursive, data->parent,
|
|
- data->ignore_bds_parents);
|
|
+ bdrv_do_drained_end(bs, data->parent, data->ignore_bds_parents);
|
|
}
|
|
aio_context_release(ctx);
|
|
} else {
|
|
@@ -310,7 +297,7 @@ static void bdrv_co_drain_bh_cb(void *opaque)
|
|
}
|
|
|
|
static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
|
|
- bool begin, bool recursive,
|
|
+ bool begin,
|
|
BdrvChild *parent,
|
|
bool ignore_bds_parents,
|
|
bool poll)
|
|
@@ -329,7 +316,6 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
|
|
.bs = bs,
|
|
.done = false,
|
|
.begin = begin,
|
|
- .recursive = recursive,
|
|
.parent = parent,
|
|
.ignore_bds_parents = ignore_bds_parents,
|
|
.poll = poll,
|
|
@@ -380,29 +366,16 @@ void bdrv_do_drained_begin_quiesce(BlockDriverState *bs,
|
|
}
|
|
}
|
|
|
|
-static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
|
|
- BdrvChild *parent, bool ignore_bds_parents,
|
|
- bool poll)
|
|
+static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent,
|
|
+ bool ignore_bds_parents, bool poll)
|
|
{
|
|
- BdrvChild *child, *next;
|
|
-
|
|
if (qemu_in_coroutine()) {
|
|
- bdrv_co_yield_to_drain(bs, true, recursive, parent, ignore_bds_parents,
|
|
- poll);
|
|
+ bdrv_co_yield_to_drain(bs, true, parent, ignore_bds_parents, poll);
|
|
return;
|
|
}
|
|
|
|
bdrv_do_drained_begin_quiesce(bs, parent, ignore_bds_parents);
|
|
|
|
- if (recursive) {
|
|
- assert(!ignore_bds_parents);
|
|
- bs->recursive_quiesce_counter++;
|
|
- QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
|
|
- bdrv_do_drained_begin(child->bs, true, child, ignore_bds_parents,
|
|
- false);
|
|
- }
|
|
- }
|
|
-
|
|
/*
|
|
* Wait for drained requests to finish.
|
|
*
|
|
@@ -414,35 +387,27 @@ static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
|
|
*/
|
|
if (poll) {
|
|
assert(!ignore_bds_parents);
|
|
- BDRV_POLL_WHILE(bs, bdrv_drain_poll_top_level(bs, recursive, parent));
|
|
+ BDRV_POLL_WHILE(bs, bdrv_drain_poll_top_level(bs, parent));
|
|
}
|
|
}
|
|
|
|
void bdrv_drained_begin(BlockDriverState *bs)
|
|
{
|
|
IO_OR_GS_CODE();
|
|
- bdrv_do_drained_begin(bs, false, NULL, false, true);
|
|
-}
|
|
-
|
|
-void bdrv_subtree_drained_begin(BlockDriverState *bs)
|
|
-{
|
|
- IO_OR_GS_CODE();
|
|
- bdrv_do_drained_begin(bs, true, NULL, false, true);
|
|
+ bdrv_do_drained_begin(bs, NULL, false, true);
|
|
}
|
|
|
|
/**
|
|
* This function does not poll, nor must any of its recursively called
|
|
* functions.
|
|
*/
|
|
-static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
|
|
- BdrvChild *parent, bool ignore_bds_parents)
|
|
+static void bdrv_do_drained_end(BlockDriverState *bs, BdrvChild *parent,
|
|
+ bool ignore_bds_parents)
|
|
{
|
|
- BdrvChild *child;
|
|
int old_quiesce_counter;
|
|
|
|
if (qemu_in_coroutine()) {
|
|
- bdrv_co_yield_to_drain(bs, false, recursive, parent, ignore_bds_parents,
|
|
- false);
|
|
+ bdrv_co_yield_to_drain(bs, false, parent, ignore_bds_parents, false);
|
|
return;
|
|
}
|
|
assert(bs->quiesce_counter > 0);
|
|
@@ -457,46 +422,12 @@ static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
|
|
if (old_quiesce_counter == 1) {
|
|
aio_enable_external(bdrv_get_aio_context(bs));
|
|
}
|
|
-
|
|
- if (recursive) {
|
|
- assert(!ignore_bds_parents);
|
|
- bs->recursive_quiesce_counter--;
|
|
- QLIST_FOREACH(child, &bs->children, next) {
|
|
- bdrv_do_drained_end(child->bs, true, child, ignore_bds_parents);
|
|
- }
|
|
- }
|
|
}
|
|
|
|
void bdrv_drained_end(BlockDriverState *bs)
|
|
{
|
|
IO_OR_GS_CODE();
|
|
- bdrv_do_drained_end(bs, false, NULL, false);
|
|
-}
|
|
-
|
|
-void bdrv_subtree_drained_end(BlockDriverState *bs)
|
|
-{
|
|
- IO_OR_GS_CODE();
|
|
- bdrv_do_drained_end(bs, true, NULL, false);
|
|
-}
|
|
-
|
|
-void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent)
|
|
-{
|
|
- int i;
|
|
- IO_OR_GS_CODE();
|
|
-
|
|
- for (i = 0; i < new_parent->recursive_quiesce_counter; i++) {
|
|
- bdrv_do_drained_begin(child->bs, true, child, false, true);
|
|
- }
|
|
-}
|
|
-
|
|
-void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent)
|
|
-{
|
|
- int i;
|
|
- IO_OR_GS_CODE();
|
|
-
|
|
- for (i = 0; i < old_parent->recursive_quiesce_counter; i++) {
|
|
- bdrv_do_drained_end(child->bs, true, child, false);
|
|
- }
|
|
+ bdrv_do_drained_end(bs, NULL, false);
|
|
}
|
|
|
|
void bdrv_drain(BlockDriverState *bs)
|
|
@@ -529,7 +460,7 @@ static bool bdrv_drain_all_poll(void)
|
|
while ((bs = bdrv_next_all_states(bs))) {
|
|
AioContext *aio_context = bdrv_get_aio_context(bs);
|
|
aio_context_acquire(aio_context);
|
|
- result |= bdrv_drain_poll(bs, false, NULL, true);
|
|
+ result |= bdrv_drain_poll(bs, NULL, true);
|
|
aio_context_release(aio_context);
|
|
}
|
|
|
|
@@ -554,7 +485,7 @@ void bdrv_drain_all_begin(void)
|
|
GLOBAL_STATE_CODE();
|
|
|
|
if (qemu_in_coroutine()) {
|
|
- bdrv_co_yield_to_drain(NULL, true, false, NULL, true, true);
|
|
+ bdrv_co_yield_to_drain(NULL, true, NULL, true, true);
|
|
return;
|
|
}
|
|
|
|
@@ -579,7 +510,7 @@ void bdrv_drain_all_begin(void)
|
|
AioContext *aio_context = bdrv_get_aio_context(bs);
|
|
|
|
aio_context_acquire(aio_context);
|
|
- bdrv_do_drained_begin(bs, false, NULL, true, false);
|
|
+ bdrv_do_drained_begin(bs, NULL, true, false);
|
|
aio_context_release(aio_context);
|
|
}
|
|
|
|
@@ -599,7 +530,7 @@ void bdrv_drain_all_end_quiesce(BlockDriverState *bs)
|
|
g_assert(!bs->refcnt);
|
|
|
|
while (bs->quiesce_counter) {
|
|
- bdrv_do_drained_end(bs, false, NULL, true);
|
|
+ bdrv_do_drained_end(bs, NULL, true);
|
|
}
|
|
}
|
|
|
|
@@ -621,7 +552,7 @@ void bdrv_drain_all_end(void)
|
|
AioContext *aio_context = bdrv_get_aio_context(bs);
|
|
|
|
aio_context_acquire(aio_context);
|
|
- bdrv_do_drained_end(bs, false, NULL, true);
|
|
+ bdrv_do_drained_end(bs, NULL, true);
|
|
aio_context_release(aio_context);
|
|
}
|
|
|
|
diff --git a/include/block/block-io.h b/include/block/block-io.h
|
|
index 054e964c9b..9c36a16a1f 100644
|
|
--- a/include/block/block-io.h
|
|
+++ b/include/block/block-io.h
|
|
@@ -302,8 +302,7 @@ void bdrv_parent_drained_end_single(BdrvChild *c);
|
|
/**
|
|
* bdrv_drain_poll:
|
|
*
|
|
- * Poll for pending requests in @bs, its parents (except for @ignore_parent),
|
|
- * and if @recursive is true its children as well (used for subtree drain).
|
|
+ * Poll for pending requests in @bs and its parents (except for @ignore_parent).
|
|
*
|
|
* If @ignore_bds_parents is true, parents that are BlockDriverStates must
|
|
* ignore the drain request because they will be drained separately (used for
|
|
@@ -311,8 +310,8 @@ void bdrv_parent_drained_end_single(BdrvChild *c);
|
|
*
|
|
* This is part of bdrv_drained_begin.
|
|
*/
|
|
-bool bdrv_drain_poll(BlockDriverState *bs, bool recursive,
|
|
- BdrvChild *ignore_parent, bool ignore_bds_parents);
|
|
+bool bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent,
|
|
+ bool ignore_bds_parents);
|
|
|
|
/**
|
|
* bdrv_drained_begin:
|
|
@@ -333,12 +332,6 @@ void bdrv_drained_begin(BlockDriverState *bs);
|
|
void bdrv_do_drained_begin_quiesce(BlockDriverState *bs,
|
|
BdrvChild *parent, bool ignore_bds_parents);
|
|
|
|
-/**
|
|
- * Like bdrv_drained_begin, but recursively begins a quiesced section for
|
|
- * exclusive access to all child nodes as well.
|
|
- */
|
|
-void bdrv_subtree_drained_begin(BlockDriverState *bs);
|
|
-
|
|
/**
|
|
* bdrv_drained_end:
|
|
*
|
|
@@ -346,9 +339,4 @@ void bdrv_subtree_drained_begin(BlockDriverState *bs);
|
|
*/
|
|
void bdrv_drained_end(BlockDriverState *bs);
|
|
|
|
-/**
|
|
- * End a quiescent section started by bdrv_subtree_drained_begin().
|
|
- */
|
|
-void bdrv_subtree_drained_end(BlockDriverState *bs);
|
|
-
|
|
#endif /* BLOCK_IO_H */
|
|
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
|
|
index 2b97576f6d..791dddfd7d 100644
|
|
--- a/include/block/block_int-common.h
|
|
+++ b/include/block/block_int-common.h
|
|
@@ -1184,7 +1184,6 @@ struct BlockDriverState {
|
|
|
|
/* Accessed with atomic ops. */
|
|
int quiesce_counter;
|
|
- int recursive_quiesce_counter;
|
|
|
|
unsigned int write_gen; /* Current data generation */
|
|
|
|
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
|
|
index 4b0b3e17ef..8bc061ebb8 100644
|
|
--- a/include/block/block_int-io.h
|
|
+++ b/include/block/block_int-io.h
|
|
@@ -179,16 +179,4 @@ void bdrv_bsc_invalidate_range(BlockDriverState *bs,
|
|
*/
|
|
void bdrv_bsc_fill(BlockDriverState *bs, int64_t offset, int64_t bytes);
|
|
|
|
-
|
|
-/*
|
|
- * "I/O or GS" API functions. These functions can run without
|
|
- * the BQL, but only in one specific iothread/main loop.
|
|
- *
|
|
- * See include/block/block-io.h for more information about
|
|
- * the "I/O or GS" API.
|
|
- */
|
|
-
|
|
-void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent);
|
|
-void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent);
|
|
-
|
|
#endif /* BLOCK_INT_IO_H */
|
|
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
|
|
index 695519ee02..dda08de8db 100644
|
|
--- a/tests/unit/test-bdrv-drain.c
|
|
+++ b/tests/unit/test-bdrv-drain.c
|
|
@@ -156,7 +156,6 @@ static void call_in_coroutine(void (*entry)(void))
|
|
enum drain_type {
|
|
BDRV_DRAIN_ALL,
|
|
BDRV_DRAIN,
|
|
- BDRV_SUBTREE_DRAIN,
|
|
DRAIN_TYPE_MAX,
|
|
};
|
|
|
|
@@ -165,7 +164,6 @@ static void do_drain_begin(enum drain_type drain_type, BlockDriverState *bs)
|
|
switch (drain_type) {
|
|
case BDRV_DRAIN_ALL: bdrv_drain_all_begin(); break;
|
|
case BDRV_DRAIN: bdrv_drained_begin(bs); break;
|
|
- case BDRV_SUBTREE_DRAIN: bdrv_subtree_drained_begin(bs); break;
|
|
default: g_assert_not_reached();
|
|
}
|
|
}
|
|
@@ -175,7 +173,6 @@ static void do_drain_end(enum drain_type drain_type, BlockDriverState *bs)
|
|
switch (drain_type) {
|
|
case BDRV_DRAIN_ALL: bdrv_drain_all_end(); break;
|
|
case BDRV_DRAIN: bdrv_drained_end(bs); break;
|
|
- case BDRV_SUBTREE_DRAIN: bdrv_subtree_drained_end(bs); break;
|
|
default: g_assert_not_reached();
|
|
}
|
|
}
|
|
@@ -271,11 +268,6 @@ static void test_drv_cb_drain(void)
|
|
test_drv_cb_common(BDRV_DRAIN, false);
|
|
}
|
|
|
|
-static void test_drv_cb_drain_subtree(void)
|
|
-{
|
|
- test_drv_cb_common(BDRV_SUBTREE_DRAIN, true);
|
|
-}
|
|
-
|
|
static void test_drv_cb_co_drain_all(void)
|
|
{
|
|
call_in_coroutine(test_drv_cb_drain_all);
|
|
@@ -286,11 +278,6 @@ static void test_drv_cb_co_drain(void)
|
|
call_in_coroutine(test_drv_cb_drain);
|
|
}
|
|
|
|
-static void test_drv_cb_co_drain_subtree(void)
|
|
-{
|
|
- call_in_coroutine(test_drv_cb_drain_subtree);
|
|
-}
|
|
-
|
|
static void test_quiesce_common(enum drain_type drain_type, bool recursive)
|
|
{
|
|
BlockBackend *blk;
|
|
@@ -332,11 +319,6 @@ static void test_quiesce_drain(void)
|
|
test_quiesce_common(BDRV_DRAIN, false);
|
|
}
|
|
|
|
-static void test_quiesce_drain_subtree(void)
|
|
-{
|
|
- test_quiesce_common(BDRV_SUBTREE_DRAIN, true);
|
|
-}
|
|
-
|
|
static void test_quiesce_co_drain_all(void)
|
|
{
|
|
call_in_coroutine(test_quiesce_drain_all);
|
|
@@ -347,11 +329,6 @@ static void test_quiesce_co_drain(void)
|
|
call_in_coroutine(test_quiesce_drain);
|
|
}
|
|
|
|
-static void test_quiesce_co_drain_subtree(void)
|
|
-{
|
|
- call_in_coroutine(test_quiesce_drain_subtree);
|
|
-}
|
|
-
|
|
static void test_nested(void)
|
|
{
|
|
BlockBackend *blk;
|
|
@@ -402,158 +379,6 @@ static void test_nested(void)
|
|
blk_unref(blk);
|
|
}
|
|
|
|
-static void test_multiparent(void)
|
|
-{
|
|
- BlockBackend *blk_a, *blk_b;
|
|
- BlockDriverState *bs_a, *bs_b, *backing;
|
|
- BDRVTestState *a_s, *b_s, *backing_s;
|
|
-
|
|
- blk_a = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
|
|
- bs_a = bdrv_new_open_driver(&bdrv_test, "test-node-a", BDRV_O_RDWR,
|
|
- &error_abort);
|
|
- a_s = bs_a->opaque;
|
|
- blk_insert_bs(blk_a, bs_a, &error_abort);
|
|
-
|
|
- blk_b = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
|
|
- bs_b = bdrv_new_open_driver(&bdrv_test, "test-node-b", BDRV_O_RDWR,
|
|
- &error_abort);
|
|
- b_s = bs_b->opaque;
|
|
- blk_insert_bs(blk_b, bs_b, &error_abort);
|
|
-
|
|
- backing = bdrv_new_open_driver(&bdrv_test, "backing", 0, &error_abort);
|
|
- backing_s = backing->opaque;
|
|
- bdrv_set_backing_hd(bs_a, backing, &error_abort);
|
|
- bdrv_set_backing_hd(bs_b, backing, &error_abort);
|
|
-
|
|
- g_assert_cmpint(bs_a->quiesce_counter, ==, 0);
|
|
- g_assert_cmpint(bs_b->quiesce_counter, ==, 0);
|
|
- g_assert_cmpint(backing->quiesce_counter, ==, 0);
|
|
- g_assert_cmpint(a_s->drain_count, ==, 0);
|
|
- g_assert_cmpint(b_s->drain_count, ==, 0);
|
|
- g_assert_cmpint(backing_s->drain_count, ==, 0);
|
|
-
|
|
- do_drain_begin(BDRV_SUBTREE_DRAIN, bs_a);
|
|
-
|
|
- g_assert_cmpint(bs_a->quiesce_counter, ==, 1);
|
|
- g_assert_cmpint(bs_b->quiesce_counter, ==, 1);
|
|
- g_assert_cmpint(backing->quiesce_counter, ==, 1);
|
|
- g_assert_cmpint(a_s->drain_count, ==, 1);
|
|
- g_assert_cmpint(b_s->drain_count, ==, 1);
|
|
- g_assert_cmpint(backing_s->drain_count, ==, 1);
|
|
-
|
|
- do_drain_begin(BDRV_SUBTREE_DRAIN, bs_b);
|
|
-
|
|
- g_assert_cmpint(bs_a->quiesce_counter, ==, 2);
|
|
- g_assert_cmpint(bs_b->quiesce_counter, ==, 2);
|
|
- g_assert_cmpint(backing->quiesce_counter, ==, 2);
|
|
- g_assert_cmpint(a_s->drain_count, ==, 2);
|
|
- g_assert_cmpint(b_s->drain_count, ==, 2);
|
|
- g_assert_cmpint(backing_s->drain_count, ==, 2);
|
|
-
|
|
- do_drain_end(BDRV_SUBTREE_DRAIN, bs_b);
|
|
-
|
|
- g_assert_cmpint(bs_a->quiesce_counter, ==, 1);
|
|
- g_assert_cmpint(bs_b->quiesce_counter, ==, 1);
|
|
- g_assert_cmpint(backing->quiesce_counter, ==, 1);
|
|
- g_assert_cmpint(a_s->drain_count, ==, 1);
|
|
- g_assert_cmpint(b_s->drain_count, ==, 1);
|
|
- g_assert_cmpint(backing_s->drain_count, ==, 1);
|
|
-
|
|
- do_drain_end(BDRV_SUBTREE_DRAIN, bs_a);
|
|
-
|
|
- g_assert_cmpint(bs_a->quiesce_counter, ==, 0);
|
|
- g_assert_cmpint(bs_b->quiesce_counter, ==, 0);
|
|
- g_assert_cmpint(backing->quiesce_counter, ==, 0);
|
|
- g_assert_cmpint(a_s->drain_count, ==, 0);
|
|
- g_assert_cmpint(b_s->drain_count, ==, 0);
|
|
- g_assert_cmpint(backing_s->drain_count, ==, 0);
|
|
-
|
|
- bdrv_unref(backing);
|
|
- bdrv_unref(bs_a);
|
|
- bdrv_unref(bs_b);
|
|
- blk_unref(blk_a);
|
|
- blk_unref(blk_b);
|
|
-}
|
|
-
|
|
-static void test_graph_change_drain_subtree(void)
|
|
-{
|
|
- BlockBackend *blk_a, *blk_b;
|
|
- BlockDriverState *bs_a, *bs_b, *backing;
|
|
- BDRVTestState *a_s, *b_s, *backing_s;
|
|
-
|
|
- blk_a = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
|
|
- bs_a = bdrv_new_open_driver(&bdrv_test, "test-node-a", BDRV_O_RDWR,
|
|
- &error_abort);
|
|
- a_s = bs_a->opaque;
|
|
- blk_insert_bs(blk_a, bs_a, &error_abort);
|
|
-
|
|
- blk_b = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
|
|
- bs_b = bdrv_new_open_driver(&bdrv_test, "test-node-b", BDRV_O_RDWR,
|
|
- &error_abort);
|
|
- b_s = bs_b->opaque;
|
|
- blk_insert_bs(blk_b, bs_b, &error_abort);
|
|
-
|
|
- backing = bdrv_new_open_driver(&bdrv_test, "backing", 0, &error_abort);
|
|
- backing_s = backing->opaque;
|
|
- bdrv_set_backing_hd(bs_a, backing, &error_abort);
|
|
-
|
|
- g_assert_cmpint(bs_a->quiesce_counter, ==, 0);
|
|
- g_assert_cmpint(bs_b->quiesce_counter, ==, 0);
|
|
- g_assert_cmpint(backing->quiesce_counter, ==, 0);
|
|
- g_assert_cmpint(a_s->drain_count, ==, 0);
|
|
- g_assert_cmpint(b_s->drain_count, ==, 0);
|
|
- g_assert_cmpint(backing_s->drain_count, ==, 0);
|
|
-
|
|
- do_drain_begin(BDRV_SUBTREE_DRAIN, bs_a);
|
|
- do_drain_begin(BDRV_SUBTREE_DRAIN, bs_a);
|
|
- do_drain_begin(BDRV_SUBTREE_DRAIN, bs_a);
|
|
- do_drain_begin(BDRV_SUBTREE_DRAIN, bs_b);
|
|
- do_drain_begin(BDRV_SUBTREE_DRAIN, bs_b);
|
|
-
|
|
- bdrv_set_backing_hd(bs_b, backing, &error_abort);
|
|
- g_assert_cmpint(bs_a->quiesce_counter, ==, 5);
|
|
- g_assert_cmpint(bs_b->quiesce_counter, ==, 5);
|
|
- g_assert_cmpint(backing->quiesce_counter, ==, 5);
|
|
- g_assert_cmpint(a_s->drain_count, ==, 5);
|
|
- g_assert_cmpint(b_s->drain_count, ==, 5);
|
|
- g_assert_cmpint(backing_s->drain_count, ==, 5);
|
|
-
|
|
- bdrv_set_backing_hd(bs_b, NULL, &error_abort);
|
|
- g_assert_cmpint(bs_a->quiesce_counter, ==, 3);
|
|
- g_assert_cmpint(bs_b->quiesce_counter, ==, 2);
|
|
- g_assert_cmpint(backing->quiesce_counter, ==, 3);
|
|
- g_assert_cmpint(a_s->drain_count, ==, 3);
|
|
- g_assert_cmpint(b_s->drain_count, ==, 2);
|
|
- g_assert_cmpint(backing_s->drain_count, ==, 3);
|
|
-
|
|
- bdrv_set_backing_hd(bs_b, backing, &error_abort);
|
|
- g_assert_cmpint(bs_a->quiesce_counter, ==, 5);
|
|
- g_assert_cmpint(bs_b->quiesce_counter, ==, 5);
|
|
- g_assert_cmpint(backing->quiesce_counter, ==, 5);
|
|
- g_assert_cmpint(a_s->drain_count, ==, 5);
|
|
- g_assert_cmpint(b_s->drain_count, ==, 5);
|
|
- g_assert_cmpint(backing_s->drain_count, ==, 5);
|
|
-
|
|
- do_drain_end(BDRV_SUBTREE_DRAIN, bs_b);
|
|
- do_drain_end(BDRV_SUBTREE_DRAIN, bs_b);
|
|
- do_drain_end(BDRV_SUBTREE_DRAIN, bs_a);
|
|
- do_drain_end(BDRV_SUBTREE_DRAIN, bs_a);
|
|
- do_drain_end(BDRV_SUBTREE_DRAIN, bs_a);
|
|
-
|
|
- g_assert_cmpint(bs_a->quiesce_counter, ==, 0);
|
|
- g_assert_cmpint(bs_b->quiesce_counter, ==, 0);
|
|
- g_assert_cmpint(backing->quiesce_counter, ==, 0);
|
|
- g_assert_cmpint(a_s->drain_count, ==, 0);
|
|
- g_assert_cmpint(b_s->drain_count, ==, 0);
|
|
- g_assert_cmpint(backing_s->drain_count, ==, 0);
|
|
-
|
|
- bdrv_unref(backing);
|
|
- bdrv_unref(bs_a);
|
|
- bdrv_unref(bs_b);
|
|
- blk_unref(blk_a);
|
|
- blk_unref(blk_b);
|
|
-}
|
|
-
|
|
static void test_graph_change_drain_all(void)
|
|
{
|
|
BlockBackend *blk_a, *blk_b;
|
|
@@ -773,12 +598,6 @@ static void test_iothread_drain(void)
|
|
test_iothread_common(BDRV_DRAIN, 1);
|
|
}
|
|
|
|
-static void test_iothread_drain_subtree(void)
|
|
-{
|
|
- test_iothread_common(BDRV_SUBTREE_DRAIN, 0);
|
|
- test_iothread_common(BDRV_SUBTREE_DRAIN, 1);
|
|
-}
|
|
-
|
|
|
|
typedef struct TestBlockJob {
|
|
BlockJob common;
|
|
@@ -863,7 +682,6 @@ enum test_job_result {
|
|
enum test_job_drain_node {
|
|
TEST_JOB_DRAIN_SRC,
|
|
TEST_JOB_DRAIN_SRC_CHILD,
|
|
- TEST_JOB_DRAIN_SRC_PARENT,
|
|
};
|
|
|
|
static void test_blockjob_common_drain_node(enum drain_type drain_type,
|
|
@@ -901,9 +719,6 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
|
|
case TEST_JOB_DRAIN_SRC_CHILD:
|
|
drain_bs = src_backing;
|
|
break;
|
|
- case TEST_JOB_DRAIN_SRC_PARENT:
|
|
- drain_bs = src_overlay;
|
|
- break;
|
|
default:
|
|
g_assert_not_reached();
|
|
}
|
|
@@ -1055,10 +870,6 @@ static void test_blockjob_common(enum drain_type drain_type, bool use_iothread,
|
|
TEST_JOB_DRAIN_SRC);
|
|
test_blockjob_common_drain_node(drain_type, use_iothread, result,
|
|
TEST_JOB_DRAIN_SRC_CHILD);
|
|
- if (drain_type == BDRV_SUBTREE_DRAIN) {
|
|
- test_blockjob_common_drain_node(drain_type, use_iothread, result,
|
|
- TEST_JOB_DRAIN_SRC_PARENT);
|
|
- }
|
|
}
|
|
|
|
static void test_blockjob_drain_all(void)
|
|
@@ -1071,11 +882,6 @@ static void test_blockjob_drain(void)
|
|
test_blockjob_common(BDRV_DRAIN, false, TEST_JOB_SUCCESS);
|
|
}
|
|
|
|
-static void test_blockjob_drain_subtree(void)
|
|
-{
|
|
- test_blockjob_common(BDRV_SUBTREE_DRAIN, false, TEST_JOB_SUCCESS);
|
|
-}
|
|
-
|
|
static void test_blockjob_error_drain_all(void)
|
|
{
|
|
test_blockjob_common(BDRV_DRAIN_ALL, false, TEST_JOB_FAIL_RUN);
|
|
@@ -1088,12 +894,6 @@ static void test_blockjob_error_drain(void)
|
|
test_blockjob_common(BDRV_DRAIN, false, TEST_JOB_FAIL_PREPARE);
|
|
}
|
|
|
|
-static void test_blockjob_error_drain_subtree(void)
|
|
-{
|
|
- test_blockjob_common(BDRV_SUBTREE_DRAIN, false, TEST_JOB_FAIL_RUN);
|
|
- test_blockjob_common(BDRV_SUBTREE_DRAIN, false, TEST_JOB_FAIL_PREPARE);
|
|
-}
|
|
-
|
|
static void test_blockjob_iothread_drain_all(void)
|
|
{
|
|
test_blockjob_common(BDRV_DRAIN_ALL, true, TEST_JOB_SUCCESS);
|
|
@@ -1104,11 +904,6 @@ static void test_blockjob_iothread_drain(void)
|
|
test_blockjob_common(BDRV_DRAIN, true, TEST_JOB_SUCCESS);
|
|
}
|
|
|
|
-static void test_blockjob_iothread_drain_subtree(void)
|
|
-{
|
|
- test_blockjob_common(BDRV_SUBTREE_DRAIN, true, TEST_JOB_SUCCESS);
|
|
-}
|
|
-
|
|
static void test_blockjob_iothread_error_drain_all(void)
|
|
{
|
|
test_blockjob_common(BDRV_DRAIN_ALL, true, TEST_JOB_FAIL_RUN);
|
|
@@ -1121,12 +916,6 @@ static void test_blockjob_iothread_error_drain(void)
|
|
test_blockjob_common(BDRV_DRAIN, true, TEST_JOB_FAIL_PREPARE);
|
|
}
|
|
|
|
-static void test_blockjob_iothread_error_drain_subtree(void)
|
|
-{
|
|
- test_blockjob_common(BDRV_SUBTREE_DRAIN, true, TEST_JOB_FAIL_RUN);
|
|
- test_blockjob_common(BDRV_SUBTREE_DRAIN, true, TEST_JOB_FAIL_PREPARE);
|
|
-}
|
|
-
|
|
|
|
typedef struct BDRVTestTopState {
|
|
BdrvChild *wait_child;
|
|
@@ -1273,14 +1062,6 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete,
|
|
bdrv_drain(child_bs);
|
|
bdrv_unref(child_bs);
|
|
break;
|
|
- case BDRV_SUBTREE_DRAIN:
|
|
- /* Would have to ref/unref bs here for !detach_instead_of_delete, but
|
|
- * then the whole test becomes pointless because the graph changes
|
|
- * don't occur during the drain any more. */
|
|
- assert(detach_instead_of_delete);
|
|
- bdrv_subtree_drained_begin(bs);
|
|
- bdrv_subtree_drained_end(bs);
|
|
- break;
|
|
case BDRV_DRAIN_ALL:
|
|
bdrv_drain_all_begin();
|
|
bdrv_drain_all_end();
|
|
@@ -1315,11 +1096,6 @@ static void test_detach_by_drain(void)
|
|
do_test_delete_by_drain(true, BDRV_DRAIN);
|
|
}
|
|
|
|
-static void test_detach_by_drain_subtree(void)
|
|
-{
|
|
- do_test_delete_by_drain(true, BDRV_SUBTREE_DRAIN);
|
|
-}
|
|
-
|
|
|
|
struct detach_by_parent_data {
|
|
BlockDriverState *parent_b;
|
|
@@ -1452,7 +1228,10 @@ static void test_detach_indirect(bool by_parent_cb)
|
|
g_assert(acb != NULL);
|
|
|
|
/* Drain and check the expected result */
|
|
- bdrv_subtree_drained_begin(parent_b);
|
|
+ bdrv_drained_begin(parent_b);
|
|
+ bdrv_drained_begin(a);
|
|
+ bdrv_drained_begin(b);
|
|
+ bdrv_drained_begin(c);
|
|
|
|
g_assert(detach_by_parent_data.child_c != NULL);
|
|
|
|
@@ -1467,12 +1246,15 @@ static void test_detach_indirect(bool by_parent_cb)
|
|
g_assert(QLIST_NEXT(child_a, next) == NULL);
|
|
|
|
g_assert_cmpint(parent_a->quiesce_counter, ==, 1);
|
|
- g_assert_cmpint(parent_b->quiesce_counter, ==, 1);
|
|
+ g_assert_cmpint(parent_b->quiesce_counter, ==, 3);
|
|
g_assert_cmpint(a->quiesce_counter, ==, 1);
|
|
- g_assert_cmpint(b->quiesce_counter, ==, 0);
|
|
+ g_assert_cmpint(b->quiesce_counter, ==, 1);
|
|
g_assert_cmpint(c->quiesce_counter, ==, 1);
|
|
|
|
- bdrv_subtree_drained_end(parent_b);
|
|
+ bdrv_drained_end(parent_b);
|
|
+ bdrv_drained_end(a);
|
|
+ bdrv_drained_end(b);
|
|
+ bdrv_drained_end(c);
|
|
|
|
bdrv_unref(parent_b);
|
|
blk_unref(blk);
|
|
@@ -2202,70 +1984,47 @@ int main(int argc, char **argv)
|
|
|
|
g_test_add_func("/bdrv-drain/driver-cb/drain_all", test_drv_cb_drain_all);
|
|
g_test_add_func("/bdrv-drain/driver-cb/drain", test_drv_cb_drain);
|
|
- g_test_add_func("/bdrv-drain/driver-cb/drain_subtree",
|
|
- test_drv_cb_drain_subtree);
|
|
|
|
g_test_add_func("/bdrv-drain/driver-cb/co/drain_all",
|
|
test_drv_cb_co_drain_all);
|
|
g_test_add_func("/bdrv-drain/driver-cb/co/drain", test_drv_cb_co_drain);
|
|
- g_test_add_func("/bdrv-drain/driver-cb/co/drain_subtree",
|
|
- test_drv_cb_co_drain_subtree);
|
|
-
|
|
|
|
g_test_add_func("/bdrv-drain/quiesce/drain_all", test_quiesce_drain_all);
|
|
g_test_add_func("/bdrv-drain/quiesce/drain", test_quiesce_drain);
|
|
- g_test_add_func("/bdrv-drain/quiesce/drain_subtree",
|
|
- test_quiesce_drain_subtree);
|
|
|
|
g_test_add_func("/bdrv-drain/quiesce/co/drain_all",
|
|
test_quiesce_co_drain_all);
|
|
g_test_add_func("/bdrv-drain/quiesce/co/drain", test_quiesce_co_drain);
|
|
- g_test_add_func("/bdrv-drain/quiesce/co/drain_subtree",
|
|
- test_quiesce_co_drain_subtree);
|
|
|
|
g_test_add_func("/bdrv-drain/nested", test_nested);
|
|
- g_test_add_func("/bdrv-drain/multiparent", test_multiparent);
|
|
|
|
- g_test_add_func("/bdrv-drain/graph-change/drain_subtree",
|
|
- test_graph_change_drain_subtree);
|
|
g_test_add_func("/bdrv-drain/graph-change/drain_all",
|
|
test_graph_change_drain_all);
|
|
|
|
g_test_add_func("/bdrv-drain/iothread/drain_all", test_iothread_drain_all);
|
|
g_test_add_func("/bdrv-drain/iothread/drain", test_iothread_drain);
|
|
- g_test_add_func("/bdrv-drain/iothread/drain_subtree",
|
|
- test_iothread_drain_subtree);
|
|
|
|
g_test_add_func("/bdrv-drain/blockjob/drain_all", test_blockjob_drain_all);
|
|
g_test_add_func("/bdrv-drain/blockjob/drain", test_blockjob_drain);
|
|
- g_test_add_func("/bdrv-drain/blockjob/drain_subtree",
|
|
- test_blockjob_drain_subtree);
|
|
|
|
g_test_add_func("/bdrv-drain/blockjob/error/drain_all",
|
|
test_blockjob_error_drain_all);
|
|
g_test_add_func("/bdrv-drain/blockjob/error/drain",
|
|
test_blockjob_error_drain);
|
|
- g_test_add_func("/bdrv-drain/blockjob/error/drain_subtree",
|
|
- test_blockjob_error_drain_subtree);
|
|
|
|
g_test_add_func("/bdrv-drain/blockjob/iothread/drain_all",
|
|
test_blockjob_iothread_drain_all);
|
|
g_test_add_func("/bdrv-drain/blockjob/iothread/drain",
|
|
test_blockjob_iothread_drain);
|
|
- g_test_add_func("/bdrv-drain/blockjob/iothread/drain_subtree",
|
|
- test_blockjob_iothread_drain_subtree);
|
|
|
|
g_test_add_func("/bdrv-drain/blockjob/iothread/error/drain_all",
|
|
test_blockjob_iothread_error_drain_all);
|
|
g_test_add_func("/bdrv-drain/blockjob/iothread/error/drain",
|
|
test_blockjob_iothread_error_drain);
|
|
- g_test_add_func("/bdrv-drain/blockjob/iothread/error/drain_subtree",
|
|
- test_blockjob_iothread_error_drain_subtree);
|
|
|
|
g_test_add_func("/bdrv-drain/deletion/drain", test_delete_by_drain);
|
|
g_test_add_func("/bdrv-drain/detach/drain_all", test_detach_by_drain_all);
|
|
g_test_add_func("/bdrv-drain/detach/drain", test_detach_by_drain);
|
|
- g_test_add_func("/bdrv-drain/detach/drain_subtree", test_detach_by_drain_subtree);
|
|
g_test_add_func("/bdrv-drain/detach/parent_cb", test_detach_by_parent_cb);
|
|
g_test_add_func("/bdrv-drain/detach/driver_cb", test_detach_by_driver_cb);
|
|
|
|
--
|
|
2.31.1
|
|
|