mirror of https://github.com/proxmox/mirror_qemu
Cleanup {alloc|get}_cluster_offset() (Gleb Natapov)
Move duplicated code into helper functions. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5860 c046a42c-6fe2-441c-8c8c-71466251a162master
parent
643e5399bb
commit
6db6c63826
166
block-qcow2.c
166
block-qcow2.c
|
@ -601,6 +601,34 @@ static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index)
|
||||||
return l2_table;
|
return l2_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int size_to_clusters(BDRVQcowState *s, int64_t size)
|
||||||
|
{
|
||||||
|
return (size + (s->cluster_size - 1)) >> s->cluster_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
|
||||||
|
uint64_t *l2_table, uint64_t mask)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint64_t offset = be64_to_cpu(l2_table[0]) & ~mask;
|
||||||
|
|
||||||
|
for (i = 0; i < nb_clusters; i++)
|
||||||
|
if (offset + i * cluster_size != (be64_to_cpu(l2_table[i]) & ~mask))
|
||||||
|
break;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int count_contiguous_free_clusters(uint64_t nb_clusters, uint64_t *l2_table)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while(nb_clusters-- && l2_table[i] == 0)
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_cluster_offset
|
* get_cluster_offset
|
||||||
*
|
*
|
||||||
|
@ -622,9 +650,9 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
|
||||||
{
|
{
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
int l1_index, l2_index;
|
int l1_index, l2_index;
|
||||||
uint64_t l2_offset, *l2_table, cluster_offset, next;
|
uint64_t l2_offset, *l2_table, cluster_offset;
|
||||||
int l1_bits;
|
int l1_bits, c;
|
||||||
int index_in_cluster, nb_available, nb_needed;
|
int index_in_cluster, nb_available, nb_needed, nb_clusters;
|
||||||
|
|
||||||
index_in_cluster = (offset >> 9) & (s->cluster_sectors - 1);
|
index_in_cluster = (offset >> 9) & (s->cluster_sectors - 1);
|
||||||
nb_needed = *num + index_in_cluster;
|
nb_needed = *num + index_in_cluster;
|
||||||
|
@ -632,7 +660,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
|
||||||
l1_bits = s->l2_bits + s->cluster_bits;
|
l1_bits = s->l2_bits + s->cluster_bits;
|
||||||
|
|
||||||
/* compute how many bytes there are between the offset and
|
/* compute how many bytes there are between the offset and
|
||||||
* and the end of the l1 entry
|
* the end of the l1 entry
|
||||||
*/
|
*/
|
||||||
|
|
||||||
nb_available = (1 << l1_bits) - (offset & ((1 << l1_bits) - 1));
|
nb_available = (1 << l1_bits) - (offset & ((1 << l1_bits) - 1));
|
||||||
|
@ -667,38 +695,25 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
|
||||||
|
|
||||||
l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
|
l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
|
||||||
cluster_offset = be64_to_cpu(l2_table[l2_index]);
|
cluster_offset = be64_to_cpu(l2_table[l2_index]);
|
||||||
nb_available = s->cluster_sectors;
|
nb_clusters = size_to_clusters(s, nb_needed << 9);
|
||||||
l2_index++;
|
|
||||||
|
|
||||||
if (!cluster_offset) {
|
if (!cluster_offset) {
|
||||||
|
/* how many empty clusters ? */
|
||||||
/* how many empty clusters ? */
|
c = count_contiguous_free_clusters(nb_clusters, &l2_table[l2_index]);
|
||||||
|
|
||||||
while (nb_available < nb_needed && !l2_table[l2_index]) {
|
|
||||||
l2_index++;
|
|
||||||
nb_available += s->cluster_sectors;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
/* how many allocated clusters ? */
|
||||||
|
c = count_contiguous_clusters(nb_clusters, s->cluster_size,
|
||||||
|
&l2_table[l2_index], QCOW_OFLAG_COPIED);
|
||||||
|
}
|
||||||
|
|
||||||
/* how many allocated clusters ? */
|
nb_available = (c * s->cluster_sectors);
|
||||||
|
|
||||||
cluster_offset &= ~QCOW_OFLAG_COPIED;
|
|
||||||
while (nb_available < nb_needed) {
|
|
||||||
next = be64_to_cpu(l2_table[l2_index]) & ~QCOW_OFLAG_COPIED;
|
|
||||||
if (next != cluster_offset + (nb_available << 9))
|
|
||||||
break;
|
|
||||||
l2_index++;
|
|
||||||
nb_available += s->cluster_sectors;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (nb_available > nb_needed)
|
if (nb_available > nb_needed)
|
||||||
nb_available = nb_needed;
|
nb_available = nb_needed;
|
||||||
|
|
||||||
*num = nb_available - index_in_cluster;
|
*num = nb_available - index_in_cluster;
|
||||||
|
|
||||||
return cluster_offset;
|
return cluster_offset & ~QCOW_OFLAG_COPIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -862,15 +877,15 @@ static uint64_t alloc_cluster_offset(BlockDriverState *bs,
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
int l2_index, ret;
|
int l2_index, ret;
|
||||||
uint64_t l2_offset, *l2_table, cluster_offset;
|
uint64_t l2_offset, *l2_table, cluster_offset;
|
||||||
int nb_available, nb_clusters, i, j;
|
int nb_available, nb_clusters, i = 0;
|
||||||
uint64_t start_sect, current;
|
uint64_t start_sect;
|
||||||
|
|
||||||
ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
|
ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
nb_clusters = ((n_end << 9) + s->cluster_size - 1) >>
|
nb_clusters = size_to_clusters(s, n_end << 9);
|
||||||
s->cluster_bits;
|
|
||||||
if (nb_clusters > s->l2_size - l2_index)
|
if (nb_clusters > s->l2_size - l2_index)
|
||||||
nb_clusters = s->l2_size - l2_index;
|
nb_clusters = s->l2_size - l2_index;
|
||||||
|
|
||||||
|
@ -879,13 +894,8 @@ static uint64_t alloc_cluster_offset(BlockDriverState *bs,
|
||||||
/* We keep all QCOW_OFLAG_COPIED clusters */
|
/* We keep all QCOW_OFLAG_COPIED clusters */
|
||||||
|
|
||||||
if (cluster_offset & QCOW_OFLAG_COPIED) {
|
if (cluster_offset & QCOW_OFLAG_COPIED) {
|
||||||
|
nb_clusters = count_contiguous_clusters(nb_clusters, s->cluster_size,
|
||||||
for (i = 1; i < nb_clusters; i++) {
|
&l2_table[l2_index], 0);
|
||||||
current = be64_to_cpu(l2_table[l2_index + i]);
|
|
||||||
if (cluster_offset + (i << s->cluster_bits) != current)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
nb_clusters = i;
|
|
||||||
|
|
||||||
nb_available = nb_clusters << (s->cluster_bits - 9);
|
nb_available = nb_clusters << (s->cluster_bits - 9);
|
||||||
if (nb_available > n_end)
|
if (nb_available > n_end)
|
||||||
|
@ -903,46 +913,27 @@ static uint64_t alloc_cluster_offset(BlockDriverState *bs,
|
||||||
|
|
||||||
/* how many available clusters ? */
|
/* how many available clusters ? */
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while (i < nb_clusters) {
|
while (i < nb_clusters) {
|
||||||
|
int j;
|
||||||
|
i += count_contiguous_free_clusters(nb_clusters - i,
|
||||||
|
&l2_table[l2_index + i]);
|
||||||
|
|
||||||
i++;
|
cluster_offset = be64_to_cpu(l2_table[l2_index + i]);
|
||||||
|
|
||||||
if (!cluster_offset) {
|
if ((cluster_offset & QCOW_OFLAG_COPIED) ||
|
||||||
|
|
||||||
/* how many free clusters ? */
|
|
||||||
|
|
||||||
while (i < nb_clusters) {
|
|
||||||
cluster_offset = be64_to_cpu(l2_table[l2_index + i]);
|
|
||||||
if (cluster_offset != 0)
|
|
||||||
break;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((cluster_offset & QCOW_OFLAG_COPIED) ||
|
|
||||||
(cluster_offset & QCOW_OFLAG_COMPRESSED))
|
(cluster_offset & QCOW_OFLAG_COMPRESSED))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
} else {
|
j = count_contiguous_clusters(nb_clusters - i, s->cluster_size,
|
||||||
|
&l2_table[l2_index + i], 0);
|
||||||
/* how many contiguous clusters ? */
|
|
||||||
|
|
||||||
j = 1;
|
|
||||||
current = 0;
|
|
||||||
while (i < nb_clusters) {
|
|
||||||
current = be64_to_cpu(l2_table[l2_index + i]);
|
|
||||||
if (cluster_offset + (j << s->cluster_bits) != current)
|
|
||||||
break;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (j)
|
||||||
free_any_clusters(bs, cluster_offset, j);
|
free_any_clusters(bs, cluster_offset, j);
|
||||||
if (current)
|
|
||||||
break;
|
i += j;
|
||||||
cluster_offset = current;
|
|
||||||
}
|
if(be64_to_cpu(l2_table[l2_index + i]))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
nb_clusters = i;
|
nb_clusters = i;
|
||||||
|
|
||||||
|
@ -2194,26 +2185,19 @@ static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size)
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
int i, nb_clusters;
|
int i, nb_clusters;
|
||||||
|
|
||||||
nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits;
|
nb_clusters = size_to_clusters(s, size);
|
||||||
for(;;) {
|
retry:
|
||||||
if (get_refcount(bs, s->free_cluster_index) == 0) {
|
for(i = 0; i < nb_clusters; i++) {
|
||||||
s->free_cluster_index++;
|
int64_t i = s->free_cluster_index++;
|
||||||
for(i = 1; i < nb_clusters; i++) {
|
if (get_refcount(bs, i) != 0)
|
||||||
if (get_refcount(bs, s->free_cluster_index) != 0)
|
goto retry;
|
||||||
goto not_found;
|
|
||||||
s->free_cluster_index++;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_ALLOC2
|
|
||||||
printf("alloc_clusters: size=%lld -> %lld\n",
|
|
||||||
size,
|
|
||||||
(s->free_cluster_index - nb_clusters) << s->cluster_bits);
|
|
||||||
#endif
|
|
||||||
return (s->free_cluster_index - nb_clusters) << s->cluster_bits;
|
|
||||||
} else {
|
|
||||||
not_found:
|
|
||||||
s->free_cluster_index++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG_ALLOC2
|
||||||
|
printf("alloc_clusters: size=%lld -> %lld\n",
|
||||||
|
size,
|
||||||
|
(s->free_cluster_index - nb_clusters) << s->cluster_bits);
|
||||||
|
#endif
|
||||||
|
return (s->free_cluster_index - nb_clusters) << s->cluster_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t alloc_clusters(BlockDriverState *bs, int64_t size)
|
static int64_t alloc_clusters(BlockDriverState *bs, int64_t size)
|
||||||
|
@ -2548,7 +2532,7 @@ static void check_refcounts(BlockDriverState *bs)
|
||||||
uint16_t *refcount_table;
|
uint16_t *refcount_table;
|
||||||
|
|
||||||
size = bdrv_getlength(s->hd);
|
size = bdrv_getlength(s->hd);
|
||||||
nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits;
|
nb_clusters = size_to_clusters(s, size);
|
||||||
refcount_table = qemu_mallocz(nb_clusters * sizeof(uint16_t));
|
refcount_table = qemu_mallocz(nb_clusters * sizeof(uint16_t));
|
||||||
|
|
||||||
/* header */
|
/* header */
|
||||||
|
@ -2600,7 +2584,7 @@ static void dump_refcounts(BlockDriverState *bs)
|
||||||
int refcount;
|
int refcount;
|
||||||
|
|
||||||
size = bdrv_getlength(s->hd);
|
size = bdrv_getlength(s->hd);
|
||||||
nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits;
|
nb_clusters = size_to_clusters(s, size);
|
||||||
for(k = 0; k < nb_clusters;) {
|
for(k = 0; k < nb_clusters;) {
|
||||||
k1 = k;
|
k1 = k;
|
||||||
refcount = get_refcount(bs, k);
|
refcount = get_refcount(bs, k);
|
||||||
|
|
Loading…
Reference in New Issue