mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 21:51:40 +00:00
io_uring: cancel reqs of all iowq's on ring exit
io_ring_exit_work() have to cancel all requests, including those staying in io-wq, however it tries only cancellation of current tctx, which is NULL. If we've got task==NULL, use the ctx-to-tctx map to go over all tctx/io-wq and try cancellations on them. Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
b5bb3a24f6
commit
1b00764f09
@ -8688,19 +8688,55 @@ static void io_cancel_defer_files(struct io_ring_ctx *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static bool io_cancel_ctx_cb(struct io_wq_work *work, void *data)
|
||||
{
|
||||
struct io_kiocb *req = container_of(work, struct io_kiocb, work);
|
||||
|
||||
return req->ctx == data;
|
||||
}
|
||||
|
||||
static bool io_uring_try_cancel_iowq(struct io_ring_ctx *ctx)
|
||||
{
|
||||
struct io_tctx_node *node;
|
||||
enum io_wq_cancel cret;
|
||||
bool ret = false;
|
||||
|
||||
mutex_lock(&ctx->uring_lock);
|
||||
list_for_each_entry(node, &ctx->tctx_list, ctx_node) {
|
||||
struct io_uring_task *tctx = node->task->io_uring;
|
||||
|
||||
/*
|
||||
* io_wq will stay alive while we hold uring_lock, because it's
|
||||
* killed after ctx nodes, which requires to take the lock.
|
||||
*/
|
||||
if (!tctx || !tctx->io_wq)
|
||||
continue;
|
||||
cret = io_wq_cancel_cb(tctx->io_wq, io_cancel_ctx_cb, ctx, true);
|
||||
ret |= (cret != IO_WQ_CANCEL_NOTFOUND);
|
||||
}
|
||||
mutex_unlock(&ctx->uring_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void io_uring_try_cancel_requests(struct io_ring_ctx *ctx,
|
||||
struct task_struct *task,
|
||||
struct files_struct *files)
|
||||
{
|
||||
struct io_task_cancel cancel = { .task = task, .files = files, };
|
||||
struct task_struct *tctx_task = task ?: current;
|
||||
struct io_uring_task *tctx = tctx_task->io_uring;
|
||||
struct io_uring_task *tctx = task ? task->io_uring : NULL;
|
||||
|
||||
while (1) {
|
||||
enum io_wq_cancel cret;
|
||||
bool ret = false;
|
||||
|
||||
if (tctx && tctx->io_wq) {
|
||||
if (!task) {
|
||||
ret |= io_uring_try_cancel_iowq(ctx);
|
||||
} else if (tctx && tctx->io_wq) {
|
||||
/*
|
||||
* Cancels requests of all rings, not only @ctx, but
|
||||
* it's fine as the task is in exit/exec.
|
||||
*/
|
||||
cret = io_wq_cancel_cb(tctx->io_wq, io_cancel_task_cb,
|
||||
&cancel, true);
|
||||
ret |= (cret != IO_WQ_CANCEL_NOTFOUND);
|
||||
|
Loading…
Reference in New Issue
Block a user