diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 9df380d52c..dfa28301c4 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1236,91 +1236,97 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, goto fail; } - ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset, - (void**) &l2_table); - if (ret < 0) { - goto fail; - } + { + ret = qcow2_cache_get(bs, s->l2_table_cache, + l2_offset, + (void **) &l2_table); + if (ret < 0) { + goto fail; + } - for (j = 0; j < s->l2_size; j++) { - uint64_t cluster_index; - uint64_t offset; + for (j = 0; j < s->l2_size; j++) { + uint64_t cluster_index; + uint64_t offset; - entry = be64_to_cpu(l2_table[j]); - old_entry = entry; - entry &= ~QCOW_OFLAG_COPIED; - offset = entry & L2E_OFFSET_MASK; + entry = be64_to_cpu(l2_table[j]); + old_entry = entry; + entry &= ~QCOW_OFLAG_COPIED; + offset = entry & L2E_OFFSET_MASK; - switch (qcow2_get_cluster_type(entry)) { - case QCOW2_CLUSTER_COMPRESSED: - nb_csectors = ((entry >> s->csize_shift) & - s->csize_mask) + 1; - if (addend != 0) { - ret = update_refcount(bs, - (entry & s->cluster_offset_mask) & ~511, + switch (qcow2_get_cluster_type(entry)) { + case QCOW2_CLUSTER_COMPRESSED: + nb_csectors = ((entry >> s->csize_shift) & + s->csize_mask) + 1; + if (addend != 0) { + ret = update_refcount( + bs, (entry & s->cluster_offset_mask) & ~511, nb_csectors * 512, abs(addend), addend < 0, QCOW2_DISCARD_SNAPSHOT); + if (ret < 0) { + goto fail; + } + } + /* compressed clusters are never modified */ + refcount = 2; + break; + + case QCOW2_CLUSTER_NORMAL: + case QCOW2_CLUSTER_ZERO_ALLOC: + if (offset_into_cluster(s, offset)) { + qcow2_signal_corruption( + bs, true, -1, -1, "Cluster " + "allocation offset %#" PRIx64 + " unaligned (L2 offset: %#" + PRIx64 ", L2 index: %#x)", + offset, l2_offset, j); + ret = -EIO; + goto fail; + } + + cluster_index = offset >> s->cluster_bits; + assert(cluster_index); + if (addend != 0) { + ret = qcow2_update_cluster_refcount( + bs, cluster_index, abs(addend), addend < 0, + QCOW2_DISCARD_SNAPSHOT); + if (ret < 0) { + goto fail; + } + } + + ret = qcow2_get_refcount(bs, cluster_index, &refcount); if (ret < 0) { goto fail; } - } - /* compressed clusters are never modified */ - refcount = 2; - break; + break; - case QCOW2_CLUSTER_NORMAL: - case QCOW2_CLUSTER_ZERO_ALLOC: - if (offset_into_cluster(s, offset)) { - qcow2_signal_corruption(bs, true, -1, -1, "Cluster " - "allocation offset %#" PRIx64 - " unaligned (L2 offset: %#" - PRIx64 ", L2 index: %#x)", - offset, l2_offset, j); - ret = -EIO; - goto fail; + case QCOW2_CLUSTER_ZERO_PLAIN: + case QCOW2_CLUSTER_UNALLOCATED: + refcount = 0; + break; + + default: + abort(); } - cluster_index = offset >> s->cluster_bits; - assert(cluster_index); - if (addend != 0) { - ret = qcow2_update_cluster_refcount(bs, - cluster_index, abs(addend), addend < 0, - QCOW2_DISCARD_SNAPSHOT); - if (ret < 0) { - goto fail; + if (refcount == 1) { + entry |= QCOW_OFLAG_COPIED; + } + if (entry != old_entry) { + if (addend > 0) { + qcow2_cache_set_dependency(bs, s->l2_table_cache, + s->refcount_block_cache); } + l2_table[j] = cpu_to_be64(entry); + qcow2_cache_entry_mark_dirty(s->l2_table_cache, + l2_table); } - - ret = qcow2_get_refcount(bs, cluster_index, &refcount); - if (ret < 0) { - goto fail; - } - break; - - case QCOW2_CLUSTER_ZERO_PLAIN: - case QCOW2_CLUSTER_UNALLOCATED: - refcount = 0; - break; - - default: - abort(); } - if (refcount == 1) { - entry |= QCOW_OFLAG_COPIED; - } - if (entry != old_entry) { - if (addend > 0) { - qcow2_cache_set_dependency(bs, s->l2_table_cache, - s->refcount_block_cache); - } - l2_table[j] = cpu_to_be64(entry); - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); - } + qcow2_cache_put(s->l2_table_cache, (void **) &l2_table); + } - qcow2_cache_put(s->l2_table_cache, (void **) &l2_table); - if (addend != 0) { ret = qcow2_update_cluster_refcount(bs, l2_offset >> s->cluster_bits,