Skip to content

Commit

Permalink
qcow2: Fix qcow2_get_cluster_offset() for zero clusters
Browse files Browse the repository at this point in the history
When searching for contiguous zero clusters, we only need to check the
cluster type. Before this patch, an increasing offset (L2E_OFFSET_MASK)
was expected, so that the function never returned more than a single
zero cluster in practice. This patch fixes it to actually return as many
contiguous zero clusters as it can.

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-id: 1446657384-5907-1-git-send-email-kwolf@redhat.com
Signed-off-by: Max Reitz <mreitz@redhat.com>
  • Loading branch information
kevmw authored and XanClic committed Nov 11, 2015
1 parent 342075f commit a99dfb4
Showing 1 changed file with 9 additions and 6 deletions.
15 changes: 9 additions & 6 deletions block/qcow2-cluster.c
Expand Up @@ -312,7 +312,7 @@ static int count_contiguous_clusters(int nb_clusters, int cluster_size,
if (!offset)
return 0;

assert(qcow2_get_cluster_type(first_entry) != QCOW2_CLUSTER_COMPRESSED);
assert(qcow2_get_cluster_type(first_entry) == QCOW2_CLUSTER_NORMAL);

for (i = 0; i < nb_clusters; i++) {
uint64_t l2_entry = be64_to_cpu(l2_table[i]) & mask;
Expand All @@ -324,14 +324,16 @@ static int count_contiguous_clusters(int nb_clusters, int cluster_size,
return i;
}

static int count_contiguous_free_clusters(int nb_clusters, uint64_t *l2_table)
static int count_contiguous_clusters_by_type(int nb_clusters,
uint64_t *l2_table,
int wanted_type)
{
int i;

for (i = 0; i < nb_clusters; i++) {
int type = qcow2_get_cluster_type(be64_to_cpu(l2_table[i]));

if (type != QCOW2_CLUSTER_UNALLOCATED) {
if (type != wanted_type) {
break;
}
}
Expand Down Expand Up @@ -554,13 +556,14 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
ret = -EIO;
goto fail;
}
c = count_contiguous_clusters(nb_clusters, s->cluster_size,
&l2_table[l2_index], QCOW_OFLAG_ZERO);
c = count_contiguous_clusters_by_type(nb_clusters, &l2_table[l2_index],
QCOW2_CLUSTER_ZERO);
*cluster_offset = 0;
break;
case QCOW2_CLUSTER_UNALLOCATED:
/* how many empty clusters ? */
c = count_contiguous_free_clusters(nb_clusters, &l2_table[l2_index]);
c = count_contiguous_clusters_by_type(nb_clusters, &l2_table[l2_index],
QCOW2_CLUSTER_UNALLOCATED);
*cluster_offset = 0;
break;
case QCOW2_CLUSTER_NORMAL:
Expand Down

0 comments on commit a99dfb4

Please sign in to comment.