Commit c9abd7ad authored by Pavel Begunkov's avatar Pavel Begunkov Committed by Jens Axboe
Browse files

io_uring: don't defer put of cancelled ltimeout



Inline io_link_cancel_timeout() and __io_kill_linked_timeout() into
io_kill_linked_timeout(). That allows to easily move a put of a cancelled
linked timeout out of completion_lock and to not deferring it. It is also
much more readable when not scattered across three different functions.

Signed-off-by: default avatarPavel Begunkov <asml.silence@gmail.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent cdfcc3ee
Loading
Loading
Loading
Loading
+20 −38
Original line number Diff line number Diff line
@@ -1846,57 +1846,39 @@ static void __io_free_req(struct io_kiocb *req)
	percpu_ref_put(&ctx->refs);
}

static bool io_link_cancel_timeout(struct io_kiocb *req)
static void io_kill_linked_timeout(struct io_kiocb *req)
{
	struct io_timeout_data *io = req->async_data;
	struct io_ring_ctx *ctx = req->ctx;
	int ret;

	ret = hrtimer_try_to_cancel(&io->timer);
	if (ret != -1) {
		io_cqring_fill_event(req, -ECANCELED);
		io_commit_cqring(ctx);
		io_put_req_deferred(req, 1);
		return true;
	}

	return false;
}

static bool __io_kill_linked_timeout(struct io_kiocb *req)
{
	struct io_kiocb *link;
	bool wake_ev;

	if (list_empty(&req->link_list))
		return false;
	link = list_first_entry(&req->link_list, struct io_kiocb, link_list);
	bool cancelled = false;
	unsigned long flags;

	spin_lock_irqsave(&ctx->completion_lock, flags);
	link = list_first_entry_or_null(&req->link_list, struct io_kiocb,
					link_list);
	/*
	 * Can happen if a linked timeout fired and link had been like
	 * req -> link t-out -> link t-out [-> ...]
	 */
	if (!(link->flags & REQ_F_LTIMEOUT_ACTIVE))
		return false;
	if (link && (link->flags & REQ_F_LTIMEOUT_ACTIVE)) {
		struct io_timeout_data *io = link->async_data;
		int ret;

		list_del_init(&link->link_list);
	wake_ev = io_link_cancel_timeout(link);
	return wake_ev;
		ret = hrtimer_try_to_cancel(&io->timer);
		if (ret != -1) {
			io_cqring_fill_event(link, -ECANCELED);
			io_commit_cqring(ctx);
			cancelled = true;
		}
	}

static void io_kill_linked_timeout(struct io_kiocb *req)
{
	struct io_ring_ctx *ctx = req->ctx;
	unsigned long flags;
	bool wake_ev;

	spin_lock_irqsave(&ctx->completion_lock, flags);
	wake_ev = __io_kill_linked_timeout(req);
	req->flags &= ~REQ_F_LINK_TIMEOUT;
	spin_unlock_irqrestore(&ctx->completion_lock, flags);

	if (wake_ev)
	if (cancelled) {
		io_cqring_ev_posted(ctx);
		io_put_req(link);
	}
}

static struct io_kiocb *io_req_link_next(struct io_kiocb *req)