qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] Re: [PATCH 2/3] qcow2: Rewrite alloc_refcount_block/grow_re


From: Juan Quintela
Subject: [Qemu-devel] Re: [PATCH 2/3] qcow2: Rewrite alloc_refcount_block/grow_refcount_table
Date: Thu, 18 Feb 2010 13:02:18 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux)

Kevin Wolf <address@hidden> wrote:

> +    /* Find the refcount block for the given cluster */
> +    refcount_table_index = cluster_index >> (s->cluster_bits - 
> REFCOUNT_SHIFT);
> +    if (refcount_table_index >= s->refcount_table_size) {
> +        refcount_block_offset = 0;
> +    } else {
> +        refcount_block_offset = s->refcount_table[refcount_table_index];
> +    }
> +
> +    /* If it's already there, we're done */
> +    if (refcount_block_offset) {
> +        if (refcount_block_offset != s->refcount_block_cache_offset) {
> +            ret = load_refcount_block(bs, refcount_block_offset);
> +            if (ret < 0) {
> +                return ret;
> +            }
> +        }
> +        return refcount_block_offset;
> +    }

I would merge  this if in the previous one.  as a bonus,
refcount_block_offset can be local to that if branch and no need of the
else one.

> +
> +    /*
> +     * If we came here, we need to allocate something. Something is at least
> +     * a cluster for the new refcount block. It may also include a new 
> refcount
> +     * table if the old refcount table is too small.
> +     *
> +     * Note that allocating clusters here needs some special care:
> +     *
> +     * - We can't use the normal qcow2_alloc_clusters(), it would try to
> +     *   increase the refcount and very likely we would end up with an 
> endless
> +     *   recursion. Instead we must place the refcount blocks in a way that
> +     *   they can describe them themselves.
> +     *
> +     * - We need to consider that at this point we are inside 
> update_refcounts
> +     *   and doing the initial refcount increase. This means that some 
> clusters
> +     *   have already been allocated by the caller, but their refcount isn't
> +     *   accurate yet. free_cluster_index tells us where this allocation ends
> +     *   as long as we don't overwrite it by freeing clusters.
> +     *
> +     * - alloc_clusters_noref and qcow2_free_clusters may load a different
> +     *   refcount block into the cache
> +     */
> +
> +    if (cache_refcount_updates) {
> +        write_refcount_block(s);

write_refconut_blocks() can return -EIO.  It is not handled anywhere
else either.


> +    /* Calculate the number of refcount blocks needed so far */
> +    uint64_t refcount_block_clusters = 1 << (s->cluster_bits - 
> REFCOUNT_SHIFT);
> +    uint64_t blocks_used = (s->free_cluster_index +
> +        refcount_block_clusters - 1) / refcount_block_clusters;
> +
> +    /* And now we need at least one block more for the new metadata */
> +    uint64_t table_size = next_refcount_table_size(s, blocks_used + 1);
> +    uint64_t last_table_size = table_size;

only place where last_table_size is assigned to.

> +    uint64_t blocks_clusters;
> +    do {
> +        uint64_t table_clusters = size_to_clusters(s, table_size);
> +        blocks_clusters = 1 +
> +            ((table_clusters + refcount_block_clusters - 1)
> +            / refcount_block_clusters);
> +        uint64_t meta_clusters = table_clusters + blocks_clusters;
> +
> +        table_size = next_refcount_table_size(s, blocks_used +
> +            ((meta_clusters + refcount_block_clusters - 1)
> +            / refcount_block_clusters));

this value can be the same than previous next_refcount_table_size()
call or bigger.

> +
> +    } while (last_table_size != table_size);

how can this converge? (already discussed on irc with keving that a
last_table_size = table_size is missing somewhere in the loop.

Later, Juan.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]