qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] Qemu-img convert with -B
@ 2011-04-27  3:05 Brad Campbell
  2011-04-27  8:10 ` Stefan Hajnoczi
  0 siblings, 1 reply; 10+ messages in thread
From: Brad Campbell @ 2011-04-27  3:05 UTC (permalink / raw)
  To: qemu-devel

G'day all,

I see there is a bug raised about the behaviour of qemu-img when used to 
convert using an output backing file. It allocates every sector whether 
or not it already exists in the output backing file.

I'm walking my way through the block driver to try and get a handle on 
why this is the case.

The comment in qemu-img.c is :

                 /* 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.

Can someone verify these assumptions for me please?
- I can bdrv_open() a file that has a chain of backing files, and the 
following is true :
	- bdrv_read() returns the most recently allocated sector contents (or 0)
	- bdrv_is_allocated() will return false only if that sector is not 
allocated in _any_ of the files in the chain

If these assumptions are true, can anyone see a logical error in 
bdrv_open() both the input file and the out_baseimg, and where sectors 
are allocated comparing them to see if the are the same. If so, not 
allocating those in the output file?

I'm assuming the comment above is to allow for the case that someone 
specifies the output backing file being different from the last input 
backing file.

Am I missing something?

Regards,
Brad

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] Qemu-img convert with -B
  2011-04-27  3:05 [Qemu-devel] Qemu-img convert with -B Brad Campbell
@ 2011-04-27  8:10 ` Stefan Hajnoczi
  2011-04-27  8:56   ` Brad Campbell
  0 siblings, 1 reply; 10+ messages in thread
From: Stefan Hajnoczi @ 2011-04-27  8:10 UTC (permalink / raw)
  To: Brad Campbell; +Cc: qemu-devel

On Wed, Apr 27, 2011 at 4:05 AM, Brad Campbell
<lists2009@fnarfbargle.com> wrote:
> I see there is a bug raised about the behaviour of qemu-img when used to convert using an output backing file. It allocates every sector whether or not it already exists in the output backing file.

Please post the link to the bug report.

> Can someone verify these assumptions for me please?
> - I can bdrv_open() a file that has a chain of backing files, and the
> following is true :
>        - bdrv_read() returns the most recently allocated sector contents (or
> 0)

Correct.

>        - bdrv_is_allocated() will return false only if that sector is not
> allocated in _any_ of the files in the chain

Incorrect.  It returns true if the sector is allocated in the top-most
file, false otherwise.  In other words bdrv_is_allocated() is flat, it
does not traverse a chain of backing files.

Stefan

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] Qemu-img convert with -B
  2011-04-27  8:10 ` Stefan Hajnoczi
@ 2011-04-27  8:56   ` Brad Campbell
  2011-04-27 10:06     ` Kevin Wolf
  0 siblings, 1 reply; 10+ messages in thread
From: Brad Campbell @ 2011-04-27  8:56 UTC (permalink / raw)
  To: Stefan Hajnoczi; +Cc: qemu-devel, Brad Campbell

On 27/04/11 16:10, Stefan Hajnoczi wrote:
> On Wed, Apr 27, 2011 at 4:05 AM, Brad Campbell
> <lists2009@fnarfbargle.com>  wrote:
>> I see there is a bug raised about the behaviour of qemu-img when used to convert using an output backing file. It allocates every sector whether or not it already exists in the output backing file.
> Please post the link to the bug report.
>
Yeah, sorry about that. Not very clever of me.

https://bugs.launchpad.net/qemu/+bug/660366
>> Can someone verify these assumptions for me please?
>> - I can bdrv_open() a file that has a chain of backing files, and the
>> following is true :
>>         - bdrv_read() returns the most recently allocated sector contents (or
>> 0)
> Correct.
>
>>         - bdrv_is_allocated() will return false only if that sector is not
>> allocated in _any_ of the files in the chain
> Incorrect.  It returns true if the sector is allocated in the top-most
> file, false otherwise.  In other words bdrv_is_allocated() is flat, it
> does not traverse a chain of backing files.

Right.

I guess the correct way to do this is to open and traverse all the input and output backing files, 
but I don't see why that should be necessary as the output file is created O_RDWR.

Now as the output file is created with the backing_file option, can I simply bdrv_read() both input 
and output files, and only write to the output file if the sector differs or != 0? Seems like that 
would be the logical way to do everything right while leveraging the complexity of the block 
drivers. It would also allow for maximum "compression" of the output file if the filesystem has all 
unused space wiped (which is my desired usage case).

Brad

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] Qemu-img convert with -B
  2011-04-27  8:56   ` Brad Campbell
@ 2011-04-27 10:06     ` Kevin Wolf
  2011-04-27 13:45       ` Brad Campbell
  0 siblings, 1 reply; 10+ messages in thread
From: Kevin Wolf @ 2011-04-27 10:06 UTC (permalink / raw)
  To: Brad Campbell; +Cc: Stefan Hajnoczi, qemu-devel, Brad Campbell

Am 27.04.2011 10:56, schrieb Brad Campbell:
> On 27/04/11 16:10, Stefan Hajnoczi wrote:
>> On Wed, Apr 27, 2011 at 4:05 AM, Brad Campbell
>> <lists2009@fnarfbargle.com>  wrote:
>>> I see there is a bug raised about the behaviour of qemu-img when used to convert using an output backing file. It allocates every sector whether or not it already exists in the output backing file.
>> Please post the link to the bug report.
>>
> Yeah, sorry about that. Not very clever of me.
> 
> https://bugs.launchpad.net/qemu/+bug/660366

I think this bug is fixed by commit a18953fb.

>>> Can someone verify these assumptions for me please?
>>> - I can bdrv_open() a file that has a chain of backing files, and the
>>> following is true :
>>>         - bdrv_read() returns the most recently allocated sector contents (or
>>> 0)
>> Correct.
>>
>>>         - bdrv_is_allocated() will return false only if that sector is not
>>> allocated in _any_ of the files in the chain
>> Incorrect.  It returns true if the sector is allocated in the top-most
>> file, false otherwise.  In other words bdrv_is_allocated() is flat, it
>> does not traverse a chain of backing files.
> 
> Right.
> 
> I guess the correct way to do this is to open and traverse all the input and output backing files, 
> but I don't see why that should be necessary as the output file is created O_RDWR.
> 
> Now as the output file is created with the backing_file option, can I simply bdrv_read() both input 
> and output files, and only write to the output file if the sector differs or != 0? Seems like that 
> would be the logical way to do everything right while leveraging the complexity of the block 
> drivers. It would also allow for maximum "compression" of the output file if the filesystem has all 
> unused space wiped (which is my desired usage case).

qemu-img convert -B is supposed to work only with unchanged backing
files! I'm not aware of any major use cases besides renaming the backing
file (for which rebase -u exists today), so it's only there for
compatibility reasons.  What you describe looks much more like qemu-img
rebase.

Kevin

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] Qemu-img convert with -B
  2011-04-27 10:06     ` Kevin Wolf
@ 2011-04-27 13:45       ` Brad Campbell
  2011-04-27 13:56         ` Kevin Wolf
  0 siblings, 1 reply; 10+ messages in thread
From: Brad Campbell @ 2011-04-27 13:45 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: Stefan Hajnoczi, qemu-devel

On 27/04/11 18:06, Kevin Wolf wrote:
> Am 27.04.2011 10:56, schrieb Brad Campbell:
>> On 27/04/11 16:10, Stefan Hajnoczi wrote:
>>> On Wed, Apr 27, 2011 at 4:05 AM, Brad Campbell
>>> <lists2009@fnarfbargle.com>   wrote:
>>>> I see there is a bug raised about the behaviour of qemu-img when used to convert using an output backing file. It allocates every sector whether or not it already exists in the output backing file.
>>> Please post the link to the bug report.
>>>
>> Yeah, sorry about that. Not very clever of me.
>>
>> https://bugs.launchpad.net/qemu/+bug/660366
>
> I think this bug is fixed by commit a18953fb.

And indeed it is. Thus while the issue I'm facing looks like that bug, 
it's either another one or my misunderstanding about how backing files work.

So what is happening here then?

- create 1.img as a 20G qcow2
- 1.img is 193k
- Install windows XP into 1.img
- 1.img is 1.5G
- create 2.img as a qcow2 with 1.img as a backing file.
- 2.img is ~150k
- Install/uninstall and generally use 2.img
- 2.img is 7G
- Mount 2.img with systemrescuecd and use ntfswipe -a which zero's all 
unused data and cluster tails.
- 2.img is 20G
- qemu-img convert -O qcow2 -o backing_file 1.img 2.img 3.img
- 3.img is 20G

If I do the same process without the backing file..

- create 1.img as a 20G qcow2
- 1.img is 193k
- Install windows XP into 1.img
- 1.img is 1.5G
- Install/Uninstall and generally use 1.img
- 1.img is 7G
- Mount 1.img with systemrescuecd and use ntfswipe
- 1.img is 20G
- qemu-img convert -O qcow2 1.img 3.img
- 3.img is 4G

Why does the first example write out all the zeroed sectors into the 
image while the second one doesn't?

Regards,
Brad

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] Qemu-img convert with -B
  2011-04-27 13:45       ` Brad Campbell
@ 2011-04-27 13:56         ` Kevin Wolf
  2011-04-27 14:02           ` Brad Campbell
  0 siblings, 1 reply; 10+ messages in thread
From: Kevin Wolf @ 2011-04-27 13:56 UTC (permalink / raw)
  To: Brad Campbell; +Cc: Stefan Hajnoczi, qemu-devel

Am 27.04.2011 15:45, schrieb Brad Campbell:
> On 27/04/11 18:06, Kevin Wolf wrote:
>> Am 27.04.2011 10:56, schrieb Brad Campbell:
>>> On 27/04/11 16:10, Stefan Hajnoczi wrote:
>>>> On Wed, Apr 27, 2011 at 4:05 AM, Brad Campbell
>>>> <lists2009@fnarfbargle.com>   wrote:
>>>>> I see there is a bug raised about the behaviour of qemu-img when used to convert using an output backing file. It allocates every sector whether or not it already exists in the output backing file.
>>>> Please post the link to the bug report.
>>>>
>>> Yeah, sorry about that. Not very clever of me.
>>>
>>> https://bugs.launchpad.net/qemu/+bug/660366
>>
>> I think this bug is fixed by commit a18953fb.
> 
> And indeed it is. Thus while the issue I'm facing looks like that bug, 
> it's either another one or my misunderstanding about how backing files work.
> 
> So what is happening here then?
> 
> - create 1.img as a 20G qcow2
> - 1.img is 193k
> - Install windows XP into 1.img
> - 1.img is 1.5G
> - create 2.img as a qcow2 with 1.img as a backing file.
> - 2.img is ~150k
> - Install/uninstall and generally use 2.img
> - 2.img is 7G
> - Mount 2.img with systemrescuecd and use ntfswipe -a which zero's all 
> unused data and cluster tails.
> - 2.img is 20G
> - qemu-img convert -O qcow2 -o backing_file 1.img 2.img 3.img
> - 3.img is 20G
> 
> If I do the same process without the backing file..
> 
> - create 1.img as a 20G qcow2
> - 1.img is 193k
> - Install windows XP into 1.img
> - 1.img is 1.5G
> - Install/Uninstall and generally use 1.img
> - 1.img is 7G
> - Mount 1.img with systemrescuecd and use ntfswipe
> - 1.img is 20G
> - qemu-img convert -O qcow2 1.img 3.img
> - 3.img is 4G
> 
> Why does the first example write out all the zeroed sectors into the 
> image while the second one doesn't?

When you don't have a backing file, leaving an cluster unallocated means
that it's zero. When you have a backing file, it could be anything. So
if qemu-img convert wanted to save this space, it would have to read
from the backing file and leave the cluster unallocated if it reads as zero.

This is something that qemu-img doesn't do today.

Kevin

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] Qemu-img convert with -B
  2011-04-27 13:56         ` Kevin Wolf
@ 2011-04-27 14:02           ` Brad Campbell
  2011-04-28  2:06             ` Brad Campbell
  0 siblings, 1 reply; 10+ messages in thread
From: Brad Campbell @ 2011-04-27 14:02 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: Stefan Hajnoczi, qemu-devel

On 27/04/11 21:56, Kevin Wolf wrote:

> When you don't have a backing file, leaving an cluster unallocated means
> that it's zero. When you have a backing file, it could be anything. So
> if qemu-img convert wanted to save this space, it would have to read
> from the backing file and leave the cluster unallocated if it reads as zero.
>
> This is something that qemu-img doesn't do today.

... which would explain the behaviour I'm seeing then. Great, time to 
dust off my Kernighan & Ritchie I guess.

Thanks for the explanation.

Regards,
Brad

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] Qemu-img convert with -B
  2011-04-27 14:02           ` Brad Campbell
@ 2011-04-28  2:06             ` Brad Campbell
  2011-04-28  6:36               ` Kevin Wolf
  0 siblings, 1 reply; 10+ messages in thread
From: Brad Campbell @ 2011-04-28  2:06 UTC (permalink / raw)
  To: Brad Campbell; +Cc: Kevin Wolf, Stefan Hajnoczi, qemu-devel

On 27/04/11 22:02, Brad Campbell wrote:
> On 27/04/11 21:56, Kevin Wolf wrote:
>
>> When you don't have a backing file, leaving an cluster unallocated means
>> that it's zero. When you have a backing file, it could be anything. So
>> if qemu-img convert wanted to save this space, it would have to read
>> from the backing file and leave the cluster unallocated if it reads as
>> zero.
>>
>> This is something that qemu-img doesn't do today.
>

This passes cursory testing, but I'm just wondering if this is along the 
right lines?

diff --git a/qemu-img.c b/qemu-img.c
index d9c2c12..ab4c70c 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1,4 +1,4 @@
-/*
+ /*
   * QEMU disk image utility
   *
   * Copyright (c) 2003-2008 Fabrice Bellard
@@ -571,11 +571,12 @@ static int img_convert(int argc, char **argv)
      int progress = 0;
      const char *fmt, *out_fmt, *out_baseimg, *out_filename;
      BlockDriver *drv, *proto_drv;
-    BlockDriverState **bs = NULL, *out_bs = NULL;
+    BlockDriverState **bs = NULL, *out_bs = NULL, *out_bf = NULL;
      int64_t total_sectors, nb_sectors, sector_num, bs_offset;
      uint64_t bs_sectors;
      uint8_t * buf = NULL;
      const uint8_t *buf1;
+    uint8_t * buf3 = NULL;
      BlockDriverInfo bdi;
      QEMUOptionParameter *param = NULL, *create_options = NULL;
      QEMUOptionParameter *out_baseimg_param;
@@ -719,6 +720,12 @@ static int img_convert(int argc, char **argv)
      out_baseimg_param = get_option_parameter(param, 
BLOCK_OPT_BACKING_FILE);
      if (out_baseimg_param) {
          out_baseimg = out_baseimg_param->value.s;
+       out_bf = bdrv_new_open(out_baseimg, NULL, BDRV_O_FLAGS);
+       if (!out_bf) {
+            error_report("Could not open backing file '%s'", out_baseimg);
+            ret = -1;
+            goto out;
+        }
      }

      /* Check if compression is supported */
@@ -767,6 +774,9 @@ static int img_convert(int argc, char **argv)
      bs_offset = 0;
      bdrv_get_geometry(bs[0], &bs_sectors);
      buf = qemu_malloc(IO_BUF_SIZE);
+    if (out_baseimg) {
+        buf3 = qemu_malloc(IO_BUF_SIZE);
+    }

      if (compress) {
          ret = bdrv_get_info(out_bs, &bdi);
@@ -889,9 +899,17 @@ 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)) {
+                    if (bdrv_read(bs[bs_i], sector_num - bs_offset, 
buf, n) < 0) {
+                        error_report("error while reading input file");
+                        goto out;
+                    }
+                    if (bdrv_read(out_bf, sector_num - bs_offset, buf3, 
n) < 0) {
+                        error_report("error while reading backing file");
+                        goto out;
+                    }
+                    if (!compare_sectors(buf, buf3, n, &n1)) {
                          sector_num += n1;
+    //                    printf("Skipping %u sectors\n",n1);
                          continue;
                      }
                      /* The next 'n1' sectors are allocated in the 
input image. Copy
@@ -939,9 +957,16 @@ out:
      free_option_parameters(create_options);
      free_option_parameters(param);
      qemu_free(buf);
+    if (buf3) {
+        qemu_free(buf3);
+    }
      if (out_bs) {
          bdrv_delete(out_bs);
      }
+    if (out_bf) {
+        bdrv_delete(out_bf);
+    }
+
      if (bs) {
          for (bs_i = 0; bs_i < bs_n; bs_i++) {
              if (bs[bs_i]) {

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] Qemu-img convert with -B
  2011-04-28  2:06             ` Brad Campbell
@ 2011-04-28  6:36               ` Kevin Wolf
  2011-04-28  9:38                 ` Brad Campbell
  0 siblings, 1 reply; 10+ messages in thread
From: Kevin Wolf @ 2011-04-28  6:36 UTC (permalink / raw)
  To: Brad Campbell; +Cc: Stefan Hajnoczi, qemu-devel, Brad Campbell

Am 28.04.2011 04:06, schrieb Brad Campbell:
> On 27/04/11 22:02, Brad Campbell wrote:
>> On 27/04/11 21:56, Kevin Wolf wrote:
>>
>>> When you don't have a backing file, leaving an cluster unallocated means
>>> that it's zero. When you have a backing file, it could be anything. So
>>> if qemu-img convert wanted to save this space, it would have to read
>>> from the backing file and leave the cluster unallocated if it reads as
>>> zero.
>>>
>>> This is something that qemu-img doesn't do today.
>>
> 
> This passes cursory testing, but I'm just wondering if this is along the 
> right lines?

I haven't checked all details, but it looks like what I would have done.
(Though something is wrong with your indentations, I suspect that the
patch wouldn't apply)

> @@ -939,9 +957,16 @@ out:
>       free_option_parameters(create_options);
>       free_option_parameters(param);
>       qemu_free(buf);
> +    if (buf3) {
> +        qemu_free(buf3);
> +    }

qemu_free (and the libc free, too) work just fine with NULL, so the
check isn't needed.

Kevin

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] Qemu-img convert with -B
  2011-04-28  6:36               ` Kevin Wolf
@ 2011-04-28  9:38                 ` Brad Campbell
  0 siblings, 0 replies; 10+ messages in thread
From: Brad Campbell @ 2011-04-28  9:38 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: Stefan Hajnoczi, qemu-devel

On 28/04/11 14:36, Kevin Wolf wrote:
> Am 28.04.2011 04:06, schrieb Brad Campbell:
>> On 27/04/11 22:02, Brad Campbell wrote:
>>> On 27/04/11 21:56, Kevin Wolf wrote:
>>>
>>>> When you don't have a backing file, leaving an cluster unallocated means
>>>> that it's zero. When you have a backing file, it could be anything. So
>>>> if qemu-img convert wanted to save this space, it would have to read
>>>> from the backing file and leave the cluster unallocated if it reads as
>>>> zero.
>>>>
>>>> This is something that qemu-img doesn't do today.
>> This passes cursory testing, but I'm just wondering if this is along the
>> right lines?
> I haven't checked all details, but it looks like what I would have done.
> (Though something is wrong with your indentations, I suspect that the
> patch wouldn't apply)
>

Odd, I generated it with git diff. Must have lost something in the copy & paste from the terminal.

I'm using tabs=spaces and a ts of 4 in vim. It seemed to fit in with the rest of the file.

>> @@ -939,9 +957,16 @@ out:
>>        free_option_parameters(create_options);
>>        free_option_parameters(param);
>>        qemu_free(buf);
>> +    if (buf3) {
>> +        qemu_free(buf3);
>> +    }
> qemu_free (and the libc free, too) work just fine with NULL, so the
> check isn't needed.

I ran some more tests on it and there are some small issues I need to fix up, but it does what it 
says on the tin.

Cheers for the feedback, I'll do some cleanups and prepare something for submission.

Regards,
Brad

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2011-04-28 10:23 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-27  3:05 [Qemu-devel] Qemu-img convert with -B Brad Campbell
2011-04-27  8:10 ` Stefan Hajnoczi
2011-04-27  8:56   ` Brad Campbell
2011-04-27 10:06     ` Kevin Wolf
2011-04-27 13:45       ` Brad Campbell
2011-04-27 13:56         ` Kevin Wolf
2011-04-27 14:02           ` Brad Campbell
2011-04-28  2:06             ` Brad Campbell
2011-04-28  6:36               ` Kevin Wolf
2011-04-28  9:38                 ` Brad Campbell

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).