From 38ebae3b93403e03d2e6a44afd2d980cce49db8c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 21 Apr 2026 16:41:32 -0600 Subject: [PATCH 1/2] io_uring/poll: fix EPOLL_URING_WAKE sometimes not being honored Rather than do the masking only when we jump straight to execution, mark it as EPOLLONESHOT regardless. This ensures it doesn't get lost. And just kill the poll entry upfront, if marked. This is an optimization in later kernels, but it's actually required on the older kernels to note the EPOLL_URING_WAKE mask correctly. Fixes: ccf06b5a981c ("io_uring: pass in EPOLL_URING_WAKE for eventfd signaling and wakeups") Signed-off-by: Jens Axboe --- io_uring/io_uring.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index 38decfc1a914..4f1dda7d68c2 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -5794,14 +5794,19 @@ static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, if (mask && !(mask & poll->events)) return 0; + /* + * If we trigger a multishot poll off our own wakeup path, + * disable multishot as there is a circular dependency between + * CQ posting and triggering the event. + */ + if (mask & EPOLL_URING_WAKE) + poll->events |= EPOLLONESHOT; + if (io_poll_get_ownership(req)) { - /* - * If we trigger a multishot poll off our own wakeup path, - * disable multishot as there is a circular dependency between - * CQ posting and triggering the event. - */ - if (mask & EPOLL_URING_WAKE) - poll->events |= EPOLLONESHOT; + if (mask && poll->events & EPOLLONESHOT) { + list_del_init(&poll->wait.entry); + smp_store_release(&poll->head, NULL); + } __io_poll_execute(req, mask); } -- 2.53.0