From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38879) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W2aos-0002rW-SW for qemu-devel@nongnu.org; Mon, 13 Jan 2014 01:16:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1W2aoi-0006BZ-24 for qemu-devel@nongnu.org; Mon, 13 Jan 2014 01:16:18 -0500 Received: from e28smtp09.in.ibm.com ([122.248.162.9]:51910) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W2aoh-0006B3-4c for qemu-devel@nongnu.org; Mon, 13 Jan 2014 01:16:07 -0500 Received: from /spool/local by e28smtp09.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 13 Jan 2014 11:46:04 +0530 Received: from d28relay02.in.ibm.com (d28relay02.in.ibm.com [9.184.220.59]) by d28dlp02.in.ibm.com (Postfix) with ESMTP id 3C747394002D for ; Mon, 13 Jan 2014 11:46:01 +0530 (IST) Received: from d28av02.in.ibm.com (d28av02.in.ibm.com [9.184.220.64]) by d28relay02.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id s0D6FvAW36700256 for ; Mon, 13 Jan 2014 11:45:57 +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 s0D6G0K8018736 for ; Mon, 13 Jan 2014 11:46:00 +0530 From: Wenchao Xia Date: Mon, 13 Jan 2014 06:15:43 +0800 Message-Id: <1389564945-27664-7-git-send-email-xiawenc@linux.vnet.ibm.com> In-Reply-To: <1389564945-27664-1-git-send-email-xiawenc@linux.vnet.ibm.com> References: <1389564945-27664-1-git-send-email-xiawenc@linux.vnet.ibm.com> Subject: [Qemu-devel] [PATCH V10 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 Reviewed-by: Max Reitz --- 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 ee8f990..12938a0 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, + "Failed to restore refcounts during rollback"); + 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, + "Failed to free the L1 table during rollback: %s", + strerror(-ret)); + } + fail: g_free(sn->id_str); g_free(sn->name); -- 1.7.1