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

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