From 0bb1bc275a5df69855e26aefb1bdde1d97d55ed1 Mon Sep 17 00:00:00 2001 From: Federico Simoncelli Date: Fri, 23 Mar 2012 12:12:58 -0300 Subject: [RHEL6 qemu-kvm PATCH 5/5] Add the drive-reopen command RH-Author: Federico Simoncelli Message-id: <1332504778-17403-14-git-send-email-fsimonce@redhat.com> Patchwork-id: 38953 O-Subject: [RHEL6.3 qemu-kvm PATCH v6 13/13] Add the drive-reopen command Bugzilla: 647384 RH-Acked-by: Kevin Wolf RH-Acked-by: Jeffrey Cody RH-Acked-by: Luiz Capitulino Signed-off-by: Federico Simoncelli Signed-off-by: Paolo Bonzini BZ: 647384 Based on an patch posted upstream: http://lists.gnu.org/archive/html/qemu-devel/2012-03/msg00900.html Deviations from upstream: - drive-reopen commands renamed with a downstream prefix --- blockdev.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ hmp.c | 11 +++++++++ hmp.h | 1 + qapi-schema.json | 22 ++++++++++++++++++ qemu-monitor.hx | 33 +++++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 0 deletions(-) Signed-off-by: Eduardo Habkost --- blockdev.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ hmp.c | 11 +++++++++ hmp.h | 1 + qapi-schema.json | 22 ++++++++++++++++++ qemu-monitor.hx | 33 +++++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 0 deletions(-) diff --git a/blockdev.c b/blockdev.c index b96d846..9b97069 100644 --- a/blockdev.c +++ b/blockdev.c @@ -631,6 +631,71 @@ void do_commit(Monitor *mon, const QDict *qdict) } #ifdef CONFIG_LIVE_SNAPSHOTS +void qmp___com_redhat_drive_reopen(const char *device, const char *new_image_file, + bool has_format, const char *format, Error **errp) +{ + BlockDriverState *bs; + BlockDriver *drv, *old_drv, *proto_drv; + int ret = 0; + int flags; + char old_filename[1024]; + + bs = bdrv_find(device); + if (!bs) { + error_set(errp, QERR_DEVICE_NOT_FOUND, device); + return; + } + if (bdrv_in_use(bs)) { + error_set(errp, QERR_DEVICE_IN_USE, device); + return; + } + + pstrcpy(old_filename, sizeof(old_filename), bs->filename); + + old_drv = bs->drv; + flags = bs->open_flags; + + if (has_format) { + drv = bdrv_find_format(format); + if (!drv) { + error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); + return; + } + } else { + drv = NULL; + } + + proto_drv = bdrv_find_protocol(new_image_file); + if (!proto_drv) { + error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); + return; + } + + qemu_aio_flush(); + if (!bdrv_is_read_only(bs) && bdrv_is_inserted(bs)) { + if (bdrv_flush(bs)) { + error_set(errp, QERR_IO_ERROR); + return; + } + } + + bdrv_close(bs); + ret = bdrv_open(bs, new_image_file, flags, drv); + /* + * If reopening the image file we just created fails, fall back + * and try to re-open the original image. If that fails too, we + * are in serious trouble. + */ + if (ret != 0) { + ret = bdrv_open(bs, old_filename, flags, old_drv); + if (ret != 0) { + error_set(errp, QERR_OPEN_FILE_FAILED, old_filename); + } else { + error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file); + } + } +} + static void blockdev_do_action(int kind, void *data, Error **errp) { BlockdevAction action; diff --git a/hmp.c b/hmp.c index 812e364..a500123 100644 --- a/hmp.c +++ b/hmp.c @@ -73,4 +73,15 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict) true, mode, &errp); hmp_handle_error(mon, &errp); } + +void hmp_drive_reopen(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *filename = qdict_get_str(qdict, "new-image-file"); + const char *format = qdict_get_try_str(qdict, "format"); + Error *errp = NULL; + + qmp___com_redhat_drive_reopen(device, filename, !!format, format, &errp); + hmp_handle_error(mon, &errp); +} #endif diff --git a/hmp.h b/hmp.h index 7c4cae4..9751498 100644 --- a/hmp.h +++ b/hmp.h @@ -21,6 +21,7 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict); void hmp_drive_mirror(Monitor *mon, const QDict *qdict); +void hmp_drive_reopen(Monitor *mon, const QDict *qdict); #endif #endif diff --git a/qapi-schema.json b/qapi-schema.json index 0a50b0d..9c9700e 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -121,6 +121,28 @@ '*mode': 'NewImageMode'} } ## +# @__com.redhat_drive-reopen +# +# Assigns a new image file to a device. +# +# @device: the name of the device for which we are changing the image file. +# +# @new-image-file: the target of the new image. If the file doesn't exists the +# command will fail. +# +# @format: #optional the format of the new image, default is 'qcow2'. +# +# Returns: nothing on success +# If @device is not a valid block device, DeviceNotFound +# If @new-image-file can't be opened, OpenFileFailed +# If @format is invalid, InvalidBlockFormat +# +# Since 1.1 +## +{ 'command': '__com.redhat_drive-reopen', + 'data': { 'device': 'str', 'new-image-file': 'str', '*format': 'str' } } + +## # @__com.redhat_drive-mirror # # Start mirroring a block device's writes to a new destination. diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 4c5b9c3..0770b7c 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -1624,6 +1624,39 @@ Example: EQMP +#ifdef CONFIG_LIVE_SNAPSHOTS + { + .name = "__com.redhat_drive-reopen", + .args_type = "device:B,new-image-file:s,format:s?", + .user_print = monitor_user_noop, + .mhandler.cmd_new = qmp_marshal_input___com_redhat_drive_reopen, + }, +#endif + +SQMP +__com.redhat_drive-reopen +------------------------- + +Assigns a new image file to a device. Except extremely rare cases where the +guest is expecting the drive to change its content, the new image should +contain the same data of the current one. One use case is to terminate +a __com.redhat-drive-mirror command. + +Arguments: + +- "device": device name to operate on (json-string) +- "new-image-file": name of new image file (json-string) +- "format": format of new image (json-string, optional) + +Example: + +-> { "execute": "__com.redhat_drive-reopen", "arguments": {"device": "ide-hd0", + "new-image-file": "/some/place/my-image", + "format": "qcow2" } } +<- { "return": {} } + +EQMP + { .name = "balloon", .args_type = "value:M", -- 1.7.3.2