]> git.proxmox.com Git - pve-qemu.git/blame - debian/patches/extra/0011-virtio-Re-enable-notifications-after-drain.patch
makefile: also filter 64-bit hppa ROM for QEMU 8.2
[pve-qemu.git] / debian / patches / extra / 0011-virtio-Re-enable-notifications-after-drain.patch
CommitLineData
4ff04bdf
TL
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Hanna Czenczek <hreitz@redhat.com>
3Date: Fri, 2 Feb 2024 16:31:57 +0100
4Subject: [PATCH] virtio: Re-enable notifications after drain
5
6During drain, we do not care about virtqueue notifications, which is why
7we remove the handlers on it. When removing those handlers, whether vq
8notifications are enabled or not depends on whether we were in polling
9mode or not; if not, they are enabled (by default); if so, they have
10been disabled by the io_poll_start callback.
11
12Because we do not care about those notifications after removing the
13handlers, this is fine. However, we have to explicitly ensure they are
14enabled when re-attaching the handlers, so we will resume receiving
15notifications. We do this in virtio_queue_aio_attach_host_notifier*().
16If such a function is called while we are in a polling section,
17attaching the notifiers will then invoke the io_poll_start callback,
18re-disabling notifications.
19
20Because we will always miss virtqueue updates in the drained section, we
21also need to poll the virtqueue once after attaching the notifiers.
22
23Buglink: https://issues.redhat.com/browse/RHEL-3934
24Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
25Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
26---
27 hw/virtio/virtio.c | 42 ++++++++++++++++++++++++++++++++++++++++++
28 include/block/aio.h | 7 ++++++-
29 2 files changed, 48 insertions(+), 1 deletion(-)
30
31diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
32index 969c25f4cf..02cce83111 100644
33--- a/hw/virtio/virtio.c
34+++ b/hw/virtio/virtio.c
35@@ -3526,6 +3526,17 @@ static void virtio_queue_host_notifier_aio_poll_end(EventNotifier *n)
36
37 void virtio_queue_aio_attach_host_notifier(VirtQueue *vq, AioContext *ctx)
38 {
39+ /*
40+ * virtio_queue_aio_detach_host_notifier() can leave notifications disabled.
41+ * Re-enable them. (And if detach has not been used before, notifications
42+ * being enabled is still the default state while a notifier is attached;
43+ * see virtio_queue_host_notifier_aio_poll_end(), which will always leave
44+ * notifications enabled once the polling section is left.)
45+ */
46+ if (!virtio_queue_get_notification(vq)) {
47+ virtio_queue_set_notification(vq, 1);
48+ }
49+
50 aio_set_event_notifier(ctx, &vq->host_notifier,
51 virtio_queue_host_notifier_read,
52 virtio_queue_host_notifier_aio_poll,
53@@ -3533,6 +3544,13 @@ void virtio_queue_aio_attach_host_notifier(VirtQueue *vq, AioContext *ctx)
54 aio_set_event_notifier_poll(ctx, &vq->host_notifier,
55 virtio_queue_host_notifier_aio_poll_begin,
56 virtio_queue_host_notifier_aio_poll_end);
57+
58+ /*
59+ * We will have ignored notifications about new requests from the guest
60+ * while no notifiers were attached, so "kick" the virt queue to process
61+ * those requests now.
62+ */
63+ event_notifier_set(&vq->host_notifier);
64 }
65
66 /*
67@@ -3543,14 +3561,38 @@ void virtio_queue_aio_attach_host_notifier(VirtQueue *vq, AioContext *ctx)
68 */
69 void virtio_queue_aio_attach_host_notifier_no_poll(VirtQueue *vq, AioContext *ctx)
70 {
71+ /* See virtio_queue_aio_attach_host_notifier() */
72+ if (!virtio_queue_get_notification(vq)) {
73+ virtio_queue_set_notification(vq, 1);
74+ }
75+
76 aio_set_event_notifier(ctx, &vq->host_notifier,
77 virtio_queue_host_notifier_read,
78 NULL, NULL);
79+
80+ /*
81+ * See virtio_queue_aio_attach_host_notifier().
82+ * Note that this may be unnecessary for the type of virtqueues this
83+ * function is used for. Still, it will not hurt to have a quick look into
84+ * whether we can/should process any of the virtqueue elements.
85+ */
86+ event_notifier_set(&vq->host_notifier);
87 }
88
89 void virtio_queue_aio_detach_host_notifier(VirtQueue *vq, AioContext *ctx)
90 {
91 aio_set_event_notifier(ctx, &vq->host_notifier, NULL, NULL, NULL);
92+
93+ /*
94+ * aio_set_event_notifier_poll() does not guarantee whether io_poll_end()
95+ * will run after io_poll_begin(), so by removing the notifier, we do not
96+ * know whether virtio_queue_host_notifier_aio_poll_end() has run after a
97+ * previous virtio_queue_host_notifier_aio_poll_begin(), i.e. whether
98+ * notifications are enabled or disabled. It does not really matter anyway;
99+ * we just removed the notifier, so we do not care about notifications until
100+ * we potentially re-attach it. The attach_host_notifier functions will
101+ * ensure that notifications are enabled again when they are needed.
102+ */
103 }
104
105 void virtio_queue_host_notifier_read(EventNotifier *n)
106diff --git a/include/block/aio.h b/include/block/aio.h
107index 32042e8905..79efadfa48 100644
108--- a/include/block/aio.h
109+++ b/include/block/aio.h
110@@ -498,9 +498,14 @@ void aio_set_event_notifier(AioContext *ctx,
111 AioPollFn *io_poll,
112 EventNotifierHandler *io_poll_ready);
113
114-/* Set polling begin/end callbacks for an event notifier that has already been
115+/*
116+ * Set polling begin/end callbacks for an event notifier that has already been
117 * registered with aio_set_event_notifier. Do nothing if the event notifier is
118 * not registered.
119+ *
120+ * Note that if the io_poll_end() callback (or the entire notifier) is removed
121+ * during polling, it will not be called, so an io_poll_begin() is not
122+ * necessarily always followed by an io_poll_end().
123 */
124 void aio_set_event_notifier_poll(AioContext *ctx,
125 EventNotifier *notifier,