Skip to content

Commit 22cad15

Browse files
isilenceaxboe
authored andcommitted
io_uring: fix cached_sq_head in io_timeout()
io_timeout() can be executed asynchronously by a worker and without holding ctx->uring_lock 1. using ctx->cached_sq_head there is racy there 2. it should count events from a moment of timeout's submission, but not execution Use req->sequence. Signed-off-by: Pavel Begunkov <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 8e2e1fa commit 22cad15

File tree

1 file changed

+8
-7
lines changed

1 file changed

+8
-7
lines changed

fs/io_uring.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4714,6 +4714,7 @@ static int io_timeout(struct io_kiocb *req)
47144714
struct io_timeout_data *data;
47154715
struct list_head *entry;
47164716
unsigned span = 0;
4717+
u32 seq = req->sequence;
47174718

47184719
data = &req->io->timeout;
47194720

@@ -4730,7 +4731,7 @@ static int io_timeout(struct io_kiocb *req)
47304731
goto add;
47314732
}
47324733

4733-
req->sequence = ctx->cached_sq_head + count - 1;
4734+
req->sequence = seq + count;
47344735
data->seq_offset = count;
47354736

47364737
/*
@@ -4740,26 +4741,26 @@ static int io_timeout(struct io_kiocb *req)
47404741
spin_lock_irq(&ctx->completion_lock);
47414742
list_for_each_prev(entry, &ctx->timeout_list) {
47424743
struct io_kiocb *nxt = list_entry(entry, struct io_kiocb, list);
4743-
unsigned nxt_sq_head;
4744+
unsigned nxt_seq;
47444745
long long tmp, tmp_nxt;
47454746
u32 nxt_offset = nxt->io->timeout.seq_offset;
47464747

47474748
if (nxt->flags & REQ_F_TIMEOUT_NOSEQ)
47484749
continue;
47494750

47504751
/*
4751-
* Since cached_sq_head + count - 1 can overflow, use type long
4752+
* Since seq + count can overflow, use type long
47524753
* long to store it.
47534754
*/
4754-
tmp = (long long)ctx->cached_sq_head + count - 1;
4755-
nxt_sq_head = nxt->sequence - nxt_offset + 1;
4756-
tmp_nxt = (long long)nxt_sq_head + nxt_offset - 1;
4755+
tmp = (long long)seq + count;
4756+
nxt_seq = nxt->sequence - nxt_offset;
4757+
tmp_nxt = (long long)nxt_seq + nxt_offset;
47574758

47584759
/*
47594760
* cached_sq_head may overflow, and it will never overflow twice
47604761
* once there is some timeout req still be valid.
47614762
*/
4762-
if (ctx->cached_sq_head < nxt_sq_head)
4763+
if (seq < nxt_seq)
47634764
tmp += UINT_MAX;
47644765

47654766
if (tmp > tmp_nxt)

0 commit comments

Comments
 (0)