Skip to content

Commit 3539b14

Browse files
committed
io_uring: include dying ring in task_work "should cancel" state
When running task_work for an exiting task, rather than perform the issue retry attempt, the task_work is canceled. However, this isn't done for a ring that has been closed. This can lead to requests being successfully completed post the ring being closed, which is somewhat confusing and surprising to an application. Rather than just check the task exit state, also include the ring ref state in deciding whether or not to terminate a given request when run from task_work. Cc: stable@vger.kernel.org # 6.1+ Link: axboe/liburing#1459 Reported-by: Benedek Thaler <thaler@thaler.hu> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent cd4ea81 commit 3539b14

5 files changed

Lines changed: 9 additions & 7 deletions

File tree

io_uring/io_uring.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,8 +1406,10 @@ static void io_req_task_cancel(struct io_kiocb *req, io_tw_token_t tw)
14061406

14071407
void io_req_task_submit(struct io_kiocb *req, io_tw_token_t tw)
14081408
{
1409-
io_tw_lock(req->ctx, tw);
1410-
if (unlikely(io_should_terminate_tw()))
1409+
struct io_ring_ctx *ctx = req->ctx;
1410+
1411+
io_tw_lock(ctx, tw);
1412+
if (unlikely(io_should_terminate_tw(ctx)))
14111413
io_req_defer_failed(req, -EFAULT);
14121414
else if (req->flags & REQ_F_FORCE_ASYNC)
14131415
io_queue_iowq(req);

io_uring/io_uring.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,9 +476,9 @@ static inline bool io_allowed_run_tw(struct io_ring_ctx *ctx)
476476
* 2) PF_KTHREAD is set, in which case the invoker of the task_work is
477477
* our fallback task_work.
478478
*/
479-
static inline bool io_should_terminate_tw(void)
479+
static inline bool io_should_terminate_tw(struct io_ring_ctx *ctx)
480480
{
481-
return current->flags & (PF_KTHREAD | PF_EXITING);
481+
return (current->flags & (PF_KTHREAD | PF_EXITING)) || percpu_ref_is_dying(&ctx->refs);
482482
}
483483

484484
static inline void io_req_queue_tw_complete(struct io_kiocb *req, s32 res)

io_uring/poll.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ static int io_poll_check_events(struct io_kiocb *req, io_tw_token_t tw)
224224
{
225225
int v;
226226

227-
if (unlikely(io_should_terminate_tw()))
227+
if (unlikely(io_should_terminate_tw(req->ctx)))
228228
return -ECANCELED;
229229

230230
do {

io_uring/timeout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ static void io_req_task_link_timeout(struct io_kiocb *req, io_tw_token_t tw)
324324
int ret;
325325

326326
if (prev) {
327-
if (!io_should_terminate_tw()) {
327+
if (!io_should_terminate_tw(req->ctx)) {
328328
struct io_cancel_data cd = {
329329
.ctx = req->ctx,
330330
.data = prev->cqe.user_data,

io_uring/uring_cmd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ static void io_uring_cmd_work(struct io_kiocb *req, io_tw_token_t tw)
118118
struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd);
119119
unsigned int flags = IO_URING_F_COMPLETE_DEFER;
120120

121-
if (io_should_terminate_tw())
121+
if (io_should_terminate_tw(req->ctx))
122122
flags |= IO_URING_F_TASK_DEAD;
123123

124124
/* task_work executor checks the deffered list completion */

0 commit comments

Comments
 (0)