From: Max Reitz <mreitz@redhat.com>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
Stefan Hajnoczi <stefanha@redhat.com>,
Max Reitz <mreitz@redhat.com>
Subject: [Qemu-devel] [PATCH 3/4] qcow2: Add runtime options for cache sizes
Date: Mon, 18 Aug 2014 22:00:28 +0200 [thread overview]
Message-ID: <1408392029-29531-4-git-send-email-mreitz@redhat.com> (raw)
In-Reply-To: <1408392029-29531-1-git-send-email-mreitz@redhat.com>
Add options for specifying the size of the metadata caches. This can
either be done directly for each cache (if only one is given, the other
will be derived according to a default ratio) or combined for both.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block/qcow2.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
block/qcow2.h | 3 ++
2 files changed, 103 insertions(+), 12 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index 910d9cf..f9e045f 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -442,6 +442,22 @@ static QemuOptsList qcow2_runtime_opts = {
.type = QEMU_OPT_BOOL,
.help = "Check for unintended writes into an inactive L2 table",
},
+ {
+ .name = QCOW2_OPT_CACHE_SIZE,
+ .type = QEMU_OPT_SIZE,
+ .help = "Maximum combined metadata (L2 tables and refcount blocks) "
+ "cache size",
+ },
+ {
+ .name = QCOW2_OPT_L2_CACHE_SIZE,
+ .type = QEMU_OPT_SIZE,
+ .help = "Maximum L2 table cache size",
+ },
+ {
+ .name = QCOW2_OPT_REFCOUNT_CACHE_SIZE,
+ .type = QEMU_OPT_SIZE,
+ .help = "Maximum refcount block cache size",
+ },
{ /* end of list */ }
},
};
@@ -457,6 +473,61 @@ static const char *overlap_bool_option_names[QCOW2_OL_MAX_BITNR] = {
[QCOW2_OL_INACTIVE_L2_BITNR] = QCOW2_OPT_OVERLAP_INACTIVE_L2,
};
+static void read_cache_sizes(QemuOpts *opts, uint64_t *l2_cache_size,
+ uint64_t *refcount_cache_size, Error **errp)
+{
+ uint64_t combined_cache_size;
+ bool l2_cache_size_set, refcount_cache_size_set, combined_cache_size_set;
+
+ combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE);
+ l2_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_L2_CACHE_SIZE);
+ refcount_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_REFCOUNT_CACHE_SIZE);
+
+ combined_cache_size = qemu_opt_get_size(opts, QCOW2_OPT_CACHE_SIZE, 0);
+ *l2_cache_size = qemu_opt_get_size(opts, QCOW2_OPT_L2_CACHE_SIZE, 0);
+ *refcount_cache_size = qemu_opt_get_size(opts,
+ QCOW2_OPT_REFCOUNT_CACHE_SIZE, 0);
+
+ if (combined_cache_size_set) {
+ if (l2_cache_size_set && refcount_cache_size_set) {
+ error_setg(errp, QCOW2_OPT_CACHE_SIZE ", " QCOW2_OPT_L2_CACHE_SIZE
+ " and " QCOW2_OPT_REFCOUNT_CACHE_SIZE " may not be set "
+ "the same time");
+ return;
+ } else if (*l2_cache_size > combined_cache_size) {
+ error_setg(errp, QCOW2_OPT_L2_CACHE_SIZE " may not exceed "
+ QCOW2_OPT_CACHE_SIZE);
+ return;
+ } else if (*refcount_cache_size > combined_cache_size) {
+ error_setg(errp, QCOW2_OPT_REFCOUNT_CACHE_SIZE " may not exceed "
+ QCOW2_OPT_CACHE_SIZE);
+ return;
+ }
+
+ if (l2_cache_size_set) {
+ *refcount_cache_size = combined_cache_size - *l2_cache_size;
+ } else if (refcount_cache_size_set) {
+ *l2_cache_size = combined_cache_size - *refcount_cache_size;
+ } else {
+ *refcount_cache_size = combined_cache_size
+ / (DEFAULT_L2_REFCOUNT_SIZE_RATIO + 1);
+ *l2_cache_size = combined_cache_size - *refcount_cache_size;
+ }
+ } else {
+ if (!l2_cache_size_set && !refcount_cache_size_set) {
+ *l2_cache_size = DEFAULT_L2_CACHE_BYTE_SIZE;
+ *refcount_cache_size = *l2_cache_size
+ / DEFAULT_L2_REFCOUNT_SIZE_RATIO;
+ } else if (!l2_cache_size_set) {
+ *l2_cache_size = *refcount_cache_size
+ * DEFAULT_L2_REFCOUNT_SIZE_RATIO;
+ } else if (!refcount_cache_size_set) {
+ *refcount_cache_size = *l2_cache_size
+ / DEFAULT_L2_REFCOUNT_SIZE_RATIO;
+ }
+ }
+}
+
static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
@@ -707,18 +778,43 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
}
}
- /* alloc L2 table/refcount block cache */
- l2_cache_size = DEFAULT_L2_CACHE_BYTE_SIZE / s->cluster_size;
+ /* get L2 table/refcount block cache size from command line options */
+ opts = qemu_opts_create(&qcow2_runtime_opts, NULL, 0, &error_abort);
+ qemu_opts_absorb_qdict(opts, options, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ read_cache_sizes(opts, &l2_cache_size, &refcount_cache_size, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ l2_cache_size /= s->cluster_size;
if (l2_cache_size < MIN_L2_CACHE_SIZE) {
l2_cache_size = MIN_L2_CACHE_SIZE;
}
+ if (l2_cache_size > INT_MAX) {
+ error_setg(errp, "L2 cache size too big");
+ ret = -EINVAL;
+ goto fail;
+ }
- refcount_cache_size = l2_cache_size
- / (DEFAULT_L2_REFCOUNT_SIZE_RATIO * s->cluster_size);
+ refcount_cache_size /= s->cluster_size;
if (refcount_cache_size < MIN_REFCOUNT_CACHE_SIZE) {
refcount_cache_size = MIN_REFCOUNT_CACHE_SIZE;
}
+ if (refcount_cache_size > INT_MAX) {
+ error_setg(errp, "Refcount cache size too big");
+ ret = -EINVAL;
+ goto fail;
+ }
+ /* alloc L2 table/refcount block cache */
s->l2_table_cache = qcow2_cache_create(bs, l2_cache_size);
s->refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size);
if (s->l2_table_cache == NULL || s->refcount_block_cache == NULL) {
@@ -810,14 +906,6 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
}
/* Enable lazy_refcounts according to image and command line options */
- opts = qemu_opts_create(&qcow2_runtime_opts, NULL, 0, &error_abort);
- qemu_opts_absorb_qdict(opts, options, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- ret = -EINVAL;
- goto fail;
- }
-
s->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
(s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
diff --git a/block/qcow2.h b/block/qcow2.h
index 671783d..6aeb7ea 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -91,6 +91,9 @@
#define QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE "overlap-check.snapshot-table"
#define QCOW2_OPT_OVERLAP_INACTIVE_L1 "overlap-check.inactive-l1"
#define QCOW2_OPT_OVERLAP_INACTIVE_L2 "overlap-check.inactive-l2"
+#define QCOW2_OPT_CACHE_SIZE "cache-size"
+#define QCOW2_OPT_L2_CACHE_SIZE "l2-cache-size"
+#define QCOW2_OPT_REFCOUNT_CACHE_SIZE "refcount-cache-size"
typedef struct QCowHeader {
uint32_t magic;
--
2.0.4
next prev parent reply other threads:[~2014-08-18 20:00 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-18 20:00 [Qemu-devel] [PATCH 0/4] qcow2: Allow runtime specification of cache sizes Max Reitz
2014-08-18 20:00 ` [Qemu-devel] [PATCH 1/4] qcow2: Constant cache size in bytes Max Reitz
2014-08-18 20:00 ` [Qemu-devel] [PATCH 2/4] qcow2: Use g_try_new0() for cache array Max Reitz
2014-08-18 20:01 ` Max Reitz
2014-08-18 20:00 ` Max Reitz [this message]
2014-08-18 20:18 ` [Qemu-devel] [PATCH 3/4] qcow2: Add runtime options for cache sizes Eric Blake
2014-08-18 20:24 ` Max Reitz
2014-08-18 20:25 ` Max Reitz
2014-08-18 20:00 ` [Qemu-devel] [PATCH 4/4] iotests: Add test for qcow2's cache options Max Reitz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1408392029-29531-4-git-send-email-mreitz@redhat.com \
--to=mreitz@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).