From patchwork Mon Jan 7 07:28:06 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wayne Xia X-Patchwork-Id: 209870 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 172AE2C007E for ; Mon, 7 Jan 2013 18:32:04 +1100 (EST) Received: from localhost ([::1]:38466 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ts7Bi-0006kN-6p for incoming@patchwork.ozlabs.org; Mon, 07 Jan 2013 02:32:02 -0500 Received: from eggs.gnu.org ([208.118.235.92]:35832) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ts7An-0005d8-4p for qemu-devel@nongnu.org; Mon, 07 Jan 2013 02:31:07 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Ts7Al-0005eL-9v for qemu-devel@nongnu.org; Mon, 07 Jan 2013 02:31:05 -0500 Received: from e23smtp08.au.ibm.com ([202.81.31.141]:60478) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ts7Ak-0005e9-D1 for qemu-devel@nongnu.org; Mon, 07 Jan 2013 02:31:03 -0500 Received: from /spool/local by e23smtp08.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 7 Jan 2013 17:29:34 +1000 Received: from d23dlp01.au.ibm.com (202.81.31.203) by e23smtp08.au.ibm.com (202.81.31.205) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 7 Jan 2013 17:29:03 +1000 Received: from d23relay03.au.ibm.com (d23relay03.au.ibm.com [9.190.235.21]) by d23dlp01.au.ibm.com (Postfix) with ESMTP id A52502CE804A for ; Mon, 7 Jan 2013 18:30:27 +1100 (EST) Received: from d23av02.au.ibm.com (d23av02.au.ibm.com [9.190.235.138]) by d23relay03.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id r077URkt49807608 for ; Mon, 7 Jan 2013 18:30:27 +1100 Received: from d23av02.au.ibm.com (loopback [127.0.0.1]) by d23av02.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id r077UQIL023248 for ; Mon, 7 Jan 2013 18:30:27 +1100 Received: from RH63Wenchao (wenchaox.cn.ibm.com [9.115.122.237]) by d23av02.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id r077Rp6c018491; Mon, 7 Jan 2013 18:30:23 +1100 From: Wenchao Xia To: qemu-devel@nongnu.org Date: Mon, 7 Jan 2013 15:28:06 +0800 Message-Id: <1357543689-11415-9-git-send-email-xiawenc@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1357543689-11415-1-git-send-email-xiawenc@linux.vnet.ibm.com> References: <1357543689-11415-1-git-send-email-xiawenc@linux.vnet.ibm.com> X-Content-Scanned: Fidelis XPS MAILER x-cbid: 13010707-5140-0000-0000-0000029559B7 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x-2.6.x [generic] X-Received-From: 202.81.31.141 Cc: kwolf@redhat.com, aliguori@us.ibm.com, quintela@redhat.com, stefanha@gmail.com, Wenchao Xia , lcapitulino@redhat.com, pbonzini@redhat.com, dietmar@proxmox.com Subject: [Qemu-devel] [PATCH V2 07/10] snapshot: qmp use new internal API for external snapshot transaction 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 switch to internal common API to take group external snapshots from qmp_transaction interface. qmp layer simply does a translation from user input. Signed-off-by: Wenchao Xia --- blockdev.c | 215 ++++++++++++++++++++++++------------------------------------ 1 files changed, 87 insertions(+), 128 deletions(-) diff --git a/blockdev.c b/blockdev.c index 668506d..299039f 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1173,157 +1173,116 @@ void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file, errp); } - -/* New and old BlockDriverState structs for group snapshots */ -typedef struct BlkTransactionStates { - BlockDriverState *old_bs; - BlockDriverState *new_bs; - QSIMPLEQ_ENTRY(BlkTransactionStates) entry; -} BlkTransactionStates; - -/* - * 'Atomic' group snapshots. The snapshots are taken as a set, and if any fail - * then we do not pivot any of the devices in the group, and abandon the - * snapshots - */ -void qmp_transaction(BlockdevActionList *dev_list, Error **errp) +/* translation from qmp commands */ +static int fill_blk_trs_ext_create_sync(BlockdevSnapshot *create_sync, + BlkTransStatesSync *st_sync, + Error **errp) { - int ret = 0; - BlockdevActionList *dev_entry = dev_list; - BlkTransactionStates *states, *next; - Error *local_err = NULL; - - QSIMPLEQ_HEAD(snap_bdrv_states, BlkTransactionStates) snap_bdrv_states; - QSIMPLEQ_INIT(&snap_bdrv_states); + const char *format = "qcow2"; + enum NewImageMode mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; + BlockDriverState *bs; + const char *device = create_sync->device; + const char *name = create_sync->snapshot_file; - /* drain all i/o before any snapshots */ - bdrv_drain_all(); + if (create_sync->has_mode) { + mode = create_sync->mode; + } + if (create_sync->has_format) { + format = create_sync->format; + } - /* We don't do anything in this loop that commits us to the snapshot */ - while (NULL != dev_entry) { - BlockdevAction *dev_info = NULL; - BlockDriver *proto_drv; - BlockDriver *drv; - int flags; - enum NewImageMode mode; - const char *new_image_file; - const char *device; - const char *format = "qcow2"; + /* find the target bs */ + bs = bdrv_find(device); + if (!bs) { + error_set(errp, QERR_DEVICE_NOT_FOUND, device); + return -1; + } - dev_info = dev_entry->value; - dev_entry = dev_entry->next; + switch (mode) { + case NEW_IMAGE_MODE_EXISTING: + st_sync->use_existing = true; + break; + case NEW_IMAGE_MODE_ABSOLUTE_PATHS: + st_sync->use_existing = false; + break; + default: + error_setg(errp, "Device %s requested invalid snapshot" + " mode %d.", device, mode); + return -1; + } - states = g_malloc0(sizeof(BlkTransactionStates)); - QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, states, entry); + st_sync->external.new_image_file = name; + st_sync->external.format = format; + st_sync->external.old_bs = bs; - switch (dev_info->kind) { - case BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC: - device = dev_info->blockdev_snapshot_sync->device; - if (!dev_info->blockdev_snapshot_sync->has_mode) { - dev_info->blockdev_snapshot_sync->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; - } - new_image_file = dev_info->blockdev_snapshot_sync->snapshot_file; - if (dev_info->blockdev_snapshot_sync->has_format) { - format = dev_info->blockdev_snapshot_sync->format; - } - mode = dev_info->blockdev_snapshot_sync->mode; - break; - default: - abort(); - } + return 0; +} - drv = bdrv_find_format(format); - if (!drv) { - error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); - goto delete_and_fail; - } +static int fill_blk_trs(BlockdevAction *dev_info, + BlkTransStates *states, + SNTime *time, + const char *time_str, + Error **errp) +{ + int ret = 0; - states->old_bs = bdrv_find(device); - if (!states->old_bs) { - error_set(errp, QERR_DEVICE_NOT_FOUND, device); - goto delete_and_fail; - } + switch (dev_info->kind) { + case BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC: + states->st_sync.type = BLK_SNAPSHOT_EXTERNAL; + states->st_sync.op = BLK_SN_SYNC_CREATE; + ret = fill_blk_trs_ext_create_sync(dev_info->blockdev_snapshot_sync, + &states->st_sync, + errp); + break; + default: + abort(); + } - if (!bdrv_is_inserted(states->old_bs)) { - error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); - goto delete_and_fail; - } + return ret; +} - if (bdrv_in_use(states->old_bs)) { - error_set(errp, QERR_DEVICE_IN_USE, device); - goto delete_and_fail; - } +/* Here this funtion prepare the request list, submit for atomic snapshot. */ +void qmp_transaction(BlockdevActionList *dev_list, Error **errp) +{ + BlockdevActionList *dev_entry = dev_list; + BlkTransStates *states; + int ret; - if (!bdrv_is_read_only(states->old_bs)) { - if (bdrv_flush(states->old_bs)) { - error_set(errp, QERR_IO_ERROR); - goto delete_and_fail; - } - } + BlkTransStatesList *snap_bdrv_states = blk_trans_st_list_new(); - flags = states->old_bs->open_flags; + /* translate qmp request */ + /* for group snapshot create we use same time stamp here */ + SNTime time = get_sn_time(); + char time_str[256]; + generate_sn_name_from_time(&time, time_str, sizeof(time_str)); + while (NULL != dev_entry) { + BlockdevAction *dev_info = NULL; - proto_drv = bdrv_find_protocol(new_image_file); - if (!proto_drv) { - error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); - goto delete_and_fail; - } + dev_info = dev_entry->value; + dev_entry = dev_entry->next; - /* create new image w/backing file */ - if (mode != NEW_IMAGE_MODE_EXISTING) { - bdrv_img_create(new_image_file, format, - states->old_bs->filename, - states->old_bs->drv->format_name, - NULL, -1, flags, &local_err); - if (error_is_set(&local_err)) { - error_propagate(errp, local_err); - goto delete_and_fail; - } + states = blk_trans_st_new(); + ret = fill_blk_trs(dev_info, states, &time, time_str, errp); + if (ret < 0) { + blk_trans_st_delete(&states); + goto exit; } - /* We will manually add the backing_hd field to the bs later */ - states->new_bs = bdrv_new(""); - ret = bdrv_open(states->new_bs, new_image_file, - flags | BDRV_O_NO_BACKING, drv); - if (ret != 0) { - error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file); - goto delete_and_fail; + ret = add_transaction(snap_bdrv_states, states, errp); + if (ret < 0) { + blk_trans_st_delete(&states); + goto exit; } } + /* submit to internal API, no need to check return for no following + action now. */ + submit_transaction(snap_bdrv_states, errp); - /* Now we are going to do the actual pivot. Everything up to this point - * is reversible, but we are committed at this point */ - QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) { - /* This removes our old bs from the bdrv_states, and adds the new bs */ - bdrv_append(states->new_bs, states->old_bs); - /* We don't need (or want) to use the transactional - * bdrv_reopen_multiple() across all the entries at once, because we - * don't want to abort all of them if one of them fails the reopen */ - bdrv_reopen(states->new_bs, states->new_bs->open_flags & ~BDRV_O_RDWR, - NULL); - } - - /* success */ - goto exit; - -delete_and_fail: - /* - * failure, and it is all-or-none; abandon each new bs, and keep using - * the original bs for all images - */ - QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) { - if (states->new_bs) { - bdrv_delete(states->new_bs); - } - } exit: - QSIMPLEQ_FOREACH_SAFE(states, &snap_bdrv_states, entry, next) { - g_free(states); - } + blk_trans_st_list_delete(&snap_bdrv_states); } - static void eject_device(BlockDriverState *bs, int force, Error **errp) { if (bdrv_in_use(bs)) {