diff --git a/fs/io-wq.c b/fs/io-wq.c index acc036f50ff97065dea7d3050a8df06db323ef24..d766119a9d7b6999240852473ca67ff3de575f58 100644 --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -457,6 +457,10 @@ static void io_worker_handle_work(struct io_worker *worker) } if (!worker->creds) worker->creds = override_creds(wq->creds); + /* + * OK to set IO_WQ_WORK_CANCEL even for uncancellable work, + * the worker function will do the right thing. + */ if (test_bit(IO_WQ_BIT_CANCEL, &wq->state)) work->flags |= IO_WQ_WORK_CANCEL; if (worker->mm) @@ -829,6 +833,7 @@ static bool io_work_cancel(struct io_worker *worker, void *cancel_data) */ spin_lock_irqsave(&worker->lock, flags); if (worker->cur_work && + !(worker->cur_work->flags & IO_WQ_WORK_NO_CANCEL) && data->cancel(worker->cur_work, data->caller_data)) { send_sig(SIGINT, worker->task, 1); ret = true; @@ -903,7 +908,8 @@ static bool io_wq_worker_cancel(struct io_worker *worker, void *data) return false; spin_lock_irqsave(&worker->lock, flags); - if (worker->cur_work == work) { + if (worker->cur_work == work && + !(worker->cur_work->flags & IO_WQ_WORK_NO_CANCEL)) { send_sig(SIGINT, worker->task, 1); ret = true; } diff --git a/fs/io-wq.h b/fs/io-wq.h index a228b30dd6ec0907a5a36d2b02be215e89d33806..1a41aa07ace1913dc7705fa5887a7b7d6c36cd32 100644 --- a/fs/io-wq.h +++ b/fs/io-wq.h @@ -12,6 +12,7 @@ enum { IO_WQ_WORK_UNBOUND = 32, IO_WQ_WORK_INTERNAL = 64, IO_WQ_WORK_CB = 128, + IO_WQ_WORK_NO_CANCEL = 256, IO_WQ_HASH_SHIFT = 24, /* upper 8 bits are used for hash key */ }; diff --git a/fs/io_uring.c b/fs/io_uring.c index 63d0e7deefe52de3f0b197f64bcc72a02ae5285b..1f93a5c696a733563c9a5f826e6f8fc6169e4d35 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -3456,8 +3456,11 @@ static void io_wq_submit_work(struct io_wq_work **workptr) struct io_kiocb *nxt = NULL; int ret = 0; - if (work->flags & IO_WQ_WORK_CANCEL) + /* if NO_CANCEL is set, we must still run the work */ + if ((work->flags & (IO_WQ_WORK_CANCEL|IO_WQ_WORK_NO_CANCEL)) == + IO_WQ_WORK_CANCEL) { ret = -ECANCELED; + } if (!ret) { req->has_user = (work->flags & IO_WQ_WORK_HAS_MM) != 0;