Blame SOURCES/kvm-qcow2-Assign-the-L2-cache-relatively-to-the-image-si.patch

ae23c9
From 85dd7b43885d64406c5ea9af9daefe89a6c7475f Mon Sep 17 00:00:00 2001
ae23c9
From: Kevin Wolf <kwolf@redhat.com>
ae23c9
Date: Thu, 6 Dec 2018 17:12:34 +0000
ae23c9
Subject: [PATCH 09/15] qcow2: Assign the L2 cache relatively to the image size
ae23c9
ae23c9
RH-Author: Kevin Wolf <kwolf@redhat.com>
ae23c9
Message-id: <20181206171240.5674-10-kwolf@redhat.com>
ae23c9
Patchwork-id: 83289
ae23c9
O-Subject: [RHEL-8.0 qemu-kvm PATCH 09/15] qcow2: Assign the L2 cache relatively to the image size
ae23c9
Bugzilla: 1656507
ae23c9
RH-Acked-by: Max Reitz <mreitz@redhat.com>
ae23c9
RH-Acked-by: John Snow <jsnow@redhat.com>
ae23c9
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
ae23c9
ae23c9
From: Leonid Bloch <lbloch@janustech.com>
ae23c9
ae23c9
Sufficient L2 cache can noticeably improve the performance when using
ae23c9
large images with frequent I/O.
ae23c9
ae23c9
Previously, unless 'cache-size' was specified and was large enough, the
ae23c9
L2 cache was set to a certain size without taking the virtual image size
ae23c9
into account.
ae23c9
ae23c9
Now, the L2 cache assignment is aware of the virtual size of the image,
ae23c9
and will cover the entire image, unless the cache size needed for that is
ae23c9
larger than a certain maximum. This maximum is set to 1 MB by default
ae23c9
(enough to cover an 8 GB image with the default cluster size) but can
ae23c9
be increased or decreased using the 'l2-cache-size' option. This option
ae23c9
was previously documented as the *maximum* L2 cache size, and this patch
ae23c9
makes it behave as such, instead of as a constant size. Also, the
ae23c9
existing option 'cache-size' can limit the sum of both L2 and refcount
ae23c9
caches, as previously.
ae23c9
ae23c9
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
ae23c9
Reviewed-by: Alberto Garcia <berto@igalia.com>
ae23c9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
(cherry picked from commit b749562d9822d14ef69c9eaa5f85903010b86c30)
ae23c9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
ae23c9
---
ae23c9
 block/qcow2.c              | 21 +++++++++------------
ae23c9
 block/qcow2.h              |  4 +---
ae23c9
 docs/qcow2-cache.txt       | 15 ++++++++++-----
ae23c9
 qemu-options.hx            |  6 +++---
ae23c9
 tests/qemu-iotests/137     |  8 +++++++-
ae23c9
 tests/qemu-iotests/137.out |  4 +++-
ae23c9
 6 files changed, 33 insertions(+), 25 deletions(-)
ae23c9
ae23c9
diff --git a/block/qcow2.c b/block/qcow2.c
ae23c9
index f3b2860..fc6bddd 100644
ae23c9
--- a/block/qcow2.c
ae23c9
+++ b/block/qcow2.c
ae23c9
@@ -773,29 +773,35 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
ae23c9
                              uint64_t *refcount_cache_size, Error **errp)
ae23c9
 {
ae23c9
     BDRVQcow2State *s = bs->opaque;
ae23c9
-    uint64_t combined_cache_size;
ae23c9
+    uint64_t combined_cache_size, l2_cache_max_setting;
ae23c9
     bool l2_cache_size_set, refcount_cache_size_set, combined_cache_size_set;
ae23c9
     int min_refcount_cache = MIN_REFCOUNT_CACHE_SIZE * s->cluster_size;
ae23c9
+    uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
ae23c9
+    uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8);
ae23c9
 
ae23c9
     combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE);
ae23c9
     l2_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_L2_CACHE_SIZE);
ae23c9
     refcount_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_REFCOUNT_CACHE_SIZE);
ae23c9
 
ae23c9
     combined_cache_size = qemu_opt_get_size(opts, QCOW2_OPT_CACHE_SIZE, 0);
ae23c9
-    *l2_cache_size = qemu_opt_get_size(opts, QCOW2_OPT_L2_CACHE_SIZE, 0);
ae23c9
+    l2_cache_max_setting = qemu_opt_get_size(opts, QCOW2_OPT_L2_CACHE_SIZE,
ae23c9
+                                             DEFAULT_L2_CACHE_MAX_SIZE);
ae23c9
     *refcount_cache_size = qemu_opt_get_size(opts,
ae23c9
                                              QCOW2_OPT_REFCOUNT_CACHE_SIZE, 0);
ae23c9
 
ae23c9
     *l2_cache_entry_size = qemu_opt_get_size(
ae23c9
         opts, QCOW2_OPT_L2_CACHE_ENTRY_SIZE, s->cluster_size);
ae23c9
 
ae23c9
+    *l2_cache_size = MIN(max_l2_cache, l2_cache_max_setting);
ae23c9
+
ae23c9
     if (combined_cache_size_set) {
ae23c9
         if (l2_cache_size_set && refcount_cache_size_set) {
ae23c9
             error_setg(errp, QCOW2_OPT_CACHE_SIZE ", " QCOW2_OPT_L2_CACHE_SIZE
ae23c9
                        " and " QCOW2_OPT_REFCOUNT_CACHE_SIZE " may not be set "
ae23c9
                        "the same time");
ae23c9
             return;
ae23c9
-        } else if (*l2_cache_size > combined_cache_size) {
ae23c9
+        } else if (l2_cache_size_set &&
ae23c9
+                   (l2_cache_max_setting > combined_cache_size)) {
ae23c9
             error_setg(errp, QCOW2_OPT_L2_CACHE_SIZE " may not exceed "
ae23c9
                        QCOW2_OPT_CACHE_SIZE);
ae23c9
             return;
ae23c9
@@ -810,9 +816,6 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
ae23c9
         } else if (refcount_cache_size_set) {
ae23c9
             *l2_cache_size = combined_cache_size - *refcount_cache_size;
ae23c9
         } else {
ae23c9
-            uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
ae23c9
-            uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8);
ae23c9
-
ae23c9
             /* Assign as much memory as possible to the L2 cache, and
ae23c9
              * use the remainder for the refcount cache */
ae23c9
             if (combined_cache_size >= max_l2_cache + min_refcount_cache) {
ae23c9
@@ -824,12 +827,6 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
ae23c9
                 *l2_cache_size = combined_cache_size - *refcount_cache_size;
ae23c9
             }
ae23c9
         }
ae23c9
-    } else {
ae23c9
-        if (!l2_cache_size_set) {
ae23c9
-            *l2_cache_size = MAX(DEFAULT_L2_CACHE_SIZE,
ae23c9
-                                 (uint64_t)DEFAULT_L2_CACHE_CLUSTERS
ae23c9
-                                 * s->cluster_size);
ae23c9
-        }
ae23c9
     }
ae23c9
     /* l2_cache_size and refcount_cache_size are ensured to have at least
ae23c9
      * their minimum values in qcow2_update_options_prepare() */
ae23c9
diff --git a/block/qcow2.h b/block/qcow2.h
ae23c9
index f73a48a..d0dd4a2 100644
ae23c9
--- a/block/qcow2.h
ae23c9
+++ b/block/qcow2.h
ae23c9
@@ -74,9 +74,7 @@
ae23c9
 /* Must be at least 4 to cover all cases of refcount table growth */
ae23c9
 #define MIN_REFCOUNT_CACHE_SIZE 4 /* clusters */
ae23c9
 
ae23c9
-/* Whichever is more */
ae23c9
-#define DEFAULT_L2_CACHE_CLUSTERS 8 /* clusters */
ae23c9
-#define DEFAULT_L2_CACHE_SIZE S_1MiB
ae23c9
+#define DEFAULT_L2_CACHE_MAX_SIZE S_1MiB
ae23c9
 
ae23c9
 #define DEFAULT_CLUSTER_SIZE S_64KiB
ae23c9
 
ae23c9
diff --git a/docs/qcow2-cache.txt b/docs/qcow2-cache.txt
ae23c9
index 7e28b41..750447e 100644
ae23c9
--- a/docs/qcow2-cache.txt
ae23c9
+++ b/docs/qcow2-cache.txt
ae23c9
@@ -125,8 +125,12 @@ There are a few things that need to be taken into account:
ae23c9
  - Both caches must have a size that is a multiple of the cluster size
ae23c9
    (or the cache entry size: see "Using smaller cache sizes" below).
ae23c9
 
ae23c9
- - The default L2 cache size is 8 clusters or 1MB (whichever is more),
ae23c9
-   and the minimum is 2 clusters (or 2 cache entries, see below).
ae23c9
+ - The maximum L2 cache size is 1 MB by default (enough for full coverage
ae23c9
+   of 8 GB images, with the default cluster size). This value can be
ae23c9
+   modified using the "l2-cache-size" option. QEMU will not use more memory
ae23c9
+   than needed to hold all of the image's L2 tables, regardless of this max.
ae23c9
+   value. The minimal L2 cache size is 2 clusters (or 2 cache entries, see
ae23c9
+   below).
ae23c9
 
ae23c9
  - The default (and minimum) refcount cache size is 4 clusters.
ae23c9
 
ae23c9
@@ -184,9 +188,10 @@ Some things to take into account:
ae23c9
    always uses the cluster size as the entry size.
ae23c9
 
ae23c9
  - If the L2 cache is big enough to hold all of the image's L2 tables
ae23c9
-   (as explained in the "Choosing the right cache sizes" section
ae23c9
-   earlier in this document) then none of this is necessary and you
ae23c9
-   can omit the "l2-cache-entry-size" parameter altogether.
ae23c9
+   (as explained in the "Choosing the right cache sizes" and "How to
ae23c9
+   configure the cache sizes" sections in this document) then none of
ae23c9
+   this is necessary and you can omit the "l2-cache-entry-size"
ae23c9
+   parameter altogether.
ae23c9
 
ae23c9
 
ae23c9
 Reducing the memory usage
ae23c9
diff --git a/qemu-options.hx b/qemu-options.hx
ae23c9
index 5e15d6f..5e3bd74 100644
ae23c9
--- a/qemu-options.hx
ae23c9
+++ b/qemu-options.hx
ae23c9
@@ -756,9 +756,9 @@ The maximum total size of the L2 table and refcount block caches in bytes
ae23c9
 
ae23c9
 @item l2-cache-size
ae23c9
 The maximum size of the L2 table cache in bytes
ae23c9
-(default: if cache-size is not defined - 1048576 bytes or 8 clusters, whichever
ae23c9
-is larger; otherwise, as large as possible or needed within the cache-size,
ae23c9
-while permitting the requested or the minimal refcount cache size)
ae23c9
+(default: if cache-size is not specified - 1M; otherwise, as large as possible
ae23c9
+within the cache-size, while permitting the requested or the minimal refcount
ae23c9
+cache size)
ae23c9
 
ae23c9
 @item refcount-cache-size
ae23c9
 The maximum size of the refcount block cache in bytes
ae23c9
diff --git a/tests/qemu-iotests/137 b/tests/qemu-iotests/137
ae23c9
index 8796562..19e8597 100755
ae23c9
--- a/tests/qemu-iotests/137
ae23c9
+++ b/tests/qemu-iotests/137
ae23c9
@@ -109,7 +109,6 @@ $QEMU_IO \
ae23c9
     -c "reopen -o cache-size=1M,l2-cache-size=64k,refcount-cache-size=64k" \
ae23c9
     -c "reopen -o cache-size=1M,l2-cache-size=2M" \
ae23c9
     -c "reopen -o cache-size=1M,refcount-cache-size=2M" \
ae23c9
-    -c "reopen -o l2-cache-size=256T" \
ae23c9
     -c "reopen -o l2-cache-entry-size=33k" \
ae23c9
     -c "reopen -o l2-cache-entry-size=128k" \
ae23c9
     -c "reopen -o refcount-cache-size=256T" \
ae23c9
@@ -119,6 +118,13 @@ $QEMU_IO \
ae23c9
     -c "reopen -o cache-clean-interval=-1" \
ae23c9
     "$TEST_IMG" | _filter_qemu_io
ae23c9
 
ae23c9
+IMGOPTS="cluster_size=256k" _make_test_img 32P
ae23c9
+$QEMU_IO \
ae23c9
+    -c "reopen -o l2-cache-entry-size=512,l2-cache-size=1T" \
ae23c9
+    "$TEST_IMG" | _filter_qemu_io
ae23c9
+
ae23c9
+_make_test_img 64M
ae23c9
+
ae23c9
 echo
ae23c9
 echo === Test transaction semantics ===
ae23c9
 echo
ae23c9
diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out
ae23c9
index 96724a6..afcc000 100644
ae23c9
--- a/tests/qemu-iotests/137.out
ae23c9
+++ b/tests/qemu-iotests/137.out
ae23c9
@@ -19,7 +19,6 @@ Parameter 'lazy-refcounts' expects 'on' or 'off'
ae23c9
 cache-size, l2-cache-size and refcount-cache-size may not be set the same time
ae23c9
 l2-cache-size may not exceed cache-size
ae23c9
 refcount-cache-size may not exceed cache-size
ae23c9
-L2 cache size too big
ae23c9
 L2 cache entry size must be a power of two between 512 and the cluster size (65536)
ae23c9
 L2 cache entry size must be a power of two between 512 and the cluster size (65536)
ae23c9
 Refcount cache size too big
ae23c9
@@ -27,6 +26,9 @@ Conflicting values for qcow2 options 'overlap-check' ('constant') and 'overlap-c
ae23c9
 Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
ae23c9
 Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
ae23c9
 Cache clean interval too big
ae23c9
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=36028797018963968
ae23c9
+L2 cache size too big
ae23c9
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
ae23c9
 
ae23c9
 === Test transaction semantics ===
ae23c9
 
ae23c9
-- 
ae23c9
1.8.3.1
ae23c9