Blame SOURCES/kvm-qcow2-Give-the-refcount-cache-the-minimum-possible-s.patch

7711c0
From f212cada55593c16cbfdfce2eee75ccd7b375e38 Mon Sep 17 00:00:00 2001
7711c0
From: Kevin Wolf <kwolf@redhat.com>
7711c0
Date: Tue, 19 Feb 2019 17:00:11 +0100
7711c0
Subject: [PATCH 10/23] qcow2: Give the refcount cache the minimum possible
7711c0
 size by default
7711c0
7711c0
RH-Author: Kevin Wolf <kwolf@redhat.com>
7711c0
Message-id: <20190219170023.27826-2-kwolf@redhat.com>
7711c0
Patchwork-id: 84541
7711c0
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 01/13] qcow2: Give the refcount cache the minimum possible size by default
7711c0
Bugzilla: 1656913
7711c0
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7711c0
RH-Acked-by: Max Reitz <mreitz@redhat.com>
7711c0
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
7711c0
7711c0
From: Alberto Garcia <berto@igalia.com>
7711c0
7711c0
The L2 and refcount caches have default sizes that can be overridden
7711c0
using the l2-cache-size and refcount-cache-size (an additional
7711c0
parameter named cache-size sets the combined size of both caches).
7711c0
7711c0
Unless forced by one of the aforementioned parameters, QEMU will set
7711c0
the unspecified sizes so that the L2 cache is 4 times larger than the
7711c0
refcount cache.
7711c0
7711c0
This is based on the premise that the refcount metadata needs to be
7711c0
only a fourth of the L2 metadata to cover the same amount of disk
7711c0
space. This is incorrect for two reasons:
7711c0
7711c0
 a) The amount of disk covered by an L2 table depends solely on the
7711c0
    cluster size, but in the case of a refcount block it depends on
7711c0
    the cluster size *and* the width of each refcount entry.
7711c0
    The 4/1 ratio is only valid with 16-bit entries (the default).
7711c0
7711c0
 b) When we talk about disk space and L2 tables we are talking about
7711c0
    guest space (L2 tables map guest clusters to host clusters),
7711c0
    whereas refcount blocks are used for host clusters (including
7711c0
    L1/L2 tables and the refcount blocks themselves). On a fully
7711c0
    populated (and uncompressed) qcow2 file, image size > virtual size
7711c0
    so there are more refcount entries than L2 entries.
7711c0
7711c0
Problem (a) could be fixed by adjusting the algorithm to take into
7711c0
account the refcount entry width. Problem (b) could be fixed by
7711c0
increasing a bit the refcount cache size to account for the clusters
7711c0
used for qcow2 metadata.
7711c0
7711c0
However this patch takes a completely different approach and instead
7711c0
of keeping a ratio between both cache sizes it assigns as much as
7711c0
possible to the L2 cache and the remainder to the refcount cache.
7711c0
7711c0
The reason is that L2 tables are used for every single I/O request
7711c0
from the guest and the effect of increasing the cache is significant
7711c0
and clearly measurable. Refcount blocks are however only used for
7711c0
cluster allocation and internal snapshots and in practice are accessed
7711c0
sequentially in most cases, so the effect of increasing the cache is
7711c0
negligible (even when doing random writes from the guest).
7711c0
7711c0
So, make the refcount cache as small as possible unless the user
7711c0
explicitly asks for a larger one.
7711c0
7711c0
Signed-off-by: Alberto Garcia <berto@igalia.com>
7711c0
Reviewed-by: Eric Blake <eblake@redhat.com>
7711c0
Reviewed-by: Max Reitz <mreitz@redhat.com>
7711c0
Message-id: 9695182c2eb11b77cb319689a1ebaa4e7c9d6591.1523968389.git.berto@igalia.com
7711c0
Signed-off-by: Max Reitz <mreitz@redhat.com>
7711c0
(cherry picked from commit 52253998ec3e523c9e20ae81e2a6431d8ff733ba)
7711c0
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7711c0
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
7711c0
---
7711c0
 block/qcow2.c              | 31 +++++++++++++++++++------------
7711c0
 block/qcow2.h              |  4 ----
7711c0
 tests/qemu-iotests/137.out |  2 +-
7711c0
 3 files changed, 20 insertions(+), 17 deletions(-)
7711c0
7711c0
diff --git a/block/qcow2.c b/block/qcow2.c
7711c0
index 36d1152..4b65e4c 100644
7711c0
--- a/block/qcow2.c
7711c0
+++ b/block/qcow2.c
7711c0
@@ -809,23 +809,30 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
7711c0
         } else if (refcount_cache_size_set) {
7711c0
             *l2_cache_size = combined_cache_size - *refcount_cache_size;
7711c0
         } else {
7711c0
-            *refcount_cache_size = combined_cache_size
7711c0
-                                 / (DEFAULT_L2_REFCOUNT_SIZE_RATIO + 1);
7711c0
-            *l2_cache_size = combined_cache_size - *refcount_cache_size;
7711c0
+            uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
7711c0
+            uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8);
7711c0
+            uint64_t min_refcount_cache =
7711c0
+                (uint64_t) MIN_REFCOUNT_CACHE_SIZE * s->cluster_size;
7711c0
+
7711c0
+            /* Assign as much memory as possible to the L2 cache, and
7711c0
+             * use the remainder for the refcount cache */
7711c0
+            if (combined_cache_size >= max_l2_cache + min_refcount_cache) {
7711c0
+                *l2_cache_size = max_l2_cache;
7711c0
+                *refcount_cache_size = combined_cache_size - *l2_cache_size;
7711c0
+            } else {
7711c0
+                *refcount_cache_size =
7711c0
+                    MIN(combined_cache_size, min_refcount_cache);
7711c0
+                *l2_cache_size = combined_cache_size - *refcount_cache_size;
7711c0
+            }
7711c0
         }
7711c0
     } else {
7711c0
-        if (!l2_cache_size_set && !refcount_cache_size_set) {
7711c0
+        if (!l2_cache_size_set) {
7711c0
             *l2_cache_size = MAX(DEFAULT_L2_CACHE_BYTE_SIZE,
7711c0
                                  (uint64_t)DEFAULT_L2_CACHE_CLUSTERS
7711c0
                                  * s->cluster_size);
7711c0
-            *refcount_cache_size = *l2_cache_size
7711c0
-                                 / DEFAULT_L2_REFCOUNT_SIZE_RATIO;
7711c0
-        } else if (!l2_cache_size_set) {
7711c0
-            *l2_cache_size = *refcount_cache_size
7711c0
-                           * DEFAULT_L2_REFCOUNT_SIZE_RATIO;
7711c0
-        } else if (!refcount_cache_size_set) {
7711c0
-            *refcount_cache_size = *l2_cache_size
7711c0
-                                 / DEFAULT_L2_REFCOUNT_SIZE_RATIO;
7711c0
+        }
7711c0
+        if (!refcount_cache_size_set) {
7711c0
+            *refcount_cache_size = MIN_REFCOUNT_CACHE_SIZE * s->cluster_size;
7711c0
         }
7711c0
     }
7711c0
 
7711c0
diff --git a/block/qcow2.h b/block/qcow2.h
7711c0
index 43163b2..3d92cdb 100644
7711c0
--- a/block/qcow2.h
7711c0
+++ b/block/qcow2.h
7711c0
@@ -77,10 +77,6 @@
7711c0
 #define DEFAULT_L2_CACHE_CLUSTERS 8 /* clusters */
7711c0
 #define DEFAULT_L2_CACHE_BYTE_SIZE 1048576 /* bytes */
7711c0
 
7711c0
-/* The refblock cache needs only a fourth of the L2 cache size to cover as many
7711c0
- * clusters */
7711c0
-#define DEFAULT_L2_REFCOUNT_SIZE_RATIO 4
7711c0
-
7711c0
 #define DEFAULT_CLUSTER_SIZE 65536
7711c0
 
7711c0
 
7711c0
diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out
7711c0
index e28e1ea..96724a6 100644
7711c0
--- a/tests/qemu-iotests/137.out
7711c0
+++ b/tests/qemu-iotests/137.out
7711c0
@@ -22,7 +22,7 @@ refcount-cache-size may not exceed cache-size
7711c0
 L2 cache size too big
7711c0
 L2 cache entry size must be a power of two between 512 and the cluster size (65536)
7711c0
 L2 cache entry size must be a power of two between 512 and the cluster size (65536)
7711c0
-L2 cache size too big
7711c0
+Refcount cache size too big
7711c0
 Conflicting values for qcow2 options 'overlap-check' ('constant') and 'overlap-check.template' ('all')
7711c0
 Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
7711c0
 Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
7711c0
-- 
7711c0
1.8.3.1
7711c0