qcow2: Fix refcount block allocation during qcow2_alloc_cluster_at()
authorKevin Wolf <kwolf@redhat.com>
Fri, 20 Apr 2012 13:50:39 +0000 (15:50 +0200)
committerKevin Wolf <kwolf@redhat.com>
Fri, 20 Apr 2012 13:56:19 +0000 (15:56 +0200)
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>
block/qcow2-refcount.c

index 565bd549026488b6d2800659cf09841ff9e8a8b3..6c383373de1d537251fab9bd48f08eddfd22f5fc 100644 (file)
@@ -587,6 +587,7 @@ int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
 {
     BDRVQcowState *s = bs->opaque;
     uint64_t cluster_index;
+    uint64_t old_free_cluster_index;
     int i, refcount, ret;
 
     /* 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 */
+    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);
     if (ret < 0) {
         return ret;
     }
 
+    s->free_cluster_index = old_free_cluster_index;
+
     return i;
 }