qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Stefan Hajnoczi <stefanha@gmail.com>
To: Maor Lipchuk <mlipchuk@redhat.com>
Cc: qemu-discuss@nongnu.org, qemu-devel@nongnu.org,
	Allon Mureinik <amureini@redhat.com>,
	Kevin Wolf <kwolf@redhat.com>, Nir Soffer <nsoffer@redhat.com>,
	John Snow Huston <jhuston@redhat.com>
Subject: Re: [Qemu-devel] Estimation of qcow2 image size converted from raw image
Date: Tue, 28 Feb 2017 09:19:42 +0000	[thread overview]
Message-ID: <20170228091942.GA26496@stefanha-x1.localdomain> (raw)
In-Reply-To: <CAJ1JNOcOKvSBswMQt+2y_jkjHRUeVo33CfJRKhsPfeqfOqMnuA@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 3453 bytes --]

On Wed, Feb 22, 2017 at 06:15:47PM +0200, Maor Lipchuk wrote:
> Hi all,
> 
> Thank you very much for your help, it was much helpful
> We adopted John Snow advice and implemented our own calculation so we
> can resolve the issue now,
> We plan to drop this code once we can get this estimation from qemu-img.
> 
> This is the link to the patch introducing the calculation:
> https://gerrit.ovirt.org/#/c/65039/14/lib/vdsm/storage/qcow2.py
> 
> And here are link to the tests that we added:
> https://gerrit.ovirt.org/#/c/65039/14/tests/storage_qcow2_test.py
> 
> Here is how the calculation goes:
> 
> We first use qemuimg map to get the used clusters and count all the
> clusters for each run returned from qemuimg.map(filename):
> 
>  def count_clusters(runs):
>     count = 0
>      last = -1
>      for r in runs:
>          # Find the cluster when start and end are located.
>          start = r["start"] // CLUSTER_SIZE
>          end = (r["start"] + r["length"]) // CLUSTER_SIZE
>          if r["data"]:
>              if start == end:
>                  # This run is smaller then a cluster. If we have several runs
>                  # in the same cluster, we want to count the cluster only once.
>                  if start != last:
>                      count += 1
>              else:
>                  # This run span over multiple clusters - we want to count all
>                  # the clusters this run touch.
>                  count += end - start
>              last = end
>      return count
> 
> 
> The following calculation is based on Kevin's comments on the original
> bug, and qcow2 spec:
> https://github.com/qemu/qemu/blob/master/docs/specs/qcow2.txt:
> 
>      header_size = 3 * CLUSTER_SIZE

Are you including the L1 table in these 3 clusters?

>      virtual_size = os.stat(filename).st_size

This assumes the input file is in raw format.  If the input file is in
vmdk, vhdx, qcow2, etc then the POSIX file size does not represent the
virtual disk size.

> 
>      # Each 512MiB has one l2 table (64K)
>      l2_tables = (virtual_size + (512 * 1024**2) - 1) // (512 * 1024**2)
>      l2_tables_size = l2_tables * CLUSTER_SIZE
> 
>      # Each cluster have a refcount entry (16 bits) in the refcount tables. It
>      # is not clear what is the size of the refcount table, lets assume it is
>      # the same size as the l2 tables.
>      refcounts_tables_size = l2_tables_size

There is a formula for calculating refcount blocks in qcow2_create2():

  /* total size of refcount blocks
   *
   * note: every host cluster is reference-counted, including metadata
   * (even refcount blocks are recursively included).
   * Let:
   *   a = total_size (this is the guest disk size)
   *   m = meta size not including refcount blocks and refcount tables
   *   c = cluster size
   *   y1 = number of refcount blocks entries
   *   y2 = meta size including everything
   *   rces = refcount entry size in bytes
   * then,
   *   y1 = (y2 + a)/c
   *   y2 = y1 * rces + y1 * rces * sizeof(u64) / c + m
   * we can get y1:
   *   y1 = (a + m) / (c - rces - rces * sizeof(u64) / c)
   */
  nrefblocke = (aligned_total_size + meta_size + cluster_size)
             / (cluster_size - rces - rces * sizeof(uint64_t)
                                           / cluster_size);
  meta_size += DIV_ROUND_UP(nrefblocke, refblock_size) * cluster_size;

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

      parent reply	other threads:[~2017-02-28  9:19 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-13 15:46 [Qemu-devel] Estimation of qcow2 image size converted from raw image Maor Lipchuk
2017-02-13 17:03 ` John Snow
2017-02-13 17:16   ` Daniel P. Berrange
2017-02-13 18:26     ` John Snow
2017-02-15 15:14 ` Stefan Hajnoczi
2017-02-15 15:20   ` Daniel P. Berrange
2017-02-15 15:34     ` Eric Blake
2017-02-15 15:57     ` Nir Soffer
2017-02-15 16:05       ` [Qemu-devel] [Qemu-discuss] " Alberto Garcia
2017-02-15 16:11         ` Daniel P. Berrange
2017-02-15 16:07       ` [Qemu-devel] " Daniel P. Berrange
2017-02-20 11:12         ` Stefan Hajnoczi
2017-02-15 15:49   ` Nir Soffer
2017-02-20 11:07     ` Stefan Hajnoczi
     [not found]       ` <CAJ1JNOdzD7DHTHGJEO2YQANDPq0kY-PEh6J1jBkP7hUW0Kvy9w@mail.gmail.com>
     [not found]         ` <CAMRbyyssi_rspwDJTtWM1Ju5CTZ15z1xBikRDONrS84rx+B8Qg@mail.gmail.com>
2017-02-22 16:15           ` Maor Lipchuk
2017-02-22 22:06             ` Maor Lipchuk
2017-02-28  9:19             ` Stefan Hajnoczi [this message]

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=20170228091942.GA26496@stefanha-x1.localdomain \
    --to=stefanha@gmail.com \
    --cc=amureini@redhat.com \
    --cc=jhuston@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mlipchuk@redhat.com \
    --cc=nsoffer@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-discuss@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).