Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: https://github.com/axboe/liburing/discussions/1459
Reported-by: Benedek Thaler <thaler@thaler.hu>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

+9 -7
+4 -2
io_uring/io_uring.c
··· 1406 1406 1407 1407 void io_req_task_submit(struct io_kiocb *req, io_tw_token_t tw) 1408 1408 { 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))) 1411 1413 io_req_defer_failed(req, -EFAULT); 1412 1414 else if (req->flags & REQ_F_FORCE_ASYNC) 1413 1415 io_queue_iowq(req);
+2 -2
io_uring/io_uring.h
··· 476 476 * 2) PF_KTHREAD is set, in which case the invoker of the task_work is 477 477 * our fallback task_work. 478 478 */ 479 - static inline bool io_should_terminate_tw(void) 479 + static inline bool io_should_terminate_tw(struct io_ring_ctx *ctx) 480 480 { 481 - return current->flags & (PF_KTHREAD | PF_EXITING); 481 + return (current->flags & (PF_KTHREAD | PF_EXITING)) || percpu_ref_is_dying(&ctx->refs); 482 482 } 483 483 484 484 static inline void io_req_queue_tw_complete(struct io_kiocb *req, s32 res)
+1 -1
io_uring/poll.c
··· 224 224 { 225 225 int v; 226 226 227 - if (unlikely(io_should_terminate_tw())) 227 + if (unlikely(io_should_terminate_tw(req->ctx))) 228 228 return -ECANCELED; 229 229 230 230 do {
+1 -1
io_uring/timeout.c
··· 324 324 int ret; 325 325 326 326 if (prev) { 327 - if (!io_should_terminate_tw()) { 327 + if (!io_should_terminate_tw(req->ctx)) { 328 328 struct io_cancel_data cd = { 329 329 .ctx = req->ctx, 330 330 .data = prev->cqe.user_data,
+1 -1
io_uring/uring_cmd.c
··· 118 118 struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd); 119 119 unsigned int flags = IO_URING_F_COMPLETE_DEFER; 120 120 121 - if (io_should_terminate_tw()) 121 + if (io_should_terminate_tw(req->ctx)) 122 122 flags |= IO_URING_F_TASK_DEAD; 123 123 124 124 /* task_work executor checks the deffered list completion */