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

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