diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 331ab0802280..b746429def0c 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1360,9 +1360,9 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset, nb_clusters = MIN(nb_clusters, s->l2_size - l2_index); for (i = 0; i < nb_clusters; i++) { - uint64_t old_offset; + uint64_t old_l2_entry; - old_offset = be64_to_cpu(l2_table[l2_index + i]); + old_l2_entry = be64_to_cpu(l2_table[l2_index + i]); /* * Make sure that a discarded area reads back as zeroes for v3 images @@ -1373,12 +1373,22 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset, * TODO We might want to use bdrv_get_block_status(bs) here, but we're * holding s->lock, so that doesn't work today. */ - if (old_offset & QCOW_OFLAG_ZERO) { - continue; - } + switch (qcow2_get_cluster_type(old_l2_entry)) { + case QCOW2_CLUSTER_UNALLOCATED: + if (!bs->backing_hd) { + continue; + } + break; - if ((old_offset & L2E_OFFSET_MASK) == 0 && !bs->backing_hd) { - continue; + case QCOW2_CLUSTER_ZERO: + continue; + + case QCOW2_CLUSTER_NORMAL: + case QCOW2_CLUSTER_COMPRESSED: + break; + + default: + abort(); } /* First remove L2 entries */ @@ -1390,7 +1400,7 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset, } /* Then decrease the refcount */ - qcow2_free_any_clusters(bs, old_offset, 1, type); + qcow2_free_any_clusters(bs, old_l2_entry, 1, type); } ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);