From 636180695ffe06b948b599fcb6788061cd9cc383 Mon Sep 17 00:00:00 2001 From: Jeffrey Cody Date: Tue, 10 Jan 2012 14:39:00 +0100 Subject: [PATCH 6/7] Revert "QMP/HMP: Drop the live snapshot commands" RH-Author: Jeffrey Cody Message-id: <1326206340.13202.16.camel@jefflaptop> Patchwork-id: 36324 O-Subject: [RHEL6.3 qemu-kvm PATCH v2 1/2] Revert "QMP/HMP: Drop the live snapshot commands" Bugzilla: 752003 RH-Acked-by: Luiz Capitulino RH-Acked-by: Alex Williamson RH-Acked-by: Kevin Wolf RH-Acked-by: Paolo Bonzini This reverts downstream rhel6 commit 1ff41c0, which removed the do_snapshot_blkdev command from blockdev.c and qemu-monitor.hx. This is moving us closer to upstream; there are two differences: 1) In blockdev.c, qemu_aio_flush() is still used instead of bdrv_drain_all(), because bdrv_drain_all() was not introduced upstream until commit 922453b (which converted qemu_aio_flush() calls to bdrv_drain_all() calls) 2) The QMP & HMP commands are in qemu-monitor.hx, instead of broken out into qmp-commands.hx and hmp-commmands.hx BZ 769111 Signed-off-by: Jeff Cody --- blockdev.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-monitor.hx | 53 +++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 0 deletions(-) Signed-off-by: Michal Novotny --- blockdev.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-monitor.hx | 53 +++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 0 deletions(-) diff --git a/blockdev.c b/blockdev.c index d07bf67..067bbee 100644 --- a/blockdev.c +++ b/blockdev.c @@ -832,6 +832,85 @@ void do_commit(Monitor *mon, const QDict *qdict) } } +int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *filename = qdict_get_try_str(qdict, "snapshot-file"); + const char *format = qdict_get_try_str(qdict, "format"); + BlockDriverState *bs; + BlockDriver *drv, *old_drv, *proto_drv; + int ret = 0; + int flags; + char old_filename[1024]; + + if (!filename) { + qerror_report(QERR_MISSING_PARAMETER, "snapshot-file"); + ret = -1; + goto out; + } + + bs = bdrv_find(device); + if (!bs) { + qerror_report(QERR_DEVICE_NOT_FOUND, device); + ret = -1; + goto out; + } + + pstrcpy(old_filename, sizeof(old_filename), bs->filename); + + old_drv = bs->drv; + flags = bs->open_flags; + + if (!format) { + format = "qcow2"; + } + + drv = bdrv_find_format(format); + if (!drv) { + qerror_report(QERR_INVALID_BLOCK_FORMAT, format); + ret = -1; + goto out; + } + + proto_drv = bdrv_find_protocol(filename); + if (!proto_drv) { + qerror_report(QERR_INVALID_BLOCK_FORMAT, format); + ret = -1; + goto out; + } + + ret = bdrv_img_create(filename, format, bs->filename, + bs->drv->format_name, NULL, -1, flags); + if (ret) { + goto out; + } + + qemu_aio_flush(); + bdrv_flush(bs); + + bdrv_close(bs); + ret = bdrv_open(bs, filename, 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) { + qerror_report(QERR_OPEN_FILE_FAILED, old_filename); + } else { + qerror_report(QERR_OPEN_FILE_FAILED, filename); + } + } +out: + if (ret) { + ret = -1; + } + + return ret; +} + static void monitor_print_block_stream(Monitor *mon, const QObject *data) { QDict *stream; diff --git a/qemu-monitor.hx b/qemu-monitor.hx index b771797..149c3a0 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -1385,6 +1385,25 @@ Example: EQMP { + .name = "snapshot_blkdev", + .args_type = "device:B,snapshot-file:s?,format:s?", + .params = "device [new-image-file] [format]", + .help = "initiates a live snapshot\n\t\t\t" + "of device. If a new image file is specified, the\n\t\t\t" + "new image file will become the new root image.\n\t\t\t" + "If format is specified, the snapshot file will\n\t\t\t" + "be created in that format. Otherwise the\n\t\t\t" + "snapshot will be internal! (currently unsupported)", + .mhandler.cmd_new = do_snapshot_blkdev, + }, + +STEXI +@item snapshot_blkdev +@findex snapshot_blkdev +Snapshot device, using snapshot file as target if provided +ETEXI + + { .name = "block_resize", .args_type = "device:B,size:o", .params = "device size", @@ -1603,6 +1622,40 @@ Remove host-to-guest TCP or UDP redirection. ETEXI { + .name = "blockdev-snapshot-sync", + .args_type = "device:B,snapshot-file:s?,format:s?", + .params = "device [new-image-file] [format]", + .user_print = monitor_user_noop, + .mhandler.cmd_new = do_snapshot_blkdev, + }, + +SQMP +blockdev-snapshot-sync +---------------------- + +Synchronous snapshot of a block device. snapshot-file specifies the +target of the new image. If the file exists, or if it is a device, the +snapshot will be created in the existing file/device. If does not +exist, a new file will be created. format specifies the format of the +snapshot image, default is qcow2. + +Arguments: + +- "device": device name to snapshot (json-string) +- "snapshot-file": name of new image file (json-string) +- "format": format of new image (json-string, optional) + +Example: + +-> { "execute": "blockdev-snapshot", "arguments": { "device": "ide-hd0", + "snapshot-file": + "/some/place/my-image", + "format": "qcow2" } } +<- { "return": {} } + +EQMP + + { .name = "balloon", .args_type = "value:M", .params = "target", -- 1.7.7.5