From patchwork Tue Mar 6 17:55:59 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 144989 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 03C16B6F62 for ; Wed, 7 Mar 2012 06:13:14 +1100 (EST) Received: from localhost ([::1]:43687 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4ydu-0001LP-KX for incoming@patchwork.ozlabs.org; Tue, 06 Mar 2012 12:57:46 -0500 Received: from eggs.gnu.org ([208.118.235.92]:56628) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4yd6-0007h5-60 for qemu-devel@nongnu.org; Tue, 06 Mar 2012 12:57:01 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S4ycs-0002FP-Pd for qemu-devel@nongnu.org; Tue, 06 Mar 2012 12:56:55 -0500 Received: from mail-iy0-f173.google.com ([209.85.210.173]:50703) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4ycs-00029J-IC for qemu-devel@nongnu.org; Tue, 06 Mar 2012 12:56:42 -0500 Received: by mail-iy0-f173.google.com with SMTP id j26so7948148iaf.4 for ; Tue, 06 Mar 2012 09:56:41 -0800 (PST) Received-SPF: pass (google.com: domain of paolo.bonzini@gmail.com designates 10.50.160.131 as permitted sender) client-ip=10.50.160.131; Authentication-Results: mr.google.com; spf=pass (google.com: domain of paolo.bonzini@gmail.com designates 10.50.160.131 as permitted sender) smtp.mail=paolo.bonzini@gmail.com; dkim=pass header.i=paolo.bonzini@gmail.com Received: from mr.google.com ([10.50.160.131]) by 10.50.160.131 with SMTP id xk3mr11231533igb.19.1331056601775 (num_hops = 1); Tue, 06 Mar 2012 09:56:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=gXhbObS1yAIVVeRHj711y2D40gI8yldyF1ONuezeAvc=; b=vnVZpBvulec/1gtUPclMODOY7aktZsEuypu4FfjJ3iX9YrRMJ7Jf68MHFFABiQHx2W LVAgUM7x0jClDgtX/o6wNFaRVbIwg1wP/W5z0rU0vijyjPC9mF+56UIaVlOFhQ+mgdXW JzOeAfzthozFliJiSd8VYt2IQLYr4E6ae3rqqcdiVUVyvIGyQOhwZz210UuI4YIv7Hfm 6+MD5E0qM6kGzTXKc6bVTYRaLUm7zrxna7bf/Bb60OmHIRkrDkvdmrVl8trZefycIs7v ClIcKewGyK9/OllDdsaeNQpTU+ybdrpDrUXeN5yOtQqYz00gh7Wnujh2IAYAkV/IXIJ8 gk9g== Received: by 10.50.160.131 with SMTP id xk3mr9355398igb.19.1331056601700; Tue, 06 Mar 2012 09:56:41 -0800 (PST) Received: from yakj.usersys.redhat.com (93-34-182-16.ip50.fastwebnet.it. [93.34.182.16]) by mx.google.com with ESMTPS id s8sm10504373igw.16.2012.03.06.09.56.38 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 06 Mar 2012 09:56:40 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 6 Mar 2012 18:55:59 +0100 Message-Id: <1331056563-7503-7-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.7.6 In-Reply-To: <1331056563-7503-1-git-send-email-pbonzini@redhat.com> References: <1331056563-7503-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.210.173 Cc: kwolf@redhat.com, fsimonce@redhat.com, eblake@redhat.com, stefanha@linux.vnet.ibm.com, lcapitulino@redhat.com Subject: [Qemu-devel] [PATCH v4 06/10] qmp: convert blockdev-snapshot-sync to a wrapper around transactions 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 Simplify the blockdev-snapshot-sync code and gain failsafe operation by turning it into a wrapper around the new transaction command. A new option is also added matching "mode". Signed-off-by: Paolo Bonzini --- blockdev.c | 85 ++++++++++++++--------------------------------------- hmp-commands.hx | 9 ++++-- hmp.c | 6 +++- qapi-schema.json | 15 +++++---- qmp-commands.hx | 2 + 5 files changed, 44 insertions(+), 73 deletions(-) diff --git a/blockdev.c b/blockdev.c index cb5bf03..067cc10 100644 --- a/blockdev.c +++ b/blockdev.c @@ -646,72 +646,33 @@ void do_commit(Monitor *mon, const QDict *qdict) } } +static void blockdev_do_action(int kind, void *data, Error **errp) +{ + BlockdevAction action; + BlockdevActionList list; + + action.kind = kind; + action.data = data; + list.value = &action; + list.next = NULL; + 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) { - BlockDriverState *bs; - BlockDriver *drv, *old_drv, *proto_drv; - int ret = 0; - int flags; - char old_filename[1024]; - - bs = bdrv_find(device); - if (!bs) { - error_set(errp, QERR_DEVICE_NOT_FOUND, device); - return; - } - if (bdrv_in_use(bs)) { - error_set(errp, QERR_DEVICE_IN_USE, device); - return; - } - - pstrcpy(old_filename, sizeof(old_filename), bs->filename); - - old_drv = bs->drv; - flags = bs->open_flags; - - if (!has_format) { - format = "qcow2"; - } - - drv = bdrv_find_format(format); - if (!drv) { - error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); - return; - } - - proto_drv = bdrv_find_protocol(snapshot_file); - if (!proto_drv) { - error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); - return; - } - - ret = bdrv_img_create(snapshot_file, format, bs->filename, - bs->drv->format_name, NULL, -1, flags); - if (ret) { - error_set(errp, QERR_UNDEFINED_ERROR); - return; - } - - bdrv_drain_all(); - bdrv_flush(bs); - - bdrv_close(bs); - ret = bdrv_open(bs, snapshot_file, flags, drv); - /* - * If reopening the image file we just created fails, fall back - * and try to re-open the original image. If that fails too, we - * are in serious trouble. - */ - if (ret != 0) { - ret = bdrv_open(bs, old_filename, flags, old_drv); - if (ret != 0) { - error_set(errp, QERR_OPEN_FILE_FAILED, old_filename); - } else { - error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file); - } - } + BlockdevSnapshot snapshot = { + .device = (char *) device, + .snapshot_file = (char *) snapshot_file, + .has_format = has_format, + .format = (char *) format, + .has_mode = has_mode, + .mode = mode, + }; + blockdev_do_action(BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC, &snapshot, + errp); } diff --git a/hmp-commands.hx b/hmp-commands.hx index ed88877..6980214 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -882,14 +882,17 @@ ETEXI { .name = "snapshot_blkdev", - .args_type = "device:B,snapshot-file:s?,format:s?", - .params = "device [new-image-file] [format]", + .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)", + "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.", .mhandler.cmd = hmp_snapshot_blkdev, }, diff --git a/hmp.c b/hmp.c index 3a54455..290c43d 100644 --- a/hmp.c +++ b/hmp.c @@ -692,6 +692,8 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict) 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"); + int reuse = qdict_get_try_bool(qdict, "reuse", 0); + enum NewImageMode mode; Error *errp = NULL; if (!filename) { @@ -702,7 +704,9 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict) return; } - qmp_blockdev_snapshot_sync(device, filename, !!format, format, &errp); + mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS; + qmp_blockdev_snapshot_sync(device, filename, !!format, format, + true, mode, &errp); hmp_handle_error(mon, &errp); } diff --git a/qapi-schema.json b/qapi-schema.json index b062d01..0d24240 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1143,6 +1143,9 @@ # @snapshot-file: the target of the new image. A new file will be created. # # @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', @@ -1199,21 +1202,19 @@ # # @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'. +# # Returns: nothing on success # If @device is not a valid block device, DeviceNotFound # If @snapshot-file can't be opened, OpenFileFailed # If @format is invalid, InvalidBlockFormat # -# Notes: One of the last steps taken by this command is to close the current -# image being used by @device and open the @snapshot-file one. If that -# fails, the command will try to reopen the original image file. If -# that also fails OpenFileFailed will be returned and the guest may get -# unexpected errors. -# # Since 0.14.0 ## { 'command': 'blockdev-snapshot-sync', - 'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str' } } + 'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str', + '*mode': 'NewImageMode'} } ## # @human-monitor-command: diff --git a/qmp-commands.hx b/qmp-commands.hx index 7c03b62..dfe8a5b 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -760,6 +760,8 @@ Arguments: - "device": device name to snapshot (json-string) - "snapshot-file": name of new image file (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) Example: