Re: [PATCH 5.10 491/491] io_uring/poll: correctly handle io_poll_add() return value on update

Jens Axboe
2026-04-21T22:58:55Z

[-- Attachment #1: Type: text/plain, Size: 1216 bytes --]

On 4/21/26 4:18 PM, Jens Axboe wrote:
>>> @@ -6024,16 +6035,17 @@ static int io_poll_update(struct io_kioc
>>> if (req->poll_update.update_user_data)
>>> preq->user_data = req->poll_update.new_user_data;
>>>
>>> - ret2 = io_poll_add(preq, issue_flags);
>>> + ret2 = __io_poll_add(preq, issue_flags);
>>> /* successfully updated, don't complete poll request */
>>> if (!ret2)
>>> goto out;
>>> + preq->result = ret2;
>>> +
>>> }
>>> - req_set_fail(preq);
>>> - io_req_complete(preq, -ECANCELED);
>>> + if (preq->result < 0)
>>> + req_set_fail(preq);
>>> + io_req_complete(preq, preq->result);
>>
>> If __io_poll_add() returned an events mask then it completed preq, but
>> then we also complete preq here. Is that really correct?
>
> Let me take a closer look, I do agree with you that the final result
> does not look entirely correct.

As far as I can tell, these two should be applied to 5.10 and 5.15
stable. The first one fixes an old backporting issue that I didn't
notice until doing some targeted testing just now. The second one should
take care of the issues that Ben spotted in the current backport.

Will be nice when 5.x is finally taken out behind the barn :-)

--
Jens Axboe

[-- Attachment #2: 0001-io_uring-poll-fix-EPOLL_URING_WAKE-sometimes-not-bei.patch --]
[-- Type: text/x-patch, Size: 1517 bytes --]

From 7fdfffce508f38d89338e8bbed421dd91ddfcb3f Mon Sep 17 00:00:00 2001
From: Jens Axboe <axboe@kernel.dk>
Date: Tue, 21 Apr 2026 16:41:32 -0600
Subject: [PATCH 1/2] io_uring/poll: fix EPOLL_URING_WAKE sometimes not being
masked in

Rather than do it only when we jump straight to execution, mark it
regardless. This ensures it doesn't get lost.

Fixes: ccf06b5a981c ("io_uring: pass in EPOLL_URING_WAKE for eventfd signaling and wakeups")
Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
io_uring/io_uring.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index 38decfc1a914..db5c9fbdec3b 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -5794,17 +5794,16 @@ static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
if (mask && !(mask & poll->events))
return 0;

- 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 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))
__io_poll_execute(req, mask);
- }
return 1;
}

--
2.53.0

[-- Attachment #3: 0002-io_uring-poll-fix-backport-of-io_poll_add-changes.patch --]
[-- Type: text/x-patch, Size: 1429 bytes --]

From 7a61c38c4d6ae3d5cbe6efa06885b1ca821a129c Mon Sep 17 00:00:00 2001
From: Jens Axboe <axboe@kernel.dk>
Date: Tue, 21 Apr 2026 16:44:06 -0600
Subject: [PATCH 2/2] io_uring/poll: fix backport of io_poll_add() changes

The 5.15/5.10 backport of 84230ad2d2af had a few issues, due to the
older poll base. Notably return value handling __io_arm_poll_handler()
and in return __io_poll_add() as well. Fix them up.

Reported-by: Ben Hutchings <ben@decadent.org.uk>
Fixes: 349ef5d2e7bf ("io_uring/poll: correctly handle io_poll_add() return value on update")
Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
io_uring/io_uring.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index db5c9fbdec3b..07519e9a695c 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -6138,19 +6138,15 @@ static int __io_poll_add(struct io_kiocb *req, unsigned int issue_flags)
if (!ret && ipt.error)
req_set_fail(req);
ret = ret ?: ipt.error;
- if (ret > 0) {
+ if (ret)
__io_req_complete(req, issue_flags, ret, 0);
- return ret;
- }
- return 0;
+ return ret;
}

static int io_poll_add(struct io_kiocb *req, unsigned int issue_flags)
{
- int ret;
-
- ret = __io_poll_add(req, issue_flags);
- return ret < 0 ? ret : 0;
+ __io_poll_add(req, issue_flags);
+ return 0;
}

static int io_poll_update(struct io_kiocb *req, unsigned int issue_flags)
--
2.53.0