mirror of https://gitee.com/openkylin/qemu.git
rename blockdev-group-snapshot-sync
We will add other kinds of operation. Prepare for this by adjusting the schema. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
dc8fb6df5a
commit
52e7c241ac
78
blockdev.c
78
blockdev.c
|
@ -719,31 +719,24 @@ void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file,
|
||||||
|
|
||||||
|
|
||||||
/* New and old BlockDriverState structs for group snapshots */
|
/* New and old BlockDriverState structs for group snapshots */
|
||||||
typedef struct BlkGroupSnapshotStates {
|
typedef struct BlkTransactionStates {
|
||||||
BlockDriverState *old_bs;
|
BlockDriverState *old_bs;
|
||||||
BlockDriverState *new_bs;
|
BlockDriverState *new_bs;
|
||||||
QSIMPLEQ_ENTRY(BlkGroupSnapshotStates) entry;
|
QSIMPLEQ_ENTRY(BlkTransactionStates) entry;
|
||||||
} BlkGroupSnapshotStates;
|
} BlkTransactionStates;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 'Atomic' group snapshots. The snapshots are taken as a set, and if any fail
|
* 'Atomic' group snapshots. The snapshots are taken as a set, and if any fail
|
||||||
* then we do not pivot any of the devices in the group, and abandon the
|
* then we do not pivot any of the devices in the group, and abandon the
|
||||||
* snapshots
|
* snapshots
|
||||||
*/
|
*/
|
||||||
void qmp_blockdev_group_snapshot_sync(SnapshotDevList *dev_list,
|
void qmp_transaction(BlockdevActionList *dev_list, Error **errp)
|
||||||
Error **errp)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
SnapshotDevList *dev_entry = dev_list;
|
BlockdevActionList *dev_entry = dev_list;
|
||||||
SnapshotDev *dev_info = NULL;
|
BlkTransactionStates *states, *next;
|
||||||
BlkGroupSnapshotStates *states, *next;
|
|
||||||
BlockDriver *proto_drv;
|
|
||||||
BlockDriver *drv;
|
|
||||||
int flags;
|
|
||||||
const char *format;
|
|
||||||
const char *snapshot_file;
|
|
||||||
|
|
||||||
QSIMPLEQ_HEAD(snap_bdrv_states, BlkGroupSnapshotStates) snap_bdrv_states;
|
QSIMPLEQ_HEAD(snap_bdrv_states, BlkTransactionStates) snap_bdrv_states;
|
||||||
QSIMPLEQ_INIT(&snap_bdrv_states);
|
QSIMPLEQ_INIT(&snap_bdrv_states);
|
||||||
|
|
||||||
/* drain all i/o before any snapshots */
|
/* drain all i/o before any snapshots */
|
||||||
|
@ -751,21 +744,46 @@ void qmp_blockdev_group_snapshot_sync(SnapshotDevList *dev_list,
|
||||||
|
|
||||||
/* We don't do anything in this loop that commits us to the snapshot */
|
/* We don't do anything in this loop that commits us to the snapshot */
|
||||||
while (NULL != dev_entry) {
|
while (NULL != dev_entry) {
|
||||||
|
BlockdevAction *dev_info = NULL;
|
||||||
|
BlockDriver *proto_drv;
|
||||||
|
BlockDriver *drv;
|
||||||
|
int flags;
|
||||||
|
const char *device;
|
||||||
|
const char *format = "qcow2";
|
||||||
|
const char *new_image_file = NULL;
|
||||||
|
|
||||||
dev_info = dev_entry->value;
|
dev_info = dev_entry->value;
|
||||||
dev_entry = dev_entry->next;
|
dev_entry = dev_entry->next;
|
||||||
|
|
||||||
states = g_malloc0(sizeof(BlkGroupSnapshotStates));
|
states = g_malloc0(sizeof(BlkTransactionStates));
|
||||||
QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, states, entry);
|
QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, states, entry);
|
||||||
|
|
||||||
states->old_bs = bdrv_find(dev_info->device);
|
switch (dev_info->kind) {
|
||||||
|
case BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC:
|
||||||
|
device = dev_info->blockdev_snapshot_sync->device;
|
||||||
|
if (dev_info->blockdev_snapshot_sync->has_format) {
|
||||||
|
format = dev_info->blockdev_snapshot_sync->format;
|
||||||
|
}
|
||||||
|
new_image_file = dev_info->blockdev_snapshot_sync->snapshot_file;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
drv = bdrv_find_format(format);
|
||||||
|
if (!drv) {
|
||||||
|
error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
|
||||||
|
goto delete_and_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
states->old_bs = bdrv_find(device);
|
||||||
if (!states->old_bs) {
|
if (!states->old_bs) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, dev_info->device);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||||
goto delete_and_fail;
|
goto delete_and_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_in_use(states->old_bs)) {
|
if (bdrv_in_use(states->old_bs)) {
|
||||||
error_set(errp, QERR_DEVICE_IN_USE, dev_info->device);
|
error_set(errp, QERR_DEVICE_IN_USE, device);
|
||||||
goto delete_and_fail;
|
goto delete_and_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,44 +796,30 @@ void qmp_blockdev_group_snapshot_sync(SnapshotDevList *dev_list,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshot_file = dev_info->snapshot_file;
|
|
||||||
|
|
||||||
flags = states->old_bs->open_flags;
|
flags = states->old_bs->open_flags;
|
||||||
|
|
||||||
if (!dev_info->has_format) {
|
proto_drv = bdrv_find_protocol(new_image_file);
|
||||||
format = "qcow2";
|
|
||||||
} else {
|
|
||||||
format = dev_info->format;
|
|
||||||
}
|
|
||||||
|
|
||||||
drv = bdrv_find_format(format);
|
|
||||||
if (!drv) {
|
|
||||||
error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
|
|
||||||
goto delete_and_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
proto_drv = bdrv_find_protocol(snapshot_file);
|
|
||||||
if (!proto_drv) {
|
if (!proto_drv) {
|
||||||
error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
|
error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
|
||||||
goto delete_and_fail;
|
goto delete_and_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create new image w/backing file */
|
/* create new image w/backing file */
|
||||||
ret = bdrv_img_create(snapshot_file, format,
|
ret = bdrv_img_create(new_image_file, format,
|
||||||
states->old_bs->filename,
|
states->old_bs->filename,
|
||||||
states->old_bs->drv->format_name,
|
states->old_bs->drv->format_name,
|
||||||
NULL, -1, flags);
|
NULL, -1, flags);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file);
|
error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file);
|
||||||
goto delete_and_fail;
|
goto delete_and_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We will manually add the backing_hd field to the bs later */
|
/* We will manually add the backing_hd field to the bs later */
|
||||||
states->new_bs = bdrv_new("");
|
states->new_bs = bdrv_new("");
|
||||||
ret = bdrv_open(states->new_bs, snapshot_file,
|
ret = bdrv_open(states->new_bs, new_image_file,
|
||||||
flags | BDRV_O_NO_BACKING, drv);
|
flags | BDRV_O_NO_BACKING, drv);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file);
|
error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file);
|
||||||
goto delete_and_fail;
|
goto delete_and_fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1118,7 +1118,7 @@
|
||||||
{ 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}
|
{ 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}
|
||||||
|
|
||||||
##
|
##
|
||||||
# @SnapshotDev
|
# @BlockdevSnapshot
|
||||||
#
|
#
|
||||||
# @device: the name of the device to generate the snapshot from.
|
# @device: the name of the device to generate the snapshot from.
|
||||||
#
|
#
|
||||||
|
@ -1126,19 +1126,30 @@
|
||||||
#
|
#
|
||||||
# @format: #optional the format of the snapshot image, default is 'qcow2'.
|
# @format: #optional the format of the snapshot image, default is 'qcow2'.
|
||||||
##
|
##
|
||||||
{ 'type': 'SnapshotDev',
|
{ 'type': 'BlockdevSnapshot',
|
||||||
'data': {'device': 'str', 'snapshot-file': 'str', '*format': 'str' } }
|
'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str' } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @blockdev-group-snapshot-sync
|
# @BlockdevAction
|
||||||
#
|
#
|
||||||
# Generates a synchronous snapshot of a group of one or more block devices,
|
# A discriminated record of operations that can be performed with
|
||||||
# as atomically as possible. If the snapshot of any device in the group
|
# @transaction.
|
||||||
# fails, then the entire group snapshot will be abandoned and the
|
##
|
||||||
# appropriate error returned.
|
{ 'union': 'BlockdevAction',
|
||||||
|
'data': {
|
||||||
|
'blockdev-snapshot-sync': 'BlockdevSnapshot',
|
||||||
|
} }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @transaction
|
||||||
|
#
|
||||||
|
# Atomically operate on a group of one or more block devices. If
|
||||||
|
# any operation fails, then the entire set of actions will be
|
||||||
|
# abandoned and the appropriate error returned. The only operation
|
||||||
|
# supported is currently blockdev-snapshot-sync.
|
||||||
#
|
#
|
||||||
# List of:
|
# List of:
|
||||||
# @SnapshotDev: information needed for the device snapshot
|
# @BlockdevAction: information needed for the device snapshot
|
||||||
#
|
#
|
||||||
# Returns: nothing on success
|
# Returns: nothing on success
|
||||||
# If @device is not a valid block device, DeviceNotFound
|
# If @device is not a valid block device, DeviceNotFound
|
||||||
|
@ -1147,13 +1158,14 @@
|
||||||
# If @snapshot-file can't be opened, OpenFileFailed
|
# If @snapshot-file can't be opened, OpenFileFailed
|
||||||
# If @format is invalid, InvalidBlockFormat
|
# If @format is invalid, InvalidBlockFormat
|
||||||
#
|
#
|
||||||
# Note: The group snapshot attempt returns failure on the first snapshot
|
# Note: The transaction aborts on the first failure. Therefore, there will
|
||||||
# device failure. Therefore, there will be only one device or snapshot file
|
# be only one device or snapshot file returned in an error condition, and
|
||||||
# returned in an error condition, and subsequent devices will not have been
|
# subsequent actions will not have been attempted.
|
||||||
# attempted.
|
#
|
||||||
|
# Since 1.1
|
||||||
##
|
##
|
||||||
{ 'command': 'blockdev-group-snapshot-sync',
|
{ 'command': 'transaction',
|
||||||
'data': { 'devlist': [ 'SnapshotDev' ] } }
|
'data': { 'actions': [ 'BlockdevAction' ] } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @blockdev-snapshot-sync
|
# @blockdev-snapshot-sync
|
||||||
|
|
|
@ -687,41 +687,45 @@ EQMP
|
||||||
.mhandler.cmd_new = qmp_marshal_input_block_job_cancel,
|
.mhandler.cmd_new = qmp_marshal_input_block_job_cancel,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "blockdev-group-snapshot-sync",
|
.name = "transaction",
|
||||||
.args_type = "devlist:O",
|
.args_type = "actions:O",
|
||||||
.params = "device:B,snapshot-file:s,format:s?",
|
.mhandler.cmd_new = qmp_marshal_input_transaction,
|
||||||
.mhandler.cmd_new = qmp_marshal_input_blockdev_group_snapshot_sync,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
blockdev-group-snapshot-sync
|
transaction
|
||||||
----------------------
|
-----------
|
||||||
|
|
||||||
Synchronous snapshot of one or more block devices. A list array input
|
Atomically operate on one or more block devices. The only supported
|
||||||
is accepted, that contains the device and snapshot file information for
|
operation for now is snapshotting. If there is any failure performing
|
||||||
each device in group. The default format, if not specified, is qcow2.
|
any of the operations, all snapshots for the group are abandoned, and
|
||||||
|
the original disks pre-snapshot attempt are used.
|
||||||
If there is any failure creating or opening a new snapshot, all snapshots
|
|
||||||
for the group are abandoned, and the original disks pre-snapshot attempt
|
|
||||||
are used.
|
|
||||||
|
|
||||||
|
A list of dictionaries is accepted, that contains the actions to be performed.
|
||||||
|
For snapshots this is the device, the file to use for the new snapshot,
|
||||||
|
and the format. The default format, if not specified, is qcow2.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
devlist array:
|
actions array:
|
||||||
- "device": device name to snapshot (json-string)
|
- "type": the operation to perform. The only supported
|
||||||
- "snapshot-file": name of new image file (json-string)
|
value is "blockdev-snapshot-sync". (json-string)
|
||||||
- "format": format of new image (json-string, optional)
|
- "data": a dictionary. The contents depend on the value
|
||||||
|
of "type". When "type" is "blockdev-snapshot-sync":
|
||||||
|
- "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:
|
Example:
|
||||||
|
|
||||||
-> { "execute": "blockdev-group-snapshot-sync", "arguments":
|
-> { "execute": "transaction",
|
||||||
{ "devlist": [{ "device": "ide-hd0",
|
"arguments": { "actions": [
|
||||||
"snapshot-file": "/some/place/my-image",
|
{ 'type': 'blockdev-snapshot-sync', 'data' : { "device": "ide-hd0",
|
||||||
"format": "qcow2" },
|
"snapshot-file": "/some/place/my-image",
|
||||||
{ "device": "ide-hd1",
|
"format": "qcow2" } },
|
||||||
"snapshot-file": "/some/place/my-image2",
|
{ 'type': 'blockdev-snapshot-sync', 'data' : { "device": "ide-hd1",
|
||||||
"format": "qcow2" }] } }
|
"snapshot-file": "/some/place/my-image2",
|
||||||
|
"format": "qcow2" } } ] } }
|
||||||
<- { "return": {} }
|
<- { "return": {} }
|
||||||
|
|
||||||
EQMP
|
EQMP
|
||||||
|
|
Loading…
Reference in New Issue