diff mbox series

[RFC,2/8] virtio: Introduce virtio_bus_set_host_notifiers()

Message ID 20210325150735.1098387-3-groug@kaod.org
State New
Headers show
Series None | expand

Commit Message

Greg Kurz March 25, 2021, 3:07 p.m. UTC
Multiqueue devices such as virtio-scsi or virtio-blk, all open-code the
same pattern to setup/tear down host notifiers of the request virtqueues.
Consolidate the pattern in a new virtio_bus_set_host_notifiers() API.
Since virtio-scsi and virtio-blk both fallback to userspace if host
notifiers can't be set, e.g. file descriptor exhaustion, go for a
warning rather than an error. Also make it oneshot to avoid flooding
the logs since the message would be very likely the same for all
virtqueues.

Devices will be converted to use virtio_bus_set_host_notifiers() in
separate patches.

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 include/hw/virtio/virtio-bus.h |  3 +++
 hw/virtio/virtio-bus.c         | 36 ++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

Comments

Stefan Hajnoczi March 29, 2021, 5:06 p.m. UTC | #1
On Thu, Mar 25, 2021 at 04:07:29PM +0100, Greg Kurz wrote:
> Multiqueue devices such as virtio-scsi or virtio-blk, all open-code the
> same pattern to setup/tear down host notifiers of the request virtqueues.
> Consolidate the pattern in a new virtio_bus_set_host_notifiers() API.
> Since virtio-scsi and virtio-blk both fallback to userspace if host
> notifiers can't be set, e.g. file descriptor exhaustion, go for a
> warning rather than an error. Also make it oneshot to avoid flooding
> the logs since the message would be very likely the same for all
> virtqueues.
> 
> Devices will be converted to use virtio_bus_set_host_notifiers() in
> separate patches.
> 
> Signed-off-by: Greg Kurz <groug@kaod.org>
> ---
>  include/hw/virtio/virtio-bus.h |  3 +++
>  hw/virtio/virtio-bus.c         | 36 ++++++++++++++++++++++++++++++++++
>  2 files changed, 39 insertions(+)

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
diff mbox series

Patch

diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
index ef8abe49c5a1..6d1e4ee3e886 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -154,5 +154,8 @@  void virtio_bus_release_ioeventfd(VirtioBusState *bus);
 int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign);
 /* Tell the bus that the ioeventfd handler is no longer required. */
 void virtio_bus_cleanup_host_notifier(VirtioBusState *bus, int n);
+/* Call virtio_bus_set_host_notifier() for several consecutive vqs */
+int virtio_bus_set_host_notifiers(VirtioBusState *bus, int nvqs, int n_offset,
+                                  bool assign);
 
 #endif /* VIRTIO_BUS_H */
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index d6332d45c3b2..c9e7cdb5c161 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -308,6 +308,42 @@  void virtio_bus_cleanup_host_notifier(VirtioBusState *bus, int n)
     event_notifier_cleanup(notifier);
 }
 
+static void virtio_bus_unset_and_cleanup_host_notifiers(VirtioBusState *bus,
+                                                        int nvqs, int n_offset)
+{
+    int i;
+
+    for (i = 0; i < nvqs; i++) {
+        virtio_bus_set_host_notifier(bus, i + n_offset, false);
+        virtio_bus_cleanup_host_notifier(bus, i + n_offset);
+    }
+}
+
+int virtio_bus_set_host_notifiers(VirtioBusState *bus, int nvqs, int n_offset,
+                                  bool assign)
+{
+    VirtIODevice *vdev = virtio_bus_get_device(bus);
+    int i;
+    int rc;
+
+    if (assign) {
+        for (i = 0; i < nvqs; i++) {
+            rc = virtio_bus_set_host_notifier(bus, i + n_offset, true);
+            if (rc != 0) {
+                warn_report_once("%s: Failed to set host notifier (%s).\n",
+                                 vdev->name, strerror(-rc));
+
+                virtio_bus_unset_and_cleanup_host_notifiers(bus, i, n_offset);
+                return rc;
+            }
+        }
+    } else {
+        virtio_bus_unset_and_cleanup_host_notifiers(bus, nvqs, n_offset);
+    }
+
+    return 0;
+}
+
 static char *virtio_bus_get_dev_path(DeviceState *dev)
 {
     BusState *bus = qdev_get_parent_bus(dev);