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>
This commit is contained in:
parent
b0b6862e5e
commit
8e37f681d5
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user