Blame SOURCES/kvm-virtio-don-t-enable-notifications-during-polling.patch

902636
From 351dd07d7b5e69cdf47260c9ea848c0c93cd2c8a Mon Sep 17 00:00:00 2001
902636
From: Stefan Hajnoczi <stefanha@redhat.com>
902636
Date: Thu, 9 Jan 2020 11:13:25 +0000
902636
Subject: [PATCH 3/5] virtio: don't enable notifications during polling
902636
902636
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
902636
Message-id: <20200109111325.559557-2-stefanha@redhat.com>
902636
Patchwork-id: 93298
902636
O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH 1/1] virtio: don't enable notifications during polling
902636
Bugzilla: 1789301
902636
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
902636
RH-Acked-by: Sergio Lopez Pascual <slp@redhat.com>
902636
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
902636
902636
Virtqueue notifications are not necessary during polling, so we disable
902636
them.  This allows the guest driver to avoid MMIO vmexits.
902636
Unfortunately the virtio-blk and virtio-scsi handler functions re-enable
902636
notifications, defeating this optimization.
902636
902636
Fix virtio-blk and virtio-scsi emulation so they leave notifications
902636
disabled.  The key thing to remember for correctness is that polling
902636
always checks one last time after ending its loop, therefore it's safe
902636
to lose the race when re-enabling notifications at the end of polling.
902636
902636
There is a measurable performance improvement of 5-10% with the null-co
902636
block driver.  Real-life storage configurations will see a smaller
902636
improvement because the MMIO vmexit overhead contributes less to
902636
latency.
902636
902636
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
902636
Message-Id: <20191209210957.65087-1-stefanha@redhat.com>
902636
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
902636
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
902636
(cherry picked from commit d0435bc513e23a4961b6af20164d1c6c219eb4ea)
902636
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
902636
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
902636
---
902636
 hw/block/virtio-blk.c      |  9 +++++++--
902636
 hw/scsi/virtio-scsi.c      |  9 +++++++--
902636
 hw/virtio/virtio.c         | 12 ++++++------
902636
 include/hw/virtio/virtio.h |  1 +
902636
 4 files changed, 21 insertions(+), 10 deletions(-)
902636
902636
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
902636
index 4c357d2..c4e55fb 100644
902636
--- a/hw/block/virtio-blk.c
902636
+++ b/hw/block/virtio-blk.c
902636
@@ -764,13 +764,16 @@ bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
902636
 {
902636
     VirtIOBlockReq *req;
902636
     MultiReqBuffer mrb = {};
902636
+    bool suppress_notifications = virtio_queue_get_notification(vq);
902636
     bool progress = false;
902636
 
902636
     aio_context_acquire(blk_get_aio_context(s->blk));
902636
     blk_io_plug(s->blk);
902636
 
902636
     do {
902636
-        virtio_queue_set_notification(vq, 0);
902636
+        if (suppress_notifications) {
902636
+            virtio_queue_set_notification(vq, 0);
902636
+        }
902636
 
902636
         while ((req = virtio_blk_get_request(s, vq))) {
902636
             progress = true;
902636
@@ -781,7 +784,9 @@ bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
902636
             }
902636
         }
902636
 
902636
-        virtio_queue_set_notification(vq, 1);
902636
+        if (suppress_notifications) {
902636
+            virtio_queue_set_notification(vq, 1);
902636
+        }
902636
     } while (!virtio_queue_empty(vq));
902636
 
902636
     if (mrb.num_reqs) {
902636
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
902636
index 54108c0..e2cd1df 100644
902636
--- a/hw/scsi/virtio-scsi.c
902636
+++ b/hw/scsi/virtio-scsi.c
902636
@@ -597,12 +597,15 @@ bool virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq)
902636
 {
902636
     VirtIOSCSIReq *req, *next;
902636
     int ret = 0;
902636
+    bool suppress_notifications = virtio_queue_get_notification(vq);
902636
     bool progress = false;
902636
 
902636
     QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs);
902636
 
902636
     do {
902636
-        virtio_queue_set_notification(vq, 0);
902636
+        if (suppress_notifications) {
902636
+            virtio_queue_set_notification(vq, 0);
902636
+        }
902636
 
902636
         while ((req = virtio_scsi_pop_req(s, vq))) {
902636
             progress = true;
902636
@@ -622,7 +625,9 @@ bool virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq)
902636
             }
902636
         }
902636
 
902636
-        virtio_queue_set_notification(vq, 1);
902636
+        if (suppress_notifications) {
902636
+            virtio_queue_set_notification(vq, 1);
902636
+        }
902636
     } while (ret != -EINVAL && !virtio_queue_empty(vq));
902636
 
902636
     QTAILQ_FOREACH_SAFE(req, &reqs, next, next) {
902636
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
902636
index 04716b5..3211135 100644
902636
--- a/hw/virtio/virtio.c
902636
+++ b/hw/virtio/virtio.c
902636
@@ -432,6 +432,11 @@ static void virtio_queue_packed_set_notification(VirtQueue *vq, int enable)
902636
     }
902636
 }
902636
 
902636
+bool virtio_queue_get_notification(VirtQueue *vq)
902636
+{
902636
+    return vq->notification;
902636
+}
902636
+
902636
 void virtio_queue_set_notification(VirtQueue *vq, int enable)
902636
 {
902636
     vq->notification = enable;
902636
@@ -3384,17 +3389,12 @@ static bool virtio_queue_host_notifier_aio_poll(void *opaque)
902636
 {
902636
     EventNotifier *n = opaque;
902636
     VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
902636
-    bool progress;
902636
 
902636
     if (!vq->vring.desc || virtio_queue_empty(vq)) {
902636
         return false;
902636
     }
902636
 
902636
-    progress = virtio_queue_notify_aio_vq(vq);
902636
-
902636
-    /* In case the handler function re-enabled notifications */
902636
-    virtio_queue_set_notification(vq, 0);
902636
-    return progress;
902636
+    return virtio_queue_notify_aio_vq(vq);
902636
 }
902636
 
902636
 static void virtio_queue_host_notifier_aio_poll_end(EventNotifier *n)
902636
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
902636
index c32a815..6a20442 100644
902636
--- a/include/hw/virtio/virtio.h
902636
+++ b/include/hw/virtio/virtio.h
902636
@@ -224,6 +224,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id);
902636
 
902636
 void virtio_notify_config(VirtIODevice *vdev);
902636
 
902636
+bool virtio_queue_get_notification(VirtQueue *vq);
902636
 void virtio_queue_set_notification(VirtQueue *vq, int enable);
902636
 
902636
 int virtio_queue_ready(VirtQueue *vq);
902636
-- 
902636
1.8.3.1
902636