Skip to content

Commit df604d2

Browse files
committed
io_uring/rw: ensure retry condition isn't lost
A previous commit removed the checking on whether or not it was possible to retry a request, since it's now possible to retry any of them. This would previously have caused the request to have been ended with an error, but now the retry condition can simply get lost instead. Cleanup the retry handling and always just punt it to task_work, which will queue it with io-wq appropriately. Reported-by: Changhui Zhong <[email protected]> Tested-by: Ming Lei <[email protected]> Fixes: cca6571 ("io_uring/rw: cleanup retry path") Signed-off-by: Jens Axboe <[email protected]>
1 parent 24c3fc5 commit df604d2

File tree

3 files changed

+20
-7
lines changed

3 files changed

+20
-7
lines changed

io_uring/io_uring.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,19 @@ static void io_queue_iowq(struct io_kiocb *req)
527527
io_queue_linked_timeout(link);
528528
}
529529

530+
static void io_tw_requeue_iowq(struct io_kiocb *req, struct io_tw_state *ts)
531+
{
532+
req->flags &= ~REQ_F_REISSUE;
533+
io_queue_iowq(req);
534+
}
535+
536+
void io_tw_queue_iowq(struct io_kiocb *req)
537+
{
538+
req->flags |= REQ_F_REISSUE | REQ_F_BL_NO_RECYCLE;
539+
req->io_task_work.func = io_tw_requeue_iowq;
540+
io_req_task_work_add(req);
541+
}
542+
530543
static __cold void io_queue_deferred(struct io_ring_ctx *ctx)
531544
{
532545
while (!list_empty(&ctx->defer_list)) {

io_uring/io_uring.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ struct file *io_file_get_fixed(struct io_kiocb *req, int fd,
7575
void __io_req_task_work_add(struct io_kiocb *req, unsigned flags);
7676
bool io_alloc_async_data(struct io_kiocb *req);
7777
void io_req_task_queue(struct io_kiocb *req);
78+
void io_tw_queue_iowq(struct io_kiocb *req);
7879
void io_req_task_complete(struct io_kiocb *req, struct io_tw_state *ts);
7980
void io_req_task_queue_fail(struct io_kiocb *req, int ret);
8081
void io_req_task_submit(struct io_kiocb *req, struct io_tw_state *ts);

io_uring/rw.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ static bool __io_complete_rw_common(struct io_kiocb *req, long res)
455455
* current cycle.
456456
*/
457457
io_req_io_end(req);
458-
req->flags |= REQ_F_REISSUE | REQ_F_BL_NO_RECYCLE;
458+
io_tw_queue_iowq(req);
459459
return true;
460460
}
461461
req_set_fail(req);
@@ -521,7 +521,7 @@ static void io_complete_rw_iopoll(struct kiocb *kiocb, long res)
521521
io_req_end_write(req);
522522
if (unlikely(res != req->cqe.res)) {
523523
if (res == -EAGAIN && io_rw_should_reissue(req)) {
524-
req->flags |= REQ_F_REISSUE | REQ_F_BL_NO_RECYCLE;
524+
io_tw_queue_iowq(req);
525525
return;
526526
}
527527
req->cqe.res = res;
@@ -839,7 +839,8 @@ static int __io_read(struct io_kiocb *req, unsigned int issue_flags)
839839
ret = io_iter_do_read(rw, &io->iter);
840840

841841
if (ret == -EAGAIN || (req->flags & REQ_F_REISSUE)) {
842-
req->flags &= ~REQ_F_REISSUE;
842+
if (req->flags & REQ_F_REISSUE)
843+
return IOU_ISSUE_SKIP_COMPLETE;
843844
/* If we can poll, just do that. */
844845
if (io_file_can_poll(req))
845846
return -EAGAIN;
@@ -1034,10 +1035,8 @@ int io_write(struct io_kiocb *req, unsigned int issue_flags)
10341035
else
10351036
ret2 = -EINVAL;
10361037

1037-
if (req->flags & REQ_F_REISSUE) {
1038-
req->flags &= ~REQ_F_REISSUE;
1039-
ret2 = -EAGAIN;
1040-
}
1038+
if (req->flags & REQ_F_REISSUE)
1039+
return IOU_ISSUE_SKIP_COMPLETE;
10411040

10421041
/*
10431042
* Raw bdev writes will return -EOPNOTSUPP for IOCB_NOWAIT. Just

0 commit comments

Comments
 (0)