mirror of https://gitee.com/openkylin/linux.git
io_uring: replace inflight_wait with tctx->wait
As tasks now cancel only theirs requests, and inflight_wait is awaited only in io_uring_cancel_files(), which should be called with ->in_idle set, instead of keeping a separate inflight_wait use tctx->wait. That will add some spurious wakeups but actually is safer from point of not hanging the task. e.g. task1 | IRQ | *start* io_complete_rw_common(link) | link: req1 -> req2 -> req3(with files) *cancel_files() | io_wq_cancel(), etc. | | put_req(link), adds to io-wq req2 schedule() | So, task1 will never try to cancel req2 or req3. If req2 is long-standing (e.g. read(empty_pipe)), this may hang. Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
10cad2c40d
commit
c98de08c99
|
@ -287,7 +287,6 @@ struct io_ring_ctx {
|
|||
struct list_head timeout_list;
|
||||
struct list_head cq_overflow_list;
|
||||
|
||||
wait_queue_head_t inflight_wait;
|
||||
struct io_uring_sqe *sq_sqes;
|
||||
} ____cacheline_aligned_in_smp;
|
||||
|
||||
|
@ -1291,7 +1290,6 @@ static struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
|
|||
INIT_LIST_HEAD(&ctx->iopoll_list);
|
||||
INIT_LIST_HEAD(&ctx->defer_list);
|
||||
INIT_LIST_HEAD(&ctx->timeout_list);
|
||||
init_waitqueue_head(&ctx->inflight_wait);
|
||||
spin_lock_init(&ctx->inflight_lock);
|
||||
INIT_LIST_HEAD(&ctx->inflight_list);
|
||||
INIT_DELAYED_WORK(&ctx->file_put_work, io_file_put_work);
|
||||
|
@ -6046,12 +6044,13 @@ static int io_req_defer(struct io_kiocb *req, const struct io_uring_sqe *sqe)
|
|||
static void io_req_drop_files(struct io_kiocb *req)
|
||||
{
|
||||
struct io_ring_ctx *ctx = req->ctx;
|
||||
struct io_uring_task *tctx = req->task->io_uring;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ctx->inflight_lock, flags);
|
||||
list_del(&req->inflight_entry);
|
||||
if (waitqueue_active(&ctx->inflight_wait))
|
||||
wake_up(&ctx->inflight_wait);
|
||||
if (atomic_read(&tctx->in_idle))
|
||||
wake_up(&tctx->wait);
|
||||
spin_unlock_irqrestore(&ctx->inflight_lock, flags);
|
||||
req->flags &= ~REQ_F_INFLIGHT;
|
||||
put_files_struct(req->work.identity->files);
|
||||
|
@ -8693,8 +8692,8 @@ static void io_uring_cancel_files(struct io_ring_ctx *ctx,
|
|||
break;
|
||||
}
|
||||
if (found)
|
||||
prepare_to_wait(&ctx->inflight_wait, &wait,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
prepare_to_wait(&task->io_uring->wait, &wait,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
spin_unlock_irq(&ctx->inflight_lock);
|
||||
|
||||
/* We need to keep going until we don't find a matching req */
|
||||
|
@ -8707,7 +8706,7 @@ static void io_uring_cancel_files(struct io_ring_ctx *ctx,
|
|||
/* cancellations _may_ trigger task work */
|
||||
io_run_task_work();
|
||||
schedule();
|
||||
finish_wait(&ctx->inflight_wait, &wait);
|
||||
finish_wait(&task->io_uring->wait, &wait);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue