[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-block] [PATCH 24/31] qcow2: Update qcow2_update_snapshot_refcount(
From: |
Alberto Garcia |
Subject: |
[Qemu-block] [PATCH 24/31] qcow2: Update qcow2_update_snapshot_refcount() to support L2 slices |
Date: |
Thu, 12 Oct 2017 16:05:38 +0300 |
qcow2_update_snapshot_refcount() increases the refcount of all
clusters of a given snapshot. In order to do that it needs to load all
its L2 tables and iterate over their entries. Since we'll be loading
L2 slices instead of full tables we need to add an extra loop that
iterates over all slices of each L2 table.
This function doesn't need any additional changes so apart from that
this patch simply updates the variable name from l2_table to l2_slice.
Signed-off-by: Alberto Garcia <address@hidden>
---
block/qcow2-refcount.c | 150 ++++++++++++++++++++++++++-----------------------
1 file changed, 80 insertions(+), 70 deletions(-)
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 64cb9f40be..94ade3d1e1 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1169,18 +1169,22 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
int64_t l1_table_offset, int l1_size, int addend)
{
BDRVQcow2State *s = bs->opaque;
- uint64_t *l1_table, *l2_table, l2_offset, entry, l1_size2, refcount;
+ uint64_t *l1_table, *l2_slice, l2_offset, entry, l1_size2, refcount;
bool l1_allocated = false;
int64_t old_entry, old_l2_offset;
+ unsigned slice, slice_size, n_slices;
int i, j, l1_modified = 0, nb_csectors;
int ret;
assert(addend >= -1 && addend <= 1);
- l2_table = NULL;
+ l2_slice = NULL;
l1_table = NULL;
l1_size2 = l1_size * sizeof(uint64_t);
+ slice_size = s->l2_slice_size * sizeof(uint64_t);
+ n_slices = s->cluster_size / slice_size;
+
s->cache_discards = true;
/* WARNING: qcow2_snapshot_goto relies on this function not using the
@@ -1222,91 +1226,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;
- }
+ for (slice = 0; slice < n_slices; slice++) {
+ ret = qcow2_cache_get(bs, s->l2_table_cache,
+ l2_offset + slice * slice_size,
+ (void **) &l2_slice);
+ 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_slice_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_slice[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) {
+ 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)) {
+ int l2_index = slice * s->l2_slice_size + j;
+ qcow2_signal_corruption(
+ bs, true, -1, -1, "Cluster "
+ "allocation offset %#" PRIx64
+ " unaligned (L2 offset: %#"
+ PRIx64 ", L2 index: %#x)",
+ offset, l2_offset, l2_index);
+ ret = -EIO;
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;
+ }
+ }
- 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);
+ ret = qcow2_get_refcount(bs, cluster_index, &refcount);
if (ret < 0) {
goto fail;
}
- }
+ break;
- 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;
- case QCOW2_CLUSTER_ZERO_PLAIN:
- case QCOW2_CLUSTER_UNALLOCATED:
- refcount = 0;
- break;
-
- default:
- abort();
- }
+ 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);
+ 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_slice[j] = cpu_to_be64(entry);
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache,
+ l2_slice);
}
- 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_slice);
}
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
-
if (addend != 0) {
ret = qcow2_update_cluster_refcount(bs, l2_offset >>
s->cluster_bits,
@@ -1332,8 +1342,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
ret = bdrv_flush(bs);
fail:
- if (l2_table) {
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
+ if (l2_slice) {
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
}
s->cache_discards = false;
--
2.11.0
- [Qemu-block] [PATCH 00/31] Allow configuring the qcow2 L2 cache entry size, Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 28/31] qcow2: Rename l2_table in count_contiguous_clusters(), Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 02/31] qcow2: Add table size field to Qcow2Cache, Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 31/31] qcow2: Allow configuring the L2 slice size, Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 27/31] qcow2: Rename l2_table in qcow2_alloc_compressed_cluster_offset(), Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 30/31] qcow2: Rename l2_table in count_cow_clusters(), Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 26/31] qcow2: Update qcow2_truncate() to support L2 slices, Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 29/31] qcow2: Rename l2_table in count_contiguous_clusters_unallocated(), Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 25/31] qcow2: Update expand_zero_clusters_in_l1() to support L2 slices, Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 24/31] qcow2: Update qcow2_update_snapshot_refcount() to support L2 slices,
Alberto Garcia <=
- [Qemu-block] [PATCH 23/31] qcow2: Update zero_single_l2() to support L2 slices, Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 22/31] qcow2: Update discard_single_l2() to support L2 slices, Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 21/31] qcow2: Update handle_alloc() to support L2 slices, Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 19/31] qcow2: Update qcow2_alloc_cluster_link_l2() to support L2 slices, Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 20/31] qcow2: Update handle_copied() to support L2 slices, Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 18/31] qcow2: Update qcow2_get_cluster_offset() to support L2 slices, Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 08/31] qcow2: Remove BDS parameter from qcow2_cache_destroy(), Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 10/31] qcow2: Remove BDS parameter from qcow2_cache_discard(), Alberto Garcia, 2017/10/12
- [Qemu-block] [PATCH 12/31] qcow2: Add offset_to_l1_index(), Alberto Garcia, 2017/10/12