From: Kevin Wolf <kwolf@suse.de>
To: Laurent.Vivier@bull.net
Cc: qemu-devel@nongnu.org
Subject: [Qemu-devel] Re: [patch 4/5][v3] Aggregate same type clusters.
Date: Thu, 14 Aug 2008 17:53:04 +0200 [thread overview]
Message-ID: <48A454E0.2010303@suse.de> (raw)
In-Reply-To: <20080813145944.132440698@bull.net>
Laurent.Vivier@bull.net schrieb:
> Modify get_cluster_offset(), alloc_cluster_offset() to specify how many clusters
> we want.
>
> Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
> ---
> block-qcow2.c | 236 ++++++++++++++++++++++++++++++++++++++++++++--------------
> 1 file changed, 182 insertions(+), 54 deletions(-)
>
> Index: qemu/block-qcow2.c
> ===================================================================
> --- qemu.orig/block-qcow2.c 2008-08-12 12:49:24.000000000 +0200
> +++ qemu/block-qcow2.c 2008-08-12 15:26:58.000000000 +0200
> @@ -52,6 +52,8 @@
> #define QCOW_CRYPT_NONE 0
> #define QCOW_CRYPT_AES 1
>
> +#define QCOW_MAX_CRYPT_CLUSTERS 32
> +
> /* indicate that the refcount of the referenced cluster is exactly one. */
> #define QCOW_OFLAG_COPIED (1LL << 63)
> /* indicate that the cluster is compressed (they never have the copied flag) */
> @@ -263,7 +265,8 @@ static int qcow_open(BlockDriverState *b
> if (!s->cluster_cache)
> goto fail;
> /* one more sector for decompressed data alignment */
> - s->cluster_data = qemu_malloc(s->cluster_size + 512);
> + s->cluster_data = qemu_malloc(QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size
> + + 512);
> if (!s->cluster_data)
> goto fail;
> s->cluster_cache_offset = -1;
> @@ -613,43 +616,98 @@ static uint64_t *l2_allocate(BlockDriver
> * For a given offset of the disk image, return cluster offset in
> * qcow2 file.
> *
> + * on entry, *num is the number of contiguous clusters we'd like to
> + * access following offset.
> + *
> + * on exit, *num is the number of contiguous clusters we can read.
> + *
> * Return 1, if the offset is found
> * Return 0, otherwise.
> *
> */
>
> -static uint64_t get_cluster_offset(BlockDriverState *bs, uint64_t offset)
> +static uint64_t get_cluster_offset(BlockDriverState *bs,
> + uint64_t offset, int *num)
> {
> BDRVQcowState *s = bs->opaque;
> int l1_index, l2_index;
> - uint64_t l2_offset, *l2_table, cluster_offset;
> + uint64_t l2_offset, *l2_table, cluster_offset, next;
> + int l1_bits;
> + int index_in_cluster, nb_available, nb_needed;
> +
> + index_in_cluster = (offset >> 9) & (s->cluster_sectors - 1);
> + nb_needed = *num + index_in_cluster;
> +
> + l1_bits = s->l2_bits + s->cluster_bits;
> +
> + /* compute how many bytes there are between the offset and
> + * and the end of the l1 entry
> + */
> +
> + nb_available = (1 << l1_bits) - (offset & ((1 << l1_bits) - 1));
> +
> + /* compute the number of available sectors */
> +
> + nb_available = (nb_available >> 9) + index_in_cluster;
> +
> + cluster_offset = 0;
>
> /* seek the the l2 offset in the l1 table */
>
> - l1_index = offset >> (s->l2_bits + s->cluster_bits);
> + l1_index = offset >> l1_bits;
> if (l1_index >= s->l1_size)
> - return 0;
> + goto out;
>
> l2_offset = s->l1_table[l1_index];
>
> /* seek the l2 table of the given l2 offset */
>
> if (!l2_offset)
> - return 0;
> + goto out;
>
> /* load the l2 table in memory */
>
> l2_offset &= ~QCOW_OFLAG_COPIED;
> l2_table = l2_load(bs, l2_offset);
> if (l2_table == NULL)
> - return 0;
> + goto out;
You agreed that return 0 is actually the right thing to do here because
this is a real error.
>
> /* find the cluster offset for the given disk offset */
>
> l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
> cluster_offset = be64_to_cpu(l2_table[l2_index]);
> + nb_available = s->cluster_sectors;
> + l2_index++;
> +
> + if (!cluster_offset) {
>
> - return cluster_offset & ~QCOW_OFLAG_COPIED;
> + /* how many empty clusters ? */
> +
> + while (nb_available < nb_needed && !l2_table[l2_index]) {
> + l2_index++;
> + nb_available += s->cluster_sectors;
> + }
> + } else {
> +
> + /* how many allocated clusters ? */
> +
> + 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:
> + if (nb_available > nb_needed)
> + nb_available = nb_needed;
> +
> + *num = nb_available - index_in_cluster;
> +
> + return cluster_offset;
> }
>
> /*
> @@ -660,13 +718,10 @@ static uint64_t get_cluster_offset(Block
> */
>
> static void free_any_clusters(BlockDriverState *bs,
> - uint64_t cluster_offset)
> + uint64_t cluster_offset, int nb_clusters)
> {
> BDRVQcowState *s = bs->opaque;
>
> - if (cluster_offset == 0)
> - return;
> -
I don't think this check hurts. Even if this should never happen anyway.
The rest of it looks good.
Kevin
next prev parent reply other threads:[~2008-08-14 15:54 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-13 14:59 [Qemu-devel] [patch 0/5][v3] Improve qcow2 performance when used with cache=off Laurent.Vivier
2008-08-13 14:59 ` [Qemu-devel] [patch 1/5][v3] Extract code from get_cluster_offset() Laurent.Vivier
2008-08-14 14:07 ` [Qemu-devel] " Kevin Wolf
2008-08-13 14:59 ` [Qemu-devel] [patch 2/5][v3] Divide get_cluster_offset() Laurent.Vivier
2008-08-14 14:10 ` [Qemu-devel] " Kevin Wolf
2008-08-13 14:59 ` [Qemu-devel] [patch 3/5][v3] Extract compressing part from alloc_cluster_offset() Laurent.Vivier
2008-08-14 14:25 ` [Qemu-devel] " Kevin Wolf
2008-08-13 14:59 ` [Qemu-devel] [patch 4/5][v3] Aggregate same type clusters Laurent.Vivier
2008-08-14 15:53 ` Kevin Wolf [this message]
2008-08-14 16:20 ` [Qemu-devel] " Anthony Liguori
2008-08-14 17:16 ` Kevin Wolf
2008-08-13 14:59 ` [Qemu-devel] [patch 5/5][v3] Try to aggregate free clusters and freed clusters Laurent.Vivier
2008-08-14 16:11 ` [Qemu-devel] " Kevin Wolf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=48A454E0.2010303@suse.de \
--to=kwolf@suse.de \
--cc=Laurent.Vivier@bull.net \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).