From: Stefan Hajnoczi <stefanha@gmail.com>
To: Dmitry Konishchev <konishchev@gmail.com>
Cc: Kevin Wolf <kwolf@redhat.com>, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH] CPU consumption optimization of 'qemu-img convert' using bdrv_is_allocated()
Date: Mon, 13 Jun 2011 09:26:08 +0100 [thread overview]
Message-ID: <20110613082608.GA25582@stefanha-thinkpad.localdomain> (raw)
In-Reply-To: <1307544625-22907-1-git-send-email-konishchev@gmail.com>
On Wed, Jun 08, 2011 at 06:50:25PM +0400, Dmitry Konishchev wrote:
> This patch optimizes 'qemu-img convert' operation for volumes which are
> almost fully unallocated. Here are the results of simple tests:
The optimization is to check allocation metadata instead of
unconditionally reading and then checking for all zeroes?
> diff --git a/qemu-img.c b/qemu-img.c
> index 4f162d1..9d905ed 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -38,6 +38,8 @@ typedef struct img_cmd_t {
> int (*handler)(int argc, char **argv);
> } img_cmd_t;
>
> +static const int SECTOR_SIZE = 512;
Why introduce a new constant instead of using BDRV_SECTOR_SIZE?
> +
> /* Default to cache=writeback as data integrity is not important for qemu-tcg. */
> #define BDRV_O_FLAGS BDRV_O_CACHE_WB
>
> @@ -531,7 +533,7 @@ static int is_not_zero(const uint8_t *sector, int len)
> }
>
> /*
> - * Returns true iff the first sector pointed to by 'buf' contains at least
> + * Returns true if the first sector pointed to by 'buf' contains at least
"iff" is not a typo. It means "if and only if".
> @@ -912,55 +944,109 @@ static int img_convert(int argc, char **argv)
> are present in both the output's and input's base images (no
> need to copy them). */
> if (out_baseimg) {
> - if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
> - n, &n1)) {
> - sector_num += n1;
> + if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, n, &cur_n)) {
> + sector_num += cur_n;
> continue;
> }
> - /* The next 'n1' sectors are allocated in the input image. Copy
> + /* The next 'cur_n' sectors are allocated in the input image. Copy
> only those as they may be followed by unallocated sectors. */
> - n = n1;
> + n = cur_n;
> }
> - } else {
> - n1 = n;
> }
>
> - ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
> - if (ret < 0) {
> - error_report("error while reading");
> - goto out;
> - }
> - /* NOTE: at the same time we convert, we do not write zero
> - sectors to have a chance to compress the image. Ideally, we
> - should add a specific call to have the info to go faster */
> - buf1 = buf;
> - while (n > 0) {
> - /* If the output image is being created as a copy on write image,
> - copy all sectors even the ones containing only NUL bytes,
> - because they may differ from the sectors in the base image.
> -
> - If the output is to a host device, we also write out
> - sectors that are entirely 0, since whatever data was
> - already there is garbage, not 0s. */
> - if (!has_zero_init || out_baseimg ||
> - is_allocated_sectors(buf1, n, &n1)) {
> - ret = bdrv_write(out_bs, sector_num, buf1, n1);
> - if (ret < 0) {
> - error_report("error while writing");
> - goto out;
> + /* If the output image is being created as a copy on write image,
> + copy all sectors even the ones containing only zero bytes,
> + because they may differ from the sectors in the base image.
> +
> + If the output is to a host device, we also write out
> + sectors that are entirely 0, since whatever data was
> + already there is garbage, not 0s. */
> + if (!has_zero_init || out_baseimg) {
> + ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
> + if (ret < 0) {
> + error_report("error while reading");
> + goto out;
> + }
> +
> + ret = bdrv_write(out_bs, sector_num, buf, n);
> + if (ret < 0) {
> + error_report("error while writing");
> + goto out;
> + }
> +
> + sector_num += n;
> + } else {
> + /* Look for the sectors in the image and if they are not
> + allocated - sequentially in all its backing images.
> +
> + Write only non-zero bytes to the output image. */
I think the recursive is_allocated() needs its own function. This
function is already long/complex enough :).
Stefan
next prev parent reply other threads:[~2011-06-13 8:26 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-06-08 14:50 [Qemu-devel] [PATCH] CPU consumption optimization of 'qemu-img convert' using bdrv_is_allocated() Dmitry Konishchev
2011-06-13 8:26 ` Stefan Hajnoczi [this message]
2011-06-13 9:13 ` Dmitry Konishchev
2011-06-14 7:43 ` Dmitry Konishchev
2011-06-14 15:58 ` Stefan Hajnoczi
2011-06-15 7:38 ` Dmitry Konishchev
2011-06-15 8:39 ` Stefan Hajnoczi
2011-06-15 9:50 ` Dmitry Konishchev
2011-06-15 12:02 ` Stefan Hajnoczi
2011-06-15 13:14 ` Dmitry Konishchev
2011-06-15 13:33 ` Stefan Hajnoczi
2011-06-15 13:37 ` Dmitry Konishchev
2011-06-15 13:57 ` Stefan Hajnoczi
2011-06-16 8:10 ` Dmitry Konishchev
2011-06-17 7:25 ` Stefan Hajnoczi
2011-06-15 10:14 ` Dmitry Konishchev
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=20110613082608.GA25582@stefanha-thinkpad.localdomain \
--to=stefanha@gmail.com \
--cc=konishchev@gmail.com \
--cc=kwolf@redhat.com \
--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).