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

Jens Axboe
2026-05-01T22:07:53Z

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

On 5/1/26 3:55 PM, Fedor Pchelkin wrote:
> On Sat, 02. May 00:50, Fedor Pchelkin wrote:
>> On Fri, 01. May 15:33, 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);
>>>
>>> This should all be handled in the fixup patch - yes this one ended up
>>> being broken, but that's why there's the followup fix.
>>>
>>> Now this is all pretty broken because some patches ended up in 5.15 and
>>> some in 5.10 and honestly I've almost lost track at this point. Sasha
>>> spotted some that were dropped in some broken commit from Greg. For
>>> 5.15, the two attached are what I recently asked for to be added. 5.10
>>> should ALWAYS get the exact same patches as 5.15, because of the whole
>>> sale backport that was done years ago. I always ask for that explicitly
>>> in the emails. But looks like that wasn't always done...
>>>
>>> 5.10 doesn't look like it ever got what is sha
>>> 349ef5d2e7bfb292e7000e6041a984ab56eccf28 in 5.15-stable, hence the fixup
>>> can be merged with queueing that backport.
>>>
>>> Sigh...
>>
>> Oh, for the fixup patch - it is in the 5.10-queue (or at least was when I
>> wrote up report today). It was taken into consideration. The concern
>> for the Fixes tag is resolved now by you, thanks for clarification.
>>
>> But that `if (preq->result) < 0` thing is not covered by the fixup patch.
>> This check is not correct in 5.10/5.15 because preq->result is unsigned.
>>
>> Taken that double complete is OK (I had doubts about that), the following
>> change should do the job now:
>>
>> diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
>> index 8b0dfea96ee0..b17a26b1b5e1 100644
>> --- a/io_uring/io_uring.c
>> +++ b/io_uring/io_uring.c
>> @@ -6006,7 +6006,7 @@ static int io_poll_update(struct io_kiocb *req, unsigned int issue_flags)
>> {
>> struct io_ring_ctx *ctx = req->ctx;
>> struct io_kiocb *preq;
>> - int ret2, ret = 0;
>> + int ret2 = -ECANCELED, ret = 0;
>>
>> io_ring_submit_lock(ctx, !(issue_flags & IO_URING_F_NONBLOCK));
>>
>> @@ -6037,7 +6037,7 @@ static int io_poll_update(struct io_kiocb *req, unsigned int issue_flags)
>> preq->result = ret2;
>>
>> }
>> - if (preq->result < 0)
>> + if (ret2 < 0)
>> req_set_fail(preq);
>> io_req_complete(preq, preq->result);
>> out:
>>
>>
>> The fixup patch may be updated with this if the changes look OK.
>>
>
> Or maybe this one which is less hassle:
>
> diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
> index 8b0dfea96ee0..bb01eaa9761f 100644
> --- a/io_uring/io_uring.c
> +++ b/io_uring/io_uring.c
> @@ -6037,7 +6037,7 @@ static int io_poll_update(struct io_kiocb *req, unsigned int issue_flags)
> preq->result = ret2;
>
> }
> - if (preq->result < 0)
> + if (preq->result)
> req_set_fail(preq);
> io_req_complete(preq, preq->result);
> out:

That'd be fine. Note that both your patches are white space damaged. I
can send out updated fixup patches, the above does improve them. But at
this point I don't even know what is queued up where. As far as I can
tell neither 5.10-stable or 5.15-stable have the fixup queued up yet,
even though I asked for it 10 days ago. Neither the fixup, nor the
EPOLL_URING_WAKE patch.

I feel like I spend a lot of time both on stable, and defending stable
against people that complain about it. And usually it's all been fine,
but lately it does seem like a bit of a mess :(, and as a maintainer, I
absolutely 100% need to rely on stable doing what they are asked to do,
and if patches fail, then I need to know about it. If patches get yanked
for whatever reason, I need to get asked. And if I ask for patches to
get included and I get an ack, I should not need to scour various stable
branches to check if that actually happened or not.

So let me make it VERY clear - apply the two attached patches to BOTH
5.10-stable and 5.15-stable. Thank you.

--
Jens Axboe

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

From 240211bd8270ea42440b1775e4d7bc005908cd46 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: 1665 bytes --]

From 8f1a401b0fce5a46935153f8572b0681d5b9a00d 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 | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index db5c9fbdec3b..97d0ecec8322 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)
@@ -6188,7 +6184,7 @@ static int io_poll_update(struct io_kiocb *req, unsigned int issue_flags)
preq->result = ret2;

}
- if (preq->result < 0)
+ if (ret2 < 0)
req_set_fail(preq);
io_req_complete(preq, preq->result);
out:
--
2.53.0