* [PATCH 1/1] io_uring: fix racy REQ_F_LINK_TIMEOUT clearing
@ 2020-10-19 15:39 Pavel Begunkov
2020-10-20 14:10 ` Jens Axboe
0 siblings, 1 reply; 2+ messages in thread
From: Pavel Begunkov @ 2020-10-19 15:39 UTC (permalink / raw)
To: Jens Axboe, io-uring
io_link_timeout_fn() removes REQ_F_LINK_TIMEOUT from the link head's
flags, it's not atomic and may race with what the head is doing.
If io_link_timeout_fn() doesn't clear the flag, as forced by this patch,
then it may happen that for "req -> link_timeout1 -> link_timeout2",
__io_kill_linked_timeout() would find link_timeout2 and try to cancel
it, so miscounting references. Teach it to ignore such double timeouts
by marking the active one with a new flag in io_prep_linked_timeout().
Signed-off-by: Pavel Begunkov <[email protected]>
---
fs/io_uring.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 5651b9d701e0..c5a00e06be52 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -585,6 +585,7 @@ enum {
REQ_F_BUFFER_SELECTED_BIT,
REQ_F_NO_FILE_TABLE_BIT,
REQ_F_WORK_INITIALIZED_BIT,
+ REQ_F_LTIMEOUT_ACTIVE_BIT,
/* not a real bit, just to check we're not overflowing the space */
__REQ_F_LAST_BIT,
@@ -614,7 +615,7 @@ enum {
REQ_F_CUR_POS = BIT(REQ_F_CUR_POS_BIT),
/* must not punt to workers */
REQ_F_NOWAIT = BIT(REQ_F_NOWAIT_BIT),
- /* has linked timeout */
+ /* has or had linked timeout */
REQ_F_LINK_TIMEOUT = BIT(REQ_F_LINK_TIMEOUT_BIT),
/* regular file */
REQ_F_ISREG = BIT(REQ_F_ISREG_BIT),
@@ -628,6 +629,8 @@ enum {
REQ_F_NO_FILE_TABLE = BIT(REQ_F_NO_FILE_TABLE_BIT),
/* io_wq_work is initialized */
REQ_F_WORK_INITIALIZED = BIT(REQ_F_WORK_INITIALIZED_BIT),
+ /* linked timeout is active, i.e. prepared by link's head */
+ REQ_F_LTIMEOUT_ACTIVE = BIT(REQ_F_LTIMEOUT_ACTIVE_BIT),
};
struct async_poll {
@@ -1865,6 +1868,12 @@ static bool __io_kill_linked_timeout(struct io_kiocb *req)
link = list_first_entry(&req->link_list, struct io_kiocb, link_list);
if (link->opcode != IORING_OP_LINK_TIMEOUT)
return false;
+ /*
+ * 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;
list_del_init(&link->link_list);
wake_ev = io_link_cancel_timeout(link);
@@ -6110,10 +6119,9 @@ static enum hrtimer_restart io_link_timeout_fn(struct hrtimer *timer)
if (!list_empty(&req->link_list)) {
prev = list_entry(req->link_list.prev, struct io_kiocb,
link_list);
- if (refcount_inc_not_zero(&prev->refs)) {
+ if (refcount_inc_not_zero(&prev->refs))
list_del_init(&req->link_list);
- prev->flags &= ~REQ_F_LINK_TIMEOUT;
- } else
+ else
prev = NULL;
}
@@ -6170,6 +6178,7 @@ static struct io_kiocb *io_prep_linked_timeout(struct io_kiocb *req)
if (!nxt || nxt->opcode != IORING_OP_LINK_TIMEOUT)
return NULL;
+ nxt->flags |= REQ_F_LTIMEOUT_ACTIVE;
req->flags |= REQ_F_LINK_TIMEOUT;
return nxt;
}
--
2.24.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH 1/1] io_uring: fix racy REQ_F_LINK_TIMEOUT clearing
2020-10-19 15:39 [PATCH 1/1] io_uring: fix racy REQ_F_LINK_TIMEOUT clearing Pavel Begunkov
@ 2020-10-20 14:10 ` Jens Axboe
0 siblings, 0 replies; 2+ messages in thread
From: Jens Axboe @ 2020-10-20 14:10 UTC (permalink / raw)
To: Pavel Begunkov, io-uring
On 10/19/20 9:39 AM, Pavel Begunkov wrote:
> io_link_timeout_fn() removes REQ_F_LINK_TIMEOUT from the link head's
> flags, it's not atomic and may race with what the head is doing.
>
> If io_link_timeout_fn() doesn't clear the flag, as forced by this patch,
> then it may happen that for "req -> link_timeout1 -> link_timeout2",
> __io_kill_linked_timeout() would find link_timeout2 and try to cancel
> it, so miscounting references. Teach it to ignore such double timeouts
> by marking the active one with a new flag in io_prep_linked_timeout().
Applied, thanks.
--
Jens Axboe
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-10-20 14:10 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-10-19 15:39 [PATCH 1/1] io_uring: fix racy REQ_F_LINK_TIMEOUT clearing Pavel Begunkov
2020-10-20 14:10 ` Jens Axboe
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox