From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:59137) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RR3cE-00071H-K1 for qemu-devel@nongnu.org; Thu, 17 Nov 2011 10:11:08 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RR3c9-0002bz-Qw for qemu-devel@nongnu.org; Thu, 17 Nov 2011 10:11:02 -0500 Received: from mx1.redhat.com ([209.132.183.28]:3561) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RR3c9-0002bq-JO for qemu-devel@nongnu.org; Thu, 17 Nov 2011 10:10:57 -0500 From: Kevin Wolf Date: Thu, 17 Nov 2011 16:13:51 +0100 Message-Id: <1321542834-6880-6-git-send-email-kwolf@redhat.com> In-Reply-To: <1321542834-6880-1-git-send-email-kwolf@redhat.com> References: <1321542834-6880-1-git-send-email-kwolf@redhat.com> Subject: [Qemu-devel] [PATCH 5/8] qcow2: Return real error in qcow2_snapshot_goto List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, stefanha@gmail.com Signed-off-by: Kevin Wolf --- block/qcow2-snapshot.c | 50 +++++++++++++++++++++++++++++++++++++---------- 1 files changed, 39 insertions(+), 11 deletions(-) diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 066d56b..9f6647f 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -392,17 +392,32 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) QCowSnapshot *sn; int i, snapshot_index; int cur_l1_bytes, sn_l1_bytes; + int ret; + /* Search the snapshot */ snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id); - if (snapshot_index < 0) + if (snapshot_index < 0) { return -ENOENT; + } sn = &s->snapshots[snapshot_index]; - if (qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, -1) < 0) + /* Decrease refcount of clusters of current L1 table. + * FIXME This is too early! */ + ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, + s->l1_size, -1); + if (ret < 0) { goto fail; + } - if (qcow2_grow_l1_table(bs, sn->l1_size, true) < 0) + /* + * Make sure that the current L1 table is big enough to contain the whole + * L1 table of the snapshot. If the snapshot L1 table is smaller, the + * current one must be padded with zeros. + */ + ret = qcow2_grow_l1_table(bs, sn->l1_size, true); + if (ret < 0) { goto fail; + } cur_l1_bytes = s->l1_size * sizeof(uint64_t); sn_l1_bytes = sn->l1_size * sizeof(uint64_t); @@ -411,19 +426,31 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) memset(s->l1_table + sn->l1_size, 0, cur_l1_bytes - sn_l1_bytes); } - /* copy the snapshot l1 table to the current l1 table */ - if (bdrv_pread(bs->file, sn->l1_table_offset, - s->l1_table, sn_l1_bytes) < 0) + /* + * Copy the snapshot L1 table to the current L1 table. + * + * Before overwriting the old current L1 table on disk, make sure to + * increase all refcounts for the clusters referenced by the new one. + */ + ret = bdrv_pread(bs->file, sn->l1_table_offset, s->l1_table, sn_l1_bytes); + if (ret < 0) { goto fail; - if (bdrv_pwrite_sync(bs->file, s->l1_table_offset, - s->l1_table, cur_l1_bytes) < 0) + } + + ret = bdrv_pwrite(bs->file, s->l1_table_offset, s->l1_table, cur_l1_bytes); + if (ret < 0) { goto fail; + } + for(i = 0;i < s->l1_size; i++) { be64_to_cpus(&s->l1_table[i]); } - if (qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1) < 0) + /* FIXME This is too late! */ + ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1); + if (ret < 0) { goto fail; + } #ifdef DEBUG_ALLOC { @@ -432,8 +459,9 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) } #endif return 0; - fail: - return -EIO; + +fail: + return ret; } int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id) -- 1.7.6.4