]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
io_uring/eventfd: reset deferred signal state
authorYufan Chen <ericterminal@gmail.com>
Sun, 3 May 2026 17:57:10 +0000 (01:57 +0800)
committerJens Axboe <axboe@kernel.dk>
Mon, 4 May 2026 05:21:40 +0000 (23:21 -0600)
Recursive eventfd wakeups must defer io_uring eventfd signaling because
eventfd_signal_mask() rejects reentry from eventfd wakeup handlers. The
io_ev_fd ops bit tracks an outstanding deferred signal so that the same
rcu_head is not queued twice.

That bit is only set today. Once the first deferred callback runs, later
recursive notifications still see the bit set and skip queueing another
deferred signal. This can leave new completions without a matching
eventfd wake after the first recursive deferral.

Clear the pending bit before issuing the deferred signal. If the wakeup
path recurses while the callback runs, a new signal can be queued for
the next RCU grace period while the current callback keeps its reference
until it returns.

Signed-off-by: Yufan Chen <ericterminal@gmail.com>
Fixes: 60b6c075e8eb ("io_uring/eventfd: move to more idiomatic RCU free usage")
Link: https://patch.msgid.link/20260503175710.37209-1-yufan.chen@linux.dev
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/eventfd.c

index 3da028500f76a67f8e0b662bf085c9532a0204b9..d656cc2a0b9ba5528136bf2940a729522117af4d 100644 (file)
@@ -43,6 +43,7 @@ static void io_eventfd_do_signal(struct rcu_head *rcu)
 {
        struct io_ev_fd *ev_fd = container_of(rcu, struct io_ev_fd, rcu);
 
+       atomic_andnot(BIT(IO_EVENTFD_OP_SIGNAL_BIT), &ev_fd->ops);
        eventfd_signal_mask(ev_fd->cq_ev_fd, EPOLL_URING_WAKE);
        io_eventfd_put(ev_fd);
 }