1
The following changes since commit 801f3db7564dcce8a37a70833c0abe40ec19f8ce:
1
The following changes since commit ca61fa4b803e5d0abaf6f1ceb690f23bb78a4def:
2
2
3
Merge remote-tracking branch 'remotes/philmd/tags/kconfig-20210720' into staging (2021-07-20 19:30:28 +0100)
3
Merge remote-tracking branch 'remotes/quic/tags/pull-hex-20211006' into staging (2021-10-06 12:11:14 -0700)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to d7ddd0a1618a75b31dc308bb37365ce1da972154:
9
for you to fetch changes up to 1cc7eada97914f090125e588497986f6f7900514:
10
10
11
linux-aio: limit the batch size using `aio-max-batch` parameter (2021-07-21 13:47:50 +0100)
11
iothread: use IOThreadParamInfo in iothread_[set|get]_param() (2021-10-07 15:29:50 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Pull request
14
Pull request
15
15
16
Stefano's performance regression fix for commit 2558cb8dd4 ("linux-aio:
17
increasing MAX_EVENTS to a larger hardcoded value").
18
19
----------------------------------------------------------------
16
----------------------------------------------------------------
20
17
21
Stefano Garzarella (3):
18
Stefano Garzarella (2):
22
iothread: generalize iothread_set_param/iothread_get_param
19
iothread: rename PollParamInfo to IOThreadParamInfo
23
iothread: add aio-max-batch parameter
20
iothread: use IOThreadParamInfo in iothread_[set|get]_param()
24
linux-aio: limit the batch size using `aio-max-batch` parameter
25
21
26
qapi/misc.json | 6 ++-
22
iothread.c | 28 +++++++++++++++-------------
27
qapi/qom.json | 7 +++-
23
1 file changed, 15 insertions(+), 13 deletions(-)
28
include/block/aio.h | 12 ++++++
29
include/sysemu/iothread.h | 3 ++
30
block/linux-aio.c | 9 ++++-
31
iothread.c | 82 ++++++++++++++++++++++++++++++++++-----
32
monitor/hmp-cmds.c | 2 +
33
util/aio-posix.c | 12 ++++++
34
util/aio-win32.c | 5 +++
35
util/async.c | 2 +
36
qemu-options.hx | 8 +++-
37
11 files changed, 134 insertions(+), 14 deletions(-)
38
24
39
--
25
--
40
2.31.1
26
2.31.1
41
27
28
29
diff view generated by jsdifflib
1
From: Stefano Garzarella <sgarzare@redhat.com>
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
2
3
The `aio-max-batch` parameter will be propagated to AIO engines
3
Commit 1793ad0247 ("iothread: add aio-max-batch parameter") added
4
and it will be used to control the maximum number of queued requests.
4
a new parameter (aio-max-batch) to IOThread and used PollParamInfo
5
structure to handle it.
5
6
6
When there are in queue a number of requests equal to `aio-max-batch`,
7
Since it is not a parameter of the polling mechanism, we rename the
7
the engine invokes the system call to forward the requests to the kernel.
8
structure to a more generic IOThreadParamInfo.
8
9
9
This parameter allows us to control the maximum batch size to reduce
10
Suggested-by: Kevin Wolf <kwolf@redhat.com>
10
the latency that requests might accumulate while queued in the AIO
11
engine queue.
12
13
If `aio-max-batch` is equal to 0 (default value), the AIO engine will
14
use its default maximum batch size value.
15
16
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
11
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
17
Message-id: 20210721094211.69853-3-sgarzare@redhat.com
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Message-id: 20210727145936.147032-2-sgarzare@redhat.com
18
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
19
---
15
---
20
qapi/misc.json | 6 ++++-
16
iothread.c | 14 +++++++-------
21
qapi/qom.json | 7 ++++-
17
1 file changed, 7 insertions(+), 7 deletions(-)
22
include/block/aio.h | 12 +++++++++
23
include/sysemu/iothread.h | 3 +++
24
iothread.c | 55 +++++++++++++++++++++++++++++++++++----
25
monitor/hmp-cmds.c | 2 ++
26
util/aio-posix.c | 12 +++++++++
27
util/aio-win32.c | 5 ++++
28
util/async.c | 2 ++
29
qemu-options.hx | 8 ++++--
30
10 files changed, 103 insertions(+), 9 deletions(-)
31
18
32
diff --git a/qapi/misc.json b/qapi/misc.json
33
index XXXXXXX..XXXXXXX 100644
34
--- a/qapi/misc.json
35
+++ b/qapi/misc.json
36
@@ -XXX,XX +XXX,XX @@
37
# @poll-shrink: how many ns will be removed from polling time, 0 means that
38
# it's not configured (since 2.9)
39
#
40
+# @aio-max-batch: maximum number of requests in a batch for the AIO engine,
41
+# 0 means that the engine will use its default (since 6.1)
42
+#
43
# Since: 2.0
44
##
45
{ 'struct': 'IOThreadInfo',
46
@@ -XXX,XX +XXX,XX @@
47
'thread-id': 'int',
48
'poll-max-ns': 'int',
49
'poll-grow': 'int',
50
- 'poll-shrink': 'int' } }
51
+ 'poll-shrink': 'int',
52
+ 'aio-max-batch': 'int' } }
53
54
##
55
# @query-iothreads:
56
diff --git a/qapi/qom.json b/qapi/qom.json
57
index XXXXXXX..XXXXXXX 100644
58
--- a/qapi/qom.json
59
+++ b/qapi/qom.json
60
@@ -XXX,XX +XXX,XX @@
61
# algorithm detects it is spending too long polling without
62
# encountering events. 0 selects a default behaviour (default: 0)
63
#
64
+# @aio-max-batch: maximum number of requests in a batch for the AIO engine,
65
+# 0 means that the engine will use its default
66
+# (default:0, since 6.1)
67
+#
68
# Since: 2.0
69
##
70
{ 'struct': 'IothreadProperties',
71
'data': { '*poll-max-ns': 'int',
72
'*poll-grow': 'int',
73
- '*poll-shrink': 'int' } }
74
+ '*poll-shrink': 'int',
75
+ '*aio-max-batch': 'int' } }
76
77
##
78
# @MemoryBackendProperties:
79
diff --git a/include/block/aio.h b/include/block/aio.h
80
index XXXXXXX..XXXXXXX 100644
81
--- a/include/block/aio.h
82
+++ b/include/block/aio.h
83
@@ -XXX,XX +XXX,XX @@ struct AioContext {
84
int64_t poll_grow; /* polling time growth factor */
85
int64_t poll_shrink; /* polling time shrink factor */
86
87
+ /* AIO engine parameters */
88
+ int64_t aio_max_batch; /* maximum number of requests in a batch */
89
+
90
/*
91
* List of handlers participating in userspace polling. Protected by
92
* ctx->list_lock. Iterated and modified mostly by the event loop thread
93
@@ -XXX,XX +XXX,XX @@ void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
94
int64_t grow, int64_t shrink,
95
Error **errp);
96
97
+/**
98
+ * aio_context_set_aio_params:
99
+ * @ctx: the aio context
100
+ * @max_batch: maximum number of requests in a batch, 0 means that the
101
+ * engine will use its default
102
+ */
103
+void aio_context_set_aio_params(AioContext *ctx, int64_t max_batch,
104
+ Error **errp);
105
+
106
#endif
107
diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
108
index XXXXXXX..XXXXXXX 100644
109
--- a/include/sysemu/iothread.h
110
+++ b/include/sysemu/iothread.h
111
@@ -XXX,XX +XXX,XX @@ struct IOThread {
112
int64_t poll_max_ns;
113
int64_t poll_grow;
114
int64_t poll_shrink;
115
+
116
+ /* AioContext AIO engine parameters */
117
+ int64_t aio_max_batch;
118
};
119
typedef struct IOThread IOThread;
120
121
diff --git a/iothread.c b/iothread.c
19
diff --git a/iothread.c b/iothread.c
122
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
123
--- a/iothread.c
21
--- a/iothread.c
124
+++ b/iothread.c
22
+++ b/iothread.c
125
@@ -XXX,XX +XXX,XX @@ static void iothread_init_gcontext(IOThread *iothread)
126
iothread->main_loop = g_main_loop_new(iothread->worker_context, TRUE);
127
}
128
129
+static void iothread_set_aio_context_params(IOThread *iothread, Error **errp)
130
+{
131
+ ERRP_GUARD();
132
+
133
+ aio_context_set_poll_params(iothread->ctx,
134
+ iothread->poll_max_ns,
135
+ iothread->poll_grow,
136
+ iothread->poll_shrink,
137
+ errp);
138
+ if (*errp) {
139
+ return;
140
+ }
141
+
142
+ aio_context_set_aio_params(iothread->ctx,
143
+ iothread->aio_max_batch,
144
+ errp);
145
+}
146
+
147
static void iothread_complete(UserCreatable *obj, Error **errp)
148
{
149
Error *local_error = NULL;
150
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
23
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
151
*/
24
typedef struct {
152
iothread_init_gcontext(iothread);
25
const char *name;
153
26
ptrdiff_t offset; /* field's byte offset in IOThread struct */
154
- aio_context_set_poll_params(iothread->ctx,
27
-} PollParamInfo;
155
- iothread->poll_max_ns,
28
+} IOThreadParamInfo;
156
- iothread->poll_grow,
29
157
- iothread->poll_shrink,
30
-static PollParamInfo poll_max_ns_info = {
158
- &local_error);
31
+static IOThreadParamInfo poll_max_ns_info = {
159
+ iothread_set_aio_context_params(iothread, &local_error);
32
"poll-max-ns", offsetof(IOThread, poll_max_ns),
160
if (local_error) {
33
};
161
error_propagate(errp, local_error);
34
-static PollParamInfo poll_grow_info = {
162
aio_context_unref(iothread->ctx);
35
+static IOThreadParamInfo poll_grow_info = {
163
@@ -XXX,XX +XXX,XX @@ static PollParamInfo poll_grow_info = {
36
"poll-grow", offsetof(IOThread, poll_grow),
164
static PollParamInfo poll_shrink_info = {
37
};
38
-static PollParamInfo poll_shrink_info = {
39
+static IOThreadParamInfo poll_shrink_info = {
165
"poll-shrink", offsetof(IOThread, poll_shrink),
40
"poll-shrink", offsetof(IOThread, poll_shrink),
166
};
41
};
167
+static PollParamInfo aio_max_batch_info = {
42
-static PollParamInfo aio_max_batch_info = {
168
+ "aio-max-batch", offsetof(IOThread, aio_max_batch),
43
+static IOThreadParamInfo aio_max_batch_info = {
169
+};
44
"aio-max-batch", offsetof(IOThread, aio_max_batch),
170
45
};
171
static void iothread_get_param(Object *obj, Visitor *v,
46
47
@@ -XXX,XX +XXX,XX @@ static void iothread_get_param(Object *obj, Visitor *v,
172
const char *name, void *opaque, Error **errp)
48
const char *name, void *opaque, Error **errp)
173
@@ -XXX,XX +XXX,XX @@ static void iothread_set_poll_param(Object *obj, Visitor *v,
174
}
175
}
176
177
+static void iothread_get_aio_param(Object *obj, Visitor *v,
178
+ const char *name, void *opaque, Error **errp)
179
+{
180
+
181
+ iothread_get_param(obj, v, name, opaque, errp);
182
+}
183
+
184
+static void iothread_set_aio_param(Object *obj, Visitor *v,
185
+ const char *name, void *opaque, Error **errp)
186
+{
187
+ IOThread *iothread = IOTHREAD(obj);
188
+
189
+ if (!iothread_set_param(obj, v, name, opaque, errp)) {
190
+ return;
191
+ }
192
+
193
+ if (iothread->ctx) {
194
+ aio_context_set_aio_params(iothread->ctx,
195
+ iothread->aio_max_batch,
196
+ errp);
197
+ }
198
+}
199
+
200
static void iothread_class_init(ObjectClass *klass, void *class_data)
201
{
49
{
202
UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
50
IOThread *iothread = IOTHREAD(obj);
203
@@ -XXX,XX +XXX,XX @@ static void iothread_class_init(ObjectClass *klass, void *class_data)
51
- PollParamInfo *info = opaque;
204
iothread_get_poll_param,
52
+ IOThreadParamInfo *info = opaque;
205
iothread_set_poll_param,
53
int64_t *field = (void *)iothread + info->offset;
206
NULL, &poll_shrink_info);
54
207
+ object_class_property_add(klass, "aio-max-batch", "int",
55
visit_type_int64(v, name, field, errp);
208
+ iothread_get_aio_param,
56
@@ -XXX,XX +XXX,XX @@ static bool iothread_set_param(Object *obj, Visitor *v,
209
+ iothread_set_aio_param,
57
const char *name, void *opaque, Error **errp)
210
+ NULL, &aio_max_batch_info);
58
{
211
}
59
IOThread *iothread = IOTHREAD(obj);
212
60
- PollParamInfo *info = opaque;
213
static const TypeInfo iothread_info = {
61
+ IOThreadParamInfo *info = opaque;
214
@@ -XXX,XX +XXX,XX @@ static int query_one_iothread(Object *object, void *opaque)
62
int64_t *field = (void *)iothread + info->offset;
215
info->poll_max_ns = iothread->poll_max_ns;
63
int64_t value;
216
info->poll_grow = iothread->poll_grow;
217
info->poll_shrink = iothread->poll_shrink;
218
+ info->aio_max_batch = iothread->aio_max_batch;
219
220
QAPI_LIST_APPEND(*tail, info);
221
return 0;
222
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
223
index XXXXXXX..XXXXXXX 100644
224
--- a/monitor/hmp-cmds.c
225
+++ b/monitor/hmp-cmds.c
226
@@ -XXX,XX +XXX,XX @@ void hmp_info_iothreads(Monitor *mon, const QDict *qdict)
227
monitor_printf(mon, " poll-max-ns=%" PRId64 "\n", value->poll_max_ns);
228
monitor_printf(mon, " poll-grow=%" PRId64 "\n", value->poll_grow);
229
monitor_printf(mon, " poll-shrink=%" PRId64 "\n", value->poll_shrink);
230
+ monitor_printf(mon, " aio-max-batch=%" PRId64 "\n",
231
+ value->aio_max_batch);
232
}
233
234
qapi_free_IOThreadInfoList(info_list);
235
diff --git a/util/aio-posix.c b/util/aio-posix.c
236
index XXXXXXX..XXXXXXX 100644
237
--- a/util/aio-posix.c
238
+++ b/util/aio-posix.c
239
@@ -XXX,XX +XXX,XX @@ void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
240
241
aio_notify(ctx);
242
}
243
+
244
+void aio_context_set_aio_params(AioContext *ctx, int64_t max_batch,
245
+ Error **errp)
246
+{
247
+ /*
248
+ * No thread synchronization here, it doesn't matter if an incorrect value
249
+ * is used once.
250
+ */
251
+ ctx->aio_max_batch = max_batch;
252
+
253
+ aio_notify(ctx);
254
+}
255
diff --git a/util/aio-win32.c b/util/aio-win32.c
256
index XXXXXXX..XXXXXXX 100644
257
--- a/util/aio-win32.c
258
+++ b/util/aio-win32.c
259
@@ -XXX,XX +XXX,XX @@ void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
260
error_setg(errp, "AioContext polling is not implemented on Windows");
261
}
262
}
263
+
264
+void aio_context_set_aio_params(AioContext *ctx, int64_t max_batch,
265
+ Error **errp)
266
+{
267
+}
268
diff --git a/util/async.c b/util/async.c
269
index XXXXXXX..XXXXXXX 100644
270
--- a/util/async.c
271
+++ b/util/async.c
272
@@ -XXX,XX +XXX,XX @@ AioContext *aio_context_new(Error **errp)
273
ctx->poll_grow = 0;
274
ctx->poll_shrink = 0;
275
276
+ ctx->aio_max_batch = 0;
277
+
278
return ctx;
279
fail:
280
g_source_destroy(&ctx->source);
281
diff --git a/qemu-options.hx b/qemu-options.hx
282
index XXXXXXX..XXXXXXX 100644
283
--- a/qemu-options.hx
284
+++ b/qemu-options.hx
285
@@ -XXX,XX +XXX,XX @@ SRST
286
287
CN=laptop.example.com,O=Example Home,L=London,ST=London,C=GB
288
289
- ``-object iothread,id=id,poll-max-ns=poll-max-ns,poll-grow=poll-grow,poll-shrink=poll-shrink``
290
+ ``-object iothread,id=id,poll-max-ns=poll-max-ns,poll-grow=poll-grow,poll-shrink=poll-shrink,aio-max-batch=aio-max-batch``
291
Creates a dedicated event loop thread that devices can be
292
assigned to. This is known as an IOThread. By default device
293
emulation happens in vCPU threads or the main event loop thread.
294
@@ -XXX,XX +XXX,XX @@ SRST
295
the polling time when the algorithm detects it is spending too
296
long polling without encountering events.
297
298
- The polling parameters can be modified at run-time using the
299
+ The ``aio-max-batch`` parameter is the maximum number of requests
300
+ in a batch for the AIO engine, 0 means that the engine will use
301
+ its default.
302
+
303
+ The IOThread parameters can be modified at run-time using the
304
``qom-set`` command (where ``iothread1`` is the IOThread's
305
``id``):
306
64
307
--
65
--
308
2.31.1
66
2.31.1
309
67
68
diff view generated by jsdifflib
1
From: Stefano Garzarella <sgarzare@redhat.com>
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
2
3
Changes in preparation for next patches where we add a new
3
Commit 0445409d74 ("iothread: generalize
4
parameter not related to the poll mechanism.
4
iothread_set_param/iothread_get_param") moved common code to set and
5
get IOThread parameters in two new functions.
5
6
6
Let's add two new generic functions (iothread_set_param and
7
These functions are called inside callbacks, so we don't need to use an
7
iothread_get_param) that we use to set and get IOThread
8
opaque pointer. Let's replace `void *opaque` parameter with
8
parameters.
9
`IOThreadParamInfo *info`.
9
10
11
Suggested-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
12
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
11
Message-id: 20210721094211.69853-2-sgarzare@redhat.com
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Message-id: 20210727145936.147032-3-sgarzare@redhat.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
16
---
14
iothread.c | 27 +++++++++++++++++++++++----
17
iothread.c | 18 ++++++++++--------
15
1 file changed, 23 insertions(+), 4 deletions(-)
18
1 file changed, 10 insertions(+), 8 deletions(-)
16
19
17
diff --git a/iothread.c b/iothread.c
20
diff --git a/iothread.c b/iothread.c
18
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
19
--- a/iothread.c
22
--- a/iothread.c
20
+++ b/iothread.c
23
+++ b/iothread.c
21
@@ -XXX,XX +XXX,XX @@ static PollParamInfo poll_shrink_info = {
24
@@ -XXX,XX +XXX,XX @@ static IOThreadParamInfo aio_max_batch_info = {
22
"poll-shrink", offsetof(IOThread, poll_shrink),
23
};
25
};
24
26
25
-static void iothread_get_poll_param(Object *obj, Visitor *v,
27
static void iothread_get_param(Object *obj, Visitor *v,
26
+static void iothread_get_param(Object *obj, Visitor *v,
28
- const char *name, void *opaque, Error **errp)
29
+ const char *name, IOThreadParamInfo *info, Error **errp)
30
{
31
IOThread *iothread = IOTHREAD(obj);
32
- IOThreadParamInfo *info = opaque;
33
int64_t *field = (void *)iothread + info->offset;
34
35
visit_type_int64(v, name, field, errp);
36
}
37
38
static bool iothread_set_param(Object *obj, Visitor *v,
39
- const char *name, void *opaque, Error **errp)
40
+ const char *name, IOThreadParamInfo *info, Error **errp)
41
{
42
IOThread *iothread = IOTHREAD(obj);
43
- IOThreadParamInfo *info = opaque;
44
int64_t *field = (void *)iothread + info->offset;
45
int64_t value;
46
47
@@ -XXX,XX +XXX,XX @@ static bool iothread_set_param(Object *obj, Visitor *v,
48
static void iothread_get_poll_param(Object *obj, Visitor *v,
49
const char *name, void *opaque, Error **errp)
50
{
51
+ IOThreadParamInfo *info = opaque;
52
53
- iothread_get_param(obj, v, name, opaque, errp);
54
+ iothread_get_param(obj, v, name, info, errp);
55
}
56
57
static void iothread_set_poll_param(Object *obj, Visitor *v,
27
const char *name, void *opaque, Error **errp)
58
const char *name, void *opaque, Error **errp)
28
{
59
{
29
IOThread *iothread = IOTHREAD(obj);
60
IOThread *iothread = IOTHREAD(obj);
30
@@ -XXX,XX +XXX,XX @@ static void iothread_get_poll_param(Object *obj, Visitor *v,
61
+ IOThreadParamInfo *info = opaque;
31
visit_type_int64(v, name, field, errp);
62
63
- if (!iothread_set_param(obj, v, name, opaque, errp)) {
64
+ if (!iothread_set_param(obj, v, name, info, errp)) {
65
return;
66
}
67
68
@@ -XXX,XX +XXX,XX @@ static void iothread_set_poll_param(Object *obj, Visitor *v,
69
static void iothread_get_aio_param(Object *obj, Visitor *v,
70
const char *name, void *opaque, Error **errp)
71
{
72
+ IOThreadParamInfo *info = opaque;
73
74
- iothread_get_param(obj, v, name, opaque, errp);
75
+ iothread_get_param(obj, v, name, info, errp);
32
}
76
}
33
77
34
-static void iothread_set_poll_param(Object *obj, Visitor *v,
78
static void iothread_set_aio_param(Object *obj, Visitor *v,
35
+static bool iothread_set_param(Object *obj, Visitor *v,
36
const char *name, void *opaque, Error **errp)
79
const char *name, void *opaque, Error **errp)
37
{
80
{
38
IOThread *iothread = IOTHREAD(obj);
81
IOThread *iothread = IOTHREAD(obj);
39
@@ -XXX,XX +XXX,XX @@ static void iothread_set_poll_param(Object *obj, Visitor *v,
82
+ IOThreadParamInfo *info = opaque;
40
int64_t value;
83
41
84
- if (!iothread_set_param(obj, v, name, opaque, errp)) {
42
if (!visit_type_int64(v, name, &value, errp)) {
85
+ if (!iothread_set_param(obj, v, name, info, errp)) {
43
- return;
86
return;
44
+ return false;
45
}
87
}
46
88
47
if (value < 0) {
48
error_setg(errp, "%s value must be in range [0, %" PRId64 "]",
49
info->name, INT64_MAX);
50
- return;
51
+ return false;
52
}
53
54
*field = value;
55
56
+ return true;
57
+}
58
+
59
+static void iothread_get_poll_param(Object *obj, Visitor *v,
60
+ const char *name, void *opaque, Error **errp)
61
+{
62
+
63
+ iothread_get_param(obj, v, name, opaque, errp);
64
+}
65
+
66
+static void iothread_set_poll_param(Object *obj, Visitor *v,
67
+ const char *name, void *opaque, Error **errp)
68
+{
69
+ IOThread *iothread = IOTHREAD(obj);
70
+
71
+ if (!iothread_set_param(obj, v, name, opaque, errp)) {
72
+ return;
73
+ }
74
+
75
if (iothread->ctx) {
76
aio_context_set_poll_params(iothread->ctx,
77
iothread->poll_max_ns,
78
--
89
--
79
2.31.1
90
2.31.1
80
91
92
diff view generated by jsdifflib
Deleted patch
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
1
3
When there are multiple queues attached to the same AIO context,
4
some requests may experience high latency, since in the worst case
5
the AIO engine queue is only flushed when it is full (MAX_EVENTS) or
6
there are no more queues plugged.
7
8
Commit 2558cb8dd4 ("linux-aio: increasing MAX_EVENTS to a larger
9
hardcoded value") changed MAX_EVENTS from 128 to 1024, to increase
10
the number of in-flight requests. But this change also increased
11
the potential maximum batch to 1024 elements.
12
13
When there is a single queue attached to the AIO context, the issue
14
is mitigated from laio_io_unplug() that will flush the queue every
15
time is invoked since there can't be others queue plugged.
16
17
Let's use the new `aio-max-batch` IOThread parameter to mitigate
18
this issue, limiting the number of requests in a batch.
19
20
We also define a default value (32): this value is obtained running
21
some benchmarks and it represents a good tradeoff between the latency
22
increase while a request is queued and the cost of the io_submit(2)
23
system call.
24
25
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
26
Message-id: 20210721094211.69853-4-sgarzare@redhat.com
27
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
28
---
29
block/linux-aio.c | 9 ++++++++-
30
1 file changed, 8 insertions(+), 1 deletion(-)
31
32
diff --git a/block/linux-aio.c b/block/linux-aio.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/block/linux-aio.c
35
+++ b/block/linux-aio.c
36
@@ -XXX,XX +XXX,XX @@
37
*/
38
#define MAX_EVENTS 1024
39
40
+/* Maximum number of requests in a batch. (default value) */
41
+#define DEFAULT_MAX_BATCH 32
42
+
43
struct qemu_laiocb {
44
Coroutine *co;
45
LinuxAioState *ctx;
46
@@ -XXX,XX +XXX,XX @@ static int laio_do_submit(int fd, struct qemu_laiocb *laiocb, off_t offset,
47
LinuxAioState *s = laiocb->ctx;
48
struct iocb *iocbs = &laiocb->iocb;
49
QEMUIOVector *qiov = laiocb->qiov;
50
+ int64_t max_batch = s->aio_context->aio_max_batch ?: DEFAULT_MAX_BATCH;
51
+
52
+ /* limit the batch with the number of available events */
53
+ max_batch = MIN_NON_ZERO(MAX_EVENTS - s->io_q.in_flight, max_batch);
54
55
switch (type) {
56
case QEMU_AIO_WRITE:
57
@@ -XXX,XX +XXX,XX @@ static int laio_do_submit(int fd, struct qemu_laiocb *laiocb, off_t offset,
58
s->io_q.in_queue++;
59
if (!s->io_q.blocked &&
60
(!s->io_q.plugged ||
61
- s->io_q.in_flight + s->io_q.in_queue >= MAX_EVENTS)) {
62
+ s->io_q.in_queue >= max_batch)) {
63
ioq_submit(s);
64
}
65
66
--
67
2.31.1
68
diff view generated by jsdifflib