From: "Benoît Canet" <benoit.canet@irqsave.net>
To: Max Reitz <mreitz@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>,
qemu-devel@nongnu.org, Stefan Hajnoczi <stefanha@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v2 6/7] block/qcow2: Simplify shared L2 handling in amend
Date: Mon, 4 Aug 2014 11:32:56 +0200 [thread overview]
Message-ID: <20140804093255.GE17835@irqsave.net> (raw)
In-Reply-To: <1406936961-20356-7-git-send-email-mreitz@redhat.com>
The Saturday 02 Aug 2014 à 01:49:20 (+0200), Max Reitz wrote :
> Currently, we have a bitmap for keeping track of which clusters have
> been created during the zero cluster expansion process. This was
> necessary because we need to properly increase the refcount for shared
> L2 tables.
>
> However, now we can simply take the L2 refcount and use it for the
> cluster allocated for expansion. This will be the correct refcount and
> therefore we don't have to remember that cluster having been allocated
> any more.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
> block/qcow2-cluster.c | 90 ++++++++++++++++-----------------------------------
> 1 file changed, 28 insertions(+), 62 deletions(-)
>
> diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
> index 2607715..7e65c13 100644
> --- a/block/qcow2-cluster.c
> +++ b/block/qcow2-cluster.c
> @@ -1543,20 +1543,12 @@ fail:
> * Expands all zero clusters in a specific L1 table (or deallocates them, for
> * non-backed non-pre-allocated zero clusters).
> *
> - * expanded_clusters is a bitmap where every bit corresponds to one cluster in
> - * the image file; a bit gets set if the corresponding cluster has been used for
> - * zero expansion (i.e., has been filled with zeroes and is referenced from an
> - * L2 table). nb_clusters contains the total cluster count of the image file,
> - * i.e., the number of bits in expanded_clusters.
> - *
> * l1_entries and *visited_l1_entries are used to keep track of progress for
> * status_cb(). l1_entries contains the total number of L1 entries and
> * *visited_l1_entries counts all visited L1 entries.
> */
> static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
> - int l1_size, uint8_t **expanded_clusters,
> - uint64_t *nb_clusters,
> - int64_t *visited_l1_entries,
> + int l1_size, int64_t *visited_l1_entries,
> int64_t l1_entries,
> BlockDriverAmendStatusCB *status_cb)
> {
> @@ -1575,6 +1567,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
> for (i = 0; i < l1_size; i++) {
> uint64_t l2_offset = l1_table[i] & L1E_OFFSET_MASK;
> bool l2_dirty = false;
> + int l2_refcount;
>
> if (!l2_offset) {
> /* unallocated */
> @@ -1598,33 +1591,19 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
> goto fail;
> }
>
> + l2_refcount = qcow2_get_refcount(bs, l2_offset >> s->cluster_bits);
> + if (l2_refcount < 0) {
> + ret = l2_refcount;
> + goto fail;
> + }
> +
> for (j = 0; j < s->l2_size; j++) {
> uint64_t l2_entry = be64_to_cpu(l2_table[j]);
> - int64_t offset = l2_entry & L2E_OFFSET_MASK, cluster_index;
> + int64_t offset = l2_entry & L2E_OFFSET_MASK;
> int cluster_type = qcow2_get_cluster_type(l2_entry);
> bool preallocated = offset != 0;
>
> - if (cluster_type == QCOW2_CLUSTER_NORMAL) {
> - cluster_index = offset >> s->cluster_bits;
> - assert((cluster_index >= 0) && (cluster_index < *nb_clusters));
> - if ((*expanded_clusters)[cluster_index / 8] &
> - (1 << (cluster_index % 8))) {
> - /* Probably a shared L2 table; this cluster was a zero
> - * cluster which has been expanded, its refcount
> - * therefore most likely requires an update. */
> - ret = qcow2_update_cluster_refcount(bs, cluster_index, 1,
> - QCOW2_DISCARD_NEVER);
> - if (ret < 0) {
> - goto fail;
> - }
> - /* Since we just increased the refcount, the COPIED flag may
> - * no longer be set. */
> - l2_table[j] = cpu_to_be64(l2_entry & ~QCOW_OFLAG_COPIED);
> - l2_dirty = true;
> - }
> - continue;
> - }
> - else if (qcow2_get_cluster_type(l2_entry) != QCOW2_CLUSTER_ZERO) {
> + if (cluster_type != QCOW2_CLUSTER_ZERO) {
> continue;
> }
>
> @@ -1642,6 +1621,19 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
> ret = offset;
> goto fail;
> }
> +
> + if (l2_refcount > 1) {
> + /* For shared L2 tables, set the refcount accordingly (it is
> + * already 1 and needs to be l2_refcount) */
> + ret = qcow2_update_cluster_refcount(bs,
> + offset >> s->cluster_bits, l2_refcount - 1,
> + QCOW2_DISCARD_OTHER);
> + if (ret < 0) {
> + qcow2_free_clusters(bs, offset, s->cluster_size,
> + QCOW2_DISCARD_OTHER);
> + goto fail;
> + }
> + }
> }
>
> ret = qcow2_pre_write_overlap_check(bs, 0, offset, s->cluster_size);
> @@ -1663,29 +1655,12 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
> goto fail;
> }
>
> - l2_table[j] = cpu_to_be64(offset | QCOW_OFLAG_COPIED);
> - l2_dirty = true;
> -
> - cluster_index = offset >> s->cluster_bits;
> -
> - if (cluster_index >= *nb_clusters) {
> - uint64_t old_bitmap_size = (*nb_clusters + 7) / 8;
> - uint64_t new_bitmap_size;
> - /* The offset may lie beyond the old end of the underlying image
> - * file for growable files only */
> - assert(bs->file->growable);
> - *nb_clusters = size_to_clusters(s, bs->file->total_sectors *
> - BDRV_SECTOR_SIZE);
> - new_bitmap_size = (*nb_clusters + 7) / 8;
> - *expanded_clusters = g_realloc(*expanded_clusters,
> - new_bitmap_size);
> - /* clear the newly allocated space */
> - memset(&(*expanded_clusters)[old_bitmap_size], 0,
> - new_bitmap_size - old_bitmap_size);
> + if (l2_refcount == 1) {
> + l2_table[j] = cpu_to_be64(offset | QCOW_OFLAG_COPIED);
> + } else {
> + l2_table[j] = cpu_to_be64(offset);
> }
> -
> - assert((cluster_index >= 0) && (cluster_index < *nb_clusters));
> - (*expanded_clusters)[cluster_index / 8] |= 1 << (cluster_index % 8);
> + l2_dirty = true;
> }
>
> if (is_active_l1) {
> @@ -1750,9 +1725,7 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs,
> {
> BDRVQcowState *s = bs->opaque;
> uint64_t *l1_table = NULL;
> - uint64_t nb_clusters;
> int64_t l1_entries = 0, visited_l1_entries = 0;
> - uint8_t *expanded_clusters;
> int ret;
> int i, j;
>
> @@ -1763,12 +1736,7 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs,
> }
> }
>
> - nb_clusters = size_to_clusters(s, bs->file->total_sectors *
> - BDRV_SECTOR_SIZE);
> - expanded_clusters = g_malloc0((nb_clusters + 7) / 8);
> -
> ret = expand_zero_clusters_in_l1(bs, s->l1_table, s->l1_size,
> - &expanded_clusters, &nb_clusters,
> &visited_l1_entries, l1_entries,
> status_cb);
> if (ret < 0) {
> @@ -1804,7 +1772,6 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs,
> }
>
> ret = expand_zero_clusters_in_l1(bs, l1_table, s->snapshots[i].l1_size,
> - &expanded_clusters, &nb_clusters,
> &visited_l1_entries, l1_entries,
> status_cb);
> if (ret < 0) {
> @@ -1815,7 +1782,6 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs,
> ret = 0;
>
> fail:
> - g_free(expanded_clusters);
> g_free(l1_table);
> return ret;
> }
> --
> 2.0.3
>
I don't understand this one very well so I will not Rev-By it.
next prev parent reply other threads:[~2014-08-04 9:33 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-01 23:49 [Qemu-devel] [PATCH v2 0/7] block/qcow2: Improve zero cluster expansion Max Reitz
2014-08-01 23:49 ` [Qemu-devel] [PATCH v2 1/7] block: Add status callback to bdrv_amend_options() Max Reitz
2014-08-04 9:19 ` Benoît Canet
2014-08-05 13:03 ` Eric Blake
2014-08-15 11:10 ` Benoît Canet
2014-08-01 23:49 ` [Qemu-devel] [PATCH v2 2/7] qemu-img: Add progress output for amend Max Reitz
2014-08-04 9:21 ` Benoît Canet
2014-08-05 13:04 ` Eric Blake
2014-08-15 11:18 ` Benoît Canet
2014-08-15 13:06 ` Max Reitz
2014-08-15 13:30 ` Benoît Canet
2014-08-01 23:49 ` [Qemu-devel] [PATCH v2 3/7] qemu-img: Fix insignificant memleak Max Reitz
2014-08-01 23:49 ` [Qemu-devel] [PATCH v2 4/7] block/qcow2: Implement status CB for amend Max Reitz
2014-08-04 9:29 ` Benoît Canet
2014-08-05 13:11 ` Eric Blake
2014-08-15 11:26 ` Benoît Canet
2014-08-01 23:49 ` [Qemu-devel] [PATCH v2 5/7] block/qcow2: Make get_refcount() global Max Reitz
2014-08-04 9:31 ` Benoît Canet
2014-08-05 13:18 ` Eric Blake
2014-08-15 11:27 ` Benoît Canet
2014-08-01 23:49 ` [Qemu-devel] [PATCH v2 6/7] block/qcow2: Simplify shared L2 handling in amend Max Reitz
2014-08-04 9:32 ` Benoît Canet [this message]
2014-08-05 13:27 ` Eric Blake
2014-08-15 11:50 ` Benoît Canet
2014-08-01 23:49 ` [Qemu-devel] [PATCH v2 7/7] iotests: Expand test 061 Max Reitz
2014-08-05 13:28 ` Eric Blake
2014-08-15 11:52 ` Benoît Canet
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=20140804093255.GE17835@irqsave.net \
--to=benoit.canet@irqsave.net \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/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).