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:
Paolo Bonzini 2012-03-06 18:55:57 +01:00 committed by Kevin Wolf
parent dc8fb6df5a
commit 52e7c241ac
3 changed files with 96 additions and 76 deletions

View File

@ -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;
}
}

View File

@ -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

View File

@ -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