mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
io_uring/wait: no early -ETIME if min_wait finds work
When the min wait time is over and there is work to run, which for
DEFER_TASKRUN includes task_work that was queued lazily and didn't wake
the waiter, io_cqring_min_timer_wakeup() ends the wait via
io_cqring_timer_wakeup(). That flags it as timed out. io_cqring_wait()
runs the work, leaves the loop, and returns 0 if the CQ ring holds
something.
Running task_work doesn't have to result in a CQE, though. A poll wake up
can turn out to be spurious, for instance if somebody else has read the
data by the time the request is retried. The application then gets -ETIME
once the min wait time has passed, no matter how far away the timeout it
asked for is.
Wake the task without declaring a timeout. From now on a single CQE
satisfies the wait, like in the case where the timer is switched over to
the normal timeout. If running the work doesn't post one, the loop in
io_cqring_wait() goes back to sleep with the normal timeout.
Fixes: 1100c4a265 ("io_uring: add support for batch wait timeout")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-32-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
dad82eb180
commit
83cce67298
|
|
@ -77,9 +77,16 @@ static enum hrtimer_restart io_cqring_min_timer_wakeup(struct hrtimer *timer)
|
|||
if (iowq->timeout == KTIME_MAX ||
|
||||
ktime_compare(iowq->min_timeout, iowq->timeout) >= 0)
|
||||
goto out_wake;
|
||||
/* work we may need to run, wake function will see if we need to wake */
|
||||
if (io_has_work(ctx))
|
||||
goto out_wake;
|
||||
/*
|
||||
* Work we need to run. It isn't known if that is going to post a CQE,
|
||||
* so this isn't a timeout. Carry on with the normal one if it doesn't.
|
||||
*/
|
||||
if (io_has_work(ctx)) {
|
||||
iowq->min_timeout = 0;
|
||||
iowq->cq_tail = iowq->cq_min_tail + 1;
|
||||
wake_up_process(iowq->wq.private);
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
/* got events since we started waiting, min timeout is done */
|
||||
scoped_guard(rcu) {
|
||||
struct io_rings *rings = io_get_rings(ctx);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user