diff options
author | Jens Axboe <axboe@kernel.dk> | 2019-12-11 19:29:43 -0700 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2020-01-20 17:01:53 -0700 |
commit | 0c9d5ccd26a004f59333c06fbbb98f9cb1eed93d (patch) | |
tree | 44cdf8ba1137666d0194c3fbe2d995d2138fa456 /fs/io-wq.c | |
parent | 6e802a4ba056a6f2f51ac9d54eead3ed6f9829a2 (diff) |
io-wq: add support for uncancellable work
Not all work can be cancelled, some of it we may need to guarantee
that it runs to completion. Allow the caller to set IO_WQ_WORK_NO_CANCEL
on work that must not be cancelled. Note that the caller work function
must also check for IO_WQ_WORK_NO_CANCEL on work that is marked
IO_WQ_WORK_CANCEL.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'fs/io-wq.c')
-rw-r--r-- | fs/io-wq.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/fs/io-wq.c b/fs/io-wq.c index 5147d2213b01..79eae29983ca 100644 --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -456,6 +456,10 @@ next: } 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) @@ -828,6 +832,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; @@ -902,7 +907,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; } |