Blame SOURCES/kvm-qemu-img-make-is_allocated_sectors-more-efficient.patch

2bc292
From a221f5a8ed02690687e6709c49ae0e1e01c5f466 Mon Sep 17 00:00:00 2001
2bc292
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2bc292
Date: Fri, 17 Dec 2021 17:46:54 +0100
2bc292
Subject: [PATCH 09/12] qemu-img: make is_allocated_sectors() more efficient
2bc292
2bc292
RH-Author: Kevin Wolf <kwolf@redhat.com>
2bc292
RH-MergeRequest: 70: qemu-img convert: Fix sparseness of output image
2bc292
RH-Commit: [2/2] cc05aa4ac506b57ff9b430c007618cdf1485a03f (kmwolf/centos-qemu-kvm)
2bc292
RH-Bugzilla: 1882917
2bc292
RH-Acked-by: Eric Blake <eblake@redhat.com>
2bc292
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
2bc292
RH-Acked-by: Hanna Reitz <hreitz@redhat.com>
2bc292
2bc292
Consider the case when the whole buffer is zero and end is unaligned.
2bc292
2bc292
If i <= tail, we return 1 and do one unaligned WRITE, RMW happens.
2bc292
2bc292
If i > tail, we do on aligned WRITE_ZERO (or skip if target is zeroed)
2bc292
and again one unaligned WRITE, RMW happens.
2bc292
2bc292
Let's do better: don't fragment the whole-zero buffer and report it as
2bc292
ZERO: in case of zeroed target we just do nothing and avoid RMW. If
2bc292
target is not zeroes, one unaligned WRITE_ZERO should not be much worse
2bc292
than one unaligned WRITE.
2bc292
2bc292
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2bc292
Message-Id: <20211217164654.1184218-3-vsementsov@virtuozzo.com>
2bc292
Tested-by: Peter Lieven <pl@kamp.de>
2bc292
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2bc292
(cherry picked from commit 96054c76ff2db74165385a69f234c57a6bbc941e)
2bc292
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2bc292
---
2bc292
 qemu-img.c                 | 23 +++++++++++++++++++----
2bc292
 tests/qemu-iotests/122.out |  8 ++------
2bc292
 2 files changed, 21 insertions(+), 10 deletions(-)
2bc292
2bc292
diff --git a/qemu-img.c b/qemu-img.c
2bc292
index f036a1d428..d7ddfcc528 100644
2bc292
--- a/qemu-img.c
2bc292
+++ b/qemu-img.c
2bc292
@@ -1171,19 +1171,34 @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum,
2bc292
         }
2bc292
     }
2bc292
 
2bc292
+    if (i == n) {
2bc292
+        /*
2bc292
+         * The whole buf is the same.
2bc292
+         * No reason to split it into chunks, so return now.
2bc292
+         */
2bc292
+        *pnum = i;
2bc292
+        return !is_zero;
2bc292
+    }
2bc292
+
2bc292
     tail = (sector_num + i) & (alignment - 1);
2bc292
     if (tail) {
2bc292
         if (is_zero && i <= tail) {
2bc292
-            /* treat unallocated areas which only consist
2bc292
-             * of a small tail as allocated. */
2bc292
+            /*
2bc292
+             * For sure next sector after i is data, and it will rewrite this
2bc292
+             * tail anyway due to RMW. So, let's just write data now.
2bc292
+             */
2bc292
             is_zero = false;
2bc292
         }
2bc292
         if (!is_zero) {
2bc292
-            /* align up end offset of allocated areas. */
2bc292
+            /* If possible, align up end offset of allocated areas. */
2bc292
             i += alignment - tail;
2bc292
             i = MIN(i, n);
2bc292
         } else {
2bc292
-            /* align down end offset of zero areas. */
2bc292
+            /*
2bc292
+             * For sure next sector after i is data, and it will rewrite this
2bc292
+             * tail anyway due to RMW. Better is avoid RMW and write zeroes up
2bc292
+             * to aligned bound.
2bc292
+             */
2bc292
             i -= tail;
2bc292
         }
2bc292
     }
2bc292
diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out
2bc292
index 69b8e8b803..e18766e167 100644
2bc292
--- a/tests/qemu-iotests/122.out
2bc292
+++ b/tests/qemu-iotests/122.out
2bc292
@@ -201,9 +201,7 @@ convert -S 4k
2bc292
 { "start": 8192, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
2bc292
 { "start": 12288, "length": 4096, "depth": 0, "present": false, "zero": true, "data": false},
2bc292
 { "start": 16384, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
2bc292
-{ "start": 20480, "length": 46080, "depth": 0, "present": false, "zero": true, "data": false},
2bc292
-{ "start": 66560, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
2bc292
-{ "start": 67584, "length": 67041280, "depth": 0, "present": false, "zero": true, "data": false}]
2bc292
+{ "start": 20480, "length": 67088384, "depth": 0, "present": false, "zero": true, "data": false}]
2bc292
 
2bc292
 convert -c -S 4k
2bc292
 [{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true},
2bc292
@@ -215,9 +213,7 @@ convert -c -S 4k
2bc292
 
2bc292
 convert -S 8k
2bc292
 [{ "start": 0, "length": 24576, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
2bc292
-{ "start": 24576, "length": 41984, "depth": 0, "present": false, "zero": true, "data": false},
2bc292
-{ "start": 66560, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
2bc292
-{ "start": 67584, "length": 67041280, "depth": 0, "present": false, "zero": true, "data": false}]
2bc292
+{ "start": 24576, "length": 67084288, "depth": 0, "present": false, "zero": true, "data": false}]
2bc292
 
2bc292
 convert -c -S 8k
2bc292
 [{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true},
2bc292
-- 
2bc292
2.27.0
2bc292