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