diff mbox

[RFC,5/5] block: bdrv_has_zero_init

Message ID 1271260214-27443-6-git-send-email-kwolf@redhat.com
State New
Headers show

Commit Message

Kevin Wolf April 14, 2010, 3:50 p.m. UTC
This fixes the problem that qemu-img's use of no_zero_init only considered the
no_zero_init flag of the format driver, but not of the underlying protocols.

Between the raw/file split and this fix, converting to host devices is broken.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c    |   13 +++++++++++++
 block.h    |    1 +
 qemu-img.c |    6 ++++--
 3 files changed, 18 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/block.c b/block.c
index 6c66974..cf75f97 100644
--- a/block.c
+++ b/block.c
@@ -1281,6 +1281,19 @@  void bdrv_flush_all(void)
     }
 }
 
+int bdrv_has_zero_init(BlockDriverState *bs)
+{
+    assert(bs->drv);
+
+    if (bs->drv->no_zero_init) {
+        return 0;
+    } else if (bs->file) {
+        return bdrv_has_zero_init(bs->file);
+    }
+
+    return 1;
+}
+
 /*
  * Returns true iff the specified sector is present in the disk image. Drivers
  * not implementing the functionality are assumed to not support backing files,
diff --git a/block.h b/block.h
index f58edf1..f87d24e 100644
--- a/block.h
+++ b/block.h
@@ -122,6 +122,7 @@  BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
 void bdrv_flush(BlockDriverState *bs);
 void bdrv_flush_all(void);
 
+int bdrv_has_zero_init(BlockDriverState *bs);
 int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
 	int *pnum);
 
diff --git a/qemu-img.c b/qemu-img.c
index 7203b8b..74311a5 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -732,6 +732,8 @@  static int img_convert(int argc, char **argv)
         /* signal EOF to align */
         bdrv_write_compressed(out_bs, 0, NULL, 0);
     } else {
+        int has_zero_init = bdrv_has_zero_init(out_bs);
+
         sector_num = 0; // total number of sectors converted so far
         for(;;) {
             nb_sectors = total_sectors - sector_num;
@@ -755,7 +757,7 @@  static int img_convert(int argc, char **argv)
             if (n > bs_offset + bs_sectors - sector_num)
                 n = bs_offset + bs_sectors - sector_num;
 
-            if (!drv->no_zero_init) {
+            if (has_zero_init) {
                 /* If the output image is being created as a copy on write image,
                    assume that sectors which are unallocated in the input image
                    are present in both the output's and input's base images (no
@@ -788,7 +790,7 @@  static int img_convert(int argc, char **argv)
                    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 (drv->no_zero_init || out_baseimg ||
+                if (!has_zero_init || out_baseimg ||
                     is_allocated_sectors(buf1, n, &n1)) {
                     if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
                         error("error while writing");