#include "qemu/osdep.h"
#include "block/block.h"
#include "block/thread-pool.h"
+#include "qapi/error.h"
#include "qemu/main-loop.h"
#include "qemu/lockcnt.h"
#include "qemu/rcu.h"
ctx->epollfd = -1;
ctx->epollfd_tag = NULL;
- /* Use the fastest fd monitoring implementation if available */
- if (fdmon_io_uring_setup(ctx)) {
- return true;
+#ifdef CONFIG_LINUX_IO_URING
+ {
+ static bool need_io_uring;
+ Error *local_err = NULL; /* ERRP_GUARD() doesn't handle error_abort */
+
+ /* io_uring takes precedence because it provides aio_add_sqe() support */
+ if (fdmon_io_uring_setup(ctx, &local_err)) {
+ /*
+ * If one AioContext gets io_uring, then all AioContexts need io_uring
+ * so that aio_add_sqe() support is available across all threads.
+ */
+ need_io_uring = true;
+ return true;
+ }
+ if (need_io_uring) {
+ error_propagate(errp, local_err);
+ return false;
+ }
+
+ /* Silently fall back on systems where io_uring is unavailable */
+ error_free(local_err);
}
+#endif /* CONFIG_LINUX_IO_URING */
fdmon_epoll_setup(ctx);
return true;
void aio_context_destroy(AioContext *ctx)
{
+#ifdef CONFIG_LINUX_IO_URING
fdmon_io_uring_destroy(ctx);
+#endif
qemu_lockcnt_lock(&ctx->list_lock);
fdmon_epoll_disable(ctx);
#define AIO_POSIX_H
#include "block/aio.h"
+#include "qapi/error.h"
struct AioHandler {
GPollFD pfd;
#endif /* !CONFIG_EPOLL_CREATE1 */
#ifdef CONFIG_LINUX_IO_URING
-bool fdmon_io_uring_setup(AioContext *ctx);
+bool fdmon_io_uring_setup(AioContext *ctx, Error **errp);
void fdmon_io_uring_destroy(AioContext *ctx);
-#else
-static inline bool fdmon_io_uring_setup(AioContext *ctx)
-{
- return false;
-}
-
-static inline void fdmon_io_uring_destroy(AioContext *ctx)
-{
-}
#endif /* !CONFIG_LINUX_IO_URING */
#endif /* AIO_POSIX_H */
#include "qemu/osdep.h"
#include <poll.h>
+#include "qapi/error.h"
#include "qemu/rcu_queue.h"
#include "aio-posix.h"
.gsource_dispatch = fdmon_io_uring_gsource_dispatch,
};
-bool fdmon_io_uring_setup(AioContext *ctx)
+bool fdmon_io_uring_setup(AioContext *ctx, Error **errp)
{
int ret;
ret = io_uring_queue_init(FDMON_IO_URING_ENTRIES, &ctx->fdmon_io_uring, 0);
if (ret != 0) {
+ error_setg_errno(errp, -ret, "Failed to initialize io_uring");
return false;
}
ctx->fdmon_ops = &fdmon_io_uring_ops;
ctx->io_uring_fd_tag = g_source_add_unix_fd(&ctx->source,
ctx->fdmon_io_uring.ring_fd, G_IO_IN);
-
return true;
}