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>
This commit is contained in:
Родитель
6e802a4ba0
Коммит
0c9d5ccd26
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
|
@ -3460,8 +3460,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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче