* [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers
@ 2016-03-17 10:01 Cornelia Huck
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 1/6] virtio-bus: common ioeventfd infrastructure Cornelia Huck
` (7 more replies)
0 siblings, 8 replies; 13+ messages in thread
From: Cornelia Huck @ 2016-03-17 10:01 UTC (permalink / raw)
To: qemu-devel; +Cc: famz, mst, borntraeger, stefanha, Cornelia Huck, pbonzini
As discussed in the virtio-blk dataplane start/stop thread, the
various transports contain a lot of similar/identical boilerplate
code for setting up ioeventfds. This makes the code hard to follow.
Let's drag all of the common handling into the virtio-bus layer,
hopefully reducing both the boilerplate code and the number of
indirections.
This RFC patchset is the result of hacking this up quickly, and I
was rather surprised that it did not die immediately on my s390
system (which is all I 'tested'). So be warned :)
Feedback about the approach and the interface would be good.
Cornelia Huck (6):
virtio-bus: common ioeventfd infrastructure
virtio-bus: have callers tolerate new host notifier api
virtio-ccw: convert to ioeventfd callbacks
virtio-pci: convert to ioeventfd callbacks
virtio-mmio: convert to ioeventfd callbacks
virtio-bus: remove old set_host_notifier callback
hw/block/dataplane/virtio-blk.c | 6 +-
hw/s390x/virtio-ccw.c | 133 ++++++++++++++--------------------------
hw/scsi/virtio-scsi-dataplane.c | 9 ++-
hw/virtio/vhost.c | 13 ++--
hw/virtio/virtio-bus.c | 108 ++++++++++++++++++++++++++++++++
hw/virtio/virtio-mmio.c | 128 +++++++++++++-------------------------
hw/virtio/virtio-pci.c | 124 +++++++++++++------------------------
include/hw/virtio/virtio-bus.h | 15 ++++-
8 files changed, 263 insertions(+), 273 deletions(-)
--
2.6.5
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH RFC 1/6] virtio-bus: common ioeventfd infrastructure
2016-03-17 10:01 [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers Cornelia Huck
@ 2016-03-17 10:01 ` Cornelia Huck
2016-03-22 0:24 ` Fam Zheng
2016-03-24 11:20 ` Michael S. Tsirkin
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 2/6] virtio-bus: have callers tolerate new host notifier api Cornelia Huck
` (6 subsequent siblings)
7 siblings, 2 replies; 13+ messages in thread
From: Cornelia Huck @ 2016-03-17 10:01 UTC (permalink / raw)
To: qemu-devel; +Cc: famz, mst, borntraeger, stefanha, Cornelia Huck, pbonzini
Introduce a set of ioeventfd callbacks on the virtio-bus level
that can be implemented by the individual transports. At the
virtio-bus level, do common handling for host notifiers (which
is actually most of it).
Two things of note:
- We always iterate over all possible virtio queues, even though
ccw (currently) has a lower limit. It does not really matter in
this place.
- We allow for the virtio-bus caller to pass an "assign" argument
down when stopping ioeventfd, which the old interface did not allow.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
hw/virtio/virtio-bus.c | 108 +++++++++++++++++++++++++++++++++++++++++
include/hw/virtio/virtio-bus.h | 14 ++++++
2 files changed, 122 insertions(+)
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index 574f0e2..501300f 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -146,6 +146,114 @@ void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config)
}
}
+static int set_host_notifier_internal(DeviceState *proxy, VirtioBusState *bus,
+ int n, bool assign, bool set_handler)
+{
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
+ VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
+ VirtQueue *vq = virtio_get_queue(vdev, n);
+ EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
+ int r = 0;
+
+ if (assign) {
+ r = event_notifier_init(notifier, 1);
+ if (r < 0) {
+ error_report("%s: unable to init event notifier: %d", __func__, r);
+ return r;
+ }
+ virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
+ r = k->ioeventfd_assign(proxy, notifier, n, assign);
+ if (r < 0) {
+ error_report("%s: unable to assign ioeventfd: %d", __func__, r);
+ virtio_queue_set_host_notifier_fd_handler(vq, false, false);
+ event_notifier_cleanup(notifier);
+ return r;
+ }
+ } else {
+ virtio_queue_set_host_notifier_fd_handler(vq, false, false);
+ k->ioeventfd_assign(proxy, notifier, n, assign);
+ event_notifier_cleanup(notifier);
+ }
+ return r;
+}
+
+void virtio_bus_start_ioeventfd(VirtioBusState *bus)
+{
+ VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
+ DeviceState *proxy = DEVICE(BUS(bus)->parent);
+ VirtIODevice *vdev;
+ int n, r;
+
+ if (!k->ioeventfd_started || k->ioeventfd_started(proxy)) {
+ return;
+ }
+ if (!k->ioeventfd_disabled(proxy)) {
+ return;
+ }
+ vdev = virtio_bus_get_device(bus);
+ for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+ r = set_host_notifier_internal(proxy, bus, n, true, true);
+ if (r < 0) {
+ goto assign_error;
+ }
+ }
+ k->ioeventfd_set_started(proxy, true, false);
+ return;
+
+assign_error:
+ while (--n >= 0) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+
+ r = set_host_notifier_internal(proxy, bus, n, false, false);
+ assert(r >= 0);
+ }
+ k->ioeventfd_set_started(proxy, false, true);
+ error_report("%s: failed. Fallback to userspace (slower).", __func__);
+}
+
+void virtio_bus_stop_ioeventfd(VirtioBusState *bus, bool assign)
+{
+ VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
+ DeviceState *proxy = DEVICE(BUS(bus)->parent);
+ VirtIODevice *vdev;
+ int n, r;
+
+ if (!k->ioeventfd_started || !k->ioeventfd_started(proxy)) {
+ return;
+ }
+ vdev = virtio_bus_get_device(bus);
+ for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+ r = set_host_notifier_internal(proxy, bus, n, assign, false);
+ assert(r >= 0);
+ }
+ k->ioeventfd_set_started(proxy, false, false);
+}
+
+int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign)
+{
+ VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
+ DeviceState *proxy = DEVICE(BUS(bus)->parent);
+
+ if (!k->ioeventfd_started) {
+ return -ENOSYS;
+ }
+ /* Stop using the generic ioeventfd, we are doing eventfd handling
+ * ourselves below */
+ k->ioeventfd_set_disabled(proxy, assign);
+ if (assign) {
+ virtio_bus_stop_ioeventfd(bus, assign);
+ }
+ return set_host_notifier_internal(proxy, bus, n, assign, false);
+}
+
static char *virtio_bus_get_dev_path(DeviceState *dev)
{
BusState *bus = qdev_get_parent_bus(dev);
diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
index 3f2c136..0281cbf 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -71,6 +71,16 @@ typedef struct VirtioBusClass {
void (*device_unplugged)(DeviceState *d);
int (*query_nvectors)(DeviceState *d);
/*
+ * ioeventfd handling: if the transport implements ioeventfd_started,
+ * it must implement the other ioeventfd callbacks as well
+ */
+ bool (*ioeventfd_started)(DeviceState *d);
+ void (*ioeventfd_set_started)(DeviceState *d, bool started, bool err);
+ bool (*ioeventfd_disabled)(DeviceState *d);
+ void (*ioeventfd_set_disabled)(DeviceState *d, bool disabled);
+ int (*ioeventfd_assign)(DeviceState *d, EventNotifier *notifier,
+ int n, bool assign);
+ /*
* Does the transport have variable vring alignment?
* (ie can it ever call virtio_queue_set_align()?)
* Note that changing this will break migration for this transport.
@@ -111,4 +121,8 @@ static inline VirtIODevice *virtio_bus_get_device(VirtioBusState *bus)
return (VirtIODevice *)qdev;
}
+void virtio_bus_start_ioeventfd(VirtioBusState *bus);
+void virtio_bus_stop_ioeventfd(VirtioBusState *bus, bool assign);
+int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign);
+
#endif /* VIRTIO_BUS_H */
--
2.6.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH RFC 2/6] virtio-bus: have callers tolerate new host notifier api
2016-03-17 10:01 [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers Cornelia Huck
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 1/6] virtio-bus: common ioeventfd infrastructure Cornelia Huck
@ 2016-03-17 10:01 ` Cornelia Huck
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 3/6] virtio-ccw: convert to ioeventfd callbacks Cornelia Huck
` (5 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Cornelia Huck @ 2016-03-17 10:01 UTC (permalink / raw)
To: qemu-devel; +Cc: famz, mst, borntraeger, stefanha, Cornelia Huck, pbonzini
Have vhost and dataplane use the new api for transports that
have been converted.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
hw/block/dataplane/virtio-blk.c | 14 +++++++++++---
hw/scsi/virtio-scsi-dataplane.c | 20 +++++++++++++++-----
hw/virtio/vhost.c | 20 ++++++++++++++++----
3 files changed, 42 insertions(+), 12 deletions(-)
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index 36f3d2b..9ca41d7 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -132,7 +132,8 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
}
/* Don't try if transport does not support notifiers. */
- if (!k->set_guest_notifiers || !k->set_host_notifier) {
+ if (!k->set_guest_notifiers ||
+ (!k->set_host_notifier && !k->ioeventfd_started)) {
error_setg(errp,
"device is incompatible with dataplane "
"(transport does not support notifiers)");
@@ -209,7 +210,10 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
s->guest_notifier = virtio_queue_get_guest_notifier(s->vq);
/* Set up virtqueue notify */
- r = k->set_host_notifier(qbus->parent, 0, true);
+ r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), 0, true);
+ if (r == -ENOSYS) {
+ r = k->set_host_notifier(qbus->parent, 0, true);
+ }
if (r != 0) {
fprintf(stderr, "virtio-blk failed to set host notifier (%d)\n", r);
goto fail_host_notifier;
@@ -244,6 +248,7 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
+ int r;
if (!vblk->dataplane_started || s->stopping) {
return;
@@ -268,7 +273,10 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
aio_context_release(s->ctx);
- k->set_host_notifier(qbus->parent, 0, false);
+ r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), 0, false);
+ if (r == -ENOSYS) {
+ k->set_host_notifier(qbus->parent, 0, false);
+ }
/* Clean up guest notifier (irq) */
k->set_guest_notifiers(qbus->parent, 1, false);
diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
index 367e476..88c3abd 100644
--- a/hw/scsi/virtio-scsi-dataplane.c
+++ b/hw/scsi/virtio-scsi-dataplane.c
@@ -32,7 +32,8 @@ void virtio_scsi_set_iothread(VirtIOSCSI *s, IOThread *iothread)
s->ctx = iothread_get_aio_context(vs->conf.iothread);
/* Don't try if transport does not support notifiers. */
- if (!k->set_guest_notifiers || !k->set_host_notifier) {
+ if (!k->set_guest_notifiers ||
+ (!k->set_host_notifier && !k->ioeventfd_started)) {
fprintf(stderr, "virtio-scsi: Failed to set iothread "
"(transport does not support notifiers)");
exit(1);
@@ -46,7 +47,10 @@ static int virtio_scsi_vring_init(VirtIOSCSI *s, VirtQueue *vq, int n)
int rc;
/* Set up virtqueue notify */
- rc = k->set_host_notifier(qbus->parent, n, true);
+ rc = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), n, true);
+ if (rc == -ENOSYS) {
+ rc = k->set_host_notifier(qbus->parent, n, true);
+ }
if (rc != 0) {
fprintf(stderr, "virtio-scsi: Failed to set host notifier (%d)\n",
rc);
@@ -129,7 +133,10 @@ fail_vrings:
virtio_scsi_clear_aio(s);
aio_context_release(s->ctx);
for (i = 0; i < vs->conf.num_queues + 2; i++) {
- k->set_host_notifier(qbus->parent, i, false);
+ rc = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
+ if (rc == -ENOSYS) {
+ k->set_host_notifier(qbus->parent, i, false);
+ }
}
k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, false);
fail_guest_notifiers:
@@ -144,7 +151,7 @@ void virtio_scsi_dataplane_stop(VirtIOSCSI *s)
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
- int i;
+ int i, rc;
if (!s->dataplane_started || s->dataplane_stopping) {
return;
@@ -168,7 +175,10 @@ void virtio_scsi_dataplane_stop(VirtIOSCSI *s)
aio_context_release(s->ctx);
for (i = 0; i < vs->conf.num_queues + 2; i++) {
- k->set_host_notifier(qbus->parent, i, false);
+ rc = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
+ if (rc == -ENOSYS) {
+ k->set_host_notifier(qbus->parent, i, false);
+ }
}
/* Clean up guest notifier (irq) */
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 392d848..38f54a2 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1113,14 +1113,18 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
VirtioBusState *vbus = VIRTIO_BUS(qbus);
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
int i, r, e;
- if (!k->set_host_notifier) {
+ if (!k->set_host_notifier || !k->ioeventfd_started) {
fprintf(stderr, "binding does not support host notifiers\n");
r = -ENOSYS;
goto fail;
}
for (i = 0; i < hdev->nvqs; ++i) {
- r = k->set_host_notifier(qbus->parent, hdev->vq_index + i, true);
+ r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), hdev->vq_index +i,
+ true);
+ if (r == -ENOSYS) {
+ r = k->set_host_notifier(qbus->parent, hdev->vq_index + i, true);
+ }
if (r < 0) {
fprintf(stderr, "vhost VQ %d notifier binding failed: %d\n", i, -r);
goto fail_vq;
@@ -1130,7 +1134,11 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
return 0;
fail_vq:
while (--i >= 0) {
- e = k->set_host_notifier(qbus->parent, hdev->vq_index + i, false);
+ e = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), hdev->vq_index +i,
+ false);
+ if (e == -ENOSYS) {
+ e = k->set_host_notifier(qbus->parent, hdev->vq_index + i, false);
+ }
if (e < 0) {
fprintf(stderr, "vhost VQ %d notifier cleanup error: %d\n", i, -r);
fflush(stderr);
@@ -1154,7 +1162,11 @@ void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
int i, r;
for (i = 0; i < hdev->nvqs; ++i) {
- r = k->set_host_notifier(qbus->parent, hdev->vq_index + i, false);
+ r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), hdev->vq_index +i,
+ false);
+ if (r == -ENOSYS) {
+ r = k->set_host_notifier(qbus->parent, hdev->vq_index + i, false);
+ }
if (r < 0) {
fprintf(stderr, "vhost VQ %d notifier cleanup failed: %d\n", i, -r);
fflush(stderr);
--
2.6.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH RFC 3/6] virtio-ccw: convert to ioeventfd callbacks
2016-03-17 10:01 [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers Cornelia Huck
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 1/6] virtio-bus: common ioeventfd infrastructure Cornelia Huck
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 2/6] virtio-bus: have callers tolerate new host notifier api Cornelia Huck
@ 2016-03-17 10:01 ` Cornelia Huck
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 4/6] virtio-pci: " Cornelia Huck
` (4 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Cornelia Huck @ 2016-03-17 10:01 UTC (permalink / raw)
To: qemu-devel; +Cc: famz, mst, borntraeger, stefanha, Cornelia Huck, pbonzini
Use the new interface.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
hw/s390x/virtio-ccw.c | 133 +++++++++++++++++---------------------------------
1 file changed, 45 insertions(+), 88 deletions(-)
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index cb887ba..8732b57 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -67,92 +67,58 @@ VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch)
return vdev;
}
-static int virtio_ccw_set_guest2host_notifier(VirtioCcwDevice *dev, int n,
- bool assign, bool set_handler)
+static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
{
- VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
- VirtQueue *vq = virtio_get_queue(vdev, n);
- EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
- int r = 0;
- SubchDev *sch = dev->sch;
- uint32_t sch_id = (css_build_subchannel_id(sch) << 16) | sch->schid;
+ virtio_bus_start_ioeventfd(&dev->bus);
+}
- if (assign) {
- r = event_notifier_init(notifier, 1);
- if (r < 0) {
- error_report("%s: unable to init event notifier: %d", __func__, r);
- return r;
- }
- virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
- r = s390_assign_subch_ioeventfd(notifier, sch_id, n, assign);
- if (r < 0) {
- error_report("%s: unable to assign ioeventfd: %d", __func__, r);
- virtio_queue_set_host_notifier_fd_handler(vq, false, false);
- event_notifier_cleanup(notifier);
- return r;
- }
- } else {
- virtio_queue_set_host_notifier_fd_handler(vq, false, false);
- s390_assign_subch_ioeventfd(notifier, sch_id, n, assign);
- event_notifier_cleanup(notifier);
- }
- return r;
+static void virtio_ccw_stop_ioeventfd(VirtioCcwDevice *dev)
+{
+ virtio_bus_start_ioeventfd(&dev->bus);
}
-static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
+static bool virtio_ccw_ioeventfd_started(DeviceState *d)
{
- VirtIODevice *vdev;
- int n, r;
+ VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
- if (!(dev->flags & VIRTIO_CCW_FLAG_USE_IOEVENTFD) ||
- dev->ioeventfd_disabled ||
- dev->ioeventfd_started) {
- return;
- }
- vdev = virtio_bus_get_device(&dev->bus);
- for (n = 0; n < VIRTIO_CCW_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
- r = virtio_ccw_set_guest2host_notifier(dev, n, true, true);
- if (r < 0) {
- goto assign_error;
- }
- }
- dev->ioeventfd_started = true;
- return;
+ return dev->ioeventfd_started;
+}
- assign_error:
- while (--n >= 0) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
- r = virtio_ccw_set_guest2host_notifier(dev, n, false, false);
- assert(r >= 0);
+static void virtio_ccw_ioeventfd_set_started(DeviceState *d, bool started,
+ bool err)
+{
+ VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+
+ dev->ioeventfd_started = started;
+ if (err) {
+ /* Disable ioeventfd for this device. */
+ dev->flags &= ~VIRTIO_CCW_FLAG_USE_IOEVENTFD;
}
- dev->ioeventfd_started = false;
- /* Disable ioeventfd for this device. */
- dev->flags &= ~VIRTIO_CCW_FLAG_USE_IOEVENTFD;
- error_report("%s: failed. Fallback to userspace (slower).", __func__);
}
-static void virtio_ccw_stop_ioeventfd(VirtioCcwDevice *dev)
+static bool virtio_ccw_ioeventfd_disabled(DeviceState *d)
{
- VirtIODevice *vdev;
- int n, r;
+ VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
- if (!dev->ioeventfd_started) {
- return;
- }
- vdev = virtio_bus_get_device(&dev->bus);
- for (n = 0; n < VIRTIO_CCW_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
- r = virtio_ccw_set_guest2host_notifier(dev, n, false, false);
- assert(r >= 0);
- }
- dev->ioeventfd_started = false;
+ return dev->ioeventfd_disabled ||
+ !(dev->flags & VIRTIO_CCW_FLAG_USE_IOEVENTFD);
+}
+
+static void virtio_ccw_ioeventfd_set_disabled(DeviceState *d, bool disabled)
+{
+ VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+
+ dev->ioeventfd_disabled = disabled;
+}
+
+static int virtio_ccw_ioeventfd_assign(DeviceState *d, EventNotifier *notifier,
+ int n, bool assign)
+{
+ VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+ SubchDev *sch = dev->sch;
+ uint32_t sch_id = (css_build_subchannel_id(sch) << 16) | sch->schid;
+
+ return s390_assign_subch_ioeventfd(notifier, sch_id, n, assign);
}
VirtualCssBus *virtual_css_bus_init(void)
@@ -1193,19 +1159,6 @@ static bool virtio_ccw_query_guest_notifiers(DeviceState *d)
return !!(dev->sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA);
}
-static int virtio_ccw_set_host_notifier(DeviceState *d, int n, bool assign)
-{
- VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
-
- /* Stop using the generic ioeventfd, we are doing eventfd handling
- * ourselves below */
- dev->ioeventfd_disabled = assign;
- if (assign) {
- virtio_ccw_stop_ioeventfd(dev);
- }
- return virtio_ccw_set_guest2host_notifier(dev, n, assign, false);
-}
-
static int virtio_ccw_get_mappings(VirtioCcwDevice *dev)
{
int r;
@@ -1834,7 +1787,6 @@ static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data)
k->notify = virtio_ccw_notify;
k->vmstate_change = virtio_ccw_vmstate_change;
k->query_guest_notifiers = virtio_ccw_query_guest_notifiers;
- k->set_host_notifier = virtio_ccw_set_host_notifier;
k->set_guest_notifiers = virtio_ccw_set_guest_notifiers;
k->save_queue = virtio_ccw_save_queue;
k->load_queue = virtio_ccw_load_queue;
@@ -1843,6 +1795,11 @@ static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data)
k->device_plugged = virtio_ccw_device_plugged;
k->post_plugged = virtio_ccw_post_plugged;
k->device_unplugged = virtio_ccw_device_unplugged;
+ k->ioeventfd_started = virtio_ccw_ioeventfd_started;
+ k->ioeventfd_set_started = virtio_ccw_ioeventfd_set_started;
+ k->ioeventfd_disabled = virtio_ccw_ioeventfd_disabled;
+ k->ioeventfd_set_disabled = virtio_ccw_ioeventfd_set_disabled;
+ k->ioeventfd_assign = virtio_ccw_ioeventfd_assign;
}
static const TypeInfo virtio_ccw_bus_info = {
--
2.6.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH RFC 4/6] virtio-pci: convert to ioeventfd callbacks
2016-03-17 10:01 [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers Cornelia Huck
` (2 preceding siblings ...)
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 3/6] virtio-ccw: convert to ioeventfd callbacks Cornelia Huck
@ 2016-03-17 10:01 ` Cornelia Huck
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 5/6] virtio-mmio: " Cornelia Huck
` (3 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Cornelia Huck @ 2016-03-17 10:01 UTC (permalink / raw)
To: qemu-devel; +Cc: famz, mst, borntraeger, stefanha, Cornelia Huck, pbonzini
Convert to new interface.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
hw/virtio/virtio-pci.c | 124 ++++++++++++++++---------------------------------
1 file changed, 41 insertions(+), 83 deletions(-)
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 0dadb66..b5e59c6 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -261,14 +261,44 @@ static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f)
return 0;
}
+static bool virtio_pci_ioeventfd_started(DeviceState *d)
+{
+ VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+
+ return proxy->ioeventfd_started;
+}
+
+static void virtio_pci_ioeventfd_set_started(DeviceState *d, bool started,
+ bool err)
+{
+ VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+
+ proxy->ioeventfd_started = started;
+}
+
+static bool virtio_pci_ioeventfd_disabled(DeviceState *d)
+{
+ VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+
+ return proxy->ioeventfd_disabled ||
+ !(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD);
+}
+
+static void virtio_pci_ioeventfd_set_disabled(DeviceState *d, bool disabled)
+{
+ VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+
+ proxy->ioeventfd_disabled = disabled;
+}
+
#define QEMU_VIRTIO_PCI_QUEUE_MEM_MULT 0x1000
-static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
- int n, bool assign, bool set_handler)
+static int virtio_pci_ioeventfd_assign(DeviceState *d, EventNotifier *notifier,
+ int n, bool assign)
{
+ VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtQueue *vq = virtio_get_queue(vdev, n);
- EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
bool legacy = !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_LEGACY);
bool modern = !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_MODERN);
bool fast_mmio = kvm_ioeventfd_any_length_enabled();
@@ -279,16 +309,8 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
hwaddr modern_addr = QEMU_VIRTIO_PCI_QUEUE_MEM_MULT *
virtio_get_queue_index(vq);
hwaddr legacy_addr = VIRTIO_PCI_QUEUE_NOTIFY;
- int r = 0;
if (assign) {
- r = event_notifier_init(notifier, 1);
- if (r < 0) {
- error_report("%s: unable to init event notifier: %d",
- __func__, r);
- return r;
- }
- virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
if (modern) {
if (fast_mmio) {
memory_region_add_eventfd(modern_mr, modern_addr, 0,
@@ -324,68 +346,18 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
memory_region_del_eventfd(legacy_mr, legacy_addr, 2,
true, n, notifier);
}
- virtio_queue_set_host_notifier_fd_handler(vq, false, false);
- event_notifier_cleanup(notifier);
}
- return r;
+ return 0;
}
static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
{
- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
- int n, r;
-
- if (!(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) ||
- proxy->ioeventfd_disabled ||
- proxy->ioeventfd_started) {
- return;
- }
-
- for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
-
- r = virtio_pci_set_host_notifier_internal(proxy, n, true, true);
- if (r < 0) {
- goto assign_error;
- }
- }
- proxy->ioeventfd_started = true;
- return;
-
-assign_error:
- while (--n >= 0) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
-
- r = virtio_pci_set_host_notifier_internal(proxy, n, false, false);
- assert(r >= 0);
- }
- proxy->ioeventfd_started = false;
- error_report("%s: failed. Fallback to a userspace (slower).", __func__);
+ virtio_bus_start_ioeventfd(&proxy->bus);
}
static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
{
- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
- int r;
- int n;
-
- if (!proxy->ioeventfd_started) {
- return;
- }
-
- for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
-
- r = virtio_pci_set_host_notifier_internal(proxy, n, false, false);
- assert(r >= 0);
- }
- proxy->ioeventfd_started = false;
+ virtio_bus_stop_ioeventfd(&proxy->bus, false);
}
static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
@@ -1111,24 +1083,6 @@ assign_error:
return r;
}
-static int virtio_pci_set_host_notifier(DeviceState *d, int n, bool assign)
-{
- VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
-
- /* Stop using ioeventfd for virtqueue kick if the device starts using host
- * notifiers. This makes it easy to avoid stepping on each others' toes.
- */
- proxy->ioeventfd_disabled = assign;
- if (assign) {
- virtio_pci_stop_ioeventfd(proxy);
- }
- /* We don't need to start here: it's not needed because backend
- * currently only stops on status change away from ok,
- * reset, vmstop and such. If we do add code to start here,
- * need to check vmstate, device state etc. */
- return virtio_pci_set_host_notifier_internal(proxy, n, assign, false);
-}
-
static void virtio_pci_vmstate_change(DeviceState *d, bool running)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
@@ -2489,12 +2443,16 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
k->load_extra_state = virtio_pci_load_extra_state;
k->has_extra_state = virtio_pci_has_extra_state;
k->query_guest_notifiers = virtio_pci_query_guest_notifiers;
- k->set_host_notifier = virtio_pci_set_host_notifier;
k->set_guest_notifiers = virtio_pci_set_guest_notifiers;
k->vmstate_change = virtio_pci_vmstate_change;
k->device_plugged = virtio_pci_device_plugged;
k->device_unplugged = virtio_pci_device_unplugged;
k->query_nvectors = virtio_pci_query_nvectors;
+ k->ioeventfd_started = virtio_pci_ioeventfd_started;
+ k->ioeventfd_set_started = virtio_pci_ioeventfd_set_started;
+ k->ioeventfd_disabled = virtio_pci_ioeventfd_disabled;
+ k->ioeventfd_set_disabled = virtio_pci_ioeventfd_set_disabled;
+ k->ioeventfd_assign = virtio_pci_ioeventfd_assign;
}
static const TypeInfo virtio_pci_bus_info = {
--
2.6.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH RFC 5/6] virtio-mmio: convert to ioeventfd callbacks
2016-03-17 10:01 [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers Cornelia Huck
` (3 preceding siblings ...)
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 4/6] virtio-pci: " Cornelia Huck
@ 2016-03-17 10:01 ` Cornelia Huck
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 6/6] virtio-bus: remove old set_host_notifier callback Cornelia Huck
` (2 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Cornelia Huck @ 2016-03-17 10:01 UTC (permalink / raw)
To: qemu-devel; +Cc: famz, mst, borntraeger, stefanha, Cornelia Huck, pbonzini
Convert to the new interface.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
hw/virtio/virtio-mmio.c | 128 ++++++++++++++++--------------------------------
1 file changed, 41 insertions(+), 87 deletions(-)
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index d4cd91f..d2accbc 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -93,90 +93,59 @@ typedef struct {
bool ioeventfd_started;
} VirtIOMMIOProxy;
-static int virtio_mmio_set_host_notifier_internal(VirtIOMMIOProxy *proxy,
- int n, bool assign,
- bool set_handler)
+static bool virtio_mmio_ioeventfd_started(DeviceState *d)
{
- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
- VirtQueue *vq = virtio_get_queue(vdev, n);
- EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
- int r = 0;
+ VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
- if (assign) {
- r = event_notifier_init(notifier, 1);
- if (r < 0) {
- error_report("%s: unable to init event notifier: %d",
- __func__, r);
- return r;
- }
- virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
- memory_region_add_eventfd(&proxy->iomem, VIRTIO_MMIO_QUEUENOTIFY, 4,
- true, n, notifier);
- } else {
- memory_region_del_eventfd(&proxy->iomem, VIRTIO_MMIO_QUEUENOTIFY, 4,
- true, n, notifier);
- virtio_queue_set_host_notifier_fd_handler(vq, false, false);
- event_notifier_cleanup(notifier);
- }
- return r;
+ return proxy->ioeventfd_started;
}
-static void virtio_mmio_start_ioeventfd(VirtIOMMIOProxy *proxy)
+static void virtio_mmio_ioeventfd_set_started(DeviceState *d, bool started,
+ bool err)
{
- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
- int n, r;
+ VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
- if (!kvm_eventfds_enabled() ||
- proxy->ioeventfd_disabled ||
- proxy->ioeventfd_started) {
- return;
- }
+ proxy->ioeventfd_started = started;
+}
- for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
+static bool virtio_mmio_ioeventfd_disabled(DeviceState *d)
+{
+ VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
- r = virtio_mmio_set_host_notifier_internal(proxy, n, true, true);
- if (r < 0) {
- goto assign_error;
- }
- }
- proxy->ioeventfd_started = true;
- return;
+ return !kvm_eventfds_enabled() || proxy->ioeventfd_disabled;
+}
-assign_error:
- while (--n >= 0) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
+static void virtio_mmio_ioeventfd_set_disabled(DeviceState *d, bool disabled)
+{
+ VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
- r = virtio_mmio_set_host_notifier_internal(proxy, n, false, false);
- assert(r >= 0);
- }
- proxy->ioeventfd_started = false;
- error_report("%s: failed. Fallback to a userspace (slower).", __func__);
+ proxy->ioeventfd_disabled = disabled;
}
-static void virtio_mmio_stop_ioeventfd(VirtIOMMIOProxy *proxy)
+static int virtio_mmio_ioeventfd_assign(DeviceState *d,
+ EventNotifier *notifier,
+ int n, bool assign)
{
- int r;
- int n;
- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
- if (!proxy->ioeventfd_started) {
- return;
+ if (assign) {
+ memory_region_add_eventfd(&proxy->iomem, VIRTIO_MMIO_QUEUENOTIFY, 4,
+ true, n, notifier);
+ } else {
+ memory_region_del_eventfd(&proxy->iomem, VIRTIO_MMIO_QUEUENOTIFY, 4,
+ true, n, notifier);
}
+ return 0;
+}
- for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
+static void virtio_mmio_start_ioeventfd(VirtIOMMIOProxy *proxy)
+{
+ virtio_bus_start_ioeventfd(&proxy->bus);
+}
- r = virtio_mmio_set_host_notifier_internal(proxy, n, false, false);
- assert(r >= 0);
- }
- proxy->ioeventfd_started = false;
+static void virtio_mmio_stop_ioeventfd(VirtIOMMIOProxy *proxy)
+{
+ virtio_bus_stop_ioeventfd(&proxy->bus, false);
}
static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
@@ -498,25 +467,6 @@ assign_error:
return r;
}
-static int virtio_mmio_set_host_notifier(DeviceState *opaque, int n,
- bool assign)
-{
- VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
-
- /* Stop using ioeventfd for virtqueue kick if the device starts using host
- * notifiers. This makes it easy to avoid stepping on each others' toes.
- */
- proxy->ioeventfd_disabled = assign;
- if (assign) {
- virtio_mmio_stop_ioeventfd(proxy);
- }
- /* We don't need to start here: it's not needed because backend
- * currently only stops on status change away from ok,
- * reset, vmstop and such. If we do add code to start here,
- * need to check vmstate, device state etc. */
- return virtio_mmio_set_host_notifier_internal(proxy, n, assign, false);
-}
-
/* virtio-mmio device */
static void virtio_mmio_realizefn(DeviceState *d, Error **errp)
@@ -558,8 +508,12 @@ static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data)
k->notify = virtio_mmio_update_irq;
k->save_config = virtio_mmio_save_config;
k->load_config = virtio_mmio_load_config;
- k->set_host_notifier = virtio_mmio_set_host_notifier;
k->set_guest_notifiers = virtio_mmio_set_guest_notifiers;
+ k->ioeventfd_started = virtio_mmio_ioeventfd_started;
+ k->ioeventfd_set_started = virtio_mmio_ioeventfd_set_started;
+ k->ioeventfd_disabled = virtio_mmio_ioeventfd_disabled;
+ k->ioeventfd_set_disabled = virtio_mmio_ioeventfd_set_disabled;
+ k->ioeventfd_assign = virtio_mmio_ioeventfd_assign;
k->has_variable_vring_alignment = true;
bus_class->max_dev = 1;
}
--
2.6.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH RFC 6/6] virtio-bus: remove old set_host_notifier callback
2016-03-17 10:01 [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers Cornelia Huck
` (4 preceding siblings ...)
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 5/6] virtio-mmio: " Cornelia Huck
@ 2016-03-17 10:01 ` Cornelia Huck
2016-03-21 15:02 ` [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers Stefan Hajnoczi
2016-03-23 9:34 ` Fam Zheng
7 siblings, 0 replies; 13+ messages in thread
From: Cornelia Huck @ 2016-03-17 10:01 UTC (permalink / raw)
To: qemu-devel; +Cc: famz, mst, borntraeger, stefanha, Cornelia Huck, pbonzini
All users have been converted to the new ioevent callbacks.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
hw/block/dataplane/virtio-blk.c | 12 ++----------
hw/scsi/virtio-scsi-dataplane.c | 19 ++++---------------
hw/virtio/vhost.c | 13 +------------
include/hw/virtio/virtio-bus.h | 1 -
4 files changed, 7 insertions(+), 38 deletions(-)
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index 9ca41d7..1b2d5fa 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -132,8 +132,7 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
}
/* Don't try if transport does not support notifiers. */
- if (!k->set_guest_notifiers ||
- (!k->set_host_notifier && !k->ioeventfd_started)) {
+ if (!k->set_guest_notifiers || !k->ioeventfd_started) {
error_setg(errp,
"device is incompatible with dataplane "
"(transport does not support notifiers)");
@@ -211,9 +210,6 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
/* Set up virtqueue notify */
r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), 0, true);
- if (r == -ENOSYS) {
- r = k->set_host_notifier(qbus->parent, 0, true);
- }
if (r != 0) {
fprintf(stderr, "virtio-blk failed to set host notifier (%d)\n", r);
goto fail_host_notifier;
@@ -248,7 +244,6 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
- int r;
if (!vblk->dataplane_started || s->stopping) {
return;
@@ -273,10 +268,7 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
aio_context_release(s->ctx);
- r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), 0, false);
- if (r == -ENOSYS) {
- k->set_host_notifier(qbus->parent, 0, false);
- }
+ virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), 0, false);
/* Clean up guest notifier (irq) */
k->set_guest_notifiers(qbus->parent, 1, false);
diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
index 88c3abd..88773d2 100644
--- a/hw/scsi/virtio-scsi-dataplane.c
+++ b/hw/scsi/virtio-scsi-dataplane.c
@@ -32,8 +32,7 @@ void virtio_scsi_set_iothread(VirtIOSCSI *s, IOThread *iothread)
s->ctx = iothread_get_aio_context(vs->conf.iothread);
/* Don't try if transport does not support notifiers. */
- if (!k->set_guest_notifiers ||
- (!k->set_host_notifier && !k->ioeventfd_started)) {
+ if (!k->set_guest_notifiers || !k->ioeventfd_started) {
fprintf(stderr, "virtio-scsi: Failed to set iothread "
"(transport does not support notifiers)");
exit(1);
@@ -43,14 +42,10 @@ void virtio_scsi_set_iothread(VirtIOSCSI *s, IOThread *iothread)
static int virtio_scsi_vring_init(VirtIOSCSI *s, VirtQueue *vq, int n)
{
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
- VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
int rc;
/* Set up virtqueue notify */
rc = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), n, true);
- if (rc == -ENOSYS) {
- rc = k->set_host_notifier(qbus->parent, n, true);
- }
if (rc != 0) {
fprintf(stderr, "virtio-scsi: Failed to set host notifier (%d)\n",
rc);
@@ -133,10 +128,7 @@ fail_vrings:
virtio_scsi_clear_aio(s);
aio_context_release(s->ctx);
for (i = 0; i < vs->conf.num_queues + 2; i++) {
- rc = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
- if (rc == -ENOSYS) {
- k->set_host_notifier(qbus->parent, i, false);
- }
+ virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
}
k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, false);
fail_guest_notifiers:
@@ -151,7 +143,7 @@ void virtio_scsi_dataplane_stop(VirtIOSCSI *s)
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
- int i, rc;
+ int i;
if (!s->dataplane_started || s->dataplane_stopping) {
return;
@@ -175,10 +167,7 @@ void virtio_scsi_dataplane_stop(VirtIOSCSI *s)
aio_context_release(s->ctx);
for (i = 0; i < vs->conf.num_queues + 2; i++) {
- rc = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
- if (rc == -ENOSYS) {
- k->set_host_notifier(qbus->parent, i, false);
- }
+ virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
}
/* Clean up guest notifier (irq) */
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 38f54a2..90febf2 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1113,7 +1113,7 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
VirtioBusState *vbus = VIRTIO_BUS(qbus);
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
int i, r, e;
- if (!k->set_host_notifier || !k->ioeventfd_started) {
+ if (!k->ioeventfd_started) {
fprintf(stderr, "binding does not support host notifiers\n");
r = -ENOSYS;
goto fail;
@@ -1122,9 +1122,6 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
for (i = 0; i < hdev->nvqs; ++i) {
r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), hdev->vq_index +i,
true);
- if (r == -ENOSYS) {
- r = k->set_host_notifier(qbus->parent, hdev->vq_index + i, true);
- }
if (r < 0) {
fprintf(stderr, "vhost VQ %d notifier binding failed: %d\n", i, -r);
goto fail_vq;
@@ -1136,9 +1133,6 @@ fail_vq:
while (--i >= 0) {
e = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), hdev->vq_index +i,
false);
- if (e == -ENOSYS) {
- e = k->set_host_notifier(qbus->parent, hdev->vq_index + i, false);
- }
if (e < 0) {
fprintf(stderr, "vhost VQ %d notifier cleanup error: %d\n", i, -r);
fflush(stderr);
@@ -1157,16 +1151,11 @@ fail:
void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
{
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
- VirtioBusState *vbus = VIRTIO_BUS(qbus);
- VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
int i, r;
for (i = 0; i < hdev->nvqs; ++i) {
r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), hdev->vq_index +i,
false);
- if (r == -ENOSYS) {
- r = k->set_host_notifier(qbus->parent, hdev->vq_index + i, false);
- }
if (r < 0) {
fprintf(stderr, "vhost VQ %d notifier cleanup failed: %d\n", i, -r);
fflush(stderr);
diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
index 0281cbf..cbe279f 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -52,7 +52,6 @@ typedef struct VirtioBusClass {
bool (*has_extra_state)(DeviceState *d);
bool (*query_guest_notifiers)(DeviceState *d);
int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assign);
- int (*set_host_notifier)(DeviceState *d, int n, bool assigned);
void (*vmstate_change)(DeviceState *d, bool running);
/*
* transport independent init function.
--
2.6.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers
2016-03-17 10:01 [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers Cornelia Huck
` (5 preceding siblings ...)
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 6/6] virtio-bus: remove old set_host_notifier callback Cornelia Huck
@ 2016-03-21 15:02 ` Stefan Hajnoczi
2016-03-23 9:34 ` Fam Zheng
7 siblings, 0 replies; 13+ messages in thread
From: Stefan Hajnoczi @ 2016-03-21 15:02 UTC (permalink / raw)
To: Cornelia Huck; +Cc: pbonzini, famz, qemu-devel, borntraeger, mst
[-- Attachment #1: Type: text/plain, Size: 1654 bytes --]
On Thu, Mar 17, 2016 at 11:01:27AM +0100, Cornelia Huck wrote:
> As discussed in the virtio-blk dataplane start/stop thread, the
> various transports contain a lot of similar/identical boilerplate
> code for setting up ioeventfds. This makes the code hard to follow.
>
> Let's drag all of the common handling into the virtio-bus layer,
> hopefully reducing both the boilerplate code and the number of
> indirections.
>
> This RFC patchset is the result of hacking this up quickly, and I
> was rather surprised that it did not die immediately on my s390
> system (which is all I 'tested'). So be warned :)
>
> Feedback about the approach and the interface would be good.
>
> Cornelia Huck (6):
> virtio-bus: common ioeventfd infrastructure
> virtio-bus: have callers tolerate new host notifier api
> virtio-ccw: convert to ioeventfd callbacks
> virtio-pci: convert to ioeventfd callbacks
> virtio-mmio: convert to ioeventfd callbacks
> virtio-bus: remove old set_host_notifier callback
>
> hw/block/dataplane/virtio-blk.c | 6 +-
> hw/s390x/virtio-ccw.c | 133 ++++++++++++++--------------------------
> hw/scsi/virtio-scsi-dataplane.c | 9 ++-
> hw/virtio/vhost.c | 13 ++--
> hw/virtio/virtio-bus.c | 108 ++++++++++++++++++++++++++++++++
> hw/virtio/virtio-mmio.c | 128 +++++++++++++-------------------------
> hw/virtio/virtio-pci.c | 124 +++++++++++++------------------------
> include/hw/virtio/virtio-bus.h | 15 ++++-
> 8 files changed, 263 insertions(+), 273 deletions(-)
I haven't reviewed it line-by-line but overall it looks good.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH RFC 1/6] virtio-bus: common ioeventfd infrastructure
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 1/6] virtio-bus: common ioeventfd infrastructure Cornelia Huck
@ 2016-03-22 0:24 ` Fam Zheng
2016-03-22 8:08 ` Cornelia Huck
2016-03-24 11:20 ` Michael S. Tsirkin
1 sibling, 1 reply; 13+ messages in thread
From: Fam Zheng @ 2016-03-22 0:24 UTC (permalink / raw)
To: Cornelia Huck; +Cc: pbonzini, borntraeger, qemu-devel, stefanha, mst
On Thu, 03/17 11:01, Cornelia Huck wrote:
> Introduce a set of ioeventfd callbacks on the virtio-bus level
> that can be implemented by the individual transports. At the
> virtio-bus level, do common handling for host notifiers (which
> is actually most of it).
>
> Two things of note:
> - We always iterate over all possible virtio queues, even though
> ccw (currently) has a lower limit. It does not really matter in
> this place.
> - We allow for the virtio-bus caller to pass an "assign" argument
> down when stopping ioeventfd, which the old interface did not allow.
>
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> ---
> hw/virtio/virtio-bus.c | 108 +++++++++++++++++++++++++++++++++++++++++
> include/hw/virtio/virtio-bus.h | 14 ++++++
> 2 files changed, 122 insertions(+)
>
> diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
> index 574f0e2..501300f 100644
> --- a/hw/virtio/virtio-bus.c
> +++ b/hw/virtio/virtio-bus.c
> @@ -146,6 +146,114 @@ void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config)
> }
> }
>
> +static int set_host_notifier_internal(DeviceState *proxy, VirtioBusState *bus,
> + int n, bool assign, bool set_handler)
> +{
> + VirtIODevice *vdev = virtio_bus_get_device(bus);
> + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
> + VirtQueue *vq = virtio_get_queue(vdev, n);
> + EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
> + int r = 0;
> +
> + if (assign) {
> + r = event_notifier_init(notifier, 1);
> + if (r < 0) {
> + error_report("%s: unable to init event notifier: %d", __func__, r);
> + return r;
> + }
> + virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
> + r = k->ioeventfd_assign(proxy, notifier, n, assign);
> + if (r < 0) {
> + error_report("%s: unable to assign ioeventfd: %d", __func__, r);
> + virtio_queue_set_host_notifier_fd_handler(vq, false, false);
> + event_notifier_cleanup(notifier);
> + return r;
> + }
> + } else {
> + virtio_queue_set_host_notifier_fd_handler(vq, false, false);
> + k->ioeventfd_assign(proxy, notifier, n, assign);
> + event_notifier_cleanup(notifier);
> + }
> + return r;
> +}
> +
> +void virtio_bus_start_ioeventfd(VirtioBusState *bus)
> +{
> + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
> + DeviceState *proxy = DEVICE(BUS(bus)->parent);
> + VirtIODevice *vdev;
> + int n, r;
> +
> + if (!k->ioeventfd_started || k->ioeventfd_started(proxy)) {
> + return;
> + }
> + if (!k->ioeventfd_disabled(proxy)) {
> + return;
> + }
> + vdev = virtio_bus_get_device(bus);
> + for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
> + if (!virtio_queue_get_num(vdev, n)) {
> + continue;
> + }
> + r = set_host_notifier_internal(proxy, bus, n, true, true);
> + if (r < 0) {
> + goto assign_error;
> + }
> + }
> + k->ioeventfd_set_started(proxy, true, false);
> + return;
> +
> +assign_error:
> + while (--n >= 0) {
> + if (!virtio_queue_get_num(vdev, n)) {
> + continue;
> + }
> +
> + r = set_host_notifier_internal(proxy, bus, n, false, false);
> + assert(r >= 0);
> + }
> + k->ioeventfd_set_started(proxy, false, true);
> + error_report("%s: failed. Fallback to userspace (slower).", __func__);
> +}
> +
> +void virtio_bus_stop_ioeventfd(VirtioBusState *bus, bool assign)
> +{
> + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
> + DeviceState *proxy = DEVICE(BUS(bus)->parent);
> + VirtIODevice *vdev;
> + int n, r;
> +
> + if (!k->ioeventfd_started || !k->ioeventfd_started(proxy)) {
> + return;
> + }
> + vdev = virtio_bus_get_device(bus);
> + for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
> + if (!virtio_queue_get_num(vdev, n)) {
> + continue;
> + }
> + r = set_host_notifier_internal(proxy, bus, n, assign, false);
> + assert(r >= 0);
> + }
> + k->ioeventfd_set_started(proxy, false, false);
> +}
> +
> +int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign)
> +{
> + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
> + DeviceState *proxy = DEVICE(BUS(bus)->parent);
> +
> + if (!k->ioeventfd_started) {
> + return -ENOSYS;
> + }
> + /* Stop using the generic ioeventfd, we are doing eventfd handling
> + * ourselves below */
> + k->ioeventfd_set_disabled(proxy, assign);
> + if (assign) {
> + virtio_bus_stop_ioeventfd(bus, assign);
> + }
> + return set_host_notifier_internal(proxy, bus, n, assign, false);
> +}
> +
> static char *virtio_bus_get_dev_path(DeviceState *dev)
> {
> BusState *bus = qdev_get_parent_bus(dev);
> diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
> index 3f2c136..0281cbf 100644
> --- a/include/hw/virtio/virtio-bus.h
> +++ b/include/hw/virtio/virtio-bus.h
> @@ -71,6 +71,16 @@ typedef struct VirtioBusClass {
> void (*device_unplugged)(DeviceState *d);
> int (*query_nvectors)(DeviceState *d);
> /*
> + * ioeventfd handling: if the transport implements ioeventfd_started,
> + * it must implement the other ioeventfd callbacks as well
> + */
> + bool (*ioeventfd_started)(DeviceState *d);
> + void (*ioeventfd_set_started)(DeviceState *d, bool started, bool err);
> + bool (*ioeventfd_disabled)(DeviceState *d);
> + void (*ioeventfd_set_disabled)(DeviceState *d, bool disabled);
> + int (*ioeventfd_assign)(DeviceState *d, EventNotifier *notifier,
> + int n, bool assign);
Maybe we should consider documenting these operations and parameters?
> + /*
> * Does the transport have variable vring alignment?
> * (ie can it ever call virtio_queue_set_align()?)
> * Note that changing this will break migration for this transport.
> @@ -111,4 +121,8 @@ static inline VirtIODevice *virtio_bus_get_device(VirtioBusState *bus)
> return (VirtIODevice *)qdev;
> }
>
> +void virtio_bus_start_ioeventfd(VirtioBusState *bus);
> +void virtio_bus_stop_ioeventfd(VirtioBusState *bus, bool assign);
> +int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign);
> +
> #endif /* VIRTIO_BUS_H */
> --
> 2.6.5
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH RFC 1/6] virtio-bus: common ioeventfd infrastructure
2016-03-22 0:24 ` Fam Zheng
@ 2016-03-22 8:08 ` Cornelia Huck
0 siblings, 0 replies; 13+ messages in thread
From: Cornelia Huck @ 2016-03-22 8:08 UTC (permalink / raw)
To: Fam Zheng; +Cc: pbonzini, borntraeger, qemu-devel, stefanha, mst
On Tue, 22 Mar 2016 08:24:33 +0800
Fam Zheng <famz@redhat.com> wrote:
> On Thu, 03/17 11:01, Cornelia Huck wrote:
> > diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
> > index 3f2c136..0281cbf 100644
> > --- a/include/hw/virtio/virtio-bus.h
> > +++ b/include/hw/virtio/virtio-bus.h
> > @@ -71,6 +71,16 @@ typedef struct VirtioBusClass {
> > void (*device_unplugged)(DeviceState *d);
> > int (*query_nvectors)(DeviceState *d);
> > /*
> > + * ioeventfd handling: if the transport implements ioeventfd_started,
> > + * it must implement the other ioeventfd callbacks as well
> > + */
> > + bool (*ioeventfd_started)(DeviceState *d);
> > + void (*ioeventfd_set_started)(DeviceState *d, bool started, bool err);
> > + bool (*ioeventfd_disabled)(DeviceState *d);
> > + void (*ioeventfd_set_disabled)(DeviceState *d, bool disabled);
> > + int (*ioeventfd_assign)(DeviceState *d, EventNotifier *notifier,
> > + int n, bool assign);
>
> Maybe we should consider documenting these operations and parameters?
Yes, we should :) I just wanted to make sure first that this is the way
to go.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers
2016-03-17 10:01 [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers Cornelia Huck
` (6 preceding siblings ...)
2016-03-21 15:02 ` [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers Stefan Hajnoczi
@ 2016-03-23 9:34 ` Fam Zheng
7 siblings, 0 replies; 13+ messages in thread
From: Fam Zheng @ 2016-03-23 9:34 UTC (permalink / raw)
To: Cornelia Huck, borntraeger; +Cc: pbonzini, qemu-devel, stefanha, mst
On Thu, 03/17 11:01, Cornelia Huck wrote:
> As discussed in the virtio-blk dataplane start/stop thread, the
> various transports contain a lot of similar/identical boilerplate
> code for setting up ioeventfds. This makes the code hard to follow.
>
> Let's drag all of the common handling into the virtio-bus layer,
> hopefully reducing both the boilerplate code and the number of
> indirections.
>
> This RFC patchset is the result of hacking this up quickly, and I
> was rather surprised that it did not die immediately on my s390
> system (which is all I 'tested'). So be warned :)
>
> Feedback about the approach and the interface would be good.
I tested this series with the two assertions (Paolo's "test" reentrancy
detection and my "assert(is_in_iothread())", in virtio-blk request handler),
and it seems to fix the crash . (A few seconds to crash on master vs. several
hours survival).
Fam
>
> Cornelia Huck (6):
> virtio-bus: common ioeventfd infrastructure
> virtio-bus: have callers tolerate new host notifier api
> virtio-ccw: convert to ioeventfd callbacks
> virtio-pci: convert to ioeventfd callbacks
> virtio-mmio: convert to ioeventfd callbacks
> virtio-bus: remove old set_host_notifier callback
>
> hw/block/dataplane/virtio-blk.c | 6 +-
> hw/s390x/virtio-ccw.c | 133 ++++++++++++++--------------------------
> hw/scsi/virtio-scsi-dataplane.c | 9 ++-
> hw/virtio/vhost.c | 13 ++--
> hw/virtio/virtio-bus.c | 108 ++++++++++++++++++++++++++++++++
> hw/virtio/virtio-mmio.c | 128 +++++++++++++-------------------------
> hw/virtio/virtio-pci.c | 124 +++++++++++++------------------------
> include/hw/virtio/virtio-bus.h | 15 ++++-
> 8 files changed, 263 insertions(+), 273 deletions(-)
>
> --
> 2.6.5
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH RFC 1/6] virtio-bus: common ioeventfd infrastructure
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 1/6] virtio-bus: common ioeventfd infrastructure Cornelia Huck
2016-03-22 0:24 ` Fam Zheng
@ 2016-03-24 11:20 ` Michael S. Tsirkin
2016-03-24 11:30 ` Cornelia Huck
1 sibling, 1 reply; 13+ messages in thread
From: Michael S. Tsirkin @ 2016-03-24 11:20 UTC (permalink / raw)
To: Cornelia Huck; +Cc: pbonzini, famz, qemu-devel, stefanha, borntraeger
On Thu, Mar 17, 2016 at 11:01:28AM +0100, Cornelia Huck wrote:
> Introduce a set of ioeventfd callbacks on the virtio-bus level
> that can be implemented by the individual transports. At the
> virtio-bus level, do common handling for host notifiers (which
> is actually most of it).
>
> Two things of note:
> - We always iterate over all possible virtio queues, even though
> ccw (currently) has a lower limit. It does not really matter in
> this place.
> - We allow for the virtio-bus caller to pass an "assign" argument
> down when stopping ioeventfd, which the old interface did not allow.
>
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
So it sounds like this is supposed to fix races
in current code, pls document how.
> ---
> hw/virtio/virtio-bus.c | 108 +++++++++++++++++++++++++++++++++++++++++
> include/hw/virtio/virtio-bus.h | 14 ++++++
> 2 files changed, 122 insertions(+)
>
> diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
> index 574f0e2..501300f 100644
> --- a/hw/virtio/virtio-bus.c
> +++ b/hw/virtio/virtio-bus.c
> @@ -146,6 +146,114 @@ void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config)
> }
> }
>
> +static int set_host_notifier_internal(DeviceState *proxy, VirtioBusState *bus,
> + int n, bool assign, bool set_handler)
> +{
> + VirtIODevice *vdev = virtio_bus_get_device(bus);
> + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
> + VirtQueue *vq = virtio_get_queue(vdev, n);
> + EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
> + int r = 0;
> +
> + if (assign) {
> + r = event_notifier_init(notifier, 1);
> + if (r < 0) {
> + error_report("%s: unable to init event notifier: %d", __func__, r);
> + return r;
> + }
> + virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
> + r = k->ioeventfd_assign(proxy, notifier, n, assign);
> + if (r < 0) {
> + error_report("%s: unable to assign ioeventfd: %d", __func__, r);
> + virtio_queue_set_host_notifier_fd_handler(vq, false, false);
> + event_notifier_cleanup(notifier);
> + return r;
> + }
> + } else {
> + virtio_queue_set_host_notifier_fd_handler(vq, false, false);
> + k->ioeventfd_assign(proxy, notifier, n, assign);
> + event_notifier_cleanup(notifier);
> + }
> + return r;
> +}
> +
> +void virtio_bus_start_ioeventfd(VirtioBusState *bus)
> +{
> + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
> + DeviceState *proxy = DEVICE(BUS(bus)->parent);
> + VirtIODevice *vdev;
> + int n, r;
> +
> + if (!k->ioeventfd_started || k->ioeventfd_started(proxy)) {
> + return;
> + }
> + if (!k->ioeventfd_disabled(proxy)) {
> + return;
> + }
> + vdev = virtio_bus_get_device(bus);
> + for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
> + if (!virtio_queue_get_num(vdev, n)) {
> + continue;
> + }
> + r = set_host_notifier_internal(proxy, bus, n, true, true);
> + if (r < 0) {
> + goto assign_error;
> + }
> + }
> + k->ioeventfd_set_started(proxy, true, false);
> + return;
> +
> +assign_error:
> + while (--n >= 0) {
> + if (!virtio_queue_get_num(vdev, n)) {
> + continue;
> + }
> +
> + r = set_host_notifier_internal(proxy, bus, n, false, false);
> + assert(r >= 0);
> + }
> + k->ioeventfd_set_started(proxy, false, true);
> + error_report("%s: failed. Fallback to userspace (slower).", __func__);
> +}
> +
> +void virtio_bus_stop_ioeventfd(VirtioBusState *bus, bool assign)
> +{
> + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
> + DeviceState *proxy = DEVICE(BUS(bus)->parent);
> + VirtIODevice *vdev;
> + int n, r;
> +
> + if (!k->ioeventfd_started || !k->ioeventfd_started(proxy)) {
> + return;
> + }
> + vdev = virtio_bus_get_device(bus);
> + for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
> + if (!virtio_queue_get_num(vdev, n)) {
> + continue;
> + }
> + r = set_host_notifier_internal(proxy, bus, n, assign, false);
> + assert(r >= 0);
> + }
> + k->ioeventfd_set_started(proxy, false, false);
> +}
> +
> +int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign)
Could you add documentation for what does "assign" mean here?
It was there as an internal API, but now it's external
so needs better docs.
> +{
> + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
> + DeviceState *proxy = DEVICE(BUS(bus)->parent);
> +
> + if (!k->ioeventfd_started) {
> + return -ENOSYS;
> + }
> + /* Stop using the generic ioeventfd, we are doing eventfd handling
> + * ourselves below */
> + k->ioeventfd_set_disabled(proxy, assign);
> + if (assign) {
> + virtio_bus_stop_ioeventfd(bus, assign);
> + }
Need comment to explain why don't we start on !assign.
> + return set_host_notifier_internal(proxy, bus, n, assign, false);
> +}
> +
> static char *virtio_bus_get_dev_path(DeviceState *dev)
> {
> BusState *bus = qdev_get_parent_bus(dev);
> diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
> index 3f2c136..0281cbf 100644
> --- a/include/hw/virtio/virtio-bus.h
> +++ b/include/hw/virtio/virtio-bus.h
> @@ -71,6 +71,16 @@ typedef struct VirtioBusClass {
> void (*device_unplugged)(DeviceState *d);
> int (*query_nvectors)(DeviceState *d);
> /*
> + * ioeventfd handling: if the transport implements ioeventfd_started,
> + * it must implement the other ioeventfd callbacks as well
> + */
> + bool (*ioeventfd_started)(DeviceState *d);
> + void (*ioeventfd_set_started)(DeviceState *d, bool started, bool err);
> + bool (*ioeventfd_disabled)(DeviceState *d);
> + void (*ioeventfd_set_disabled)(DeviceState *d, bool disabled);
> + int (*ioeventfd_assign)(DeviceState *d, EventNotifier *notifier,
> + int n, bool assign);
> + /*
> * Does the transport have variable vring alignment?
> * (ie can it ever call virtio_queue_set_align()?)
> * Note that changing this will break migration for this transport.
> @@ -111,4 +121,8 @@ static inline VirtIODevice *virtio_bus_get_device(VirtioBusState *bus)
> return (VirtIODevice *)qdev;
> }
>
> +void virtio_bus_start_ioeventfd(VirtioBusState *bus);
> +void virtio_bus_stop_ioeventfd(VirtioBusState *bus, bool assign);
> +int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign);
> +
> #endif /* VIRTIO_BUS_H */
> --
> 2.6.5
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH RFC 1/6] virtio-bus: common ioeventfd infrastructure
2016-03-24 11:20 ` Michael S. Tsirkin
@ 2016-03-24 11:30 ` Cornelia Huck
0 siblings, 0 replies; 13+ messages in thread
From: Cornelia Huck @ 2016-03-24 11:30 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: pbonzini, famz, qemu-devel, stefanha, borntraeger
On Thu, 24 Mar 2016 13:20:34 +0200
"Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Thu, Mar 17, 2016 at 11:01:28AM +0100, Cornelia Huck wrote:
> > Introduce a set of ioeventfd callbacks on the virtio-bus level
> > that can be implemented by the individual transports. At the
> > virtio-bus level, do common handling for host notifiers (which
> > is actually most of it).
> >
> > Two things of note:
> > - We always iterate over all possible virtio queues, even though
> > ccw (currently) has a lower limit. It does not really matter in
> > this place.
> > - We allow for the virtio-bus caller to pass an "assign" argument
> > down when stopping ioeventfd, which the old interface did not allow.
> >
> > Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
>
> So it sounds like this is supposed to fix races
> in current code, pls document how.
Yes, final version will have more description + comments.
>
>
> > ---
> > hw/virtio/virtio-bus.c | 108 +++++++++++++++++++++++++++++++++++++++++
> > include/hw/virtio/virtio-bus.h | 14 ++++++
> > 2 files changed, 122 insertions(+)
> >
> > diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
> > index 574f0e2..501300f 100644
> > --- a/hw/virtio/virtio-bus.c
> > +++ b/hw/virtio/virtio-bus.c
> > @@ -146,6 +146,114 @@ void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config)
> > }
> > }
> >
> > +static int set_host_notifier_internal(DeviceState *proxy, VirtioBusState *bus,
> > + int n, bool assign, bool set_handler)
> > +{
> > + VirtIODevice *vdev = virtio_bus_get_device(bus);
> > + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
> > + VirtQueue *vq = virtio_get_queue(vdev, n);
> > + EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
> > + int r = 0;
> > +
> > + if (assign) {
> > + r = event_notifier_init(notifier, 1);
> > + if (r < 0) {
> > + error_report("%s: unable to init event notifier: %d", __func__, r);
> > + return r;
> > + }
> > + virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
> > + r = k->ioeventfd_assign(proxy, notifier, n, assign);
> > + if (r < 0) {
> > + error_report("%s: unable to assign ioeventfd: %d", __func__, r);
> > + virtio_queue_set_host_notifier_fd_handler(vq, false, false);
> > + event_notifier_cleanup(notifier);
> > + return r;
> > + }
> > + } else {
> > + virtio_queue_set_host_notifier_fd_handler(vq, false, false);
> > + k->ioeventfd_assign(proxy, notifier, n, assign);
> > + event_notifier_cleanup(notifier);
> > + }
> > + return r;
> > +}
Note that I'm currently trying to disentangle ioeventfd registration
and handler assignment, so this will look a bit different in the final
patch.
> > +
> > +void virtio_bus_start_ioeventfd(VirtioBusState *bus)
> > +{
> > + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
> > + DeviceState *proxy = DEVICE(BUS(bus)->parent);
> > + VirtIODevice *vdev;
> > + int n, r;
> > +
> > + if (!k->ioeventfd_started || k->ioeventfd_started(proxy)) {
> > + return;
> > + }
> > + if (!k->ioeventfd_disabled(proxy)) {
And this one is actually the wrong way around, as mentioned in the
other thread. Will be fixed.
> > + return;
> > + }
> > + vdev = virtio_bus_get_device(bus);
> > + for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
> > + if (!virtio_queue_get_num(vdev, n)) {
> > + continue;
> > + }
> > + r = set_host_notifier_internal(proxy, bus, n, true, true);
> > + if (r < 0) {
> > + goto assign_error;
> > + }
> > + }
> > + k->ioeventfd_set_started(proxy, true, false);
> > + return;
> > +
> > +assign_error:
> > + while (--n >= 0) {
> > + if (!virtio_queue_get_num(vdev, n)) {
> > + continue;
> > + }
> > +
> > + r = set_host_notifier_internal(proxy, bus, n, false, false);
> > + assert(r >= 0);
> > + }
> > + k->ioeventfd_set_started(proxy, false, true);
> > + error_report("%s: failed. Fallback to userspace (slower).", __func__);
> > +}
> > +
> > +void virtio_bus_stop_ioeventfd(VirtioBusState *bus, bool assign)
> > +{
> > + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
> > + DeviceState *proxy = DEVICE(BUS(bus)->parent);
> > + VirtIODevice *vdev;
> > + int n, r;
> > +
> > + if (!k->ioeventfd_started || !k->ioeventfd_started(proxy)) {
> > + return;
> > + }
> > + vdev = virtio_bus_get_device(bus);
> > + for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
> > + if (!virtio_queue_get_num(vdev, n)) {
> > + continue;
> > + }
> > + r = set_host_notifier_internal(proxy, bus, n, assign, false);
> > + assert(r >= 0);
> > + }
> > + k->ioeventfd_set_started(proxy, false, false);
> > +}
> > +
> > +int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign)
>
>
> Could you add documentation for what does "assign" mean here?
> It was there as an internal API, but now it's external
> so needs better docs.
On my list.
>
> > +{
> > + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
> > + DeviceState *proxy = DEVICE(BUS(bus)->parent);
> > +
> > + if (!k->ioeventfd_started) {
> > + return -ENOSYS;
> > + }
> > + /* Stop using the generic ioeventfd, we are doing eventfd handling
> > + * ourselves below */
> > + k->ioeventfd_set_disabled(proxy, assign);
> > + if (assign) {
> > + virtio_bus_stop_ioeventfd(bus, assign);
> > + }
>
> Need comment to explain why don't we start on !assign.
That's a part I'm currently reworking anyway, as we don't want to try
to assign ioeventfds twice, but just keep them. It will be hopefully
clearer then.
>
> > + return set_host_notifier_internal(proxy, bus, n, assign, false);
> > +}
> > +
> > static char *virtio_bus_get_dev_path(DeviceState *dev)
> > {
> > BusState *bus = qdev_get_parent_bus(dev);
> > diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
> > index 3f2c136..0281cbf 100644
> > --- a/include/hw/virtio/virtio-bus.h
> > +++ b/include/hw/virtio/virtio-bus.h
> > @@ -71,6 +71,16 @@ typedef struct VirtioBusClass {
> > void (*device_unplugged)(DeviceState *d);
> > int (*query_nvectors)(DeviceState *d);
> > /*
> > + * ioeventfd handling: if the transport implements ioeventfd_started,
> > + * it must implement the other ioeventfd callbacks as well
> > + */
> > + bool (*ioeventfd_started)(DeviceState *d);
> > + void (*ioeventfd_set_started)(DeviceState *d, bool started, bool err);
> > + bool (*ioeventfd_disabled)(DeviceState *d);
> > + void (*ioeventfd_set_disabled)(DeviceState *d, bool disabled);
> > + int (*ioeventfd_assign)(DeviceState *d, EventNotifier *notifier,
> > + int n, bool assign);
I've also added a short description for the callbacks in the meantime.
> > + /*
> > * Does the transport have variable vring alignment?
> > * (ie can it ever call virtio_queue_set_align()?)
> > * Note that changing this will break migration for this transport.
> > @@ -111,4 +121,8 @@ static inline VirtIODevice *virtio_bus_get_device(VirtioBusState *bus)
> > return (VirtIODevice *)qdev;
> > }
> >
> > +void virtio_bus_start_ioeventfd(VirtioBusState *bus);
> > +void virtio_bus_stop_ioeventfd(VirtioBusState *bus, bool assign);
> > +int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign);
> > +
> > #endif /* VIRTIO_BUS_H */
> > --
> > 2.6.5
>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2016-03-24 11:30 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-17 10:01 [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers Cornelia Huck
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 1/6] virtio-bus: common ioeventfd infrastructure Cornelia Huck
2016-03-22 0:24 ` Fam Zheng
2016-03-22 8:08 ` Cornelia Huck
2016-03-24 11:20 ` Michael S. Tsirkin
2016-03-24 11:30 ` Cornelia Huck
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 2/6] virtio-bus: have callers tolerate new host notifier api Cornelia Huck
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 3/6] virtio-ccw: convert to ioeventfd callbacks Cornelia Huck
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 4/6] virtio-pci: " Cornelia Huck
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 5/6] virtio-mmio: " Cornelia Huck
2016-03-17 10:01 ` [Qemu-devel] [PATCH RFC 6/6] virtio-bus: remove old set_host_notifier callback Cornelia Huck
2016-03-21 15:02 ` [Qemu-devel] [PATCH RFC 0/6] virtio: refactor host notifiers Stefan Hajnoczi
2016-03-23 9:34 ` Fam Zheng
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.