summaryrefslogtreecommitdiff
path: root/fs/io-wq.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2021-04-01 19:57:07 -0600
committerJens Axboe <axboe@kernel.dk>2021-04-11 19:30:25 -0600
commitc80ca4707d1aa8b6ba2cb8e57a521ebb6f9f22a2 (patch)
tree300d3b98eacd64ba7377079eb7156977a64b2c01 /fs/io-wq.c
parentc7aab1a7c52b82d9afd7e03c398eb03dc2aa0507 (diff)
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 <axboe@kernel.dk>
Diffstat (limited to 'fs/io-wq.c')
-rw-r--r--fs/io-wq.c12
1 files changed, 11 insertions, 1 deletions
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);