Skip to content

Commit b7f5a0b

Browse files
isilenceaxboe
authored andcommitted
io_uring: fix sqpoll cancellation via task_work
Running sqpoll cancellations via task_work_run() is a bad idea because it depends on other task works to be run, but those may be locked in currently running task_work_run() because of how it's (splicing the list in batches). Enqueue and run them through a separate callback head, namely struct io_sq_data::park_task_work. As a nice bonus we now precisely control where it's run, that's much safer than guessing where it can happen as it was before. Reported-by: Jens Axboe <[email protected]> Signed-off-by: Pavel Begunkov <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 9b46571 commit b7f5a0b

File tree

1 file changed

+5
-1
lines changed

1 file changed

+5
-1
lines changed

fs/io_uring.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ struct io_sq_data {
274274

275275
unsigned long state;
276276
struct completion exited;
277+
struct callback_head *park_task_work;
277278
};
278279

279280
#define IO_IOPOLL_BATCH 8
@@ -6727,6 +6728,7 @@ static int io_sq_thread(void *data)
67276728
cond_resched();
67286729
mutex_lock(&sqd->lock);
67296730
io_run_task_work();
6731+
io_run_task_work_head(&sqd->park_task_work);
67306732
timeout = jiffies + sqd->sq_thread_idle;
67316733
continue;
67326734
}
@@ -6781,6 +6783,7 @@ static int io_sq_thread(void *data)
67816783
}
67826784

67836785
finish_wait(&sqd->wait, &wait);
6786+
io_run_task_work_head(&sqd->park_task_work);
67846787
timeout = jiffies + sqd->sq_thread_idle;
67856788
}
67866789

@@ -6792,6 +6795,7 @@ static int io_sq_thread(void *data)
67926795
mutex_unlock(&sqd->lock);
67936796

67946797
io_run_task_work();
6798+
io_run_task_work_head(&sqd->park_task_work);
67956799
complete(&sqd->exited);
67966800
do_exit(0);
67976801
}
@@ -8890,7 +8894,7 @@ static void io_sqpoll_cancel_sync(struct io_ring_ctx *ctx)
88908894
if (task) {
88918895
init_completion(&work.completion);
88928896
init_task_work(&work.task_work, io_sqpoll_cancel_cb);
8893-
WARN_ON_ONCE(task_work_add(task, &work.task_work, TWA_SIGNAL));
8897+
io_task_work_add_head(&sqd->park_task_work, &work.task_work);
88948898
wake_up_process(task);
88958899
}
88968900
io_sq_thread_unpark(sqd);

0 commit comments

Comments
 (0)