aboutsummaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/qcow2-cluster.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 331ab08..b746429 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);