Host notifiers are guaranteed to be idle until the callbacks are hooked up with virtio_queue_aio_set_host_notifier_handler(). They thus don't need to be set or unset with the AioContext lock held.
Do this outside the critical section, like virtio-blk already does : basically splitting virtio_scsi_vring_init() in two functions, one to set/unset the host notifier and one for the aio handler. Further improvement is to convert virtio-scsi-pci to use the virtio_bus_set_host_notifiers() API in order to batch setup and tear down of ioeventfds. This is expected to significantly reduce boot time of VMs with high number of vCPUs. Signed-off-by: Greg Kurz <gr...@kaod.org> --- hw/scsi/virtio-scsi-dataplane.c | 46 ++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index 4ad879340645..11b53ab767be 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -94,8 +94,7 @@ static bool virtio_scsi_data_plane_handle_event(VirtIODevice *vdev, return progress; } -static int virtio_scsi_vring_init(VirtIOSCSI *s, VirtQueue *vq, int n, - VirtIOHandleAIOOutput fn) +static int virtio_scsi_set_host_notifier(VirtIOSCSI *s, VirtQueue *vq, int n) { BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s))); int rc; @@ -109,10 +108,15 @@ static int virtio_scsi_vring_init(VirtIOSCSI *s, VirtQueue *vq, int n, return rc; } - virtio_queue_aio_set_host_notifier_handler(vq, s->ctx, fn); return 0; } +static void virtio_scsi_set_host_notifier_handler(VirtIOSCSI *s, VirtQueue *vq, + VirtIOHandleAIOOutput fn) +{ + virtio_queue_aio_set_host_notifier_handler(vq, s->ctx, fn); +} + /* Context: BH in IOThread */ static void virtio_scsi_dataplane_stop_bh(void *opaque) { @@ -154,38 +158,44 @@ int virtio_scsi_dataplane_start(VirtIODevice *vdev) goto fail_guest_notifiers; } - aio_context_acquire(s->ctx); - rc = virtio_scsi_vring_init(s, vs->ctrl_vq, 0, - virtio_scsi_data_plane_handle_ctrl); - if (rc) { - goto fail_vrings; + rc = virtio_scsi_set_host_notifier(s, vs->ctrl_vq, 0); + if (rc != 0) { + goto fail_host_notifiers; } vq_init_count++; - rc = virtio_scsi_vring_init(s, vs->event_vq, 1, - virtio_scsi_data_plane_handle_event); - if (rc) { - goto fail_vrings; + rc = virtio_scsi_set_host_notifier(s, vs->event_vq, 1); + if (rc != 0) { + goto fail_host_notifiers; } vq_init_count++; + for (i = 0; i < vs->conf.num_queues; i++) { - rc = virtio_scsi_vring_init(s, vs->cmd_vqs[i], i + 2, - virtio_scsi_data_plane_handle_cmd); + rc = virtio_scsi_set_host_notifier(s, vs->cmd_vqs[i], i + 2); if (rc) { - goto fail_vrings; + goto fail_host_notifiers; } vq_init_count++; } + aio_context_acquire(s->ctx); + virtio_scsi_set_host_notifier_handler(s, vs->ctrl_vq, + virtio_scsi_data_plane_handle_ctrl); + virtio_scsi_set_host_notifier_handler(s, vs->event_vq, + virtio_scsi_data_plane_handle_event); + + for (i = 0; i < vs->conf.num_queues; i++) { + virtio_scsi_set_host_notifier_handler(s, vs->cmd_vqs[i], + virtio_scsi_data_plane_handle_cmd); + } + s->dataplane_starting = false; s->dataplane_started = true; aio_context_release(s->ctx); return 0; -fail_vrings: - aio_wait_bh_oneshot(s->ctx, virtio_scsi_dataplane_stop_bh, s); - aio_context_release(s->ctx); +fail_host_notifiers: for (i = 0; i < vq_init_count; i++) { virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false); virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i); -- 2.26.3