[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v13 05/10] qapi: create BlockdevOptionsCor structure for COR driv
From: |
Andrey Shinkevich |
Subject: |
[PATCH v13 05/10] qapi: create BlockdevOptionsCor structure for COR driver |
Date: |
Wed, 2 Dec 2020 21:30:56 +0300 |
Create the BlockdevOptionsCor structure for COR driver specific options
splitting it off form the BlockdevOptionsGenericFormat. The only option
'bottom' node in the structure denotes an image file that limits the
COR operations in the backing chain.
We are going to use the COR-filter for a block-stream job and will pass
a bottom node name to the COR driver. The bottom node is the first
non-filter overlay of the base. It was introduced because the base node
itself may change due to possible concurrent jobs.
Suggested-by: Max Reitz <mreitz@redhat.com>
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---
block/copy-on-read.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++--
qapi/block-core.json | 21 ++++++++++++++++++-
2 files changed, 75 insertions(+), 3 deletions(-)
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
index 618c4c4..2cddc96 100644
--- a/block/copy-on-read.c
+++ b/block/copy-on-read.c
@@ -24,18 +24,23 @@
#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;
} 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 +56,17 @@ 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_lookup_bs(NULL, bottom_node, errp);
+ if (!bottom_bs) {
+ error_setg(errp, "Bottom node '%s' not found", bottom_node);
+ qdict_del(options, "bottom");
+ return -EINVAL;
+ }
+ qdict_del(options, "bottom");
+ }
state->active = true;
+ state->bottom_bs = bottom_bs;
/*
* We don't need to call bdrv_child_refresh_perms() now as the permissions
@@ -107,8 +122,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 == 1 || 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;
}
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 8ef3df6..04055ef 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -3942,6 +3942,25 @@
'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).
+# For the block-stream job, it will be the first non-filter overlay of
+# the base node. We do not involve the base node into the COR
+# operations because the base may change due to a concurrent
+# block-commit job on the same backing chain.
+#
+# Since: 5.2
+##
+{ 'struct': 'BlockdevOptionsCor',
+ 'base': 'BlockdevOptionsGenericFormat',
+ 'data': { '*bottom': 'str' } }
+
##
# @BlockdevOptions:
#
@@ -3994,7 +4013,7 @@
'bochs': 'BlockdevOptionsGenericFormat',
'cloop': 'BlockdevOptionsGenericFormat',
'compress': 'BlockdevOptionsGenericFormat',
- 'copy-on-read':'BlockdevOptionsGenericFormat',
+ 'copy-on-read':'BlockdevOptionsCor',
'dmg': 'BlockdevOptionsGenericFormat',
'file': 'BlockdevOptionsFile',
'ftp': 'BlockdevOptionsCurlFtp',
--
1.8.3.1
- [PATCH v13 00/10] Apply COR-filter to the block-stream permanently, Andrey Shinkevich, 2020/12/02
- [PATCH v13 08/10] copy-on-read: skip non-guest reads if no copy needed, Andrey Shinkevich, 2020/12/02
- [PATCH v13 06/10] iotests: add #310 to test bottom node in COR driver, Andrey Shinkevich, 2020/12/02
- [PATCH v13 01/10] copy-on-read: support preadv/pwritev_part functions, Andrey Shinkevich, 2020/12/02
- [PATCH v13 07/10] block: include supported_read_flags into BDS structure, Andrey Shinkevich, 2020/12/02
- [PATCH v13 04/10] qapi: add filter-node-name to block-stream, Andrey Shinkevich, 2020/12/02
- [PATCH v13 05/10] qapi: create BlockdevOptionsCor structure for COR driver,
Andrey Shinkevich <=
- [PATCH v13 02/10] block: add API function to insert a node, Andrey Shinkevich, 2020/12/02
- [PATCH v13 03/10] copy-on-read: add filter drop function, Andrey Shinkevich, 2020/12/02
- [PATCH v13 10/10] block: apply COR-filter to block-stream jobs, Andrey Shinkevich, 2020/12/02
- [PATCH v13 09/10] stream: skip filters when writing backing file name to QCOW2 header, Andrey Shinkevich, 2020/12/02
- Re: [PATCH v13 00/10] Apply COR-filter to the block-stream permanently, Vladimir Sementsov-Ogievskiy, 2020/12/04