* [Qemu-devel] [PATCH] qmp: add 'drive' to enum NewImageMode
@ 2013-06-17 6:44 Fam Zheng
2013-06-18 11:33 ` Stefan Hajnoczi
0 siblings, 1 reply; 2+ messages in thread
From: Fam Zheng @ 2013-06-17 6:44 UTC (permalink / raw)
To: qemu-devel; +Cc: Kevin Wolf, famz, Ian Main, stefanha, Paolo Bonzini, dietmar
Introduce a "drive" option to new image mode. With this mode, QMP command
should (this patch only modified drive-backup to support it, and report invalid
parameter error for drive-mirror) skip creating the image file or trying to
open it, it should just reuse the existing BDS by looking for the named drive
with bdrv_find(). It will be useful to utilize "none" sync mode of drive-backup
for point-in-time snapshot.
The example with drive-backup is:
-> { "execute": "drive-backup", "arguments": { "device": "ide0-hd0",
"mode": "drive",
"target": "drive_id_here" } }
<- { "return": {} }
Target bs is not released when block job completes in this case since it's
still used as a device drive or exported by nbd server.
Signed-off-by: Fam Zheng <famz@redhat.com>
---
block/backup.c | 9 ++++++--
blockdev.c | 57 ++++++++++++++++++++++++++++++++---------------
include/block/block_int.h | 3 ++-
qapi-schema.json | 4 +++-
4 files changed, 51 insertions(+), 22 deletions(-)
diff --git a/block/backup.c b/block/backup.c
index 6515e04..5ef4724 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -45,6 +45,7 @@ typedef struct CowRequest {
typedef struct BackupBlockJob {
BlockJob common;
BlockDriverState *target;
+ bool release_target;
RateLimit limit;
CoRwlock flush_rwlock;
uint64_t sectors_read;
@@ -255,14 +256,17 @@ static void coroutine_fn backup_run(void *opaque)
hbitmap_free(job->bitmap);
- bdrv_delete(job->target);
+ if (job->release_target) {
+ bdrv_close(job->target);
+ bdrv_delete(job->target);
+ }
DPRINTF("backup_run complete %d\n", ret);
block_job_completed(&job->common, ret);
}
void backup_start(BlockDriverState *bs, BlockDriverState *target,
- int64_t speed,
+ int64_t speed, bool release_target,
BlockDriverCompletionFunc *cb, void *opaque,
Error **errp)
{
@@ -279,6 +283,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
}
job->target = target;
+ job->release_target = release_target;
job->common.len = bdrv_getlength(bs);
job->common.co = qemu_coroutine_create(backup_run);
qemu_coroutine_enter(job->common.co, job);
diff --git a/blockdev.c b/blockdev.c
index 692803f..1d0c4dc 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -908,6 +908,11 @@ static void external_snapshot_prepare(BlkTransactionState *common,
flags = state->old_bs->open_flags;
+ if (mode == NEW_IMAGE_MODE_DRIVE) {
+ error_set(errp, QERR_INVALID_PARAMETER, "mode");
+ return;
+ }
+
/* create new image w/backing file */
if (mode != NEW_IMAGE_MODE_EXISTING) {
bdrv_img_create(new_image_file, format,
@@ -1505,28 +1510,39 @@ void qmp_drive_backup(const char *device, const char *target,
return;
}
- if (mode != NEW_IMAGE_MODE_EXISTING) {
- assert(format && drv);
- bdrv_img_create(target, format,
- NULL, NULL, NULL, size, flags, &local_err, false);
- }
-
- if (error_is_set(&local_err)) {
- error_propagate(errp, local_err);
- return;
- }
+ if (mode == NEW_IMAGE_MODE_DRIVE) {
+ target_bs = bdrv_find(target);
+ if (!target_bs) {
+ error_set(errp, QERR_DEVICE_NOT_FOUND, target);
+ return;
+ }
+ } else {
+ if (mode != NEW_IMAGE_MODE_EXISTING) {
+ assert(format && drv);
+ bdrv_img_create(target, format,
+ NULL, NULL, NULL, size, flags, &local_err, false);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
- target_bs = bdrv_new("");
- ret = bdrv_open(target_bs, target, NULL, flags, drv);
- if (ret < 0) {
- bdrv_delete(target_bs);
- error_set(errp, QERR_OPEN_FILE_FAILED, target);
- return;
+ target_bs = bdrv_new("");
+ ret = bdrv_open(target_bs, target, NULL, flags, drv);
+ if (ret < 0) {
+ bdrv_delete(target_bs);
+ error_set(errp, QERR_OPEN_FILE_FAILED, target);
+ return;
+ }
}
- backup_start(bs, target_bs, speed, block_job_cb, bs, &local_err);
+ backup_start(bs, target_bs, speed,
+ mode != NEW_IMAGE_MODE_DRIVE,
+ block_job_cb, bs, &local_err);
if (local_err != NULL) {
- bdrv_delete(target_bs);
+ if (mode != NEW_IMAGE_MODE_DRIVE) {
+ bdrv_delete(target_bs);
+ }
error_propagate(errp, local_err);
return;
}
@@ -1577,6 +1593,11 @@ void qmp_drive_mirror(const char *device, const char *target,
buf_size = DEFAULT_MIRROR_BUF_SIZE;
}
+ if (mode == NEW_IMAGE_MODE_DRIVE) {
+ error_set(errp, QERR_INVALID_PARAMETER, "mode");
+ return;
+ }
+
if (granularity != 0 && (granularity < 512 || granularity > 1048576 * 64)) {
error_set(errp, QERR_INVALID_PARAMETER, device);
return;
diff --git a/include/block/block_int.h b/include/block/block_int.h
index f7a7892..e1fde9e 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -403,6 +403,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
* @bs: Block device to operate on.
* @target: Block device to write to.
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
+ * @release_target: If block job should release target bs before completion
* @cb: Completion function for the job.
* @opaque: Opaque pointer value passed to @cb.
*
@@ -410,7 +411,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
* until the job is cancelled or manually completed.
*/
void backup_start(BlockDriverState *bs, BlockDriverState *target,
- int64_t speed,
+ int64_t speed, bool release_target,
BlockDriverCompletionFunc *cb, void *opaque,
Error **errp);
diff --git a/qapi-schema.json b/qapi-schema.json
index 134a92d..9391e39 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1593,10 +1593,12 @@
# @absolute-paths: QEMU should create a new image with absolute paths
# for the backing file.
#
+# @drive: QEMU should look for an existing drive
+#
# Since: 1.1
##
{ 'enum': 'NewImageMode'
- 'data': [ 'existing', 'absolute-paths' ] }
+ 'data': [ 'existing', 'absolute-paths', 'drive' ] }
##
# @BlockdevSnapshot
--
1.8.3.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [Qemu-devel] [PATCH] qmp: add 'drive' to enum NewImageMode
2013-06-17 6:44 [Qemu-devel] [PATCH] qmp: add 'drive' to enum NewImageMode Fam Zheng
@ 2013-06-18 11:33 ` Stefan Hajnoczi
0 siblings, 0 replies; 2+ messages in thread
From: Stefan Hajnoczi @ 2013-06-18 11:33 UTC (permalink / raw)
To: Fam Zheng; +Cc: Kevin Wolf, qemu-devel, Ian Main, Paolo Bonzini, dietmar
On Mon, Jun 17, 2013 at 02:44:46PM +0800, Fam Zheng wrote:
> Introduce a "drive" option to new image mode. With this mode, QMP command
> should (this patch only modified drive-backup to support it, and report invalid
> parameter error for drive-mirror) skip creating the image file or trying to
> open it, it should just reuse the existing BDS by looking for the named drive
> with bdrv_find(). It will be useful to utilize "none" sync mode of drive-backup
> for point-in-time snapshot.
>
> The example with drive-backup is:
>
> -> { "execute": "drive-backup", "arguments": { "device": "ide0-hd0",
> "mode": "drive",
> "target": "drive_id_here" } }
> <- { "return": {} }
>
>
> Target bs is not released when block job completes in this case since it's
> still used as a device drive or exported by nbd server.
>
> Signed-off-by: Fam Zheng <famz@redhat.com>
> ---
> block/backup.c | 9 ++++++--
> blockdev.c | 57 ++++++++++++++++++++++++++++++++---------------
> include/block/block_int.h | 3 ++-
> qapi-schema.json | 4 +++-
> 4 files changed, 51 insertions(+), 22 deletions(-)
Fam and I chatted about this yesterday. The QMP API change here is that
traditionally 'target' and 'mode' always referred to existing filenames.
Now you can set 'mode': 'drive' and then 'target' becomes a QEMU block
device name.
I think this API extension is reasonable but I think we haven't nailed
down the lifecycle of the snapshot block drive yet...
Stefan
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2013-06-18 11:33 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-17 6:44 [Qemu-devel] [PATCH] qmp: add 'drive' to enum NewImageMode Fam Zheng
2013-06-18 11:33 ` Stefan Hajnoczi
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).