From 67968bc615637394c3ef7dfefa360dab90f33d5d Mon Sep 17 00:00:00 2001 Message-Id: <67968bc615637394c3ef7dfefa360dab90f33d5d.1429902956.git.jen@redhat.com> From: Max Reitz Date: Wed, 18 Mar 2015 19:21:44 -0500 Subject: [CHANGE 01/42] qcow2: Ignore reserved bits in L1/L2 entries To: rhvirt-patches@redhat.com, jen@redhat.com RH-Author: Max Reitz Message-id: <1426706542-30384-2-git-send-email-mreitz@redhat.com> Patchwork-id: 64465 O-Subject: [RHEL-6.7 qemu-kvm PATCH v2 01/39] qcow2: Ignore reserved bits in L1/L2 entries Bugzilla: 1129892 RH-Acked-by: Jeffrey Cody RH-Acked-by: Kevin Wolf RH-Acked-by: Stefan Hajnoczi From: Kevin Wolf BZ: 1129892 This changes the still existing places that assume that the only flags are QCOW_OFLAG_COPIED and QCOW_OFLAG_COMPRESSED to properly mask out reserved bits. It does not convert bdrv_check yet. Signed-off-by: Kevin Wolf (cherry picked from commit 8e37f681d58bbe166c20559e77fd55b1cb8e6e4b) Signed-off-by: Jeff E. Nelson Conflicts: block/qcow2-cluster.c Signed-off-by: Max Reitz --- block/qcow2-cluster.c | 21 +++++++++------------ block/qcow2-refcount.c | 12 ++++++------ 2 files changed, 15 insertions(+), 18 deletions(-) Signed-off-by: Jeff E. Nelson --- block/qcow2-cluster.c | 21 +++++++++------------ block/qcow2-refcount.c | 12 ++++++------ 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index deffd6d..439c86d 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -207,7 +207,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) l2_table = *table; - if (old_l2_offset == 0) { + if ((old_l2_offset & L1E_OFFSET_MASK) == 0) { /* if there was no old l2 table, clear the new table */ memset(l2_table, 0, s->l2_size * sizeof(uint64_t)); } else { @@ -215,7 +215,8 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) /* if there was an old l2 table, read it from the disk */ BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_COW_READ); - ret = qcow2_cache_get(bs, s->l2_table_cache, old_l2_offset, + ret = qcow2_cache_get(bs, s->l2_table_cache, + old_l2_offset & L1E_OFFSET_MASK, (void**) &old_table); if (ret < 0) { goto fail; @@ -543,13 +544,12 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset, } assert(l1_index < s->l1_size); - l2_offset = s->l1_table[l1_index]; + l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK; /* seek the l2 table of the given l2 offset */ - if (l2_offset & QCOW_OFLAG_COPIED) { + if (s->l1_table[l1_index] & QCOW_OFLAG_COPIED) { /* load the l2 table in memory */ - l2_offset &= ~QCOW_OFLAG_COPIED; ret = l2_load(bs, l2_offset, &l2_table); if (ret < 0) { return ret; @@ -565,7 +565,7 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset, if (l2_offset) { qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t)); } - l2_offset = s->l1_table[l1_index] & ~QCOW_OFLAG_COPIED; + l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK; } /* find the cluster offset for the given disk offset */ @@ -718,8 +718,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) */ if (j != 0) { for (i = 0; i < j; i++) { - qcow2_free_any_clusters(bs, - be64_to_cpu(old_cluster[i]) & ~QCOW_OFLAG_COPIED, 1); + qcow2_free_any_clusters(bs, be64_to_cpu(old_cluster[i]), 1); } } @@ -776,7 +775,7 @@ again: nb_clusters = count_contiguous_clusters(nb_clusters, s->cluster_size, &l2_table[l2_index], 0, 0); - cluster_offset &= ~QCOW_OFLAG_COPIED; + cluster_offset &= L2E_OFFSET_MASK; m->nb_clusters = 0; m->depends_on = NULL; @@ -965,9 +964,7 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset, uint64_t old_offset; old_offset = be64_to_cpu(l2_table[l2_index + i]); - old_offset &= ~QCOW_OFLAG_COPIED; - - if (old_offset == 0) { + if ((old_offset & L2E_OFFSET_MASK) == 0) { continue; } diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 5c79fc8..dbb26d6 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -685,9 +685,8 @@ void qcow2_free_any_clusters(BlockDriverState *bs, return; } - qcow2_free_clusters(bs, cluster_offset, nb_clusters << s->cluster_bits); - - return; + qcow2_free_clusters(bs, cluster_offset & L2E_OFFSET_MASK, + nb_clusters << s->cluster_bits); } @@ -764,7 +763,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, l2_offset = l1_table[i]; if (l2_offset) { old_l2_offset = l2_offset; - l2_offset &= ~QCOW_OFLAG_COPIED; + l2_offset &= L1E_OFFSET_MASK; ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset, (void**) &l2_table); @@ -796,10 +795,11 @@ 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; if (addend != 0) { - refcount = update_cluster_refcount(bs, offset >> s->cluster_bits, addend); + refcount = update_cluster_refcount(bs, cluster_index, addend); } else { - refcount = get_refcount(bs, offset >> s->cluster_bits); + refcount = get_refcount(bs, cluster_index); } if (refcount < 0) { -- 2.1.0