qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] Possibly incorrect data sparsification by qemu-img


From: Martin Kletzander
Subject: [Qemu-devel] Possibly incorrect data sparsification by qemu-img
Date: Tue, 23 Apr 2019 13:30:28 +0200
User-agent: Mutt/1.11.4 (2019-03-13)

Hi,

I am using qemu-img with nbdkit to transfer a disk image and the update it with
extra data from newer snapshots.  The end image cannot be transferred because
the snapshots will be created later than the first transfer and we want to save
some time up front.  You might think of it as a continuous synchronisation.  It
looks something like this:

I first transfer the whole image:

 qemu-img convert -p $nbd disk.raw

Where `$nbd` is something along the lines of `nbd+unix:///?socket=nbdkit.sock`

Then, after the next snapshot is created, I can update it thanks to the `-n`
parameter (the $nbd now points to the newer snapshot with unchanged data looking
like holes in the file):

 qemu-img convert -p -n $nbd disk.raw

This is fast and efficient as it uses block status nbd extension, so it only
transfers new data.  This can be done over and over again to keep the local
`disk.raw` image up to date with the latest remote snapshot.

However, when the guest OS zeroes some of the data and it gets written into the
snapshot, qemu-img scans for those zeros and does not write them to the
destination image.  Checking the output of `qemu-img map --output=json $nbd`
shows that the zeroed data is properly marked as `data: true`.

Using `-S 0` would write zeros even where the holes are, effectively overwriting
the data from the last snapshot even though they should not be changed.

Having gone through some workarounds I would like there to be another way.  I
know this is far from the typical usage of qemu-img, but is this really the
expected behaviour or is this just something nobody really needed before?  If it
is the former, would it be possible to have a parameter that would control this
behaviour?  If the latter is the case, can that behaviour be changed so that it
properly replicates the data when `-n` parameter is used?

Basically the only thing we need is to either:

1) write zeros where they actually are or

2) turn off explicit sparsification without requesting dense image (basically
   sparsify only the par that is reported as hole on the source) or

3) ideally, just FALLOC_FL_PUNCH_HOLE in places where source did report data,
   but qemu-img found they are all zeros (or source reported HOLE+ZERO which, I
   believe, is effectively the same)

If you want to try this out, I found the easiest reproducible way is using
nbdkit's data plugin, which can simulate whatever source image you like.

The first iteration, which transfers the whole image can be simulated like this:

 nbdkit --run 'qemu-img convert -p $nbd output.raw' data data="1" size=2M

That command will expose an artificial disk with the size of 2MB which has first
byte '1' and the rest is zeros/holes and runs the specified qemu-img command on
that ($nbd is supplied by nbdkit, so the string needs to be enclosed in single
parentheses).

You can see how that data is exposed by running:

 nbdkit --run 'qemu-img map --output=json $nbd' data data="1" size=2M

For completeness I get this output:

 [{ "start": 0, "length": 32768, "depth": 0, "zero": false, "data": true},
  { "start": 32768, "length": 2064384, "depth": 0, "zero": true, "data": false}]

Consequent update from a snapshot (with the first block explicitly zeroed) could
be simulated by running:

 nbdkit --run 'qemu-img convert -n -p $nbd output.raw' data data="0" size=2M

Again, the mapping exposed by nbdkit can be seen by running:

 nbdkit --run 'qemu-img map --output=json $nbd' data data="0" size=2M

For completeness I get this output:

 [{ "start": 0, "length": 32768, "depth": 0, "zero": true, "data": true},
  { "start": 32768, "length": 2064384, "depth": 0, "zero": true, "data": false}]

The resulting image still has `1` as its first byte (following is the output of
`hexdump -C output.raw`):

 00000000  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 *
 00200000

Have a nice day,
Martin

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]