[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v15 10/13] qapi: block-stream: add "bottom" argument
From: |
Vladimir Sementsov-Ogievskiy |
Subject: |
[PATCH v15 10/13] qapi: block-stream: add "bottom" argument |
Date: |
Wed, 16 Dec 2020 09:17:00 +0300 |
The code already don't freeze base node and we try to make it prepared
for the situation when base node is changed during the operation. In
other words, block-stream doesn't own base node.
Let's introduce a new interface which should replace the current one,
which will in better relations with the code. Specifying bottom node
instead of base, and requiring it to be non-filter gives us the
following benefits:
- drop difference between above_base and base_overlay, which will be
renamed to just bottom, when old interface dropped
- clean way to work with parallel streams/commits on the same backing
chain, which otherwise become a problem when we introduce a filter
for stream job
- cleaner interface. Nobody will surprised the fact that base node may
disappear during block-stream, when there is no word about "base" in
the interface.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---
qapi/block-core.json | 12 ++++---
include/block/block_int.h | 1 +
block/monitor/block-hmp-cmds.c | 3 +-
block/stream.c | 50 +++++++++++++++++++---------
blockdev.c | 59 ++++++++++++++++++++++++++++------
5 files changed, 94 insertions(+), 31 deletions(-)
diff --git a/qapi/block-core.json b/qapi/block-core.json
index b8094a5ec7..cb0066fd5c 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2517,10 +2517,14 @@
# @device: the device or node name of the top image
#
# @base: the common backing file name.
-# It cannot be set if @base-node is also set.
+# It cannot be set if @base-node or @bottom is also set.
#
# @base-node: the node name of the backing file.
-# It cannot be set if @base is also set. (Since 2.8)
+# It cannot be set if @base or @bottom is also set. (Since 2.8)
+#
+# @bottom: the last node in the chain that should be streamed into
+# top. It cannot be set if @base or @base-node is also set.
+# It cannot be filter node. (Since 6.0)
#
# @backing-file: The backing file string to write into the top
# image. This filename is not validated.
@@ -2576,8 +2580,8 @@
##
{ 'command': 'block-stream',
'data': { '*job-id': 'str', 'device': 'str', '*base': 'str',
- '*base-node': 'str', '*backing-file': 'str', '*speed': 'int',
- '*on-error': 'BlockdevOnError',
+ '*base-node': 'str', '*backing-file': 'str', '*bottom': 'str',
+ '*speed': 'int', '*on-error': 'BlockdevOnError',
'*filter-node-name': 'str',
'*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 1f56443440..4b8aa61fb4 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -1160,6 +1160,7 @@ int is_windows_drive(const char *filename);
*/
void stream_start(const char *job_id, BlockDriverState *bs,
BlockDriverState *base, const char *backing_file_str,
+ BlockDriverState *bottom,
int creation_flags, int64_t speed,
BlockdevOnError on_error,
const char *filter_node_name,
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index e8a58f326e..afd75ab628 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -507,7 +507,8 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict)
int64_t speed = qdict_get_try_int(qdict, "speed", 0);
qmp_block_stream(true, device, device, base != NULL, base, false, NULL,
- false, NULL, qdict_haskey(qdict, "speed"), speed, true,
+ false, NULL, false, NULL,
+ qdict_haskey(qdict, "speed"), speed, true,
BLOCKDEV_ON_ERROR_REPORT, false, NULL, false, false,
false,
false, &error);
diff --git a/block/stream.c b/block/stream.c
index 6a525a5edf..045d6bc76b 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -221,6 +221,7 @@ static const BlockJobDriver stream_job_driver = {
void stream_start(const char *job_id, BlockDriverState *bs,
BlockDriverState *base, const char *backing_file_str,
+ BlockDriverState *bottom,
int creation_flags, int64_t speed,
BlockdevOnError on_error,
const char *filter_node_name,
@@ -230,25 +231,42 @@ void stream_start(const char *job_id, BlockDriverState
*bs,
BlockDriverState *iter;
bool bs_read_only;
int basic_flags = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED;
- BlockDriverState *base_overlay = bdrv_find_overlay(bs, base);
+ BlockDriverState *base_overlay;
BlockDriverState *above_base;
- if (!base_overlay) {
- error_setg(errp, "'%s' is not in the backing chain of '%s'",
- base->node_name, bs->node_name);
- return;
- }
+ assert(!(base && bottom));
+ assert(!(backing_file_str && bottom));
+
+ if (bottom) {
+ /*
+ * New simple interface. The code is written in terms of old interface
+ * with @base parameter (still, it doesn't freeze link to base, so in
+ * this mean old code is correct for new interface). So, for now, just
+ * emulate base_overlay and above_base. Still, when old interface
+ * finally removed, we should refactor code to use only "bottom", but
+ * not "*base*" things.
+ */
+ assert(!bottom->drv->is_filter);
+ base_overlay = above_base = bottom;
+ } else {
+ base_overlay = bdrv_find_overlay(bs, base);
+ if (!base_overlay) {
+ error_setg(errp, "'%s' is not in the backing chain of '%s'",
+ base->node_name, bs->node_name);
+ return;
+ }
- /*
- * Find the node directly above @base. @base_overlay is a COW overlay, so
- * it must have a bdrv_cow_child(), but it is the immediate overlay of
- * @base, so between the two there can only be filters.
- */
- above_base = base_overlay;
- if (bdrv_cow_bs(above_base) != base) {
- above_base = bdrv_cow_bs(above_base);
- while (bdrv_filter_bs(above_base) != base) {
- above_base = bdrv_filter_bs(above_base);
+ /*
+ * Find the node directly above @base. @base_overlay is a COW overlay,
+ * so it must have a bdrv_cow_child(), but it is the immediate overlay
+ * of @base, so between the two there can only be filters.
+ */
+ above_base = base_overlay;
+ if (bdrv_cow_bs(above_base) != base) {
+ above_base = bdrv_cow_bs(above_base);
+ while (bdrv_filter_bs(above_base) != base) {
+ above_base = bdrv_filter_bs(above_base);
+ }
}
}
diff --git a/blockdev.c b/blockdev.c
index b58f36fc31..18699d3cda 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2499,6 +2499,7 @@ void qmp_block_stream(bool has_job_id, const char
*job_id, const char *device,
bool has_base, const char *base,
bool has_base_node, const char *base_node,
bool has_backing_file, const char *backing_file,
+ bool has_bottom, const char *bottom,
bool has_speed, int64_t speed,
bool has_on_error, BlockdevOnError on_error,
bool has_filter_node_name, const char *filter_node_name,
@@ -2506,12 +2507,31 @@ void qmp_block_stream(bool has_job_id, const char
*job_id, const char *device,
bool has_auto_dismiss, bool auto_dismiss,
Error **errp)
{
- BlockDriverState *bs, *iter;
+ BlockDriverState *bs, *iter, *iter_end;
BlockDriverState *base_bs = NULL;
+ BlockDriverState *bottom_bs = NULL;
AioContext *aio_context;
Error *local_err = NULL;
int job_flags = JOB_DEFAULT;
+ if (has_base && has_base_node) {
+ error_setg(errp, "'base' and 'base-node' cannot be specified "
+ "at the same time");
+ return;
+ }
+
+ if (has_base && has_bottom) {
+ error_setg(errp, "'base' and 'bottom' cannot be specified "
+ "at the same time");
+ return;
+ }
+
+ if (has_bottom && has_base_node) {
+ error_setg(errp, "'bottom' and 'base-node' cannot be specified "
+ "at the same time");
+ return;
+ }
+
if (!has_on_error) {
on_error = BLOCKDEV_ON_ERROR_REPORT;
}
@@ -2524,12 +2544,6 @@ void qmp_block_stream(bool has_job_id, const char
*job_id, const char *device,
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
- if (has_base && has_base_node) {
- error_setg(errp, "'base' and 'base-node' cannot be specified "
- "at the same time");
- goto out;
- }
-
if (has_base) {
base_bs = bdrv_find_backing_image(bs, base);
if (base_bs == NULL) {
@@ -2553,8 +2567,33 @@ void qmp_block_stream(bool has_job_id, const char
*job_id, const char *device,
bdrv_refresh_filename(base_bs);
}
- /* Check for op blockers in the whole chain between bs and base */
- for (iter = bs; iter && iter != base_bs;
+ if (has_bottom) {
+ bottom_bs = bdrv_lookup_bs(NULL, bottom, errp);
+ if (!bottom_bs) {
+ goto out;
+ }
+ if (!bottom_bs->drv) {
+ error_setg(errp, "Node '%s' is not open", bottom);
+ goto out;
+ }
+ if (bottom_bs->drv->is_filter) {
+ error_setg(errp, "Node '%s' is a filter, use a non-filter node "
+ "as 'bottom'", bottom);
+ goto out;
+ }
+ if (!bdrv_chain_contains(bs, bottom_bs)) {
+ error_setg(errp, "Node '%s' is not in a chain starting from '%s'",
+ bottom, device);
+ goto out;
+ }
+ assert(bdrv_get_aio_context(bottom_bs) == aio_context);
+ }
+
+ /*
+ * Check for op blockers in the whole chain between bs and base (or bottom)
+ */
+ iter_end = has_bottom ? bdrv_filter_or_cow_bs(bottom_bs) : base_bs;
+ for (iter = bs; iter && iter != iter_end;
iter = bdrv_filter_or_cow_bs(iter))
{
if (bdrv_op_is_blocked(iter, BLOCK_OP_TYPE_STREAM, errp)) {
@@ -2578,7 +2617,7 @@ void qmp_block_stream(bool has_job_id, const char
*job_id, const char *device,
}
stream_start(has_job_id ? job_id : NULL, bs, base_bs, backing_file,
- job_flags, has_speed ? speed : 0, on_error,
+ bottom_bs, job_flags, has_speed ? speed : 0, on_error,
filter_node_name, &local_err);
if (local_err) {
error_propagate(errp, local_err);
--
2.25.4
- [PATCH v15 01/13] copy-on-read: support preadv/pwritev_part functions, (continued)
- [PATCH v15 01/13] copy-on-read: support preadv/pwritev_part functions, Vladimir Sementsov-Ogievskiy, 2020/12/16
- [PATCH v15 04/13] qapi: add filter-node-name to block-stream, Vladimir Sementsov-Ogievskiy, 2020/12/16
- [PATCH v15 03/13] copy-on-read: add filter drop function, Vladimir Sementsov-Ogievskiy, 2020/12/16
- [PATCH v15 05/13] qapi: copy-on-read filter: add 'bottom' option, Vladimir Sementsov-Ogievskiy, 2020/12/16
- [PATCH v15 06/13] iotests: add #310 to test bottom node in COR driver, Vladimir Sementsov-Ogievskiy, 2020/12/16
- [PATCH v15 08/13] copy-on-read: skip non-guest reads if no copy needed, Vladimir Sementsov-Ogievskiy, 2020/12/16
- [PATCH v15 09/13] stream: rework backing-file changing, Vladimir Sementsov-Ogievskiy, 2020/12/16
- [PATCH v15 10/13] qapi: block-stream: add "bottom" argument,
Vladimir Sementsov-Ogievskiy <=
- [PATCH v15 11/13] iotests: 30: prepare to COR filter insertion by stream job, Vladimir Sementsov-Ogievskiy, 2020/12/16
- [PATCH v15 07/13] block: include supported_read_flags into BDS structure, Vladimir Sementsov-Ogievskiy, 2020/12/16
- [PATCH v15 12/13] block/stream: add s->target_bs, Vladimir Sementsov-Ogievskiy, 2020/12/16
- [PATCH v15 13/13] block: apply COR-filter to block-stream jobs, Vladimir Sementsov-Ogievskiy, 2020/12/16