mirror of https://github.com/proxmox/mirror_qemu
virtio: add aio handler
In addition to handling IO in vcpu thread and in io thread, blk dataplane introduces yet another mode: handling it by AioContext. Currently, this reuses the same handler as previous modes, which triggers races as these were not designed to be reentrant. Add instead a separate handler just for aio; this will make it possible to disable regular handlers when dataplane is active. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>master
parent
43c696a298
commit
344dc16fae
|
@ -96,6 +96,7 @@ struct VirtQueue
|
||||||
|
|
||||||
uint16_t vector;
|
uint16_t vector;
|
||||||
void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
|
void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
|
||||||
|
void (*handle_aio_output)(VirtIODevice *vdev, VirtQueue *vq);
|
||||||
VirtIODevice *vdev;
|
VirtIODevice *vdev;
|
||||||
EventNotifier guest_notifier;
|
EventNotifier guest_notifier;
|
||||||
EventNotifier host_notifier;
|
EventNotifier host_notifier;
|
||||||
|
@ -1088,6 +1089,16 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align)
|
||||||
virtio_queue_update_rings(vdev, n);
|
virtio_queue_update_rings(vdev, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void virtio_queue_notify_aio_vq(VirtQueue *vq)
|
||||||
|
{
|
||||||
|
if (vq->vring.desc && vq->handle_aio_output) {
|
||||||
|
VirtIODevice *vdev = vq->vdev;
|
||||||
|
|
||||||
|
trace_virtio_queue_notify(vdev, vq - vdev->vq, vq);
|
||||||
|
vq->handle_aio_output(vdev, vq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void virtio_queue_notify_vq(VirtQueue *vq)
|
static void virtio_queue_notify_vq(VirtQueue *vq)
|
||||||
{
|
{
|
||||||
if (vq->vring.desc && vq->handle_output) {
|
if (vq->vring.desc && vq->handle_output) {
|
||||||
|
@ -1143,10 +1154,19 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
|
||||||
vdev->vq[i].vring.num_default = queue_size;
|
vdev->vq[i].vring.num_default = queue_size;
|
||||||
vdev->vq[i].vring.align = VIRTIO_PCI_VRING_ALIGN;
|
vdev->vq[i].vring.align = VIRTIO_PCI_VRING_ALIGN;
|
||||||
vdev->vq[i].handle_output = handle_output;
|
vdev->vq[i].handle_output = handle_output;
|
||||||
|
vdev->vq[i].handle_aio_output = NULL;
|
||||||
|
|
||||||
return &vdev->vq[i];
|
return &vdev->vq[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void virtio_set_queue_aio(VirtQueue *vq,
|
||||||
|
void (*handle_output)(VirtIODevice *, VirtQueue *))
|
||||||
|
{
|
||||||
|
assert(vq->handle_output);
|
||||||
|
|
||||||
|
vq->handle_aio_output = handle_output;
|
||||||
|
}
|
||||||
|
|
||||||
void virtio_del_queue(VirtIODevice *vdev, int n)
|
void virtio_del_queue(VirtIODevice *vdev, int n)
|
||||||
{
|
{
|
||||||
if (n < 0 || n >= VIRTIO_QUEUE_MAX) {
|
if (n < 0 || n >= VIRTIO_QUEUE_MAX) {
|
||||||
|
@ -1780,11 +1800,11 @@ EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq)
|
||||||
return &vq->guest_notifier;
|
return &vq->guest_notifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_queue_host_notifier_read(EventNotifier *n)
|
static void virtio_queue_host_notifier_aio_read(EventNotifier *n)
|
||||||
{
|
{
|
||||||
VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
|
VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
|
||||||
if (event_notifier_test_and_clear(n)) {
|
if (event_notifier_test_and_clear(n)) {
|
||||||
virtio_queue_notify_vq(vq);
|
virtio_queue_notify_aio_vq(vq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1793,14 +1813,22 @@ void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx,
|
||||||
{
|
{
|
||||||
if (assign && set_handler) {
|
if (assign && set_handler) {
|
||||||
aio_set_event_notifier(ctx, &vq->host_notifier, true,
|
aio_set_event_notifier(ctx, &vq->host_notifier, true,
|
||||||
virtio_queue_host_notifier_read);
|
virtio_queue_host_notifier_aio_read);
|
||||||
} else {
|
} else {
|
||||||
aio_set_event_notifier(ctx, &vq->host_notifier, true, NULL);
|
aio_set_event_notifier(ctx, &vq->host_notifier, true, NULL);
|
||||||
}
|
}
|
||||||
if (!assign) {
|
if (!assign) {
|
||||||
/* Test and clear notifier before after disabling event,
|
/* Test and clear notifier before after disabling event,
|
||||||
* in case poll callback didn't have time to run. */
|
* in case poll callback didn't have time to run. */
|
||||||
virtio_queue_host_notifier_read(&vq->host_notifier);
|
virtio_queue_host_notifier_aio_read(&vq->host_notifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_queue_host_notifier_read(EventNotifier *n)
|
||||||
|
{
|
||||||
|
VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
|
||||||
|
if (event_notifier_test_and_clear(n)) {
|
||||||
|
virtio_queue_notify_vq(vq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,9 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
|
||||||
void (*handle_output)(VirtIODevice *,
|
void (*handle_output)(VirtIODevice *,
|
||||||
VirtQueue *));
|
VirtQueue *));
|
||||||
|
|
||||||
|
void virtio_set_queue_aio(VirtQueue *vq,
|
||||||
|
void (*handle_output)(VirtIODevice *, VirtQueue *));
|
||||||
|
|
||||||
void virtio_del_queue(VirtIODevice *vdev, int n);
|
void virtio_del_queue(VirtIODevice *vdev, int n);
|
||||||
|
|
||||||
void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_num);
|
void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_num);
|
||||||
|
|
Loading…
Reference in New Issue