]>
Commit | Line | Data |
---|---|---|
14ed5546 FE |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: Stefan Hajnoczi <stefanha@redhat.com> | |
3 | Date: Wed, 27 Apr 2022 15:35:37 +0100 | |
4 | Subject: [PATCH] virtio-scsi: don't waste CPU polling the event virtqueue | |
5 | ||
6 | The virtio-scsi event virtqueue is not emptied by its handler function. | |
7 | This is typical for rx virtqueues where the device uses buffers when | |
8 | some event occurs (e.g. a packet is received, an error condition | |
9 | happens, etc). | |
10 | ||
11 | Polling non-empty virtqueues wastes CPU cycles. We are not waiting for | |
12 | new buffers to become available, we are waiting for an event to occur, | |
13 | so it's a misuse of CPU resources to poll for buffers. | |
14 | ||
15 | Introduce the new virtio_queue_aio_attach_host_notifier_no_poll() API, | |
16 | which is identical to virtio_queue_aio_attach_host_notifier() except | |
17 | that it does not poll the virtqueue. | |
18 | ||
19 | Before this patch the following command-line consumed 100% CPU in the | |
20 | IOThread polling and calling virtio_scsi_handle_event(): | |
21 | ||
22 | $ qemu-system-x86_64 -M accel=kvm -m 1G -cpu host \ | |
23 | --object iothread,id=iothread0 \ | |
24 | --device virtio-scsi-pci,iothread=iothread0 \ | |
25 | --blockdev file,filename=test.img,aio=native,cache.direct=on,node-name=drive0 \ | |
26 | --device scsi-hd,drive=drive0 | |
27 | ||
28 | After this patch CPU is no longer wasted. | |
29 | ||
30 | Reported-by: Nir Soffer <nsoffer@redhat.com> | |
31 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | |
32 | Tested-by: Nir Soffer <nsoffer@redhat.com> | |
33 | Message-id: 20220427143541.119567-3-stefanha@redhat.com | |
34 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | |
35 | (cherry-picked from commit 38738f7dbbda90fbc161757b7f4be35b52205552) | |
36 | Signed-off-by: Fabian Ebner <f.ebner@proxmox.com> | |
37 | --- | |
38 | hw/scsi/virtio-scsi-dataplane.c | 2 +- | |
39 | hw/virtio/virtio.c | 13 +++++++++++++ | |
40 | include/hw/virtio/virtio.h | 1 + | |
41 | 3 files changed, 15 insertions(+), 1 deletion(-) | |
42 | ||
43 | diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c | |
44 | index 29575cbaf6..8bb6e6acfc 100644 | |
45 | --- a/hw/scsi/virtio-scsi-dataplane.c | |
46 | +++ b/hw/scsi/virtio-scsi-dataplane.c | |
47 | @@ -138,7 +138,7 @@ int virtio_scsi_dataplane_start(VirtIODevice *vdev) | |
48 | ||
49 | aio_context_acquire(s->ctx); | |
50 | virtio_queue_aio_attach_host_notifier(vs->ctrl_vq, s->ctx); | |
51 | - virtio_queue_aio_attach_host_notifier(vs->event_vq, s->ctx); | |
52 | + virtio_queue_aio_attach_host_notifier_no_poll(vs->event_vq, s->ctx); | |
53 | ||
54 | for (i = 0; i < vs->conf.num_queues; i++) { | |
55 | virtio_queue_aio_attach_host_notifier(vs->cmd_vqs[i], s->ctx); | |
56 | diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c | |
57 | index 9d637e043e..67a873f54a 100644 | |
58 | --- a/hw/virtio/virtio.c | |
59 | +++ b/hw/virtio/virtio.c | |
60 | @@ -3534,6 +3534,19 @@ void virtio_queue_aio_attach_host_notifier(VirtQueue *vq, AioContext *ctx) | |
61 | virtio_queue_host_notifier_aio_poll_end); | |
62 | } | |
63 | ||
64 | +/* | |
65 | + * Same as virtio_queue_aio_attach_host_notifier() but without polling. Use | |
66 | + * this for rx virtqueues and similar cases where the virtqueue handler | |
67 | + * function does not pop all elements. When the virtqueue is left non-empty | |
68 | + * polling consumes CPU cycles and should not be used. | |
69 | + */ | |
70 | +void virtio_queue_aio_attach_host_notifier_no_poll(VirtQueue *vq, AioContext *ctx) | |
71 | +{ | |
72 | + aio_set_event_notifier(ctx, &vq->host_notifier, true, | |
73 | + virtio_queue_host_notifier_read, | |
74 | + NULL, NULL); | |
75 | +} | |
76 | + | |
77 | void virtio_queue_aio_detach_host_notifier(VirtQueue *vq, AioContext *ctx) | |
78 | { | |
79 | aio_set_event_notifier(ctx, &vq->host_notifier, true, NULL, NULL, NULL); | |
80 | diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h | |
81 | index b31c4507f5..b62a35fdca 100644 | |
82 | --- a/include/hw/virtio/virtio.h | |
83 | +++ b/include/hw/virtio/virtio.h | |
84 | @@ -317,6 +317,7 @@ EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq); | |
85 | void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled); | |
86 | void virtio_queue_host_notifier_read(EventNotifier *n); | |
87 | void virtio_queue_aio_attach_host_notifier(VirtQueue *vq, AioContext *ctx); | |
88 | +void virtio_queue_aio_attach_host_notifier_no_poll(VirtQueue *vq, AioContext *ctx); | |
89 | void virtio_queue_aio_detach_host_notifier(VirtQueue *vq, AioContext *ctx); | |
90 | VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector); | |
91 | VirtQueue *virtio_vector_next_queue(VirtQueue *vq); |