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