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

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