[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 13/51] stream: Replace subtree drain with a single node drain
From: |
Kevin Wolf |
Subject: |
[PULL 13/51] stream: Replace subtree drain with a single node drain |
Date: |
Wed, 14 Dec 2022 14:44:15 +0100 |
The subtree drain was introduced in commit b1e1af394d9 as a way to avoid
graph changes between finding the base node and changing the block graph
as necessary on completion of the image streaming job.
The block graph could change between these two points because
bdrv_set_backing_hd() first drains the parent node, which involved
polling and can do anything.
Subtree draining was an imperfect way to make this less likely (because
with it, fewer callbacks are called during this window). Everyone agreed
that it's not really the right solution, and it was only committed as a
stopgap solution.
This replaces the subtree drain with a solution that simply drains the
parent node before we try to find the base node, and then call a version
of bdrv_set_backing_hd() that doesn't drain, but just asserts that the
parent node is already drained.
This way, any graph changes caused by draining happen before we start
looking at the graph and things stay consistent between finding the base
node and changing the graph.
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-10-kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
include/block/block-global-state.h | 3 +++
block.c | 17 ++++++++++++++---
block/stream.c | 26 ++++++++++++++++----------
3 files changed, 33 insertions(+), 13 deletions(-)
diff --git a/include/block/block-global-state.h
b/include/block/block-global-state.h
index c7bd4a2088..00e0cf8aea 100644
--- a/include/block/block-global-state.h
+++ b/include/block/block-global-state.h
@@ -82,6 +82,9 @@ int bdrv_open_file_child(const char *filename,
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
Error **errp);
+int bdrv_set_backing_hd_drained(BlockDriverState *bs,
+ BlockDriverState *backing_hd,
+ Error **errp);
int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
const char *bdref_key, Error **errp);
BlockDriverState *bdrv_open(const char *filename, const char *reference,
diff --git a/block.c b/block.c
index db043346d8..97bfb1494f 100644
--- a/block.c
+++ b/block.c
@@ -3426,14 +3426,15 @@ static int bdrv_set_backing_noperm(BlockDriverState *bs,
return bdrv_set_file_or_backing_noperm(bs, backing_hd, true, tran, errp);
}
-int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
- Error **errp)
+int bdrv_set_backing_hd_drained(BlockDriverState *bs,
+ BlockDriverState *backing_hd,
+ Error **errp)
{
int ret;
Transaction *tran = tran_new();
GLOBAL_STATE_CODE();
- bdrv_drained_begin(bs);
+ assert(bs->quiesce_counter > 0);
ret = bdrv_set_backing_noperm(bs, backing_hd, tran, errp);
if (ret < 0) {
@@ -3443,7 +3444,17 @@ int bdrv_set_backing_hd(BlockDriverState *bs,
BlockDriverState *backing_hd,
ret = bdrv_refresh_perms(bs, tran, errp);
out:
tran_finalize(tran, ret);
+ return ret;
+}
+int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
+ Error **errp)
+{
+ int ret;
+ GLOBAL_STATE_CODE();
+
+ bdrv_drained_begin(bs);
+ ret = bdrv_set_backing_hd_drained(bs, backing_hd, errp);
bdrv_drained_end(bs);
return ret;
diff --git a/block/stream.c b/block/stream.c
index 694709bd25..8744ad103f 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -64,13 +64,16 @@ static int stream_prepare(Job *job)
bdrv_cor_filter_drop(s->cor_filter_bs);
s->cor_filter_bs = NULL;
- bdrv_subtree_drained_begin(s->above_base);
+ /*
+ * bdrv_set_backing_hd() requires that unfiltered_bs is drained. Drain
+ * already here and use bdrv_set_backing_hd_drained() instead because
+ * the polling during drained_begin() might change the graph, and if we do
+ * this only later, we may end up working with the wrong base node (or it
+ * might even have gone away by the time we want to use it).
+ */
+ bdrv_drained_begin(unfiltered_bs);
base = bdrv_filter_or_cow_bs(s->above_base);
- if (base) {
- bdrv_ref(base);
- }
-
unfiltered_base = bdrv_skip_filters(base);
if (bdrv_cow_child(unfiltered_bs)) {
@@ -82,7 +85,13 @@ static int stream_prepare(Job *job)
}
}
- bdrv_set_backing_hd(unfiltered_bs, base, &local_err);
+ bdrv_set_backing_hd_drained(unfiltered_bs, base, &local_err);
+
+ /*
+ * This call will do I/O, so the graph can change again from here on.
+ * We have already completed the graph change, so we are not in danger
+ * of operating on the wrong node any more if this happens.
+ */
ret = bdrv_change_backing_file(unfiltered_bs, base_id, base_fmt,
false);
if (local_err) {
error_report_err(local_err);
@@ -92,10 +101,7 @@ static int stream_prepare(Job *job)
}
out:
- if (base) {
- bdrv_unref(base);
- }
- bdrv_subtree_drained_end(s->above_base);
+ bdrv_drained_end(unfiltered_bs);
return ret;
}
--
2.38.1
- [PULL 06/51] test-bdrv-drain: Don't yield in .bdrv_co_drained_begin/end(), (continued)
- [PULL 06/51] test-bdrv-drain: Don't yield in .bdrv_co_drained_begin/end(), Kevin Wolf, 2022/12/14
- [PULL 11/51] block: Drain individual nodes during reopen, Kevin Wolf, 2022/12/14
- [PULL 14/51] block: Remove subtree drains, Kevin Wolf, 2022/12/14
- [PULL 26/51] block: distinguish between bdrv_create running in coroutine and not, Kevin Wolf, 2022/12/14
- [PULL 09/51] block: Inline bdrv_drain_invoke(), Kevin Wolf, 2022/12/14
- [PULL 12/51] block: Don't use subtree drains in bdrv_drop_intermediate(), Kevin Wolf, 2022/12/14
- [PULL 23/51] block-backend: replace bdrv_*_above with blk_*_above, Kevin Wolf, 2022/12/14
- [PULL 15/51] block: Call drain callbacks only once, Kevin Wolf, 2022/12/14
- [PULL 19/51] block: Remove poll parameter from bdrv_parent_drained_begin_single(), Kevin Wolf, 2022/12/14
- [PULL 17/51] block: Drop out of coroutine in bdrv_do_drained_begin_quiesce(), Kevin Wolf, 2022/12/14
- [PULL 13/51] stream: Replace subtree drain with a single node drain,
Kevin Wolf <=
- [PULL 18/51] block: Don't poll in bdrv_replace_child_noperm(), Kevin Wolf, 2022/12/14
- [PULL 30/51] block-coroutine-wrapper.py: support functions without bs arg, Kevin Wolf, 2022/12/14
- [PULL 21/51] block-copy: add coroutine_fn annotations, Kevin Wolf, 2022/12/14
- [PULL 20/51] block-io: introduce coroutine_fn duplicates for bdrv_common_block_status_above callers, Kevin Wolf, 2022/12/14
- [PULL 22/51] nbd/server.c: add coroutine_fn annotations, Kevin Wolf, 2022/12/14
- [PULL 31/51] block-coroutine-wrapper.py: support also basic return types, Kevin Wolf, 2022/12/14
- [PULL 36/51] graph-lock: Implement guard macros, Kevin Wolf, 2022/12/14
- [PULL 25/51] block: avoid duplicating filename string in bdrv_create, Kevin Wolf, 2022/12/14
- [PULL 29/51] block-coroutine-wrapper.py: introduce co_wrapper, Kevin Wolf, 2022/12/14
- [PULL 27/51] block: bdrv_create_file is a coroutine_fn, Kevin Wolf, 2022/12/14