From c80ca4707d1aa8b6ba2cb8e57a521ebb6f9f22a2 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 1 Apr 2021 19:57:07 -0600 Subject: [PATCH] io-wq: cancel task_work on exit only targeting the current 'wq' With using task_work_cancel(), we're potentially canceling task_work that isn't related to this specific io_wq. Use the newly added task_work_cancel_match() to ensure that we only remove and cancel work items that are specific to this io_wq. Fixes: 685fe7feedb9 ("io-wq: eliminate the need for a manager thread") Signed-off-by: Jens Axboe --- fs/io-wq.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/fs/io-wq.c b/fs/io-wq.c index 8ba4ccaafbaf..5551272cf553 100644 --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -986,6 +986,16 @@ err_wq: return ERR_PTR(ret); } +static bool io_task_work_match(struct callback_head *cb, void *data) +{ + struct create_worker_data *cwd; + + if (cb->func != create_worker_cb) + return false; + cwd = container_of(cb, struct create_worker_data, work); + return cwd->wqe->wq == data; +} + static void io_wq_exit_workers(struct io_wq *wq) { struct callback_head *cb; @@ -996,7 +1006,7 @@ static void io_wq_exit_workers(struct io_wq *wq) if (!wq->task) return; - while ((cb = task_work_cancel(wq->task, create_worker_cb)) != NULL) { + while ((cb = task_work_cancel_match(wq->task, io_task_work_match, wq)) != NULL) { struct create_worker_data *cwd; cwd = container_of(cb, struct create_worker_data, work); -- 2.20.1