From 0b07947750205e5329b4805072834a86df1b72ed Mon Sep 17 00:00:00 2001 From: Federico Simoncelli Date: Fri, 23 Mar 2012 12:12:47 -0300 Subject: [RHEL6 qemu-kvm PATCH 2/9] qapi: Convert blockdev_snapshot_sync RH-Author: Federico Simoncelli Message-id: <1332504778-17403-3-git-send-email-fsimonce@redhat.com> Patchwork-id: 38951 O-Subject: [RHEL6.3 qemu-kvm PATCH v6 02/13] qapi: Convert blockdev_snapshot_sync Bugzilla: 802284 RH-Acked-by: Jeffrey Cody RH-Acked-by: Kevin Wolf RH-Acked-by: Laszlo Ersek From: Luiz Capitulino Unfortunately, this conversion required an additional change. In the old QMP command, the 'snapshot-file' argument is specified as optional. The idea is to take the snapshot internally if 'snapshot-file' is not passed. However, internal snapshots are not supported yet so the command returns a MissingParamater error if 'snapshot-file' is not passed. Which makes the argument actually required and will cause compatibility breakage if we change that in the future. To fix this the QAPI converted blockdev_snapshot_sync command makes the 'snapshot-file' argument required. Again, in practice it's actually required, so this is not incompatible. If we do implement internal snapshots someday, we'll need a new argument for it. Note that this discussion doesn't affect HMP. Signed-off-by: Luiz Capitulino BZ: 802284 (cherry picked from 6106e2492fe0080ad85d4862dec9c3bebc57b2f0) RHEL6 notes: hmp.c and hmp.h were added taking bits from 48a32be (qapi: convert query-name) and 0cfd6a9 (qapi: Convert memsave). Both patches had several dependencies and it wasn't possible to backport them completely. Signed-off-by: Federico Simoncelli --- Makefile.objs | 1 + blockdev.c | 54 +++++++++++++++++++----------------------------------- hmp.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ hmp.h | 25 +++++++++++++++++++++++++ monitor.c | 1 + qapi-schema.json | 29 +++++++++++++++++++++++++++++ qemu-monitor.hx | 6 +++--- 7 files changed, 122 insertions(+), 38 deletions(-) create mode 100644 hmp.c create mode 100644 hmp.h Signed-off-by: Eduardo Habkost --- Makefile.objs | 1 + blockdev.c | 54 +++++++++++++++++++----------------------------------- hmp.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ hmp.h | 25 +++++++++++++++++++++++++ monitor.c | 1 + qapi-schema.json | 29 +++++++++++++++++++++++++++++ qemu-monitor.hx | 6 +++--- 7 files changed, 122 insertions(+), 38 deletions(-) create mode 100644 hmp.c create mode 100644 hmp.h diff --git a/Makefile.objs b/Makefile.objs index d21d747..4d35939 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -204,6 +204,7 @@ endif qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y)) common-obj-y += $(qapi-obj-y) $(qapi-generated-y) +common-obj-y += hmp.o ###################################################################### # guest agent diff --git a/blockdev.c b/blockdev.c index 12ef6f5..130c23e 100644 --- a/blockdev.c +++ b/blockdev.c @@ -631,33 +631,24 @@ void do_commit(Monitor *mon, const QDict *qdict) } #ifdef CONFIG_LIVE_SNAPSHOTS -int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data) +void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file, + bool has_format, const char *format, + Error **errp) { - 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; + error_set(errp, QERR_DEVICE_NOT_FOUND, device); + return; } if (bdrv_in_use(bs)) { - qerror_report(QERR_DEVICE_IN_USE, device); - ret = -1; - goto out; + error_set(errp, QERR_DEVICE_IN_USE, device); + return; } pstrcpy(old_filename, sizeof(old_filename), bs->filename); @@ -665,35 +656,34 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data) old_drv = bs->drv; flags = bs->open_flags; - if (!format) { + if (!has_format) { format = "qcow2"; } drv = bdrv_find_format(format); if (!drv) { - qerror_report(QERR_INVALID_BLOCK_FORMAT, format); - ret = -1; - goto out; + error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); + return; } - proto_drv = bdrv_find_protocol(filename); + proto_drv = bdrv_find_protocol(snapshot_file); if (!proto_drv) { - qerror_report(QERR_INVALID_BLOCK_FORMAT, format); - ret = -1; - goto out; + error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); + return; } - ret = bdrv_img_create(filename, format, bs->filename, + ret = bdrv_img_create(snapshot_file, format, bs->filename, bs->drv->format_name, NULL, -1, flags); if (ret) { - goto out; + error_set(errp, QERR_UNDEFINED_ERROR); + return; } bdrv_drain_all(); bdrv_flush(bs); bdrv_close(bs); - ret = bdrv_open(bs, filename, flags, drv); + ret = bdrv_open(bs, snapshot_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 @@ -702,17 +692,11 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data) if (ret != 0) { ret = bdrv_open(bs, old_filename, flags, old_drv); if (ret != 0) { - qerror_report(QERR_OPEN_FILE_FAILED, old_filename); + error_set(errp, QERR_OPEN_FILE_FAILED, old_filename); } else { - qerror_report(QERR_OPEN_FILE_FAILED, filename); + error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file); } } -out: - if (ret) { - ret = -1; - } - - return ret; } #endif diff --git a/hmp.c b/hmp.c new file mode 100644 index 0000000..dccd5ff --- /dev/null +++ b/hmp.c @@ -0,0 +1,44 @@ +/* + * Human Monitor Interface + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include "hmp.h" +#include "qmp-commands.h" + +#ifdef CONFIG_LIVE_SNAPSHOTS +static void hmp_handle_error(Monitor *mon, Error **errp) +{ + if (error_is_set(errp)) { + monitor_printf(mon, "%s\n", error_get_pretty(*errp)); + error_free(*errp); + } +} + +void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict) +{ + 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"); + Error *errp = NULL; + + if (!filename) { + /* In the future, if 'snapshot-file' is not specified, the snapshot + will be taken internally. Today it's actually required. */ + error_set(&errp, QERR_MISSING_PARAMETER, "snapshot-file"); + hmp_handle_error(mon, &errp); + return; + } + + qmp_blockdev_snapshot_sync(device, filename, !!format, format, &errp); + hmp_handle_error(mon, &errp); +} +#endif diff --git a/hmp.h b/hmp.h new file mode 100644 index 0000000..3f5643b --- /dev/null +++ b/hmp.h @@ -0,0 +1,25 @@ +/* + * Human Monitor Interface + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#ifndef HMP_H +#define HMP_H + +#include "qemu-common.h" + +#ifdef CONFIG_LIVE_SNAPSHOTS +#include "rhev-qapi-types.h" + +void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict); +#endif + +#endif diff --git a/monitor.c b/monitor.c index e73dce7..f81698c 100644 --- a/monitor.c +++ b/monitor.c @@ -63,6 +63,7 @@ #include "qemu-kvm.h" #include "ui/qemu-spice.h" #include "qmp-commands.h" +#include "hmp.h" //#define DEBUG //#define DEBUG_COMPLETION diff --git a/qapi-schema.json b/qapi-schema.json index 5fb482a..59edf0e 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -40,4 +40,33 @@ ## { 'command': 'blockdev-group-snapshot-sync', 'data': { 'devlist': [ 'SnapshotDev' ] } } + +## +# @blockdev-snapshot-sync +# +# Generates a synchronous snapshot of a block device. +# +# @device: the name of the device to generate the snapshot from. +# +# @snapshot-file: 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: #optional the format of the snapshot image, default is 'qcow2'. +# +# Returns: nothing on success +# If @device is not a valid block device, DeviceNotFound +# If @snapshot-file can't be opened, OpenFileFailed +# If @format is invalid, InvalidBlockFormat +# +# Notes: One of the last steps taken by this command is to close the current +# image being used by @device and open the @snapshot-file one. If that +# fails, the command will try to reopen the original image file. If +# that also fails OpenFileFailed will be returned and the guest may get +# unexpected errors. +# +# Since 0.14.0 +## +{ 'command': 'blockdev-snapshot-sync', + 'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str' } } #endif diff --git a/qemu-monitor.hx b/qemu-monitor.hx index fa9f552..ac032ec 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -1253,7 +1253,7 @@ EQMP "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, + .mhandler.cmd = hmp_snapshot_blkdev, }, #endif @@ -1527,10 +1527,10 @@ EQMP #ifdef CONFIG_LIVE_SNAPSHOTS { .name = "blockdev-snapshot-sync", - .args_type = "device:B,snapshot-file:s?,format:s?", + .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, + .mhandler.cmd_new = qmp_marshal_input_blockdev_snapshot_sync, }, #endif -- 1.7.3.2