IORING_SETUP_SINGLE_ISSUER enables optimizations in the host Linux kernel's io_uring code when the io_uring context is only used from a single thread. This is true is QEMU because io_uring SQEs are submitted from the same thread that processes the CQEs.
Signed-off-by: Stefan Hajnoczi <stefa...@redhat.com> --- util/fdmon-io_uring.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/util/fdmon-io_uring.c b/util/fdmon-io_uring.c index 28b93c8ab9..4798439097 100644 --- a/util/fdmon-io_uring.c +++ b/util/fdmon-io_uring.c @@ -456,13 +456,30 @@ static const FDMonOps fdmon_io_uring_ops = { .add_sqe = fdmon_io_uring_add_sqe, }; +static inline bool is_creating_iothread(void) +{ + return qemu_get_thread_id() != getpid(); +} + void fdmon_io_uring_setup(AioContext *ctx, Error **errp) { int ret; + /* TODO only enable these flags if they are available in the host's kernel headers */ + unsigned flags = 0; ctx->io_uring_fd_tag = NULL; - ret = io_uring_queue_init(FDMON_IO_URING_ENTRIES, &ctx->fdmon_io_uring, 0); + /* + * The main thread's AioContexts are created from the main loop thread but + * may be accessed from multiple threads (e.g. vCPUs or the migration + * thread). IOThread AioContexts are only accessed from the IOThread + * itself. + */ + if (is_creating_iothread()) { + flags = IORING_SETUP_SINGLE_ISSUER; + } + + ret = io_uring_queue_init(FDMON_IO_URING_ENTRIES, &ctx->fdmon_io_uring, flags); if (ret != 0) { error_setg_errno(errp, -ret, "Failed to initialize io_uring"); return; -- 2.50.1