diff --git a/aio-posix.c b/aio-posix.c index 7fd565fbdea768b4ade9a042b37707aa3a89eee5..6006122e0b9a3841d901cb856bc45529364e5995 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -282,10 +282,12 @@ bool aio_pending(AioContext *ctx) int revents; revents = node->pfd.revents & node->pfd.events; - if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) { + if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read && + aio_node_check(ctx, node->is_external)) { return true; } - if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) { + if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write && + aio_node_check(ctx, node->is_external)) { return true; } } @@ -323,6 +325,7 @@ bool aio_dispatch(AioContext *ctx) if (!node->deleted && (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) && + aio_node_check(ctx, node->is_external) && node->io_read) { node->io_read(node->opaque); @@ -333,6 +336,7 @@ bool aio_dispatch(AioContext *ctx) } if (!node->deleted && (revents & (G_IO_OUT | G_IO_ERR)) && + aio_node_check(ctx, node->is_external) && node->io_write) { node->io_write(node->opaque); progress = true; diff --git a/block/mirror.c b/block/mirror.c index d56e30e4724aaefd040ad468183f63e3e4eb14c2..039f48125ea42a87d30cbec6b18588b5e967bf02 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -495,6 +495,9 @@ out: block_job_completed(&s->common, data->ret); g_free(data); bdrv_drained_end(src); + if (qemu_get_aio_context() == bdrv_get_aio_context(src)) { + aio_enable_external(iohandler_get_aio_context()); + } bdrv_unref(src); } @@ -716,6 +719,12 @@ immediate_exit: /* Before we switch to target in mirror_exit, make sure data doesn't * change. */ bdrv_drained_begin(s->common.bs); + if (qemu_get_aio_context() == bdrv_get_aio_context(bs)) { + /* FIXME: virtio host notifiers run on iohandler_ctx, therefore the + * above bdrv_drained_end isn't enough to quiesce it. This is ugly, we + * need a block layer API change to achieve this. */ + aio_disable_external(iohandler_get_aio_context()); + } block_job_defer_to_main_loop(&s->common, mirror_exit, data); } diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c index 9ddd5ad75b0c5839e9722c302a613cb914c6a74b..3213f9f8afb9063e882117101233639a92f79b4c 100644 --- a/hw/usb/ccid-card-emulated.c +++ b/hw/usb/ccid-card-emulated.c @@ -407,7 +407,7 @@ static int init_event_notifier(EmulatedState *card) DPRINTF(card, 2, "event notifier creation failed\n"); return -1; } - event_notifier_set_handler(&card->notifier, card_event_handler); + event_notifier_set_handler(&card->notifier, false, card_event_handler); return 0; } diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index f745c4abd04bba22753d6dcc5cb5036660a5849b..30ede3d1cc7bebc8e9eeea006b2af9395498a425 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -1775,10 +1775,10 @@ void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, bool with_irqfd) { if (assign && !with_irqfd) { - event_notifier_set_handler(&vq->guest_notifier, + event_notifier_set_handler(&vq->guest_notifier, false, virtio_queue_guest_notifier_read); } else { - event_notifier_set_handler(&vq->guest_notifier, NULL); + event_notifier_set_handler(&vq->guest_notifier, false, NULL); } if (!assign) { /* Test and clear notifier before closing it, @@ -1829,10 +1829,10 @@ void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign, bool set_handler) { if (assign && set_handler) { - event_notifier_set_handler(&vq->host_notifier, + event_notifier_set_handler(&vq->host_notifier, true, virtio_queue_host_notifier_read); } else { - event_notifier_set_handler(&vq->host_notifier, NULL); + event_notifier_set_handler(&vq->host_notifier, true, NULL); } if (!assign) { /* Test and clear notifier before after disabling event, diff --git a/include/qemu/event_notifier.h b/include/qemu/event_notifier.h index a8f28540c9993e7a6d1046caefcd838976b419eb..e326990db405d752c68d77a5afd1bd65b544a2c7 100644 --- a/include/qemu/event_notifier.h +++ b/include/qemu/event_notifier.h @@ -34,7 +34,9 @@ int event_notifier_init(EventNotifier *, int active); void event_notifier_cleanup(EventNotifier *); int event_notifier_set(EventNotifier *); int event_notifier_test_and_clear(EventNotifier *); -int event_notifier_set_handler(EventNotifier *, EventNotifierHandler *); +int event_notifier_set_handler(EventNotifier *, + bool is_external, + EventNotifierHandler *); #ifdef CONFIG_POSIX void event_notifier_init_fd(EventNotifier *, int fd); diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index 99769093fc74876ba72af54a6b5b548fbf3efdfd..19b5de3dd5668fa2a48ed469c69a35233883c4d2 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -204,6 +204,7 @@ void qemu_set_fd_handler(int fd, void *opaque); GSource *iohandler_get_g_source(void); +AioContext *iohandler_get_aio_context(void); #ifdef CONFIG_POSIX /** * qemu_add_child_watch: Register a child process for reaping. diff --git a/iohandler.c b/iohandler.c index 3f23433b5a901efc26afa85d2e877dbd169e4215..f2fc8a9bd6c02645cf3276bf23e0fbc0516a2f7e 100644 --- a/iohandler.c +++ b/iohandler.c @@ -44,6 +44,12 @@ static void iohandler_init(void) } } +AioContext *iohandler_get_aio_context(void) +{ + iohandler_init(); + return iohandler_ctx; +} + GSource *iohandler_get_g_source(void) { iohandler_init(); diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index b6d1e650db934a685ebdacfe03ea19a9d0768c97..4b258a673145f3469690e1224833e487cb79b454 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -40,3 +40,4 @@ stub-obj-y += qmp_pc_dimm_device_list.o stub-obj-y += target-monitor-defs.o stub-obj-y += target-get-monitor-def.o stub-obj-y += vhost.o +stub-obj-y += iohandler.o diff --git a/stubs/iohandler.c b/stubs/iohandler.c new file mode 100644 index 0000000000000000000000000000000000000000..22b0ee5b0ac869482e28ba178d81f3a808680f40 --- /dev/null +++ b/stubs/iohandler.c @@ -0,0 +1,8 @@ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/main-loop.h" + +AioContext *iohandler_get_aio_context(void) +{ + abort(); +} diff --git a/stubs/set-fd-handler.c b/stubs/set-fd-handler.c index 26965de4c36fb0875070a3a8f03827464f151141..06a5da48f1223059a7452c4b7ed874868213da38 100644 --- a/stubs/set-fd-handler.c +++ b/stubs/set-fd-handler.c @@ -9,3 +9,13 @@ void qemu_set_fd_handler(int fd, { abort(); } + +void aio_set_fd_handler(AioContext *ctx, + int fd, + bool is_external, + IOHandler *io_read, + IOHandler *io_write, + void *opaque) +{ + abort(); +} diff --git a/target-i386/hyperv.c b/target-i386/hyperv.c index c4d6a9b2b16199503520a33558558e9507cd0197..39a230f11970127e773f28b4b6a6f5c9acf3801e 100644 --- a/target-i386/hyperv.c +++ b/target-i386/hyperv.c @@ -88,7 +88,7 @@ HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint, goto err_sint_set_notifier; } - event_notifier_set_handler(&sint_route->sint_ack_notifier, + event_notifier_set_handler(&sint_route->sint_ack_notifier, false, kvm_hv_sint_ack_handler); gsi = kvm_irqchip_add_hv_sint_route(kvm_state, vcpu_id, sint); @@ -112,7 +112,7 @@ HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint, err_irqfd: kvm_irqchip_release_virq(kvm_state, gsi); err_gsi: - event_notifier_set_handler(&sint_route->sint_ack_notifier, NULL); + event_notifier_set_handler(&sint_route->sint_ack_notifier, false, NULL); event_notifier_cleanup(&sint_route->sint_ack_notifier); err_sint_set_notifier: event_notifier_cleanup(&sint_route->sint_set_notifier); @@ -128,7 +128,7 @@ void kvm_hv_sint_route_destroy(HvSintRoute *sint_route) &sint_route->sint_set_notifier, sint_route->gsi); kvm_irqchip_release_virq(kvm_state, sint_route->gsi); - event_notifier_set_handler(&sint_route->sint_ack_notifier, NULL); + event_notifier_set_handler(&sint_route->sint_ack_notifier, false, NULL); event_notifier_cleanup(&sint_route->sint_ack_notifier); event_notifier_cleanup(&sint_route->sint_set_notifier); g_free(sint_route); diff --git a/util/event_notifier-posix.c b/util/event_notifier-posix.c index e150301c3313dcef49316c3654131a60def768e6..c1f0d79b3480a093243cfd4b75d8742cc1914bc1 100644 --- a/util/event_notifier-posix.c +++ b/util/event_notifier-posix.c @@ -91,9 +91,11 @@ int event_notifier_get_fd(const EventNotifier *e) } int event_notifier_set_handler(EventNotifier *e, + bool is_external, EventNotifierHandler *handler) { - qemu_set_fd_handler(e->rfd, (IOHandler *)handler, NULL, e); + aio_set_fd_handler(iohandler_get_aio_context(), e->rfd, is_external, + (IOHandler *)handler, NULL, e); return 0; } diff --git a/util/event_notifier-win32.c b/util/event_notifier-win32.c index 14b4f7d2c04c0a9f2d5011ae86f93b502ac8204b..de87df02d67922f3adf1e8cce7da573b8d83d406 100644 --- a/util/event_notifier-win32.c +++ b/util/event_notifier-win32.c @@ -33,6 +33,7 @@ HANDLE event_notifier_get_handle(EventNotifier *e) } int event_notifier_set_handler(EventNotifier *e, + bool is_external, EventNotifierHandler *handler) { if (handler) {