From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58025) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W016N-0001jY-DJ for qemu-devel@nongnu.org; Sun, 05 Jan 2014 22:43:52 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1W016E-0001GW-8z for qemu-devel@nongnu.org; Sun, 05 Jan 2014 22:43:43 -0500 Received: from e28smtp08.in.ibm.com ([122.248.162.8]:56245) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W016D-0001GN-My for qemu-devel@nongnu.org; Sun, 05 Jan 2014 22:43:34 -0500 Received: from /spool/local by e28smtp08.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 6 Jan 2014 09:13:32 +0530 Received: from d28relay05.in.ibm.com (d28relay05.in.ibm.com [9.184.220.62]) by d28dlp03.in.ibm.com (Postfix) with ESMTP id 3AD071258053 for ; Mon, 6 Jan 2014 09:14:57 +0530 (IST) Received: from d28av02.in.ibm.com (d28av02.in.ibm.com [9.184.220.64]) by d28relay05.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id s063hRds8782184 for ; Mon, 6 Jan 2014 09:13:27 +0530 Received: from d28av02.in.ibm.com (localhost [127.0.0.1]) by d28av02.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id s063hTtU022912 for ; Mon, 6 Jan 2014 09:13:29 +0530 From: Wenchao Xia Date: Mon, 6 Jan 2014 03:43:09 +0800 Message-Id: <1388950991-30105-7-git-send-email-xiawenc@linux.vnet.ibm.com> In-Reply-To: <1388950991-30105-1-git-send-email-xiawenc@linux.vnet.ibm.com> References: <1388950991-30105-1-git-send-email-xiawenc@linux.vnet.ibm.com> Subject: [Qemu-devel] [PATCH V9 6/8] qcow2: rollback on fail in qcow2_snapshot_create() List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, peter.crosthwaite@xilinx.com, jcody@redhat.com, mreitz@redhat.com, stefanha@redhat.com, Wenchao Xia A new variable *err_rollback is added to detect sub function's rollback failure. If one step in rollback procedure fails, following steps will be skipped, and the error message will be appended to errp. Signed-off-by: Wenchao Xia --- block/qcow2-snapshot.c | 37 ++++++++++++++++++++++++++++++++----- 1 files changed, 32 insertions(+), 5 deletions(-) diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 5cac714..29ba534 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -423,6 +423,7 @@ void qcow2_snapshot_create(BlockDriverState *bs, int i, ret; uint64_t *l1_table = NULL; int64_t l1_table_offset; + Error *err_rollback = NULL; memset(sn, 0, sizeof(*sn)); @@ -471,7 +472,7 @@ void qcow2_snapshot_create(BlockDriverState *bs, PRIu64 " with size %" PRIu64, sn->l1_table_offset, (uint64_t)(s->l1_size * sizeof(uint64_t))); - goto fail; + goto dealloc_l1_table; } ret = bdrv_pwrite(bs->file, sn->l1_table_offset, l1_table, @@ -482,7 +483,7 @@ void qcow2_snapshot_create(BlockDriverState *bs, PRIu64 " with size %" PRIu64, sn->l1_table_offset, (uint64_t)(s->l1_size * sizeof(uint64_t))); - goto fail; + goto dealloc_l1_table; } g_free(l1_table); @@ -499,7 +500,7 @@ void qcow2_snapshot_create(BlockDriverState *bs, "Failed in update of refcount for snapshot at %" PRIu64 " with size %d", s->l1_table_offset, s->l1_size); - goto fail; + goto dealloc_l1_table; } /* Append the new snapshot to the snapshot list */ @@ -512,12 +513,18 @@ void qcow2_snapshot_create(BlockDriverState *bs, s->snapshots = new_snapshot_list; s->snapshots[s->nb_snapshots++] = *sn; - ret = qcow2_write_snapshots(bs, errp, NULL); + ret = qcow2_write_snapshots(bs, errp, &err_rollback); if (ret < 0) { g_free(s->snapshots); s->snapshots = old_snapshot_list; s->nb_snapshots--; - goto fail; + if (error_is_set(&err_rollback)) { + error_append(errp, "%s", error_get_pretty(err_rollback)); + error_free(err_rollback); + goto fail; + } else { + goto restore_refcount; + } } g_free(old_snapshot_list); @@ -537,6 +544,26 @@ void qcow2_snapshot_create(BlockDriverState *bs, #endif return; +restore_refcount: + if (qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, -1) + < 0) { + /* Nothing can be done now, need image check later, skip following + rollback action. */ + error_append(errp, + "In rollback failed to restore refcount in snapshot"); + goto fail; + } + +dealloc_l1_table: + ret = qcow2_free_clusters(bs, sn->l1_table_offset, + sn->l1_size * sizeof(uint64_t), + QCOW2_DISCARD_ALWAYS); + if (ret < 0) { + error_append(errp, + "In rollback failed to free L1 table: %s\n", + strerror(-ret)); + } + fail: g_free(sn->id_str); g_free(sn->name); -- 1.7.1