@@ -394,7 +394,8 @@ struct io_timeout {
394
394
struct file * file ;
395
395
u64 addr ;
396
396
int flags ;
397
- u32 count ;
397
+ u32 off ;
398
+ u32 target_seq ;
398
399
};
399
400
400
401
struct io_rw {
@@ -1124,8 +1125,10 @@ static void io_flush_timeouts(struct io_ring_ctx *ctx)
1124
1125
1125
1126
if (req -> flags & REQ_F_TIMEOUT_NOSEQ )
1126
1127
break ;
1127
- if (__req_need_defer (req ))
1128
+ if (req -> timeout .target_seq != ctx -> cached_cq_tail
1129
+ - atomic_read (& ctx -> cq_timeouts ))
1128
1130
break ;
1131
+
1129
1132
list_del_init (& req -> list );
1130
1133
io_kill_timeout (req );
1131
1134
}
@@ -4660,20 +4663,8 @@ static enum hrtimer_restart io_timeout_fn(struct hrtimer *timer)
4660
4663
* We could be racing with timeout deletion. If the list is empty,
4661
4664
* then timeout lookup already found it and will be handling it.
4662
4665
*/
4663
- if (!list_empty (& req -> list )) {
4664
- struct io_kiocb * prev ;
4665
-
4666
- /*
4667
- * Adjust the reqs sequence before the current one because it
4668
- * will consume a slot in the cq_ring and the cq_tail
4669
- * pointer will be increased, otherwise other timeout reqs may
4670
- * return in advance without waiting for enough wait_nr.
4671
- */
4672
- prev = req ;
4673
- list_for_each_entry_continue_reverse (prev , & ctx -> timeout_list , list )
4674
- prev -> sequence ++ ;
4666
+ if (!list_empty (& req -> list ))
4675
4667
list_del_init (& req -> list );
4676
- }
4677
4668
4678
4669
io_cqring_fill_event (req , - ETIME );
4679
4670
io_commit_cqring (ctx );
@@ -4765,7 +4756,7 @@ static int io_timeout_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe,
4765
4756
if (flags & ~IORING_TIMEOUT_ABS )
4766
4757
return - EINVAL ;
4767
4758
4768
- req -> timeout .count = off ;
4759
+ req -> timeout .off = off ;
4769
4760
4770
4761
if (!req -> io && io_alloc_async_ctx (req ))
4771
4762
return - ENOMEM ;
@@ -4789,67 +4780,39 @@ static int io_timeout_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe,
4789
4780
static int io_timeout (struct io_kiocb * req )
4790
4781
{
4791
4782
struct io_ring_ctx * ctx = req -> ctx ;
4792
- struct io_timeout_data * data ;
4783
+ struct io_timeout_data * data = & req -> io -> timeout ;
4793
4784
struct list_head * entry ;
4794
- unsigned span = 0 ;
4795
- u32 count = req -> timeout .count ;
4796
- u32 seq = req -> sequence ;
4785
+ u32 tail , off = req -> timeout .off ;
4797
4786
4798
- data = & req -> io -> timeout ;
4799
4787
spin_lock_irq (& ctx -> completion_lock );
4800
4788
4801
4789
/*
4802
4790
* sqe->off holds how many events that need to occur for this
4803
4791
* timeout event to be satisfied. If it isn't set, then this is
4804
4792
* a pure timeout request, sequence isn't used.
4805
4793
*/
4806
- if (!count ) {
4794
+ if (!off ) {
4807
4795
req -> flags |= REQ_F_TIMEOUT_NOSEQ ;
4808
4796
entry = ctx -> timeout_list .prev ;
4809
4797
goto add ;
4810
4798
}
4811
4799
4812
- req -> sequence = seq + count ;
4800
+ tail = ctx -> cached_cq_tail - atomic_read (& ctx -> cq_timeouts );
4801
+ req -> timeout .target_seq = tail + off ;
4813
4802
4814
4803
/*
4815
4804
* Insertion sort, ensuring the first entry in the list is always
4816
4805
* the one we need first.
4817
4806
*/
4818
4807
list_for_each_prev (entry , & ctx -> timeout_list ) {
4819
4808
struct io_kiocb * nxt = list_entry (entry , struct io_kiocb , list );
4820
- unsigned nxt_seq ;
4821
- long long tmp , tmp_nxt ;
4822
- u32 nxt_offset = nxt -> timeout .count ;
4823
4809
4824
4810
if (nxt -> flags & REQ_F_TIMEOUT_NOSEQ )
4825
4811
continue ;
4826
-
4827
- /*
4828
- * Since seq + count can overflow, use type long
4829
- * long to store it.
4830
- */
4831
- tmp = (long long )seq + count ;
4832
- nxt_seq = nxt -> sequence - nxt_offset ;
4833
- tmp_nxt = (long long )nxt_seq + nxt_offset ;
4834
-
4835
- /*
4836
- * cached_sq_head may overflow, and it will never overflow twice
4837
- * once there is some timeout req still be valid.
4838
- */
4839
- if (seq < nxt_seq )
4840
- tmp += UINT_MAX ;
4841
-
4842
- if (tmp > tmp_nxt )
4812
+ /* nxt.seq is behind @tail, otherwise would've been completed */
4813
+ if (off >= nxt -> timeout .target_seq - tail )
4843
4814
break ;
4844
-
4845
- /*
4846
- * Sequence of reqs after the insert one and itself should
4847
- * be adjusted because each timeout req consumes a slot.
4848
- */
4849
- span ++ ;
4850
- nxt -> sequence ++ ;
4851
4815
}
4852
- req -> sequence -= span ;
4853
4816
add :
4854
4817
list_add (& req -> list , entry );
4855
4818
data -> timer .function = io_timeout_fn ;
0 commit comments