[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/3] block: Add QMP support for streaming to an inte
From: |
Alberto Garcia |
Subject: |
[Qemu-devel] [PATCH 2/3] block: Add QMP support for streaming to an intermediate layer |
Date: |
Fri, 20 Feb 2015 15:53:18 +0200 |
This adds the 'top' parameter to the 'block-stream' QMP command and
checks that its value is valid before passing it to stream_start().
Signed-off-by: Alberto Garcia <address@hidden>
---
blockdev.c | 19 +++++++++++++++----
hmp.c | 2 +-
include/qapi/qmp/qerror.h | 3 +++
qapi/block-core.json | 18 ++++++++++++++----
qmp-commands.hx | 2 +-
5 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/blockdev.c b/blockdev.c
index 06628ca..2404f89 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2099,6 +2099,7 @@ static void block_job_cb(void *opaque, int ret)
void qmp_block_stream(const char *device,
bool has_base, const char *base,
+ bool has_top, const char *top,
bool has_backing_file, const char *backing_file,
bool has_speed, int64_t speed,
bool has_on_error, BlockdevOnError on_error,
@@ -2106,6 +2107,7 @@ void qmp_block_stream(const char *device,
{
BlockDriverState *bs;
BlockDriverState *base_bs = NULL;
+ BlockDriverState *top_bs;
AioContext *aio_context;
Error *local_err = NULL;
const char *base_name = NULL;
@@ -2114,7 +2116,7 @@ void qmp_block_stream(const char *device,
on_error = BLOCKDEV_ON_ERROR_REPORT;
}
- bs = bdrv_find(device);
+ top_bs = bs = bdrv_find(device);
if (!bs) {
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
return;
@@ -2123,12 +2125,21 @@ void qmp_block_stream(const char *device,
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
- if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_STREAM, errp)) {
+ if (has_top) {
+ top_bs = bdrv_find_backing_image(bs, top);
+ if (top_bs == NULL) {
+ error_set(errp, QERR_TOP_NOT_FOUND, top);
+ goto out;
+ }
+ assert(bdrv_get_aio_context(top_bs) == aio_context);
+ }
+
+ if (bdrv_op_is_blocked(top_bs, BLOCK_OP_TYPE_STREAM, errp)) {
goto out;
}
if (has_base) {
- base_bs = bdrv_find_backing_image(bs, base);
+ base_bs = bdrv_find_backing_image(top_bs, base);
if (base_bs == NULL) {
error_set(errp, QERR_BASE_NOT_FOUND, base);
goto out;
@@ -2148,7 +2159,7 @@ void qmp_block_stream(const char *device,
/* backing_file string overrides base bs filename */
base_name = has_backing_file ? backing_file : base_name;
- stream_start(bs, NULL, base_bs, base_name, has_speed ? speed : 0,
+ stream_start(bs, top_bs, base_bs, base_name, has_speed ? speed : 0,
on_error, block_job_cb, bs, &local_err);
if (local_err) {
error_propagate(errp, local_err);
diff --git a/hmp.c b/hmp.c
index b47f331..28f7adb 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1239,7 +1239,7 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict)
const char *base = qdict_get_try_str(qdict, "base");
int64_t speed = qdict_get_try_int(qdict, "speed", 0);
- qmp_block_stream(device, base != NULL, base, false, NULL,
+ qmp_block_stream(device, base != NULL, base, false, NULL, false, NULL,
qdict_haskey(qdict, "speed"), speed,
true, BLOCKDEV_ON_ERROR_REPORT, &error);
diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h
index 986260f..d075f78 100644
--- a/include/qapi/qmp/qerror.h
+++ b/include/qapi/qmp/qerror.h
@@ -127,6 +127,9 @@ void qerror_report_err(Error *err);
#define QERR_SET_PASSWD_FAILED \
ERROR_CLASS_GENERIC_ERROR, "Could not set password"
+#define QERR_TOP_NOT_FOUND \
+ ERROR_CLASS_GENERIC_ERROR, "Top '%s' not found"
+
#define QERR_UNDEFINED_ERROR \
ERROR_CLASS_GENERIC_ERROR, "An undefined error has occurred"
diff --git a/qapi/block-core.json b/qapi/block-core.json
index a3fdaf0..3073be6 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1013,6 +1013,9 @@
# with query-block-jobs. The operation can be stopped before it has completed
# using the block-job-cancel command.
#
+# Data is copied to the top image, which defaults to the active layer if no
other
+# file is selected.
+#
# If a base file is specified then sectors are not copied from that base file
and
# its backing chain. When streaming completes the image file will have the
base
# file as its backing file. This can be used to stream a subset of the backing
@@ -1025,8 +1028,14 @@
#
# @base: #optional the common backing file name
#
-# @backing-file: #optional The backing file string to write into the active
-# layer. This filename is not validated.
+# @top: #optional Top image, only sectors below this image are streamed
+# into it.
+#
+# If not specified, the top image is the active layer.
+# (Since 2.3)
+#
+# @backing-file: #optional The backing file string to write into the top
+# image. This filename is not validated.
#
# If a pathname string is such that it cannot be
# resolved by QEMU, that means that subsequent QMP or
@@ -1052,8 +1061,9 @@
# Since: 1.1
##
{ 'command': 'block-stream',
- 'data': { 'device': 'str', '*base': 'str', '*backing-file': 'str',
- '*speed': 'int', '*on-error': 'BlockdevOnError' } }
+ 'data': { 'device': 'str', '*base': 'str', '*top': 'str',
+ '*backing-file': 'str', '*speed': 'int',
+ '*on-error': 'BlockdevOnError' } }
##
# @block-job-set-speed:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index a85d847..a02f19f 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -978,7 +978,7 @@ EQMP
{
.name = "block-stream",
- .args_type = "device:B,base:s?,speed:o?,backing-file:s?,on-error:s?",
+ .args_type =
"device:B,base:s?,top:s?,speed:o?,backing-file:s?,on-error:s?",
.mhandler.cmd_new = qmp_marshal_input_block_stream,
},
--
2.1.4
Re: [Qemu-devel] [PATCH 0/3] Support streaming to an intermediate layer, Eric Blake, 2015/02/20