@@ -25,6 +25,7 @@
#include "block/snapshot.h"
#include "block/block_int.h"
#include "qapi/qmp/qerror.h"
+#include "sysemu/block-backend.h"
QemuOptsList internal_snapshot_opts = {
.name = "snapshot",
@@ -475,18 +476,53 @@ int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn,
return err;
}
-BlockDriverState *bdrv_all_find_vmstate_bs(void)
+
+BlockDriverState *bdrv_all_find_vmstate_bs(const char *device, Error **errp)
{
bool not_found = true;
BlockDriverState *bs = NULL;
+ AioContext *ctx;
+
+ if (device != NULL) {
+ BlockBackend *blk = blk_by_name(device);
+ bool can_snapshot;
+
+ if (blk == NULL) {
+ error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
+ "Device '%s' not found", device);
+ return NULL;
+ }
+ bs = blk_bs(blk);
+ if (bs == NULL) {
+ error_setg(errp, "Device '%s' does not have block driver attached",
+ device);
+ return NULL;
+ }
+
+ ctx = bdrv_get_aio_context(bs);
+
+ aio_context_acquire(ctx);
+ can_snapshot = bdrv_can_snapshot(bs);
+ aio_context_release(ctx);
+
+ if (!can_snapshot) {
+ error_setg(errp, "Device '%s' does not support snapshots", device);
+ return NULL;
+ }
+ return bs;
+ }
while (not_found && (bs = bdrv_next(bs))) {
- AioContext *ctx = bdrv_get_aio_context(bs);
+ ctx = bdrv_get_aio_context(bs);
aio_context_acquire(ctx);
not_found = !bdrv_can_snapshot(bs);
aio_context_release(ctx);
}
+
+ if (bs == NULL) {
+ error_setg(errp, "No block device can accept snapshots");
+ }
return bs;
}
@@ -2405,7 +2405,7 @@ void hmp_savevm(Monitor *mon, const QDict *qdict)
name = name_buf;
}
- qmp_savevm(name, &local_err);
+ qmp_savevm(name, false, NULL, &local_err);
if (local_err != NULL) {
error_report_err(local_err);
@@ -91,7 +91,7 @@ int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn,
uint64_t vm_state_size,
BlockDriverState **first_bad_bs);
-BlockDriverState *bdrv_all_find_vmstate_bs(void);
+BlockDriverState *bdrv_all_find_vmstate_bs(const char *device, Error **errp);
BlockDriverState *bdrv_all_validate_snapshot(const char *name, Error **errp);
#endif
@@ -1905,7 +1905,8 @@ int qemu_loadvm_state(QEMUFile *f)
return ret;
}
-void qmp_savevm(const char *name, Error **errp)
+void qmp_savevm(const char *name, bool has_device, const char *device,
+ Error **errp)
{
BlockDriverState *bs, *bs1;
QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
@@ -1932,9 +1933,8 @@ void qmp_savevm(const char *name, Error **errp)
return;
}
- bs = bdrv_all_find_vmstate_bs();
+ bs = bdrv_all_find_vmstate_bs(has_device ? device : NULL, errp);
if (bs == NULL) {
- error_setg(errp, "No block device can accept snapshots");
return;
}
aio_context = bdrv_get_aio_context(bs);
@@ -2097,10 +2097,11 @@ void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
int total;
int *available_snapshots;
AioContext *aio_context;
+ Error *local_err = NULL;
- bs = bdrv_all_find_vmstate_bs();
+ bs = bdrv_all_find_vmstate_bs(NULL, &local_err);
if (!bs) {
- monitor_printf(mon, "No available block device supports snapshots\n");
+ error_report_err(local_err);
return;
}
aio_context = bdrv_get_aio_context(bs);
@@ -4061,12 +4061,13 @@
# Save a VM snapshot. Old snapshot with the same name will be deleted if exists.
#
# @name: identifier of a snapshot to be created
+# @device: #optional device name to save VM state to
#
# Returns: Nothing on success
#
# Since 2.6
##
-{ 'command': 'savevm', 'data': {'name': 'str'} }
+{ 'command': 'savevm', 'data': {'name': 'str', '*device': 'str'} }
##
# @delvm
@@ -4807,17 +4807,19 @@ Save a VM snapshot. Old snapshot with the same name will be deleted if exists.
Arguments:
- "name": snapshot name
+- "device": block device name
Example:
--> { "execute": "savevm", "arguments": { "name": "snapshot1" } }
+-> { "execute": "savevm",
+ "arguments": { "name": "snapshot1", "device": "ide1-hd0" } }
<- { "return": {} }
EQMP
{
.name = "savevm",
- .args_type = "name:s",
+ .args_type = "name:s,device:s?",
.mhandler.cmd_new = qmp_marshal_savevm,
},
Signed-off-by: Denis V. Lunev <den@openvz.org> CC: Kevin Wolf <kwolf@redhat.com> CC: Juan Quintela <quintela@redhat.com> CC: Amit Shah <amit.shah@redhat.com> CC: Markus Armbruster <armbru@redhat.com> CC: Eric Blake <eblake@redhat.com> --- block/snapshot.c | 40 ++++++++++++++++++++++++++++++++++++++-- hmp.c | 2 +- include/block/snapshot.h | 2 +- migration/savevm.c | 11 ++++++----- qapi-schema.json | 3 ++- qmp-commands.hx | 6 ++++-- 6 files changed, 52 insertions(+), 12 deletions(-)