From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
To: qemu-block@nongnu.org
Cc: fam@euphon.net, kwolf@redhat.com, vsementsov@virtuozzo.com,
qemu-devel@nongnu.org, armbru@redhat.com, stefanha@redhat.com,
den@openvz.org, andrey.shinkevich@virtuozzo.com,
mreitz@redhat.com, jsnow@redhat.com
Subject: [PATCH v15 05/13] qapi: copy-on-read filter: add 'bottom' option
Date: Wed, 16 Dec 2020 09:16:55 +0300 [thread overview]
Message-ID: <20201216061703.70908-6-vsementsov@virtuozzo.com> (raw)
In-Reply-To: <20201216061703.70908-1-vsementsov@virtuozzo.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]
---
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 6050cf3c39..b8094a5ec7 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -3942,6 +3942,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:
#
@@ -3994,7 +4012,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.25.4
next prev parent reply other threads:[~2020-12-16 6:22 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-16 6:16 [PATCH v15 00/13] Apply COR-filter to the block-stream permanently Vladimir Sementsov-Ogievskiy
2020-12-16 6:16 ` [PATCH v15 01/13] copy-on-read: support preadv/pwritev_part functions Vladimir Sementsov-Ogievskiy
2020-12-16 6:16 ` [PATCH v15 02/13] block: add API function to insert a node Vladimir Sementsov-Ogievskiy
2020-12-16 6:16 ` [PATCH v15 03/13] copy-on-read: add filter drop function Vladimir Sementsov-Ogievskiy
2020-12-16 6:16 ` [PATCH v15 04/13] qapi: add filter-node-name to block-stream Vladimir Sementsov-Ogievskiy
2020-12-22 15:24 ` Max Reitz
2020-12-16 6:16 ` Vladimir Sementsov-Ogievskiy [this message]
2020-12-16 6:16 ` [PATCH v15 06/13] iotests: add #310 to test bottom node in COR driver Vladimir Sementsov-Ogievskiy
2020-12-16 6:16 ` [PATCH v15 07/13] block: include supported_read_flags into BDS structure Vladimir Sementsov-Ogievskiy
2020-12-16 6:16 ` [PATCH v15 08/13] copy-on-read: skip non-guest reads if no copy needed Vladimir Sementsov-Ogievskiy
2020-12-16 6:16 ` [PATCH v15 09/13] stream: rework backing-file changing Vladimir Sementsov-Ogievskiy
2020-12-22 15:59 ` Max Reitz
2020-12-22 17:53 ` Vladimir Sementsov-Ogievskiy
2021-01-05 12:51 ` Max Reitz
2020-12-16 6:17 ` [PATCH v15 10/13] qapi: block-stream: add "bottom" argument Vladimir Sementsov-Ogievskiy
2020-12-22 16:07 ` Max Reitz
2020-12-22 18:00 ` Vladimir Sementsov-Ogievskiy
2020-12-22 18:11 ` Vladimir Sementsov-Ogievskiy
2021-01-05 12:51 ` Max Reitz
2020-12-16 6:17 ` [PATCH v15 11/13] iotests: 30: prepare to COR filter insertion by stream job Vladimir Sementsov-Ogievskiy
2020-12-16 6:17 ` [PATCH v15 12/13] block/stream: add s->target_bs Vladimir Sementsov-Ogievskiy
2020-12-16 6:17 ` [PATCH v15 13/13] block: apply COR-filter to block-stream jobs Vladimir Sementsov-Ogievskiy
2020-12-22 16:20 ` Max Reitz
2020-12-22 18:07 ` Vladimir Sementsov-Ogievskiy
2021-01-05 12:52 ` Max Reitz
2021-01-05 15:30 ` Max Reitz
2021-01-05 16:08 ` [PATCH v15 00/13] Apply COR-filter to the block-stream permanently Max Reitz
2021-01-08 10:24 ` Vladimir Sementsov-Ogievskiy
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=20201216061703.70908-6-vsementsov@virtuozzo.com \
--to=vsementsov@virtuozzo.com \
--cc=andrey.shinkevich@virtuozzo.com \
--cc=armbru@redhat.com \
--cc=den@openvz.org \
--cc=fam@euphon.net \
--cc=jsnow@redhat.com \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/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).