diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2019-12-09 21:09:57 +0000 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2020-01-05 07:03:03 -0500 |
commit | d0435bc513e23a4961b6af20164d1c6c219eb4ea (patch) | |
tree | 0434e1d07119ee8ea9e80143a5aa0a8c82cff41c /hw/block | |
parent | 6620801f39f0cd02b30ab5ad8729c92c78ce9fd3 (diff) |
virtio: don't enable notifications during polling
Virtqueue notifications are not necessary during polling, so we disable
them. This allows the guest driver to avoid MMIO vmexits.
Unfortunately the virtio-blk and virtio-scsi handler functions re-enable
notifications, defeating this optimization.
Fix virtio-blk and virtio-scsi emulation so they leave notifications
disabled. The key thing to remember for correctness is that polling
always checks one last time after ending its loop, therefore it's safe
to lose the race when re-enabling notifications at the end of polling.
There is a measurable performance improvement of 5-10% with the null-co
block driver. Real-life storage configurations will see a smaller
improvement because the MMIO vmexit overhead contributes less to
latency.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <20191209210957.65087-1-stefanha@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/block')
-rw-r--r-- | hw/block/virtio-blk.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index d62e6377c2..b12157b5eb 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -764,13 +764,16 @@ bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq) { VirtIOBlockReq *req; MultiReqBuffer mrb = {}; + bool suppress_notifications = virtio_queue_get_notification(vq); bool progress = false; aio_context_acquire(blk_get_aio_context(s->blk)); blk_io_plug(s->blk); do { - virtio_queue_set_notification(vq, 0); + if (suppress_notifications) { + virtio_queue_set_notification(vq, 0); + } while ((req = virtio_blk_get_request(s, vq))) { progress = true; @@ -781,7 +784,9 @@ bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq) } } - virtio_queue_set_notification(vq, 1); + if (suppress_notifications) { + virtio_queue_set_notification(vq, 1); + } } while (!virtio_queue_empty(vq)); if (mrb.num_reqs) { |