From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48609) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VFPjO-0008U0-Q4 for qemu-devel@nongnu.org; Fri, 30 Aug 2013 10:31:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VFPjI-0002mK-Qk for qemu-devel@nongnu.org; Fri, 30 Aug 2013 10:31:22 -0400 Received: from mx1.redhat.com ([209.132.183.28]:36102) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VFPjI-0002m7-EK for qemu-devel@nongnu.org; Fri, 30 Aug 2013 10:31:16 -0400 From: Kevin Wolf Date: Fri, 30 Aug 2013 16:30:42 +0200 Message-Id: <1377873051-18981-18-git-send-email-kwolf@redhat.com> In-Reply-To: <1377873051-18981-1-git-send-email-kwolf@redhat.com> References: <1377873051-18981-1-git-send-email-kwolf@redhat.com> Subject: [Qemu-devel] [PULL 17/26] qcow2-refcount: Snapshot update for zero clusters List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: anthony@codemonkey.ws Cc: kwolf@redhat.com, qemu-devel@nongnu.org From: Max Reitz Account for all cluster types in qcow2_update_snapshot_refcounts; this prevents this function from updating the refcount of unallocated zero clusters which effectively led to wrong adjustments of the refcount of cluster 0 (the main qcow2 header). This in turn resulted in images with (unallocated) zero clusters having a cluster 0 refcount greater than one after creating a snapshot. Signed-off-by: Max Reitz Signed-off-by: Kevin Wolf --- block/qcow2-refcount.c | 52 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 1244693..a61224a 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -861,11 +861,14 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, } for(j = 0; j < s->l2_size; j++) { + uint64_t cluster_index; + offset = be64_to_cpu(l2_table[j]); - if (offset != 0) { - old_offset = offset; - offset &= ~QCOW_OFLAG_COPIED; - if (offset & QCOW_OFLAG_COMPRESSED) { + old_offset = offset; + offset &= ~QCOW_OFLAG_COPIED; + + switch (qcow2_get_cluster_type(offset)) { + case QCOW2_CLUSTER_COMPRESSED: nb_csectors = ((offset >> s->csize_shift) & s->csize_mask) + 1; if (addend != 0) { @@ -880,8 +883,16 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, } /* compressed clusters are never modified */ refcount = 2; - } else { - uint64_t cluster_index = (offset & L2E_OFFSET_MASK) >> s->cluster_bits; + break; + + case QCOW2_CLUSTER_NORMAL: + case QCOW2_CLUSTER_ZERO: + cluster_index = (offset & L2E_OFFSET_MASK) >> s->cluster_bits; + if (!cluster_index) { + /* unallocated */ + refcount = 0; + break; + } if (addend != 0) { refcount = update_cluster_refcount(bs, cluster_index, addend, QCOW2_DISCARD_SNAPSHOT); @@ -893,19 +904,26 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, ret = refcount; goto fail; } - } + break; - if (refcount == 1) { - offset |= QCOW_OFLAG_COPIED; - } - if (offset != old_offset) { - if (addend > 0) { - qcow2_cache_set_dependency(bs, s->l2_table_cache, - s->refcount_block_cache); - } - l2_table[j] = cpu_to_be64(offset); - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); + case QCOW2_CLUSTER_UNALLOCATED: + refcount = 0; + break; + + default: + abort(); + } + + if (refcount == 1) { + offset |= QCOW_OFLAG_COPIED; + } + if (offset != old_offset) { + if (addend > 0) { + qcow2_cache_set_dependency(bs, s->l2_table_cache, + s->refcount_block_cache); } + l2_table[j] = cpu_to_be64(offset); + qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); } } -- 1.8.1.4