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

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