Because of need_resched() check, io_uring_enter() -> io_iopoll_check() can return 0 even if @min_complete wasn't satisfied. If that's the case, __io_uring_get_cqe() sets submit=0 and wait_nr=0, disabling setting IORING_ENTER_GETEVENTS as well. So, it goes crazy calling io_uring_enter() in a loop, not actually submitting nor polling. Set @wait_nr based on actual number of CQEs ready. BTW, atomic_load_acquire() in io_uring_cq_ready() can be replaced with a relaxed one for this particular place. Signed-off-by: Pavel Begunkov <asml.silence@xxxxxxxxx> --- src/queue.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/queue.c b/src/queue.c index 14a0777..638d0ac 100644 --- a/src/queue.c +++ b/src/queue.c @@ -32,6 +32,14 @@ static inline bool sq_ring_needs_enter(struct io_uring *ring, return false; } +static inline unsigned int io_adjut_wait_nr(struct io_uring *ring, + unsigned int to_wait) +{ + unsigned int ready = io_uring_cq_ready(ring); + + return (to_wait <= ready) ? 0 : (to_wait - ready); +} + int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, unsigned submit, unsigned wait_nr, sigset_t *sigmask) { @@ -60,7 +68,8 @@ int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, err = -errno; } else if (ret == (int)submit) { submit = 0; - wait_nr = 0; + if (to_wait) + wait_nr = io_adjut_wait_nr(ring, to_wait); } else { submit -= ret; } -- 2.24.0