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 */
|
||||
typedef struct BlkGroupSnapshotStates {
|
||||
typedef struct BlkTransactionStates {
|
||||
BlockDriverState *old_bs;
|
||||
BlockDriverState *new_bs;
|
||||
QSIMPLEQ_ENTRY(BlkGroupSnapshotStates) entry;
|
||||
} BlkGroupSnapshotStates;
|
||||
QSIMPLEQ_ENTRY(BlkTransactionStates) entry;
|
||||
} BlkTransactionStates;
|
||||
|
||||
/*
|
||||
* '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
|
||||
* snapshots
|
||||
*/
|
||||
void qmp_blockdev_group_snapshot_sync(SnapshotDevList *dev_list,
|
||||
Error **errp)
|
||||
void qmp_transaction(BlockdevActionList *dev_list, Error **errp)
|
||||
{
|
||||
int ret = 0;
|
||||
SnapshotDevList *dev_entry = dev_list;
|
||||
SnapshotDev *dev_info = NULL;
|
||||
BlkGroupSnapshotStates *states, *next;
|
||||
BlockDriver *proto_drv;
|
||||
BlockDriver *drv;
|
||||
int flags;
|
||||
const char *format;
|
||||
const char *snapshot_file;
|
||||
BlockdevActionList *dev_entry = dev_list;
|
||||
BlkTransactionStates *states, *next;
|
||||
|
||||
QSIMPLEQ_HEAD(snap_bdrv_states, BlkGroupSnapshotStates) snap_bdrv_states;
|
||||
QSIMPLEQ_HEAD(snap_bdrv_states, BlkTransactionStates) snap_bdrv_states;
|
||||
QSIMPLEQ_INIT(&snap_bdrv_states);
|
||||
|
||||
/* 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 */
|
||||
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_entry = dev_entry->next;
|
||||
|
||||
states = g_malloc0(sizeof(BlkGroupSnapshotStates));
|
||||
states = g_malloc0(sizeof(BlkTransactionStates));
|
||||
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) {
|
||||
error_set(errp, QERR_DEVICE_NOT_FOUND, dev_info->device);
|
||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||
goto delete_and_fail;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
if (!dev_info->has_format) {
|
||||
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);
|
||||
proto_drv = bdrv_find_protocol(new_image_file);
|
||||
if (!proto_drv) {
|
||||
error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
|
||||
goto delete_and_fail;
|
||||
}
|
||||
|
||||
/* 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->drv->format_name,
|
||||
NULL, -1, flags);
|
||||
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;
|
||||
}
|
||||
|
||||
/* We will manually add the backing_hd field to the bs later */
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1118,7 +1118,7 @@
|
||||
{ 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}
|
||||
|
||||
##
|
||||
# @SnapshotDev
|
||||
# @BlockdevSnapshot
|
||||
#
|
||||
# @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'.
|
||||
##
|
||||
{ 'type': 'SnapshotDev',
|
||||
'data': {'device': 'str', 'snapshot-file': 'str', '*format': 'str' } }
|
||||
{ 'type': 'BlockdevSnapshot',
|
||||
'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,
|
||||
# as atomically as possible. If the snapshot of any device in the group
|
||||
# fails, then the entire group snapshot will be abandoned and the
|
||||
# appropriate error returned.
|
||||
# A discriminated record of operations that can be performed with
|
||||
# @transaction.
|
||||
##
|
||||
{ '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:
|
||||
# @SnapshotDev: information needed for the device snapshot
|
||||
# @BlockdevAction: information needed for the device snapshot
|
||||
#
|
||||
# Returns: nothing on success
|
||||
# If @device is not a valid block device, DeviceNotFound
|
||||
@ -1147,13 +1158,14 @@
|
||||
# If @snapshot-file can't be opened, OpenFileFailed
|
||||
# If @format is invalid, InvalidBlockFormat
|
||||
#
|
||||
# Note: The group snapshot attempt returns failure on the first snapshot
|
||||
# device failure. Therefore, there will be only one device or snapshot file
|
||||
# returned in an error condition, and subsequent devices will not have been
|
||||
# attempted.
|
||||
# Note: The transaction aborts on the first failure. Therefore, there will
|
||||
# be only one device or snapshot file returned in an error condition, and
|
||||
# subsequent actions will not have been attempted.
|
||||
#
|
||||
# Since 1.1
|
||||
##
|
||||
{ 'command': 'blockdev-group-snapshot-sync',
|
||||
'data': { 'devlist': [ 'SnapshotDev' ] } }
|
||||
{ 'command': 'transaction',
|
||||
'data': { 'actions': [ 'BlockdevAction' ] } }
|
||||
|
||||
##
|
||||
# @blockdev-snapshot-sync
|
||||
|
@ -687,41 +687,45 @@ EQMP
|
||||
.mhandler.cmd_new = qmp_marshal_input_block_job_cancel,
|
||||
},
|
||||
{
|
||||
.name = "blockdev-group-snapshot-sync",
|
||||
.args_type = "devlist:O",
|
||||
.params = "device:B,snapshot-file:s,format:s?",
|
||||
.mhandler.cmd_new = qmp_marshal_input_blockdev_group_snapshot_sync,
|
||||
.name = "transaction",
|
||||
.args_type = "actions:O",
|
||||
.mhandler.cmd_new = qmp_marshal_input_transaction,
|
||||
},
|
||||
|
||||
SQMP
|
||||
blockdev-group-snapshot-sync
|
||||
----------------------
|
||||
transaction
|
||||
-----------
|
||||
|
||||
Synchronous snapshot of one or more block devices. A list array input
|
||||
is accepted, that contains the device and snapshot file information for
|
||||
each device in group. The default format, if not specified, is qcow2.
|
||||
|
||||
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.
|
||||
Atomically operate on one or more block devices. The only supported
|
||||
operation for now is snapshotting. If there is any failure performing
|
||||
any of the operations, 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:
|
||||
|
||||
devlist array:
|
||||
- "device": device name to snapshot (json-string)
|
||||
- "snapshot-file": name of new image file (json-string)
|
||||
- "format": format of new image (json-string, optional)
|
||||
actions array:
|
||||
- "type": the operation to perform. The only supported
|
||||
value is "blockdev-snapshot-sync". (json-string)
|
||||
- "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:
|
||||
|
||||
-> { "execute": "blockdev-group-snapshot-sync", "arguments":
|
||||
{ "devlist": [{ "device": "ide-hd0",
|
||||
"snapshot-file": "/some/place/my-image",
|
||||
"format": "qcow2" },
|
||||
{ "device": "ide-hd1",
|
||||
"snapshot-file": "/some/place/my-image2",
|
||||
"format": "qcow2" }] } }
|
||||
-> { "execute": "transaction",
|
||||
"arguments": { "actions": [
|
||||
{ 'type': 'blockdev-snapshot-sync', 'data' : { "device": "ide-hd0",
|
||||
"snapshot-file": "/some/place/my-image",
|
||||
"format": "qcow2" } },
|
||||
{ 'type': 'blockdev-snapshot-sync', 'data' : { "device": "ide-hd1",
|
||||
"snapshot-file": "/some/place/my-image2",
|
||||
"format": "qcow2" } } ] } }
|
||||
<- { "return": {} }
|
||||
|
||||
EQMP
|
||||
|
Loading…
Reference in New Issue
Block a user