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-71466251a162
master
aliguori 2008-12-02 20:11:27 +00:00
parent 643e5399bb
commit 6db6c63826
1 changed files with 75 additions and 91 deletions

View File

@ -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 ? */ /* how many allocated clusters ? */
c = count_contiguous_clusters(nb_clusters, s->cluster_size,
cluster_offset &= ~QCOW_OFLAG_COPIED; &l2_table[l2_index], 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;
}
} }
nb_available = (c * 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++;
if (!cluster_offset) {
/* how many free clusters ? */
while (i < nb_clusters) {
cluster_offset = be64_to_cpu(l2_table[l2_index + i]); cluster_offset = be64_to_cpu(l2_table[l2_index + i]);
if (cluster_offset != 0)
break;
i++;
}
if ((cluster_offset & QCOW_OFLAG_COPIED) || 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)
i += j;
if(be64_to_cpu(l2_table[l2_index + i]))
break; break;
cluster_offset = current;
}
} }
nb_clusters = i; nb_clusters = i;
@ -2194,14 +2185,12 @@ 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 #ifdef DEBUG_ALLOC2
printf("alloc_clusters: size=%lld -> %lld\n", printf("alloc_clusters: size=%lld -> %lld\n",
@ -2209,11 +2198,6 @@ static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size)
(s->free_cluster_index - nb_clusters) << s->cluster_bits); (s->free_cluster_index - nb_clusters) << s->cluster_bits);
#endif #endif
return (s->free_cluster_index - nb_clusters) << s->cluster_bits; return (s->free_cluster_index - nb_clusters) << s->cluster_bits;
} else {
not_found:
s->free_cluster_index++;
}
}
} }
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);