From: Max Reitz <mreitz@redhat.com>
To: qemu-block@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
Peter Maydell <peter.maydell@linaro.org>,
qemu-devel@nongnu.org, Max Reitz <mreitz@redhat.com>
Subject: [PULL 06/53] qapi: copy-on-read filter: add 'bottom' option
Date: Tue, 26 Jan 2021 15:19:29 +0100 [thread overview]
Message-ID: <20210126142016.806073-7-mreitz@redhat.com> (raw)
In-Reply-To: <20210126142016.806073-1-mreitz@redhat.com>
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
Add an option to limit copy-on-read operations to specified sub-chain
of backing-chain, to make copy-on-read filter useful for block-stream
job.
Suggested-by: Max Reitz <mreitz@redhat.com>
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
[vsementsov: change subject, modified to freeze the chain,
do some fixes]
Message-Id: <20201216061703.70908-6-vsementsov@virtuozzo.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
qapi/block-core.json | 20 ++++++++-
block/copy-on-read.c | 98 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 115 insertions(+), 3 deletions(-)
diff --git a/qapi/block-core.json b/qapi/block-core.json
index b55732d802..65167ebf56 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -3959,6 +3959,24 @@
'data': { 'throttle-group': 'str',
'file' : 'BlockdevRef'
} }
+
+##
+# @BlockdevOptionsCor:
+#
+# Driver specific block device options for the copy-on-read driver.
+#
+# @bottom: The name of a non-filter node (allocation-bearing layer) that
+# limits the COR operations in the backing chain (inclusive), so
+# that no data below this node will be copied by this filter.
+# If option is absent, the limit is not applied, so that data
+# from all backing layers may be copied.
+#
+# Since: 6.0
+##
+{ 'struct': 'BlockdevOptionsCor',
+ 'base': 'BlockdevOptionsGenericFormat',
+ 'data': { '*bottom': 'str' } }
+
##
# @BlockdevOptions:
#
@@ -4011,7 +4029,7 @@
'bochs': 'BlockdevOptionsGenericFormat',
'cloop': 'BlockdevOptionsGenericFormat',
'compress': 'BlockdevOptionsGenericFormat',
- 'copy-on-read':'BlockdevOptionsGenericFormat',
+ 'copy-on-read':'BlockdevOptionsCor',
'dmg': 'BlockdevOptionsGenericFormat',
'file': 'BlockdevOptionsFile',
'ftp': 'BlockdevOptionsCurlFtp',
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
index 618c4c4f43..71560984f6 100644
--- a/block/copy-on-read.c
+++ b/block/copy-on-read.c
@@ -24,18 +24,24 @@
#include "block/block_int.h"
#include "qemu/module.h"
#include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
#include "block/copy-on-read.h"
typedef struct BDRVStateCOR {
bool active;
+ BlockDriverState *bottom_bs;
+ bool chain_frozen;
} BDRVStateCOR;
static int cor_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
+ BlockDriverState *bottom_bs = NULL;
BDRVStateCOR *state = bs->opaque;
+ /* Find a bottom node name, if any */
+ const char *bottom_node = qdict_get_try_str(options, "bottom");
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
@@ -51,7 +57,38 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
bs->file->bs->supported_zero_flags);
+ if (bottom_node) {
+ bottom_bs = bdrv_find_node(bottom_node);
+ if (!bottom_bs) {
+ error_setg(errp, "Bottom node '%s' not found", bottom_node);
+ qdict_del(options, "bottom");
+ return -EINVAL;
+ }
+ qdict_del(options, "bottom");
+
+ if (!bottom_bs->drv) {
+ error_setg(errp, "Bottom node '%s' not opened", bottom_node);
+ return -EINVAL;
+ }
+
+ if (bottom_bs->drv->is_filter) {
+ error_setg(errp, "Bottom node '%s' is a filter", bottom_node);
+ return -EINVAL;
+ }
+
+ if (bdrv_freeze_backing_chain(bs, bottom_bs, errp) < 0) {
+ return -EINVAL;
+ }
+ state->chain_frozen = true;
+
+ /*
+ * We do freeze the chain, so it shouldn't be removed. Still, storing a
+ * pointer worth bdrv_ref().
+ */
+ bdrv_ref(bottom_bs);
+ }
state->active = true;
+ state->bottom_bs = bottom_bs;
/*
* We don't need to call bdrv_child_refresh_perms() now as the permissions
@@ -107,8 +144,46 @@ static int coroutine_fn cor_co_preadv_part(BlockDriverState *bs,
size_t qiov_offset,
int flags)
{
- return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
- flags | BDRV_REQ_COPY_ON_READ);
+ int64_t n;
+ int local_flags;
+ int ret;
+ BDRVStateCOR *state = bs->opaque;
+
+ if (!state->bottom_bs) {
+ return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
+ flags | BDRV_REQ_COPY_ON_READ);
+ }
+
+ while (bytes) {
+ local_flags = flags;
+
+ /* In case of failure, try to copy-on-read anyway */
+ ret = bdrv_is_allocated(bs->file->bs, offset, bytes, &n);
+ if (ret <= 0) {
+ ret = bdrv_is_allocated_above(bdrv_backing_chain_next(bs->file->bs),
+ state->bottom_bs, true, offset,
+ n, &n);
+ if (ret > 0 || ret < 0) {
+ local_flags |= BDRV_REQ_COPY_ON_READ;
+ }
+ /* Finish earlier if the end of a backing file has been reached */
+ if (n == 0) {
+ break;
+ }
+ }
+
+ ret = bdrv_co_preadv_part(bs->file, offset, n, qiov, qiov_offset,
+ local_flags);
+ if (ret < 0) {
+ return ret;
+ }
+
+ offset += n;
+ qiov_offset += n;
+ bytes -= n;
+ }
+
+ return 0;
}
@@ -160,11 +235,25 @@ static void cor_lock_medium(BlockDriverState *bs, bool locked)
}
+static void cor_close(BlockDriverState *bs)
+{
+ BDRVStateCOR *s = bs->opaque;
+
+ if (s->chain_frozen) {
+ s->chain_frozen = false;
+ bdrv_unfreeze_backing_chain(bs, s->bottom_bs);
+ }
+
+ bdrv_unref(s->bottom_bs);
+}
+
+
static BlockDriver bdrv_copy_on_read = {
.format_name = "copy-on-read",
.instance_size = sizeof(BDRVStateCOR),
.bdrv_open = cor_open,
+ .bdrv_close = cor_close,
.bdrv_child_perm = cor_child_perm,
.bdrv_getlength = cor_getlength,
@@ -201,6 +290,11 @@ void bdrv_cor_filter_drop(BlockDriverState *cor_filter_bs)
bdrv_drained_begin(bs);
/* Drop permissions before the graph change. */
s->active = false;
+ /* unfreeze, as otherwise bdrv_replace_node() will fail */
+ if (s->chain_frozen) {
+ s->chain_frozen = false;
+ bdrv_unfreeze_backing_chain(cor_filter_bs, s->bottom_bs);
+ }
bdrv_child_refresh_perms(cor_filter_bs, child, &error_abort);
bdrv_replace_node(cor_filter_bs, bs, &error_abort);
--
2.29.2
next prev parent reply other threads:[~2021-01-26 14:28 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-26 14:19 [PULL 00/53] Block patches Max Reitz
2021-01-26 14:19 ` [PULL 01/53] iotests: fix _check_o_direct Max Reitz
2021-01-26 14:19 ` [PULL 02/53] copy-on-read: support preadv/pwritev_part functions Max Reitz
2021-01-26 14:19 ` [PULL 03/53] block: add API function to insert a node Max Reitz
2021-01-26 14:19 ` [PULL 04/53] copy-on-read: add filter drop function Max Reitz
2021-01-26 14:19 ` [PULL 05/53] qapi: add filter-node-name to block-stream Max Reitz
2021-01-26 14:19 ` Max Reitz [this message]
2021-01-26 14:19 ` [PULL 07/53] iotests: add #310 to test bottom node in COR driver Max Reitz
2021-01-26 14:19 ` [PULL 08/53] block: include supported_read_flags into BDS structure Max Reitz
2021-01-26 14:19 ` [PULL 09/53] copy-on-read: skip non-guest reads if no copy needed Max Reitz
2021-01-26 14:19 ` [PULL 10/53] stream: rework backing-file changing Max Reitz
2021-01-26 14:19 ` [PULL 11/53] qapi: block-stream: add "bottom" argument Max Reitz
2021-01-26 14:19 ` [PULL 12/53] iotests: 30: prepare to COR filter insertion by stream job Max Reitz
2021-01-26 14:19 ` [PULL 13/53] block/stream: add s->target_bs Max Reitz
2021-01-26 14:19 ` [PULL 14/53] block: apply COR-filter to block-stream jobs Max Reitz
2021-01-28 18:38 ` Philippe Mathieu-Daudé
2021-01-29 5:26 ` Vladimir Sementsov-Ogievskiy
2021-01-29 8:23 ` Max Reitz
2021-01-29 9:23 ` Philippe Mathieu-Daudé
2021-01-26 14:19 ` [PULL 15/53] iotests.py: Assume a couple of variables as given Max Reitz
2021-01-26 14:19 ` [PULL 16/53] iotests/297: Rewrite in Python and extend reach Max Reitz
2021-01-26 14:19 ` [PULL 17/53] iotests: Move try_remove to iotests.py Max Reitz
2021-01-26 14:19 ` [PULL 18/53] iotests/129: Remove test images in tearDown() Max Reitz
2021-01-26 14:19 ` [PULL 19/53] iotests/129: Do not check @busy Max Reitz
2021-01-26 14:19 ` [PULL 20/53] iotests/129: Use throttle node Max Reitz
2021-01-26 14:19 ` [PULL 21/53] iotests/129: Actually test a commit job Max Reitz
2021-01-26 14:19 ` [PULL 22/53] iotests/129: Limit mirror job's buffer size Max Reitz
2021-01-26 14:19 ` [PULL 23/53] iotests/129: Clean up pylint and mypy complaints Max Reitz
2021-01-26 14:19 ` [PULL 24/53] iotests/300: " Max Reitz
2021-01-26 14:19 ` [PULL 25/53] coroutine-sigaltstack: Add SIGUSR2 mutex Max Reitz
2021-01-26 14:19 ` [PULL 26/53] qapi: backup: add perf.use-copy-range parameter Max Reitz
2021-01-26 14:19 ` [PULL 27/53] block/block-copy: More explicit call_state Max Reitz
2021-01-26 14:19 ` [PULL 28/53] block/block-copy: implement block_copy_async Max Reitz
2021-01-26 14:19 ` [PULL 29/53] block/block-copy: add max_chunk and max_workers parameters Max Reitz
2021-01-26 14:19 ` [PULL 30/53] block/block-copy: add list of all call-states Max Reitz
2021-01-26 14:19 ` [PULL 31/53] block/block-copy: add ratelimit to block-copy Max Reitz
2021-01-26 14:19 ` [PULL 32/53] block/block-copy: add block_copy_cancel Max Reitz
2021-01-26 14:19 ` [PULL 33/53] blockjob: add set_speed to BlockJobDriver Max Reitz
2021-01-26 14:19 ` [PULL 34/53] job: call job_enter from job_pause Max Reitz
2021-01-26 14:19 ` [PULL 35/53] qapi: backup: add max-chunk and max-workers to x-perf struct Max Reitz
2021-01-26 14:19 ` [PULL 36/53] iotests: 56: prepare for backup over block-copy Max Reitz
2021-01-26 14:20 ` [PULL 37/53] iotests/129: Limit backup's max-chunk/max-workers Max Reitz
2021-01-26 14:20 ` [PULL 38/53] iotests: 185: prepare for backup over block-copy Max Reitz
2021-01-26 14:20 ` [PULL 39/53] iotests: 219: " Max Reitz
2021-01-26 14:20 ` [PULL 40/53] iotests: 257: " Max Reitz
2021-01-26 14:20 ` [PULL 41/53] block/block-copy: make progress_bytes_callback optional Max Reitz
2021-01-26 14:20 ` [PULL 42/53] block/backup: drop extra gotos from backup_run() Max Reitz
2021-01-26 14:20 ` [PULL 43/53] backup: move to block-copy Max Reitz
2021-01-26 14:20 ` [PULL 44/53] qapi: backup: disable copy_range by default Max Reitz
2021-01-26 14:20 ` [PULL 45/53] block/block-copy: drop unused block_copy_set_progress_callback() Max Reitz
2021-01-26 14:20 ` [PULL 46/53] block/block-copy: drop unused argument of block_copy() Max Reitz
2021-01-26 14:20 ` [PULL 47/53] simplebench/bench_block_job: use correct shebang line with python3 Max Reitz
2021-01-26 14:20 ` [PULL 48/53] simplebench: bench_block_job: add cmd_options argument Max Reitz
2021-01-26 14:20 ` [PULL 49/53] simplebench: add bench-backup.py Max Reitz
2021-01-26 14:20 ` [PULL 50/53] block: report errno when flock fcntl fails Max Reitz
2021-01-26 14:20 ` [PULL 51/53] iotests: Add test for the regression fixed in c8bf9a9169 Max Reitz
2021-01-26 14:20 ` [PULL 52/53] iotests/118: Drop 'change' test Max Reitz
2021-01-26 14:20 ` [PULL 53/53] iotests/178: Pass value to invalid option Max Reitz
2021-01-27 17:40 ` [PULL 00/53] Block patches Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210126142016.806073-7-mreitz@redhat.com \
--to=mreitz@redhat.com \
--cc=kwolf@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).