diff options
author | Kevin Wolf <kwolf@redhat.com> | 2012-02-23 15:40:55 +0100 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2012-04-20 15:57:28 +0200 |
commit | 8e37f681d58bbe166c20559e77fd55b1cb8e6e4b (patch) | |
tree | 5c98c646b56e21ac9f04b26a6248ee93331d313b /block | |
parent | b0b6862e5e1a1394e0ab3d5da94ba8b0da8664e2 (diff) | |
download | qemu-8e37f681d58bbe166c20559e77fd55b1cb8e6e4b.zip qemu-8e37f681d58bbe166c20559e77fd55b1cb8e6e4b.tar.gz qemu-8e37f681d58bbe166c20559e77fd55b1cb8e6e4b.tar.bz2 |
qcow2: Ignore reserved bits in L1/L2 entries
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 <kwolf@redhat.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/qcow2-cluster.c | 26 | ||||
-rw-r--r-- | block/qcow2-refcount.c | 12 |
2 files changed, 19 insertions, 19 deletions
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index dff782f..d1602d4 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -195,7 +195,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 { @@ -203,7 +203,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; @@ -508,13 +509,13 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset, return ret; } } - 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; @@ -530,7 +531,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 */ @@ -687,8 +688,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); } } @@ -867,7 +867,9 @@ again: * Check how many clusters are already allocated and don't need COW, and how * many need a new allocation. */ - if (cluster_offset & QCOW_OFLAG_COPIED) { + if (qcow2_get_cluster_type(cluster_offset) == QCOW2_CLUSTER_NORMAL + && (cluster_offset & QCOW_OFLAG_COPIED)) + { /* We keep all QCOW_OFLAG_COPIED clusters */ keep_clusters = count_contiguous_clusters(nb_clusters, s->cluster_size, &l2_table[l2_index], 0, @@ -886,7 +888,7 @@ again: cluster_offset = 0; } - cluster_offset &= ~QCOW_OFLAG_COPIED; + cluster_offset &= L2E_OFFSET_MASK; /* If there is something left to allocate, do that now */ *m = (QCowL2Meta) { @@ -1041,9 +1043,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 6c38337..84fa343 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -702,9 +702,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) { |