From: Max Reitz <mreitz@redhat.com>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>, Peter Lieven <pl@kamp.de>,
Stefan Hajnoczi <stefanha@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v2 01/12] qcow2: Add new overlap check functions
Date: Tue, 25 Nov 2014 12:02:19 +0100 [thread overview]
Message-ID: <547461BB.2000509@redhat.com> (raw)
In-Reply-To: <1416844620-17717-2-git-send-email-mreitz@redhat.com>
On 2014-11-24 at 16:56, Max Reitz wrote:
> The existing qcow2 metadata overlap detection function used existing
> structures to determine the location of the image metadata, from plain
> fields such as l1_table_offset and l1_size in the BDRVQcowState, over
> image structures in memory such as the L1 table for the L2 tables'
> positions, or it even read the required data directly from disk for
> every requested check, such as the snapshot L1 tables for the inactive
> L2 tables' positions.
>
> These new functions instead keep a dedicated structure for keeping track
> of the metadata positions in memory. It consists of two parts: First,
> there is one structure which is basically a list of all metadata
> structures. Each entry has a bitmask of types (because some metadata
> structures may actually overlap, such as active and inactive L2 tables),
> a number of clusters occupied and the offset from the previous entry in
> clusters. This structure requires relatively few memory, but checking a
> certain point may take relatively long. Each entry is called a
> "fragment".
>
> Therefore, there is another representation which is a bitmap, or rather
> a bytemap, of metadata types. The previously described list is split
> into multiple windows with each describing a constant number of clusters
> (WINDOW_SIZE). If the list is to be queried or changed, the respective
> window is selected in constant time and the bitmap is generated from the
> fragments belonging to the window. This bitmap can then be queried in
> constant time and easily be changed.
>
> Because the bitmap representation requires more memory, it is only used
> as a cache. Whenever a window is removed from the cache, the fragment
> list will be rebuilt from the bitmap if the latter has been modified.
> Therefore, the fragment list is only used as the background
> representation to save memory, whereas the bitmap is used whenever
> possible.
>
> Regarding the size of the fragment list in memory: As one refcount block
> can handle cluster_size / 2 entries and one L2 table can handle
> cluster_size / 8 entries, for a qcow2 image with the standard cluster
> size of 64 kB, there is a ratio of data to metadata of about 1/6000
> (1/32768 refblocks and 1/8192 L2 tables) if one ignores the fact that
> not every cluster requires an L2 table entry. The refcount table and the
> L1 table is generally negligible. At the worst, each metadata cluster
> requires its own entry in the fragment list; each entry takes up four
> bytes, therefore, at the worst, the fragment list should take up (for an
> image with 64 kB clusters) (4 B) / (64 kB * 6000) of the image size,
> which is about 1.e-8 (i.e., 11 kB for a 1 TB image, or 11 MB for a 1 PB
> image).
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
> block/Makefile.objs | 3 +-
> block/qcow2-overlap.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++++++
> block/qcow2.h | 13 ++
> 3 files changed, 419 insertions(+), 1 deletion(-)
> create mode 100644 block/qcow2-overlap.c
>
> diff --git a/block/qcow2-overlap.c b/block/qcow2-overlap.c
> new file mode 100644
> index 0000000..9f3f2aa
> --- /dev/null
> +++ b/block/qcow2-overlap.c
[snip]
> +
> +/**
> + * Destroys the cached window bitmap. If it has been modified, the fragment list
> + * will be rebuilt accordingly.
> + */
> +static void destroy_window_bitmap(Qcow2MetadataList *mdl,
> + Qcow2MetadataWindow *window)
> +{
> + if (!window->bitmap) {
> + return;
> + }
> +
> + if (window->bitmap_modified) {
> + int bitmap_i, fragment_i = 0;
> + QCow2MetadataOverlap current_types = 0;
> + int current_nb_clusters = 0;
> +
> + /* Rebuild the fragment list; the case bitmap_i == WINDOW_SIZE is for
> + * entering the last fragment at the bitmap end */
> +
> + for (bitmap_i = 0; bitmap_i <= WINDOW_SIZE; bitmap_i++) {
> + /* Qcow2MetadataFragment::nb_clusters is a uint8_t, so
> + * current_nb_clusters may not exceed 255 */
> + if (bitmap_i < WINDOW_SIZE &&
> + current_types == window->bitmap[bitmap_i] &&
> + current_nb_clusters < 255)
> + {
> + current_nb_clusters++;
> + } else {
> + if (current_types && current_nb_clusters) {
> + if (fragment_i >= window->fragments_array_size) {
> + window->fragments_array_size =
> + 3 * window->fragments_array_size / 2 + 1;
> +
> + /* new_nb_fragments should be small enough, and there is
> + * nothing we can do on failure anyway, so do not use
> + * g_try_renew() here */
> + window->fragments =
> + g_renew(Qcow2MetadataFragment, window->fragments,
> + window->fragments_array_size);
> + }
> +
> + window->fragments[fragment_i++] = (Qcow2MetadataFragment){
> + .types = current_types,
> + .nb_clusters = current_nb_clusters,
> + .relative_start = bitmap_i - current_nb_clusters,
> + };
> + }
> +
> + current_nb_clusters = 0;
Because I don't want to write a new version every time I find a single
bug myself, I'll just reply here, so you know which things I know about.
This should be 1, and not 0. At this point, we have found the first
cluster of this fragment, which is why this should be 1.
Max
> + if (bitmap_i < WINDOW_SIZE) {
> + current_types = window->bitmap[bitmap_i];
> + }
> + }
> + }
> +
> + window->nb_fragments = fragment_i;
> + }
> +
> + g_free(window->bitmap);
> + window->bitmap = NULL;
> +}
next prev parent reply other threads:[~2014-11-25 11:02 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-24 15:56 [Qemu-devel] [PATCH v2 00/12] qcow2: Add new overlap check functions Max Reitz
2014-11-24 15:56 ` [Qemu-devel] [PATCH v2 01/12] " Max Reitz
2014-11-25 11:02 ` Max Reitz [this message]
2015-01-21 16:53 ` Stefan Hajnoczi
2015-01-21 22:12 ` Max Reitz
2015-02-03 23:08 ` Eric Blake
2015-02-04 16:29 ` Max Reitz
2014-11-24 15:56 ` [Qemu-devel] [PATCH v2 02/12] qcow2: Pull up overlap check option evaluation Max Reitz
2015-02-03 23:33 ` Eric Blake
2014-11-24 15:56 ` [Qemu-devel] [PATCH v2 03/12] qcow2: Create metadata list Max Reitz
2015-02-03 23:34 ` Eric Blake
2015-02-04 16:31 ` Max Reitz
2014-11-24 15:56 ` [Qemu-devel] [PATCH v2 04/12] qcow2/overlaps: Protect image header Max Reitz
2015-02-03 23:47 ` Eric Blake
2014-11-24 15:56 ` [Qemu-devel] [PATCH v2 05/12] qcow2/overlaps: Protect refcount table Max Reitz
2015-02-03 23:55 ` Eric Blake
2014-11-24 15:56 ` [Qemu-devel] [PATCH v2 06/12] qcow2/overlaps: Protect refcount blocks Max Reitz
2015-02-05 1:24 ` Eric Blake
2014-11-24 15:56 ` [Qemu-devel] [PATCH v2 07/12] qcow2/overlaps: Protect active L1 table Max Reitz
2015-02-05 1:25 ` Eric Blake
2014-11-24 15:56 ` [Qemu-devel] [PATCH v2 08/12] qcow2/overlaps: Protect active L2 tables Max Reitz
2015-02-05 15:27 ` Eric Blake
2014-11-24 15:56 ` [Qemu-devel] [PATCH v2 09/12] qcow2/overlaps: Protect snapshot table Max Reitz
2015-02-05 15:29 ` Eric Blake
2015-02-05 15:30 ` Max Reitz
2014-11-24 15:56 ` [Qemu-devel] [PATCH v2 10/12] qcow2/overlaps: Protect inactive L1 tables Max Reitz
2015-02-05 19:41 ` Eric Blake
2014-11-24 15:56 ` [Qemu-devel] [PATCH v2 11/12] qcow2/overlaps: Protect inactive L2 tables Max Reitz
2015-01-21 15:23 ` Stefan Hajnoczi
2015-01-21 16:07 ` Max Reitz
2014-11-24 15:57 ` [Qemu-devel] [PATCH v2 12/12] qcow2: Use new metadata overlap check function Max Reitz
2015-01-21 15:28 ` Stefan Hajnoczi
2014-11-24 16:56 ` [Qemu-devel] [PATCH v2 00/12] qcow2: Add new overlap check functions Eric Blake
2014-11-24 17:35 ` Max Reitz
2014-11-25 10:55 ` Max Reitz
2014-11-25 13:25 ` Stefan Hajnoczi
2014-12-15 9:43 ` Max Reitz
2015-01-20 22:48 ` Max Reitz
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=547461BB.2000509@redhat.com \
--to=mreitz@redhat.com \
--cc=kwolf@redhat.com \
--cc=pl@kamp.de \
--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).