325 lines
11 KiB
Diff
325 lines
11 KiB
Diff
From d8682ef60e3a658d776473fee2299015dd5105d7 Mon Sep 17 00:00:00 2001
|
|
From: Stefano Garzarella <sgarzare@redhat.com>
|
|
Date: Thu, 29 Jul 2021 07:42:31 -0400
|
|
Subject: [PATCH 18/39] iothread: add aio-max-batch parameter
|
|
|
|
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
|
RH-MergeRequest: 32: Synchronize with RHEL-AV 8.5 release 27 to RHEL 9
|
|
RH-Commit: [10/15] d033b3c8ddd71bae799103832039d6daa6dfad52 (mrezanin/centos-src-qemu-kvm)
|
|
RH-Bugzilla: 1957194
|
|
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
|
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
|
|
RH-Acked-by: Andrew Jones <drjones@redhat.com>
|
|
|
|
The `aio-max-batch` parameter will be propagated to AIO engines
|
|
and it will be used to control the maximum number of queued requests.
|
|
|
|
When there are in queue a number of requests equal to `aio-max-batch`,
|
|
the engine invokes the system call to forward the requests to the kernel.
|
|
|
|
This parameter allows us to control the maximum batch size to reduce
|
|
the latency that requests might accumulate while queued in the AIO
|
|
engine queue.
|
|
|
|
If `aio-max-batch` is equal to 0 (default value), the AIO engine will
|
|
use its default maximum batch size value.
|
|
|
|
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
Message-id: 20210721094211.69853-3-sgarzare@redhat.com
|
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
(cherry picked from commit 1793ad0247cad35db1ebbc04fbea0446c30a27ca)
|
|
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
---
|
|
include/block/aio.h | 12 +++++++++
|
|
include/sysemu/iothread.h | 3 +++
|
|
iothread.c | 55 +++++++++++++++++++++++++++++++++++----
|
|
monitor/hmp-cmds.c | 2 ++
|
|
qapi/misc.json | 6 ++++-
|
|
qapi/qom.json | 7 ++++-
|
|
qemu-options.hx | 8 ++++--
|
|
util/aio-posix.c | 12 +++++++++
|
|
util/aio-win32.c | 5 ++++
|
|
util/async.c | 2 ++
|
|
10 files changed, 103 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/include/block/aio.h b/include/block/aio.h
|
|
index 5f342267d5..ea68a139c8 100644
|
|
--- a/include/block/aio.h
|
|
+++ b/include/block/aio.h
|
|
@@ -232,6 +232,9 @@ struct AioContext {
|
|
int64_t poll_grow; /* polling time growth factor */
|
|
int64_t poll_shrink; /* polling time shrink factor */
|
|
|
|
+ /* AIO engine parameters */
|
|
+ int64_t aio_max_batch; /* maximum number of requests in a batch */
|
|
+
|
|
/*
|
|
* List of handlers participating in userspace polling. Protected by
|
|
* ctx->list_lock. Iterated and modified mostly by the event loop thread
|
|
@@ -727,4 +730,13 @@ void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
|
|
int64_t grow, int64_t shrink,
|
|
Error **errp);
|
|
|
|
+/**
|
|
+ * aio_context_set_aio_params:
|
|
+ * @ctx: the aio context
|
|
+ * @max_batch: maximum number of requests in a batch, 0 means that the
|
|
+ * engine will use its default
|
|
+ */
|
|
+void aio_context_set_aio_params(AioContext *ctx, int64_t max_batch,
|
|
+ Error **errp);
|
|
+
|
|
#endif
|
|
diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
|
|
index f177142f16..7f714bd136 100644
|
|
--- a/include/sysemu/iothread.h
|
|
+++ b/include/sysemu/iothread.h
|
|
@@ -37,6 +37,9 @@ struct IOThread {
|
|
int64_t poll_max_ns;
|
|
int64_t poll_grow;
|
|
int64_t poll_shrink;
|
|
+
|
|
+ /* AioContext AIO engine parameters */
|
|
+ int64_t aio_max_batch;
|
|
};
|
|
typedef struct IOThread IOThread;
|
|
|
|
diff --git a/iothread.c b/iothread.c
|
|
index a12de6e455..272be5e146 100644
|
|
--- a/iothread.c
|
|
+++ b/iothread.c
|
|
@@ -159,6 +159,24 @@ static void iothread_init_gcontext(IOThread *iothread)
|
|
iothread->main_loop = g_main_loop_new(iothread->worker_context, TRUE);
|
|
}
|
|
|
|
+static void iothread_set_aio_context_params(IOThread *iothread, Error **errp)
|
|
+{
|
|
+ ERRP_GUARD();
|
|
+
|
|
+ aio_context_set_poll_params(iothread->ctx,
|
|
+ iothread->poll_max_ns,
|
|
+ iothread->poll_grow,
|
|
+ iothread->poll_shrink,
|
|
+ errp);
|
|
+ if (*errp) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ aio_context_set_aio_params(iothread->ctx,
|
|
+ iothread->aio_max_batch,
|
|
+ errp);
|
|
+}
|
|
+
|
|
static void iothread_complete(UserCreatable *obj, Error **errp)
|
|
{
|
|
Error *local_error = NULL;
|
|
@@ -178,11 +196,7 @@ static void iothread_complete(UserCreatable *obj, Error **errp)
|
|
*/
|
|
iothread_init_gcontext(iothread);
|
|
|
|
- aio_context_set_poll_params(iothread->ctx,
|
|
- iothread->poll_max_ns,
|
|
- iothread->poll_grow,
|
|
- iothread->poll_shrink,
|
|
- &local_error);
|
|
+ iothread_set_aio_context_params(iothread, &local_error);
|
|
if (local_error) {
|
|
error_propagate(errp, local_error);
|
|
aio_context_unref(iothread->ctx);
|
|
@@ -219,6 +233,9 @@ static PollParamInfo poll_grow_info = {
|
|
static PollParamInfo poll_shrink_info = {
|
|
"poll-shrink", offsetof(IOThread, poll_shrink),
|
|
};
|
|
+static PollParamInfo aio_max_batch_info = {
|
|
+ "aio-max-batch", offsetof(IOThread, aio_max_batch),
|
|
+};
|
|
|
|
static void iothread_get_param(Object *obj, Visitor *v,
|
|
const char *name, void *opaque, Error **errp)
|
|
@@ -278,6 +295,29 @@ static void iothread_set_poll_param(Object *obj, Visitor *v,
|
|
}
|
|
}
|
|
|
|
+static void iothread_get_aio_param(Object *obj, Visitor *v,
|
|
+ const char *name, void *opaque, Error **errp)
|
|
+{
|
|
+
|
|
+ iothread_get_param(obj, v, name, opaque, errp);
|
|
+}
|
|
+
|
|
+static void iothread_set_aio_param(Object *obj, Visitor *v,
|
|
+ const char *name, void *opaque, Error **errp)
|
|
+{
|
|
+ IOThread *iothread = IOTHREAD(obj);
|
|
+
|
|
+ if (!iothread_set_param(obj, v, name, opaque, errp)) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (iothread->ctx) {
|
|
+ aio_context_set_aio_params(iothread->ctx,
|
|
+ iothread->aio_max_batch,
|
|
+ errp);
|
|
+ }
|
|
+}
|
|
+
|
|
static void iothread_class_init(ObjectClass *klass, void *class_data)
|
|
{
|
|
UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
|
|
@@ -295,6 +335,10 @@ static void iothread_class_init(ObjectClass *klass, void *class_data)
|
|
iothread_get_poll_param,
|
|
iothread_set_poll_param,
|
|
NULL, &poll_shrink_info);
|
|
+ object_class_property_add(klass, "aio-max-batch", "int",
|
|
+ iothread_get_aio_param,
|
|
+ iothread_set_aio_param,
|
|
+ NULL, &aio_max_batch_info);
|
|
}
|
|
|
|
static const TypeInfo iothread_info = {
|
|
@@ -344,6 +388,7 @@ static int query_one_iothread(Object *object, void *opaque)
|
|
info->poll_max_ns = iothread->poll_max_ns;
|
|
info->poll_grow = iothread->poll_grow;
|
|
info->poll_shrink = iothread->poll_shrink;
|
|
+ info->aio_max_batch = iothread->aio_max_batch;
|
|
|
|
QAPI_LIST_APPEND(*tail, info);
|
|
return 0;
|
|
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
|
|
index cc15d9b6ee..2905bc1594 100644
|
|
--- a/monitor/hmp-cmds.c
|
|
+++ b/monitor/hmp-cmds.c
|
|
@@ -1889,6 +1889,8 @@ void hmp_info_iothreads(Monitor *mon, const QDict *qdict)
|
|
monitor_printf(mon, " poll-max-ns=%" PRId64 "\n", value->poll_max_ns);
|
|
monitor_printf(mon, " poll-grow=%" PRId64 "\n", value->poll_grow);
|
|
monitor_printf(mon, " poll-shrink=%" PRId64 "\n", value->poll_shrink);
|
|
+ monitor_printf(mon, " aio-max-batch=%" PRId64 "\n",
|
|
+ value->aio_max_batch);
|
|
}
|
|
|
|
qapi_free_IOThreadInfoList(info_list);
|
|
diff --git a/qapi/misc.json b/qapi/misc.json
|
|
index 156f98203e..5c2ca3b556 100644
|
|
--- a/qapi/misc.json
|
|
+++ b/qapi/misc.json
|
|
@@ -86,6 +86,9 @@
|
|
# @poll-shrink: how many ns will be removed from polling time, 0 means that
|
|
# it's not configured (since 2.9)
|
|
#
|
|
+# @aio-max-batch: maximum number of requests in a batch for the AIO engine,
|
|
+# 0 means that the engine will use its default (since 6.1)
|
|
+#
|
|
# Since: 2.0
|
|
##
|
|
{ 'struct': 'IOThreadInfo',
|
|
@@ -93,7 +96,8 @@
|
|
'thread-id': 'int',
|
|
'poll-max-ns': 'int',
|
|
'poll-grow': 'int',
|
|
- 'poll-shrink': 'int' } }
|
|
+ 'poll-shrink': 'int',
|
|
+ 'aio-max-batch': 'int' } }
|
|
|
|
##
|
|
# @query-iothreads:
|
|
diff --git a/qapi/qom.json b/qapi/qom.json
|
|
index cd0e76d564..f361157903 100644
|
|
--- a/qapi/qom.json
|
|
+++ b/qapi/qom.json
|
|
@@ -516,12 +516,17 @@
|
|
# algorithm detects it is spending too long polling without
|
|
# encountering events. 0 selects a default behaviour (default: 0)
|
|
#
|
|
+# @aio-max-batch: maximum number of requests in a batch for the AIO engine,
|
|
+# 0 means that the engine will use its default
|
|
+# (default:0, since 6.1)
|
|
+#
|
|
# Since: 2.0
|
|
##
|
|
{ 'struct': 'IothreadProperties',
|
|
'data': { '*poll-max-ns': 'int',
|
|
'*poll-grow': 'int',
|
|
- '*poll-shrink': 'int' } }
|
|
+ '*poll-shrink': 'int',
|
|
+ '*aio-max-batch': 'int' } }
|
|
|
|
##
|
|
# @MemoryBackendProperties:
|
|
diff --git a/qemu-options.hx b/qemu-options.hx
|
|
index 79ca09feac..d5f1ec27c5 100644
|
|
--- a/qemu-options.hx
|
|
+++ b/qemu-options.hx
|
|
@@ -5185,7 +5185,7 @@ SRST
|
|
|
|
CN=laptop.example.com,O=Example Home,L=London,ST=London,C=GB
|
|
|
|
- ``-object iothread,id=id,poll-max-ns=poll-max-ns,poll-grow=poll-grow,poll-shrink=poll-shrink``
|
|
+ ``-object iothread,id=id,poll-max-ns=poll-max-ns,poll-grow=poll-grow,poll-shrink=poll-shrink,aio-max-batch=aio-max-batch``
|
|
Creates a dedicated event loop thread that devices can be
|
|
assigned to. This is known as an IOThread. By default device
|
|
emulation happens in vCPU threads or the main event loop thread.
|
|
@@ -5221,7 +5221,11 @@ SRST
|
|
the polling time when the algorithm detects it is spending too
|
|
long polling without encountering events.
|
|
|
|
- The polling parameters can be modified at run-time using the
|
|
+ The ``aio-max-batch`` parameter is the maximum number of requests
|
|
+ in a batch for the AIO engine, 0 means that the engine will use
|
|
+ its default.
|
|
+
|
|
+ The IOThread parameters can be modified at run-time using the
|
|
``qom-set`` command (where ``iothread1`` is the IOThread's
|
|
``id``):
|
|
|
|
diff --git a/util/aio-posix.c b/util/aio-posix.c
|
|
index 30f5354b1e..2b86777e91 100644
|
|
--- a/util/aio-posix.c
|
|
+++ b/util/aio-posix.c
|
|
@@ -716,3 +716,15 @@ void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
|
|
|
|
aio_notify(ctx);
|
|
}
|
|
+
|
|
+void aio_context_set_aio_params(AioContext *ctx, int64_t max_batch,
|
|
+ Error **errp)
|
|
+{
|
|
+ /*
|
|
+ * No thread synchronization here, it doesn't matter if an incorrect value
|
|
+ * is used once.
|
|
+ */
|
|
+ ctx->aio_max_batch = max_batch;
|
|
+
|
|
+ aio_notify(ctx);
|
|
+}
|
|
diff --git a/util/aio-win32.c b/util/aio-win32.c
|
|
index 168717b51b..d5b09a1193 100644
|
|
--- a/util/aio-win32.c
|
|
+++ b/util/aio-win32.c
|
|
@@ -440,3 +440,8 @@ void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
|
|
error_setg(errp, "AioContext polling is not implemented on Windows");
|
|
}
|
|
}
|
|
+
|
|
+void aio_context_set_aio_params(AioContext *ctx, int64_t max_batch,
|
|
+ Error **errp)
|
|
+{
|
|
+}
|
|
diff --git a/util/async.c b/util/async.c
|
|
index 674dbefb7c..6a9588d86b 100644
|
|
--- a/util/async.c
|
|
+++ b/util/async.c
|
|
@@ -537,6 +537,8 @@ AioContext *aio_context_new(Error **errp)
|
|
ctx->poll_grow = 0;
|
|
ctx->poll_shrink = 0;
|
|
|
|
+ ctx->aio_max_batch = 0;
|
|
+
|
|
return ctx;
|
|
fail:
|
|
g_source_destroy(&ctx->source);
|
|
--
|
|
2.27.0
|
|
|