Signed-off-by: Benoit Canet <ben...@irqsave.net> --- blockdev.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- hmp.c | 4 +++- qapi-schema.json | 13 ++++++++++--- qmp-commands.hx | 11 ++++++++++- 4 files changed, 64 insertions(+), 13 deletions(-)
diff --git a/blockdev.c b/blockdev.c index e314d62..68d4ad1 100644 --- a/blockdev.c +++ b/blockdev.c @@ -940,14 +940,22 @@ static void blockdev_do_action(int kind, void *data, Error **errp) 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) +void qmp_blockdev_snapshot_sync(bool has_device, const char * device, + bool has_node_name, const char * node_name, + const char * snapshot_file, + bool has_snapshot_node_name, + const char * snapshot_node_name, + bool has_format, const char * format, + bool has_mode, NewImageMode mode, Error **errp) { BlockdevSnapshot snapshot = { + .has_device = has_device, .device = (char *) device, + .has_node_name = has_node_name, + .node_name = (char *) node_name, .snapshot_file = (char *) snapshot_file, + .has_snapshot_node_name = has_snapshot_node_name, + .snapshot_node_name = (char *) snapshot_node_name, .has_format = has_format, .format = (char *) format, .has_mode = has_mode, @@ -1186,7 +1194,12 @@ static void external_snapshot_prepare(BlkTransactionState *common, BlockDriver *drv; int flags, ret; Error *local_err = NULL; + bool has_device = false; const char *device; + bool has_node_name = false; + const char *node_name; + bool has_snapshot_node_name = false; + const char *snapshot_node_name; const char *new_image_file; const char *format = "qcow2"; enum NewImageMode mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; @@ -1197,7 +1210,14 @@ static void external_snapshot_prepare(BlkTransactionState *common, /* get parameters */ g_assert(action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC); + has_device = action->blockdev_snapshot_sync->has_device; device = action->blockdev_snapshot_sync->device; + has_node_name = action->blockdev_snapshot_sync->has_node_name; + node_name = action->blockdev_snapshot_sync->node_name; + has_snapshot_node_name = + action->blockdev_snapshot_sync->has_snapshot_node_name; + snapshot_node_name = action->blockdev_snapshot_sync->snapshot_node_name; + new_image_file = action->blockdev_snapshot_sync->snapshot_file; if (action->blockdev_snapshot_sync->has_format) { format = action->blockdev_snapshot_sync->format; @@ -1213,9 +1233,21 @@ static void external_snapshot_prepare(BlkTransactionState *common, return; } - state->old_bs = bdrv_find(device); - if (!state->old_bs) { - error_set(errp, QERR_DEVICE_NOT_FOUND, device); + state->old_bs = bdrv_lookup_bs(has_device, device, + has_node_name, node_name, + &local_err); + if (error_is_set(&local_err)) { + error_propagate(errp, local_err); + return; + } + + if (has_node_name && !has_snapshot_node_name) { + error_setg(errp, "New snapshot node name missing"); + return; + } + + if (has_snapshot_node_name && bdrv_find_node(snapshot_node_name)) { + error_setg(errp, "New snapshot node name already existing"); return; } @@ -1256,7 +1288,8 @@ static void external_snapshot_prepare(BlkTransactionState *common, } /* We will manually add the backing_hd field to the bs later */ - state->new_bs = bdrv_new("", ""); + state->new_bs = bdrv_new("", + has_snapshot_node_name ? snapshot_node_name : ""); /* TODO Inherit bs->options or only take explicit options with an * extended QMP command? */ ret = bdrv_open(state->new_bs, new_image_file, NULL, diff --git a/hmp.c b/hmp.c index 906ddb7..47dcf0c 100644 --- a/hmp.c +++ b/hmp.c @@ -971,7 +971,9 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict) } mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS; - qmp_blockdev_snapshot_sync(device, filename, !!format, format, + qmp_blockdev_snapshot_sync(true, device, false, NULL, + filename, false, NULL, + !!format, format, true, mode, &errp); hmp_handle_error(mon, &errp); } diff --git a/qapi-schema.json b/qapi-schema.json index 92a7768..8d3ff1a 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1758,18 +1758,25 @@ ## # @BlockdevSnapshot # -# @device: the name of the device to generate the snapshot from. +# Either @device or @node-name must be set but not both. +# +# @device: #optional the name of the device to generate the snapshot from. +# +# @node-name: #optional graph node name to generate the snapshot from (Since 1.8) # # @snapshot-file: the target of the new image. A new file will be created. # +# @snapshot-node-name: the graph node name of the new image (Since 1.8) +# # @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', - '*mode': 'NewImageMode' } } + 'data': { '*device': 'str', '*node-name': 'str', + 'snapshot-file': 'str', '*snapshot-node-name': 'str', + '*format': 'str', '*mode': 'NewImageMode' } } ## # @BlockdevSnapshotInternal diff --git a/qmp-commands.hx b/qmp-commands.hx index 6b309a1..853cc67 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1038,7 +1038,9 @@ actions array: - "data": a dictionary. The contents depend on the value of "type". When "type" is "blockdev-snapshot-sync": - "device": device name to snapshot (json-string) + - "node-name": graph node name to snapshot (json-string) - "snapshot-file": name of new image file (json-string) + - "snapshot-node-name": graph node name of the new snapshot (json-string) - "format": format of new image (json-string, optional) - "mode": whether and how QEMU should create the snapshot file (NewImageMode, optional, default "absolute-paths") @@ -1053,6 +1055,11 @@ Example: { 'type': 'blockdev-snapshot-sync', 'data' : { "device": "ide-hd0", "snapshot-file": "/some/place/my-image", "format": "qcow2" } }, + { 'type': 'blockdev-snapshot-sync', 'data' : { "node-name": "myfile", + "snapshot-file": "/some/place/my-image2", + "snapshot-node-name": "node3432", + "mode": "existing", + "format": "qcow2" } }, { 'type': 'blockdev-snapshot-sync', 'data' : { "device": "ide-hd1", "snapshot-file": "/some/place/my-image2", "mode": "existing", @@ -1066,7 +1073,7 @@ EQMP { .name = "blockdev-snapshot-sync", - .args_type = "device:B,snapshot-file:s,format:s?,mode:s?", + .args_type = "device:s?,node-name:s?,snapshot-file:s,snapshot-node-name:s?,format:s?,mode:s?", .mhandler.cmd_new = qmp_marshal_input_blockdev_snapshot_sync, }, @@ -1083,7 +1090,9 @@ snapshot image, default is qcow2. Arguments: - "device": device name to snapshot (json-string) +- "node-name": graph node name to snapshot (json-string) - "snapshot-file": name of new image file (json-string) +- "snapshot-node-name": graph node name of the new snapshot (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) -- 1.8.3.2