| From 6ad6d8e2917f309e12ba92f001536d2d05409d01 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 13 Oct 2020 09:43:56 +0100 |
| Subject: io_uring: don't set COMP_LOCKED if won't put |
| |
| From: Pavel Begunkov <asml.silence@gmail.com> |
| |
| [ Upstream commit 368c5481ae7c6a9719c40984faea35480d9f4872 ] |
| |
| __io_kill_linked_timeout() sets REQ_F_COMP_LOCKED for a linked timeout |
| even if it can't cancel it, e.g. it's already running. It not only races |
| with io_link_timeout_fn() for ->flags field, but also leaves the flag |
| set and so io_link_timeout_fn() may find it and decide that it holds the |
| lock. Hopefully, the second problem is potential. |
| |
| Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> |
| Signed-off-by: Jens Axboe <axboe@kernel.dk> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/io_uring.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| diff --git a/fs/io_uring.c b/fs/io_uring.c |
| index 59ab8c5c2aaaa..50a7a99dad4ca 100644 |
| --- a/fs/io_uring.c |
| +++ b/fs/io_uring.c |
| @@ -1650,6 +1650,7 @@ static bool io_link_cancel_timeout(struct io_kiocb *req) |
| |
| ret = hrtimer_try_to_cancel(&req->io->timeout.timer); |
| if (ret != -1) { |
| + req->flags |= REQ_F_COMP_LOCKED; |
| io_cqring_fill_event(req, -ECANCELED); |
| io_commit_cqring(ctx); |
| req->flags &= ~REQ_F_LINK_HEAD; |
| @@ -1672,7 +1673,6 @@ static bool __io_kill_linked_timeout(struct io_kiocb *req) |
| return false; |
| |
| list_del_init(&link->link_list); |
| - link->flags |= REQ_F_COMP_LOCKED; |
| wake_ev = io_link_cancel_timeout(link); |
| req->flags &= ~REQ_F_LINK_TIMEOUT; |
| return wake_ev; |
| -- |
| 2.27.0 |
| |