1
The following changes since commit d0ed6a69d399ae193959225cdeaa9382746c91cc:
1
The following changes since commit ca61fa4b803e5d0abaf6f1ceb690f23bb78a4def:
2
2
3
Update version for v5.1.0 release (2020-08-11 17:07:03 +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://github.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 44277bf914471962c9e88e09c859aae65ae109c4:
9
for you to fetch changes up to 1cc7eada97914f090125e588497986f6f7900514:
10
10
11
aio-posix: keep aio_notify_me disabled during polling (2020-08-13 13:34:14 =
11
iothread: use IOThreadParamInfo in iothread_[set|get]_param() (2021-10-07 15:29:50 +0100)
12
+0100)
13
12
14
----------------------------------------------------------------
13
----------------------------------------------------------------
15
Pull request
14
Pull request
16
15
17
----------------------------------------------------------------
16
----------------------------------------------------------------
18
17
19
Stefan Hajnoczi (3):
18
Stefano Garzarella (2):
20
async: rename event_notifier_dummy_cb/poll()
19
iothread: rename PollParamInfo to IOThreadParamInfo
21
async: always set ctx->notified in aio_notify()
20
iothread: use IOThreadParamInfo in iothread_[set|get]_param()
22
aio-posix: keep aio_notify_me disabled during polling
23
21
24
util/aio-posix.c | 47 +++++++++++++++++++++++++----------------------
22
iothread.c | 28 +++++++++++++++-------------
25
util/async.c | 36 +++++++++++++++++++++++-------------
23
1 file changed, 15 insertions(+), 13 deletions(-)
26
2 files changed, 48 insertions(+), 35 deletions(-)
27
24
28
--=20
25
--
29
2.26.2
26
2.31.1
30
27
28
29
diff view generated by jsdifflib
1
Polling only monitors the ctx->notified field and does not need the
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
ctx->notifier EventNotifier to be signalled. Keep ctx->aio_notify_me
3
disabled while polling to avoid unnecessary EventNotifier syscalls.
4
2
5
This optimization improves virtio-blk 4KB random read performance by
3
Commit 1793ad0247 ("iothread: add aio-max-batch parameter") added
6
18%. The following results are with an IOThread and the null-co block
4
a new parameter (aio-max-batch) to IOThread and used PollParamInfo
7
driver:
5
structure to handle it.
8
6
9
Test IOPS Error
7
Since it is not a parameter of the polling mechanism, we rename the
10
Before 244518.62 ± 1.20%
8
structure to a more generic IOThreadParamInfo.
11
After 290706.11 ± 0.44%
12
9
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Suggested-by: Kevin Wolf <kwolf@redhat.com>
14
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
11
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
Message-id: 20200806131802.569478-4-stefanha@redhat.com
13
Message-id: 20210727145936.147032-2-sgarzare@redhat.com
17
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
18
---
15
---
19
util/aio-posix.c | 47 +++++++++++++++++++++++++----------------------
16
iothread.c | 14 +++++++-------
20
1 file changed, 25 insertions(+), 22 deletions(-)
17
1 file changed, 7 insertions(+), 7 deletions(-)
21
18
22
diff --git a/util/aio-posix.c b/util/aio-posix.c
19
diff --git a/iothread.c b/iothread.c
23
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
24
--- a/util/aio-posix.c
21
--- a/iothread.c
25
+++ b/util/aio-posix.c
22
+++ b/iothread.c
26
@@ -XXX,XX +XXX,XX @@ static bool remove_idle_poll_handlers(AioContext *ctx, int64_t now)
23
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
27
*
24
typedef struct {
28
* Polls for a given time.
25
const char *name;
29
*
26
ptrdiff_t offset; /* field's byte offset in IOThread struct */
30
- * Note that ctx->notify_me must be non-zero so this function can detect
27
-} PollParamInfo;
31
- * aio_notify().
28
+} IOThreadParamInfo;
32
- *
29
33
* Note that the caller must have incremented ctx->list_lock.
30
-static PollParamInfo poll_max_ns_info = {
34
*
31
+static IOThreadParamInfo poll_max_ns_info = {
35
* Returns: true if progress was made, false otherwise
32
"poll-max-ns", offsetof(IOThread, poll_max_ns),
36
@@ -XXX,XX +XXX,XX @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout)
33
};
37
bool progress;
34
-static PollParamInfo poll_grow_info = {
38
int64_t start_time, elapsed_time;
35
+static IOThreadParamInfo poll_grow_info = {
39
36
"poll-grow", offsetof(IOThread, poll_grow),
40
- assert(ctx->notify_me);
37
};
41
assert(qemu_lockcnt_count(&ctx->list_lock) > 0);
38
-static PollParamInfo poll_shrink_info = {
42
39
+static IOThreadParamInfo poll_shrink_info = {
43
trace_run_poll_handlers_begin(ctx, max_ns, *timeout);
40
"poll-shrink", offsetof(IOThread, poll_shrink),
44
@@ -XXX,XX +XXX,XX @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout)
41
};
45
* @timeout: timeout for blocking wait, computed by the caller and updated if
42
-static PollParamInfo aio_max_batch_info = {
46
* polling succeeds.
43
+static IOThreadParamInfo aio_max_batch_info = {
47
*
44
"aio-max-batch", offsetof(IOThread, aio_max_batch),
48
- * ctx->notify_me must be non-zero so this function can detect aio_notify().
45
};
49
- *
46
50
* Note that the caller must have incremented ctx->list_lock.
47
@@ -XXX,XX +XXX,XX @@ static void iothread_get_param(Object *obj, Visitor *v,
51
*
48
const char *name, void *opaque, Error **errp)
52
* Returns: true if progress was made, false otherwise
49
{
53
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
50
IOThread *iothread = IOTHREAD(obj);
54
AioHandlerList ready_list = QLIST_HEAD_INITIALIZER(ready_list);
51
- PollParamInfo *info = opaque;
55
int ret = 0;
52
+ IOThreadParamInfo *info = opaque;
56
bool progress;
53
int64_t *field = (void *)iothread + info->offset;
57
+ bool use_notify_me;
54
58
int64_t timeout;
55
visit_type_int64(v, name, field, errp);
59
int64_t start = 0;
56
@@ -XXX,XX +XXX,XX @@ static bool iothread_set_param(Object *obj, Visitor *v,
60
57
const char *name, void *opaque, Error **errp)
61
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
58
{
62
*/
59
IOThread *iothread = IOTHREAD(obj);
63
assert(in_aio_context_home_thread(ctx));
60
- PollParamInfo *info = opaque;
64
61
+ IOThreadParamInfo *info = opaque;
65
- /* aio_notify can avoid the expensive event_notifier_set if
62
int64_t *field = (void *)iothread + info->offset;
66
+ qemu_lockcnt_inc(&ctx->list_lock);
63
int64_t value;
67
+
64
68
+ if (ctx->poll_max_ns) {
69
+ start = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
70
+ }
71
+
72
+ timeout = blocking ? aio_compute_timeout(ctx) : 0;
73
+ progress = try_poll_mode(ctx, &timeout);
74
+ assert(!(timeout && progress));
75
+
76
+ /*
77
+ * aio_notify can avoid the expensive event_notifier_set if
78
* everything (file descriptors, bottom halves, timers) will
79
* be re-evaluated before the next blocking poll(). This is
80
* already true when aio_poll is called with blocking == false;
81
* if blocking == true, it is only true after poll() returns,
82
* so disable the optimization now.
83
*/
84
- if (blocking) {
85
+ use_notify_me = timeout != 0;
86
+ if (use_notify_me) {
87
atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) + 2);
88
/*
89
- * Write ctx->notify_me before computing the timeout
90
- * (reading bottom half flags, etc.). Pairs with
91
+ * Write ctx->notify_me before reading ctx->notified. Pairs with
92
* smp_mb in aio_notify().
93
*/
94
smp_mb();
95
- }
96
-
97
- qemu_lockcnt_inc(&ctx->list_lock);
98
99
- if (ctx->poll_max_ns) {
100
- start = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
101
+ /* Don't block if aio_notify() was called */
102
+ if (atomic_read(&ctx->notified)) {
103
+ timeout = 0;
104
+ }
105
}
106
107
- timeout = blocking ? aio_compute_timeout(ctx) : 0;
108
- progress = try_poll_mode(ctx, &timeout);
109
- assert(!(timeout && progress));
110
-
111
/* If polling is allowed, non-blocking aio_poll does not need the
112
* system call---a single round of run_poll_handlers_once suffices.
113
*/
114
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
115
ret = ctx->fdmon_ops->wait(ctx, &ready_list, timeout);
116
}
117
118
- if (blocking) {
119
+ if (use_notify_me) {
120
/* Finish the poll before clearing the flag. */
121
- atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) - 2);
122
- aio_notify_accept(ctx);
123
+ atomic_store_release(&ctx->notify_me,
124
+ atomic_read(&ctx->notify_me) - 2);
125
}
126
127
+ aio_notify_accept(ctx);
128
+
129
/* Adjust polling time */
130
if (ctx->poll_max_ns) {
131
int64_t block_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - start;
132
--
65
--
133
2.26.2
66
2.31.1
134
67
68
diff view generated by jsdifflib
1
The event_notifier_*() prefix can be confused with the EventNotifier
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
APIs that are also called event_notifier_*().
3
2
4
Rename the functions to aio_context_notifier_*() to make it clear that
3
Commit 0445409d74 ("iothread: generalize
5
they relate to the AioContext::notifier field.
4
iothread_set_param/iothread_get_param") moved common code to set and
5
get IOThread parameters in two new functions.
6
6
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
These functions are called inside callbacks, so we don't need to use an
8
opaque pointer. Let's replace `void *opaque` parameter with
9
`IOThreadParamInfo *info`.
10
11
Suggested-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
14
Message-id: 20210727145936.147032-3-sgarzare@redhat.com
10
Message-id: 20200806131802.569478-2-stefanha@redhat.com
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
16
---
13
util/async.c | 8 ++++----
17
iothread.c | 18 ++++++++++--------
14
1 file changed, 4 insertions(+), 4 deletions(-)
18
1 file changed, 10 insertions(+), 8 deletions(-)
15
19
16
diff --git a/util/async.c b/util/async.c
20
diff --git a/iothread.c b/iothread.c
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/util/async.c
22
--- a/iothread.c
19
+++ b/util/async.c
23
+++ b/iothread.c
20
@@ -XXX,XX +XXX,XX @@ static void aio_timerlist_notify(void *opaque, QEMUClockType type)
24
@@ -XXX,XX +XXX,XX @@ static IOThreadParamInfo aio_max_batch_info = {
21
aio_notify(opaque);
25
};
26
27
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);
22
}
36
}
23
37
24
-static void event_notifier_dummy_cb(EventNotifier *e)
38
static bool iothread_set_param(Object *obj, Visitor *v,
25
+static void aio_context_notifier_dummy_cb(EventNotifier *e)
39
- const char *name, void *opaque, Error **errp)
40
+ const char *name, IOThreadParamInfo *info, Error **errp)
26
{
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);
27
}
55
}
28
56
29
/* Returns true if aio_notify() was called (e.g. a BH was scheduled) */
57
static void iothread_set_poll_param(Object *obj, Visitor *v,
30
-static bool event_notifier_poll(void *opaque)
58
const char *name, void *opaque, Error **errp)
31
+static bool aio_context_notifier_poll(void *opaque)
32
{
59
{
33
EventNotifier *e = opaque;
60
IOThread *iothread = IOTHREAD(obj);
34
AioContext *ctx = container_of(e, AioContext, notifier);
61
+ IOThreadParamInfo *info = opaque;
35
@@ -XXX,XX +XXX,XX @@ AioContext *aio_context_new(Error **errp)
62
36
63
- if (!iothread_set_param(obj, v, name, opaque, errp)) {
37
aio_set_event_notifier(ctx, &ctx->notifier,
64
+ if (!iothread_set_param(obj, v, name, info, errp)) {
38
false,
65
return;
39
- event_notifier_dummy_cb,
66
}
40
- event_notifier_poll);
67
41
+ aio_context_notifier_dummy_cb,
68
@@ -XXX,XX +XXX,XX @@ static void iothread_set_poll_param(Object *obj, Visitor *v,
42
+ aio_context_notifier_poll);
69
static void iothread_get_aio_param(Object *obj, Visitor *v,
43
#ifdef CONFIG_LINUX_AIO
70
const char *name, void *opaque, Error **errp)
44
ctx->linux_aio = NULL;
71
{
45
#endif
72
+ IOThreadParamInfo *info = opaque;
73
74
- iothread_get_param(obj, v, name, opaque, errp);
75
+ iothread_get_param(obj, v, name, info, errp);
76
}
77
78
static void iothread_set_aio_param(Object *obj, Visitor *v,
79
const char *name, void *opaque, Error **errp)
80
{
81
IOThread *iothread = IOTHREAD(obj);
82
+ IOThreadParamInfo *info = opaque;
83
84
- if (!iothread_set_param(obj, v, name, opaque, errp)) {
85
+ if (!iothread_set_param(obj, v, name, info, errp)) {
86
return;
87
}
88
46
--
89
--
47
2.26.2
90
2.31.1
48
91
92
diff view generated by jsdifflib
Deleted patch
1
aio_notify() does not set ctx->notified when called with
2
ctx->aio_notify_me disabled. Therefore aio_notify_me needs to be enabled
3
during polling.
4
1
5
This is suboptimal since expensive event_notifier_set(&ctx->notifier)
6
and event_notifier_test_and_clear(&ctx->notifier) calls are required
7
when ctx->aio_notify_me is enabled.
8
9
Change aio_notify() so that aio->notified is always set, regardless of
10
ctx->aio_notify_me. This will make polling cheaper since
11
ctx->aio_notify_me can remain disabled. Move the
12
event_notifier_test_and_clear() to the fd handler function (which is now
13
no longer an empty function so "dummy" has been dropped from its name).
14
15
The next patch takes advantage of this by optimizing polling in
16
util/aio-posix.c.
17
18
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
19
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
21
Message-id: 20200806131802.569478-3-stefanha@redhat.com
22
23
[Paolo Bonzini pointed out that the smp_wmb() in aio_notify_accept()
24
should be smp_wb() but the comment should be smp_wmb() instead of
25
smp_wb(). Fixed.
26
--Stefan]
27
28
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
29
---
30
util/async.c | 32 +++++++++++++++++++++-----------
31
1 file changed, 21 insertions(+), 11 deletions(-)
32
33
diff --git a/util/async.c b/util/async.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/util/async.c
36
+++ b/util/async.c
37
@@ -XXX,XX +XXX,XX @@ LuringState *aio_get_linux_io_uring(AioContext *ctx)
38
39
void aio_notify(AioContext *ctx)
40
{
41
- /* Write e.g. bh->scheduled before reading ctx->notify_me. Pairs
42
+ /*
43
+ * Write e.g. bh->flags before writing ctx->notified. Pairs with smp_mb in
44
+ * aio_notify_accept.
45
+ */
46
+ smp_wmb();
47
+ atomic_set(&ctx->notified, true);
48
+
49
+ /*
50
+ * Write ctx->notified before reading ctx->notify_me. Pairs
51
* with smp_mb in aio_ctx_prepare or aio_poll.
52
*/
53
smp_mb();
54
if (atomic_read(&ctx->notify_me)) {
55
event_notifier_set(&ctx->notifier);
56
- atomic_mb_set(&ctx->notified, true);
57
}
58
}
59
60
void aio_notify_accept(AioContext *ctx)
61
{
62
- if (atomic_xchg(&ctx->notified, false)
63
-#ifdef WIN32
64
- || true
65
-#endif
66
- ) {
67
- event_notifier_test_and_clear(&ctx->notifier);
68
- }
69
+ atomic_set(&ctx->notified, false);
70
+
71
+ /*
72
+ * Write ctx->notified before reading e.g. bh->flags. Pairs with smp_wmb
73
+ * in aio_notify.
74
+ */
75
+ smp_mb();
76
}
77
78
static void aio_timerlist_notify(void *opaque, QEMUClockType type)
79
@@ -XXX,XX +XXX,XX @@ static void aio_timerlist_notify(void *opaque, QEMUClockType type)
80
aio_notify(opaque);
81
}
82
83
-static void aio_context_notifier_dummy_cb(EventNotifier *e)
84
+static void aio_context_notifier_cb(EventNotifier *e)
85
{
86
+ AioContext *ctx = container_of(e, AioContext, notifier);
87
+
88
+ event_notifier_test_and_clear(&ctx->notifier);
89
}
90
91
/* Returns true if aio_notify() was called (e.g. a BH was scheduled) */
92
@@ -XXX,XX +XXX,XX @@ AioContext *aio_context_new(Error **errp)
93
94
aio_set_event_notifier(ctx, &ctx->notifier,
95
false,
96
- aio_context_notifier_dummy_cb,
97
+ aio_context_notifier_cb,
98
aio_context_notifier_poll);
99
#ifdef CONFIG_LINUX_AIO
100
ctx->linux_aio = NULL;
101
--
102
2.26.2
103
diff view generated by jsdifflib