qcow2: Fix refcount block allocation during qcow2_alloc_cluster_at()

Refcount block allocation and refcount table growth rely on
s->free_cluster_index pointing to somewhere after the current
allocation. Change qcow2_alloc_cluster_at() to fulfill this
assumption.

Without this change it could happen that a newly allocated refcount
block and the allocated data block point to the same area in the image
file, causing data corruption in the long run.

This fixes a bug that became first visible after commit 250196f1.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Kevin Wolf 2012-04-20 15:50:39 +02:00
parent 29926112a2
commit f24423bd90

View File

@ -587,6 +587,7 @@ int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
{ {
BDRVQcowState *s = bs->opaque; BDRVQcowState *s = bs->opaque;
uint64_t cluster_index; uint64_t cluster_index;
uint64_t old_free_cluster_index;
int i, refcount, ret; int i, refcount, ret;
/* Check how many clusters there are free */ /* Check how many clusters there are free */
@ -602,11 +603,16 @@ int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
} }
/* And then allocate them */ /* And then allocate them */
old_free_cluster_index = s->free_cluster_index;
s->free_cluster_index = cluster_index + i;
ret = update_refcount(bs, offset, i << s->cluster_bits, 1); ret = update_refcount(bs, offset, i << s->cluster_bits, 1);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
s->free_cluster_index = old_free_cluster_index;
return i; return i;
} }