Blame SOURCES/kvm-qcow2-Forward-ZERO_WRITE-flag-for-full-preallocation.patch

77c23f
From 4290173219e15065e9a7c2e95774ac979b5fd869 Mon Sep 17 00:00:00 2001
77c23f
From: Kevin Wolf <kwolf@redhat.com>
77c23f
Date: Mon, 8 Jun 2020 15:01:40 +0100
77c23f
Subject: [PATCH 12/17] qcow2: Forward ZERO_WRITE flag for full preallocation
77c23f
77c23f
RH-Author: Kevin Wolf <kwolf@redhat.com>
77c23f
Message-id: <20200608150140.38218-12-kwolf@redhat.com>
77c23f
Patchwork-id: 97456
77c23f
O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 11/11] qcow2: Forward ZERO_WRITE flag for full preallocation
77c23f
Bugzilla: 1780574
77c23f
RH-Acked-by: Sergio Lopez Pascual <slp@redhat.com>
77c23f
RH-Acked-by: Eric Blake <eblake@redhat.com>
77c23f
RH-Acked-by: Max Reitz <mreitz@redhat.com>
77c23f
77c23f
The BDRV_REQ_ZERO_WRITE is currently implemented in a way that first the
77c23f
image is possibly preallocated and then the zero flag is added to all
77c23f
clusters. This means that a copy-on-write operation may be needed when
77c23f
writing to these clusters, despite having used preallocation, negating
77c23f
one of the major benefits of preallocation.
77c23f
77c23f
Instead, try to forward the BDRV_REQ_ZERO_WRITE to the protocol driver,
77c23f
and if the protocol driver can ensure that the new area reads as zeros,
77c23f
we can skip setting the zero flag in the qcow2 layer.
77c23f
77c23f
Unfortunately, the same approach doesn't work for metadata
77c23f
preallocation, so we'll still set the zero flag there.
77c23f
77c23f
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
77c23f
Reviewed-by: Max Reitz <mreitz@redhat.com>
77c23f
Message-Id: <20200424142701.67053-1-kwolf@redhat.com>
77c23f
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
77c23f
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
77c23f
(cherry picked from commit eb8a0cf3ba26611f3981f8f45ac6a868975a68cc)
77c23f
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
77c23f
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
77c23f
---
77c23f
 block/qcow2.c              | 22 +++++++++++++++++++---
77c23f
 tests/qemu-iotests/274.out |  4 ++--
77c23f
 2 files changed, 21 insertions(+), 5 deletions(-)
77c23f
77c23f
diff --git a/block/qcow2.c b/block/qcow2.c
77c23f
index f3d6cb0..b783662 100644
77c23f
--- a/block/qcow2.c
77c23f
+++ b/block/qcow2.c
77c23f
@@ -4153,9 +4153,25 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
77c23f
         /* Allocate the data area */
77c23f
         new_file_size = allocation_start +
77c23f
                         nb_new_data_clusters * s->cluster_size;
77c23f
-        /* Image file grows, so @exact does not matter */
77c23f
-        ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
77c23f
-                               errp);
77c23f
+        /*
77c23f
+         * Image file grows, so @exact does not matter.
77c23f
+         *
77c23f
+         * If we need to zero out the new area, try first whether the protocol
77c23f
+         * driver can already take care of this.
77c23f
+         */
77c23f
+        if (flags & BDRV_REQ_ZERO_WRITE) {
77c23f
+            ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc,
77c23f
+                                   BDRV_REQ_ZERO_WRITE, NULL);
77c23f
+            if (ret >= 0) {
77c23f
+                flags &= ~BDRV_REQ_ZERO_WRITE;
77c23f
+            }
77c23f
+        } else {
77c23f
+            ret = -1;
77c23f
+        }
77c23f
+        if (ret < 0) {
77c23f
+            ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
77c23f
+                                   errp);
77c23f
+        }
77c23f
         if (ret < 0) {
77c23f
             error_prepend(errp, "Failed to resize underlying file: ");
77c23f
             qcow2_free_clusters(bs, allocation_start,
77c23f
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
77c23f
index 1a796fd..9d6fdeb 100644
77c23f
--- a/tests/qemu-iotests/274.out
77c23f
+++ b/tests/qemu-iotests/274.out
77c23f
@@ -187,7 +187,7 @@ read 65536/65536 bytes at offset 9437184
77c23f
 10 MiB (0xa00000) bytes     allocated at offset 5 MiB (0x500000)
77c23f
 
77c23f
 [{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
77c23f
-{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
77c23f
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
77c23f
 
77c23f
 === preallocation=full ===
77c23f
 Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
77c23f
@@ -206,7 +206,7 @@ read 65536/65536 bytes at offset 11534336
77c23f
 4 MiB (0x400000) bytes     allocated at offset 8 MiB (0x800000)
77c23f
 
77c23f
 [{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
77c23f
-{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
77c23f
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
77c23f
 
77c23f
 === preallocation=off ===
77c23f
 Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
77c23f
-- 
77c23f
1.8.3.1
77c23f