提交 6cc2a415 编写于 作者: P Paolo Bonzini 提交者: Kevin Wolf

qmp: convert blockdev-snapshot-sync to a wrapper around transactions

Simplify the blockdev-snapshot-sync code and gain failsafe operation
by turning it into a wrapper around the new transaction command.  A new
option is also added matching "mode".
Signed-off-by: NPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: NKevin Wolf <kwolf@redhat.com>
上级 bc8b094f
......@@ -649,72 +649,33 @@ void do_commit(Monitor *mon, const QDict *qdict)
}
}
static void blockdev_do_action(int kind, void *data, Error **errp)
{
BlockdevAction action;
BlockdevActionList list;
action.kind = kind;
action.data = data;
list.value = &action;
list.next = NULL;
qmp_transaction(&list, errp);
}
void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file,
bool has_format, const char *format,
bool has_mode, enum NewImageMode mode,
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) {
format = "qcow2";
}
drv = bdrv_find_format(format);
if (!drv) {
error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
return;
}
proto_drv = bdrv_find_protocol(snapshot_file);
if (!proto_drv) {
error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
return;
}
ret = bdrv_img_create(snapshot_file, format, bs->filename,
bs->drv->format_name, NULL, -1, flags);
if (ret) {
error_set(errp, QERR_UNDEFINED_ERROR);
return;
}
bdrv_drain_all();
bdrv_flush(bs);
bdrv_close(bs);
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
* 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, snapshot_file);
}
}
BlockdevSnapshot snapshot = {
.device = (char *) device,
.snapshot_file = (char *) snapshot_file,
.has_format = has_format,
.format = (char *) format,
.has_mode = has_mode,
.mode = mode,
};
blockdev_do_action(BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC, &snapshot,
errp);
}
......
......@@ -882,14 +882,17 @@ ETEXI
{
.name = "snapshot_blkdev",
.args_type = "device:B,snapshot-file:s?,format:s?",
.params = "device [new-image-file] [format]",
.args_type = "reuse:-n,device:B,snapshot-file:s?,format:s?",
.params = "[-n] 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)",
"snapshot will be internal! (currently unsupported).\n\t\t\t"
"The default format is qcow2. The -n flag requests QEMU\n\t\t\t"
"to reuse the image found in new-image-file, instead of\n\t\t\t"
"recreating it from scratch.",
.mhandler.cmd = hmp_snapshot_blkdev,
},
......
......@@ -692,6 +692,8 @@ 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");
int reuse = qdict_get_try_bool(qdict, "reuse", 0);
enum NewImageMode mode;
Error *errp = NULL;
if (!filename) {
......@@ -702,7 +704,9 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
return;
}
qmp_blockdev_snapshot_sync(device, filename, !!format, format, &errp);
mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
qmp_blockdev_snapshot_sync(device, filename, !!format, format,
true, mode, &errp);
hmp_handle_error(mon, &errp);
}
......
......@@ -1141,6 +1141,9 @@
# @snapshot-file: the target of the new image. A new file will be created.
#
# @format: #optional the format of the snapshot image, default is 'qcow2'.
#
# @mode: #optional whether and how QEMU should create a new image, default is
# 'absolute-paths'.
##
{ 'type': 'BlockdevSnapshot',
'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str',
......@@ -1197,21 +1200,19 @@
#
# @format: #optional the format of the snapshot image, default is 'qcow2'.
#
# @mode: #optional whether and how QEMU should create a new image, default is
# 'absolute-paths'.
#
# 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' } }
'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str',
'*mode': 'NewImageMode'} }
##
# @human-monitor-command:
......
......@@ -760,6 +760,8 @@ Arguments:
- "device": device name to snapshot (json-string)
- "snapshot-file": name of new image file (json-string)
- "mode": whether and how QEMU should create the snapshot file
(NewImageMode, optional, default "absolute-paths")
- "format": format of new image (json-string, optional)
Example:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册