aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJes Sorensen <Jes.Sorensen@redhat.com>2010-12-16 13:52:16 +0100
committerKevin Wolf <kwolf@redhat.com>2010-12-17 16:11:03 +0100
commitf88825680aa71eb4069cdaee9d65f2269f5c7cf3 (patch)
treebfe1c1e288f16f716489a27ff8e7df9903204312
parentf88e1a4201e31cac0438df395dfcdd45ac35c17d (diff)
Introduce do_snapshot_blkdev() and monitor command to handle it.
The monitor command is: snapshot_blkdev <device> [snapshot-file] [format] Default format is qcow2. For now snapshots without a snapshot-file, eg internal snapshots, are not supported. Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
-rw-r--r--blockdev.c62
-rw-r--r--blockdev.h1
-rw-r--r--hmp-commands.hx19
3 files changed, 82 insertions, 0 deletions
diff --git a/blockdev.c b/blockdev.c
index 3b3b82dba7..d7add36929 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -516,6 +516,68 @@ void do_commit(Monitor *mon, const QDict *qdict)
}
}
+int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+ const char *device = qdict_get_str(qdict, "device");
+ const char *filename = qdict_get_try_str(qdict, "snapshot_file");
+ const char *format = qdict_get_try_str(qdict, "format");
+ BlockDriverState *bs;
+ BlockDriver *drv, *proto_drv;
+ int ret = 0;
+ int flags;
+
+ bs = bdrv_find(device);
+ if (!bs) {
+ qerror_report(QERR_DEVICE_NOT_FOUND, device);
+ ret = -1;
+ goto out;
+ }
+
+ if (!format) {
+ format = "qcow2";
+ }
+
+ drv = bdrv_find_format(format);
+ if (!drv) {
+ qerror_report(QERR_INVALID_BLOCK_FORMAT, format);
+ ret = -1;
+ goto out;
+ }
+
+ proto_drv = bdrv_find_protocol(filename);
+ if (!proto_drv) {
+ qerror_report(QERR_INVALID_BLOCK_FORMAT, format);
+ ret = -1;
+ goto out;
+ }
+
+ ret = bdrv_img_create(filename, format, bs->filename,
+ bs->drv->format_name, NULL, -1, bs->open_flags);
+ if (ret) {
+ goto out;
+ }
+
+ qemu_aio_flush();
+ bdrv_flush(bs);
+
+ flags = bs->open_flags;
+ bdrv_close(bs);
+ ret = bdrv_open(bs, filename, flags, drv);
+ /*
+ * If reopening the image file we just created fails, we really
+ * are in trouble :(
+ */
+ if (ret != 0) {
+ abort();
+ }
+out:
+ if (ret) {
+ ret = -1;
+ }
+
+ return ret;
+}
+
static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
{
if (!force) {
diff --git a/blockdev.h b/blockdev.h
index 4cb8ca93d4..4536b5cab1 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -52,5 +52,6 @@ int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data);
int do_change_block(Monitor *mon, const char *device,
const char *filename, const char *fmt);
int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data);
#endif
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 23024ba6f2..dd3db36108 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -801,6 +801,25 @@ STEXI
Set maximum tolerated downtime (in seconds) for migration.
ETEXI
+ {
+ .name = "snapshot_blkdev",
+ .args_type = "device:s,snapshot_file:s?,format:s?",
+ .params = "device [new-image-file] [format]",
+ .help = "initiates a live snapshot\n\t\t\t"
+ "of device. If a new image file is specified, the\n\t\t\t"
+ "new image file will become the new root image.\n\t\t\t"
+ "If format is specified, the snapshot file will\n\t\t\t"
+ "be created in that format. Otherwise the\n\t\t\t"
+ "snapshot will be internal! (currently unsupported)",
+ .mhandler.cmd_new = do_snapshot_blkdev,
+ },
+
+STEXI
+@item snapshot_blkdev
+@findex snapshot_blkdev
+Snapshot device, using snapshot file as target if provided
+ETEXI
+
#if defined(TARGET_I386)
{
.name = "drive_add",