Blame SOURCES/kvm-qemu-img-Special-post-backing-convert-handling.patch

383d26
From 66e67847293522848a74624c0477299cb87dafa4 Mon Sep 17 00:00:00 2001
383d26
From: Max Reitz <mreitz@redhat.com>
383d26
Date: Mon, 18 Jun 2018 18:04:50 +0200
383d26
Subject: [PATCH 12/89] qemu-img: Special post-backing convert handling
383d26
383d26
RH-Author: Max Reitz <mreitz@redhat.com>
383d26
Message-id: <20180618180451.23808-2-mreitz@redhat.com>
383d26
Patchwork-id: 80795
383d26
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH 1/2] qemu-img: Special post-backing convert handling
383d26
Bugzilla: 1527898
383d26
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
383d26
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
383d26
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
383d26
383d26
Currently, qemu-img convert writes zeroes when it reads zeroes.
383d26
Sometimes it does not because the target is initialized to zeroes
383d26
anyway, so we do not need to overwrite (and thus potentially allocate)
383d26
it.  This is never the case for targets with backing files, though.  But
383d26
even they may have an area that is initialized to zeroes, and that is
383d26
the area past the end of the backing file (if that is shorter than the
383d26
overlay).
383d26
383d26
So if the target format's unallocated blocks are zero and there is a gap
383d26
between the target's backing file's end and the target's end, we do not
383d26
have to explicitly write zeroes there.
383d26
383d26
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1527898
383d26
Signed-off-by: Max Reitz <mreitz@redhat.com>
383d26
Message-id: 20180501165750.19242-2-mreitz@redhat.com
383d26
Reviewed-by: Eric Blake <eblake@redhat.com>
383d26
Signed-off-by: Max Reitz <mreitz@redhat.com>
383d26
(cherry picked from commit 351c8efff9ad809c822d55620df54d575d536f68)
383d26
Signed-off-by: Max Reitz <mreitz@redhat.com>
383d26
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
383d26
---
383d26
 qemu-img.c | 26 +++++++++++++++++++++++++-
383d26
 1 file changed, 25 insertions(+), 1 deletion(-)
383d26
383d26
diff --git a/qemu-img.c b/qemu-img.c
383d26
index 76d6e47..e2395b9 100644
383d26
--- a/qemu-img.c
383d26
+++ b/qemu-img.c
383d26
@@ -1553,7 +1553,9 @@ typedef struct ImgConvertState {
383d26
     BlockBackend *target;
383d26
     bool has_zero_init;
383d26
     bool compressed;
383d26
+    bool unallocated_blocks_are_zero;
383d26
     bool target_has_backing;
383d26
+    int64_t target_backing_sectors; /* negative if unknown */
383d26
     bool wr_in_order;
383d26
     int min_sparse;
383d26
     size_t cluster_sectors;
383d26
@@ -1582,12 +1584,23 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
383d26
 {
383d26
     int64_t src_cur_offset;
383d26
     int ret, n, src_cur;
383d26
+    bool post_backing_zero = false;
383d26
 
383d26
     convert_select_part(s, sector_num, &src_cur, &src_cur_offset);
383d26
 
383d26
     assert(s->total_sectors > sector_num);
383d26
     n = MIN(s->total_sectors - sector_num, BDRV_REQUEST_MAX_SECTORS);
383d26
 
383d26
+    if (s->target_backing_sectors >= 0) {
383d26
+        if (sector_num >= s->target_backing_sectors) {
383d26
+            post_backing_zero = s->unallocated_blocks_are_zero;
383d26
+        } else if (sector_num + n > s->target_backing_sectors) {
383d26
+            /* Split requests around target_backing_sectors (because
383d26
+             * starting from there, zeros are handled differently) */
383d26
+            n = s->target_backing_sectors - sector_num;
383d26
+        }
383d26
+    }
383d26
+
383d26
     if (s->sector_next_status <= sector_num) {
383d26
         int64_t count = n * BDRV_SECTOR_SIZE;
383d26
 
383d26
@@ -1609,7 +1622,7 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
383d26
         n = DIV_ROUND_UP(count, BDRV_SECTOR_SIZE);
383d26
 
383d26
         if (ret & BDRV_BLOCK_ZERO) {
383d26
-            s->status = BLK_ZERO;
383d26
+            s->status = post_backing_zero ? BLK_BACKING_FILE : BLK_ZERO;
383d26
         } else if (ret & BDRV_BLOCK_DATA) {
383d26
             s->status = BLK_DATA;
383d26
         } else {
383d26
@@ -2330,6 +2343,16 @@ static int img_convert(int argc, char **argv)
383d26
         }
383d26
     }
383d26
 
383d26
+    if (s.target_has_backing) {
383d26
+        /* Errors are treated as "backing length unknown" (which means
383d26
+         * s.target_backing_sectors has to be negative, which it will
383d26
+         * be automatically).  The backing file length is used only
383d26
+         * for optimizations, so such a case is not fatal. */
383d26
+        s.target_backing_sectors = bdrv_nb_sectors(out_bs->backing->bs);
383d26
+    } else {
383d26
+        s.target_backing_sectors = -1;
383d26
+    }
383d26
+
383d26
     ret = bdrv_get_info(out_bs, &bdi;;
383d26
     if (ret < 0) {
383d26
         if (s.compressed) {
383d26
@@ -2339,6 +2362,7 @@ static int img_convert(int argc, char **argv)
383d26
     } else {
383d26
         s.compressed = s.compressed || bdi.needs_compressed_writes;
383d26
         s.cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE;
383d26
+        s.unallocated_blocks_are_zero = bdi.unallocated_blocks_are_zero;
383d26
     }
383d26
 
383d26
     ret = convert_do_copy(&s);
383d26
-- 
383d26
1.8.3.1
383d26