From patchwork Mon Dec 17 06:25:09 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wayne Xia X-Patchwork-Id: 206785 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id B47F72C008C for ; Mon, 17 Dec 2012 17:35:27 +1100 (EST) Received: from localhost ([::1]:50213 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TkUIP-0006c1-QL for incoming@patchwork.ozlabs.org; Mon, 17 Dec 2012 01:35:25 -0500 Received: from eggs.gnu.org ([208.118.235.92]:52656) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TkUEV-0002lb-C5 for qemu-devel@nongnu.org; Mon, 17 Dec 2012 01:35:01 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TkUB2-0006u4-Fq for qemu-devel@nongnu.org; Mon, 17 Dec 2012 01:31:23 -0500 Received: from e23smtp03.au.ibm.com ([202.81.31.145]:45487) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TkUB1-0006tr-In for qemu-devel@nongnu.org; Mon, 17 Dec 2012 01:27:48 -0500 Received: from /spool/local by e23smtp03.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 17 Dec 2012 16:23:33 +1000 Received: from d23dlp03.au.ibm.com (202.81.31.214) by e23smtp03.au.ibm.com (202.81.31.209) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 17 Dec 2012 16:23:32 +1000 Received: from d23relay04.au.ibm.com (d23relay04.au.ibm.com [9.190.234.120]) by d23dlp03.au.ibm.com (Postfix) with ESMTP id C586D357804D for ; Mon, 17 Dec 2012 17:27:42 +1100 (EST) Received: from d23av04.au.ibm.com (d23av04.au.ibm.com [9.190.235.139]) by d23relay04.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id qBH6GeNQ2687332 for ; Mon, 17 Dec 2012 17:16:40 +1100 Received: from d23av04.au.ibm.com (loopback [127.0.0.1]) by d23av04.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id qBH6RgWZ031983 for ; Mon, 17 Dec 2012 17:27:42 +1100 Received: from RedHat62GAWSWenchao (wenchaox.cn.ibm.com [9.115.122.150]) by d23av04.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id qBH6PGrk027846; Mon, 17 Dec 2012 17:27:40 +1100 From: Wenchao Xia To: qemu-devel@nongnu.org Date: Mon, 17 Dec 2012 14:25:09 +0800 Message-Id: <1355725509-5429-7-git-send-email-xiawenc@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1355725509-5429-1-git-send-email-xiawenc@linux.vnet.ibm.com> References: <1355725509-5429-1-git-send-email-xiawenc@linux.vnet.ibm.com> X-Content-Scanned: Fidelis XPS MAILER x-cbid: 12121706-6102-0000-0000-000002B9EAB3 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x-2.6.x [generic] X-Received-From: 202.81.31.145 Cc: kwolf@redhat.com, aliguori@us.ibm.com, stefanha@gmail.com, blauwirbel@gmail.com, pbonzini@redhat.com, Wenchao Xia Subject: [Qemu-devel] [PATCH 6/6] snapshot: human monitor interface X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch add support in human monitor to create/delete/check internal snapshot on a single blk device. To make info command get parameter, added a new info handler type which can take QDict as parameter. Signed-off-by: Wenchao Xia --- hmp-commands.hx | 50 +++++++++++++++++++++++++++++++++++++------------- hmp.c | 30 +++++++++++++++++++++++++----- hmp.h | 1 + monitor.c | 21 +++++++++++++++------ savevm.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- sysemu.h | 2 +- 6 files changed, 133 insertions(+), 26 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index 010b8c9..ee74723 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -983,17 +983,22 @@ ETEXI { .name = "snapshot_blkdev", - .args_type = "reuse:-n,device:B,snapshot-file:s?,format:s?", - .params = "[-n] 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).\n\t\t\t" - "The default format is qcow2. The -n flag requests QEMU\n\t\t\t" - "to reuse the image found in new-image-file, instead of\n\t\t\t" - "recreating it from scratch.", + .args_type = "internal:-i,reuse:-n,device:B,snapshot-file:s?,format:s?", + .params = "[-i] [-n] device [new-image-file] [format]", + .help = "initiates a live snapshot of device.\n\t\t\t" + " The -i flag requests QEMU to create internal snapshot\n\t\t\t" + "instead of external one.\n\t\t\t" + " The -n flag requests QEMU to use existing snapshot\n\t\t\t" + "instead of creating new snapshot, which would fails if\n\t\t\t" + "snapshot does not exist ahead.\n\t\t\t" + " new-image-file is the snapshot's name, in external case\n\t\t\t" + "it is the new image's name which will become the new root\n\t\t\t" + "image and must be specified, in internal case it is the\n\t\t\t" + "record's name and if not specified QEMU will create\n\t\t\t" + "internal snapshot with name generated according to time.\n\t\t\t" + " format is only valid in external case, which is the new\n\t\t\t" + "snapshot image's format. If not sepcified default format\n\t\t\t" + "qcow2 will be used.", .mhandler.cmd = hmp_snapshot_blkdev, }, @@ -1004,6 +1009,25 @@ Snapshot device, using snapshot file as target if provided ETEXI { + .name = "snapshot_delete_blkdev", + .args_type = "internal:-i,device:B,snapshot-file:s", + .params = "[-i] device new-image-file", + .help = "delete a snapshot synchronous.\n\t\t\t" + " The -i flag requests QEMU to delete internal snapshot\n\t\t\t" + "instead of external one.\n\t\t\t" + " new-image-file is the snapshot's name, in external case\n\t\t\t" + "it is the image's name which is not supported now.\n\t\t\t" + "in internal case it is the snapshot record's id or name.", + .mhandler.cmd = hmp_snapshot_delete_blkdev, + }, + +STEXI +@item snapshot_delete_blkdev +@findex snapshot_delete_blkdev +Delete a snapshot on a block device. +ETEXI + + { .name = "drive_mirror", .args_type = "reuse:-n,full:-f,device:B,target:s,format:s?", .params = "[-n] [-f] device target [format]", @@ -1486,8 +1510,8 @@ ETEXI { .name = "info", - .args_type = "item:s?", - .params = "[subcommand]", + .args_type = "item:s?,params:s?", + .params = "[subcommand] [params]", .help = "show various information about the system state", .mhandler.cmd = do_info, }, diff --git a/hmp.c b/hmp.c index 180ba2b..f247f51 100644 --- a/hmp.c +++ b/hmp.c @@ -806,20 +806,40 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict) const char *filename = qdict_get_try_str(qdict, "snapshot-file"); const char *format = qdict_get_try_str(qdict, "format"); int reuse = qdict_get_try_bool(qdict, "reuse", 0); + int internal = qdict_get_try_bool(qdict, "internal", 0); enum NewImageMode mode; + enum SnapshotType type; Error *errp = NULL; - if (!filename) { - /* In the future, if 'snapshot-file' is not specified, the snapshot - will be taken internally. Today it's actually required. */ + if ((!internal) && (!filename)) { + /* in external case filename must be set, should we generate + it automatically? */ error_set(&errp, QERR_MISSING_PARAMETER, "snapshot-file"); hmp_handle_error(mon, &errp); return; } - + type = internal ? SNAPSHOT_TYPE_INTERNAL : SNAPSHOT_TYPE_EXTERNAL; mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS; qmp_blockdev_snapshot_sync(device, filename, !!format, format, - true, mode, &errp); + true, mode, true, type, &errp); + hmp_handle_error(mon, &errp); +} + +void hmp_snapshot_delete_blkdev(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *filename = qdict_get_try_str(qdict, "snapshot-file"); + int internal = qdict_get_try_bool(qdict, "internal", 0); + enum SnapshotType type; + Error *errp = NULL; + + if (!internal) { + error_setg(&errp, "external snapshot delete not supported now."); + hmp_handle_error(mon, &errp); + return; + } + type = internal ? SNAPSHOT_TYPE_INTERNAL : SNAPSHOT_TYPE_EXTERNAL; + qmp_blockdev_snapshot_delete_sync(device, filename, true, type, &errp); hmp_handle_error(mon, &errp); } diff --git a/hmp.h b/hmp.h index 0ab03be..2ea67be 100644 --- a/hmp.h +++ b/hmp.h @@ -51,6 +51,7 @@ void hmp_block_passwd(Monitor *mon, const QDict *qdict); void hmp_balloon(Monitor *mon, const QDict *qdict); void hmp_block_resize(Monitor *mon, const QDict *qdict); void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict); +void hmp_snapshot_delete_blkdev(Monitor *mon, const QDict *qdict); void hmp_drive_mirror(Monitor *mon, const QDict *qdict); void hmp_migrate_cancel(Monitor *mon, const QDict *qdict); void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict); diff --git a/monitor.c b/monitor.c index c0e32d6..81de470 100644 --- a/monitor.c +++ b/monitor.c @@ -124,11 +124,14 @@ typedef struct mon_cmd_t { void (*user_print)(Monitor *mon, const QObject *data); union { void (*info)(Monitor *mon); + void (*info_qdict)(Monitor *mon, const QDict *qdict); void (*cmd)(Monitor *mon, const QDict *qdict); - int (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data); + int (*cmd_new)(Monitor *mon, const QDict *params, + QObject **ret_data); int (*cmd_async)(Monitor *mon, const QDict *params, MonitorCompletion *cb, void *opaque); } mhandler; + int info_cmd_need_qdict; int flags; } mon_cmd_t; @@ -824,7 +827,11 @@ static void do_info(Monitor *mon, const QDict *qdict) goto help; } - cmd->mhandler.info(mon); + if (cmd->info_cmd_need_qdict) { + cmd->mhandler.info_qdict(mon, qdict); + } else { + cmd->mhandler.info(mon); + } return; help: @@ -2605,10 +2612,12 @@ static mon_cmd_t info_cmds[] = { }, { .name = "snapshots", - .args_type = "", - .params = "", - .help = "show the currently saved VM snapshots", - .mhandler.info = do_info_snapshots, + .args_type = "device:B?", + .params = "[device]", + .help = "show the currently saved VM snapshots or snapshots on " + "a single device.", + .mhandler.info_qdict = do_info_snapshots, + .info_cmd_need_qdict = 1, }, { .name = "status", diff --git a/savevm.c b/savevm.c index c027529..5982aa9 100644 --- a/savevm.c +++ b/savevm.c @@ -2336,7 +2336,7 @@ void do_delvm(Monitor *mon, const QDict *qdict) } } -void do_info_snapshots(Monitor *mon) +static void do_info_snapshots_vm(Monitor *mon) { BlockDriverState *bs, *bs1; QEMUSnapshotInfo *sn_tab, *sn, s, *sn_info = &s; @@ -2400,6 +2400,59 @@ void do_info_snapshots(Monitor *mon) } +static void do_info_snapshots_blk(Monitor *mon, const char *device) +{ + BlockDriverState *bs; + QEMUSnapshotInfo *sn_tab, *sn; + int nb_sns, i; + char buf[256]; + + /* find the target bs */ + bs = bdrv_find(device); + if (!bs) { + monitor_printf(mon, "Device '%s' not found.\n", device); + return ; + } + + if (!bdrv_can_snapshot(bs)) { + monitor_printf(mon, "Device '%s' can't have snapshot.\n", device); + return ; + } + + nb_sns = bdrv_snapshot_list(bs, &sn_tab); + if (nb_sns < 0) { + monitor_printf(mon, "Device %s bdrv_snapshot_list: error %d\n", + device, nb_sns); + return; + } + + if (nb_sns == 0) { + monitor_printf(mon, "There is no snapshot available.\n"); + return; + } + + monitor_printf(mon, "Device %s:\n", device); + monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL)); + for (i = 0; i < nb_sns; i++) { + sn = &sn_tab[i]; + monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn)); + } + g_free(sn_tab); + return; +} + +void do_info_snapshots(Monitor *mon, const QDict *qdict) +{ + /* Todo, there should be a layer rebuild qdict before enter this func. */ + const char *device = qdict_get_try_str(qdict, "params"); + if (!device) { + do_info_snapshots_vm(mon); + } else { + do_info_snapshots_blk(mon, device); + } + return; +} + void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev) { qemu_ram_set_idstr(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK, diff --git a/sysemu.h b/sysemu.h index 1b6add2..a1254bf 100644 --- a/sysemu.h +++ b/sysemu.h @@ -68,7 +68,7 @@ void qemu_add_machine_init_done_notifier(Notifier *notify); void do_savevm(Monitor *mon, const QDict *qdict); int load_vmstate(const char *name); void do_delvm(Monitor *mon, const QDict *qdict); -void do_info_snapshots(Monitor *mon); +void do_info_snapshots(Monitor *mon, const QDict *qdict); void qemu_announce_self(void);