@@ -453,6 +453,10 @@ struct io_timeout {
453453struct io_timeout_rem {
454454 struct file * file ;
455455 u64 addr ;
456+
457+ /* timeout update */
458+ struct timespec64 ts ;
459+ u32 flags ;
456460};
457461
458462struct io_rw {
@@ -867,7 +871,10 @@ static const struct io_op_def io_op_defs[] = {
867871 .async_size = sizeof (struct io_timeout_data ),
868872 .work_flags = IO_WQ_WORK_MM ,
869873 },
870- [IORING_OP_TIMEOUT_REMOVE ] = {},
874+ [IORING_OP_TIMEOUT_REMOVE ] = {
875+ /* used by timeout updates' prep() */
876+ .work_flags = IO_WQ_WORK_MM ,
877+ },
871878 [IORING_OP_ACCEPT ] = {
872879 .needs_file = 1 ,
873880 .unbound_nonreg_file = 1 ,
@@ -5671,17 +5678,48 @@ static int io_timeout_cancel(struct io_ring_ctx *ctx, __u64 user_data)
56715678 return 0 ;
56725679}
56735680
5681+ static int io_timeout_update (struct io_ring_ctx * ctx , __u64 user_data ,
5682+ struct timespec64 * ts , enum hrtimer_mode mode )
5683+ {
5684+ struct io_kiocb * req = io_timeout_extract (ctx , user_data );
5685+ struct io_timeout_data * data ;
5686+
5687+ if (IS_ERR (req ))
5688+ return PTR_ERR (req );
5689+
5690+ req -> timeout .off = 0 ; /* noseq */
5691+ data = req -> async_data ;
5692+ list_add_tail (& req -> timeout .list , & ctx -> timeout_list );
5693+ hrtimer_init (& data -> timer , CLOCK_MONOTONIC , mode );
5694+ data -> timer .function = io_timeout_fn ;
5695+ hrtimer_start (& data -> timer , timespec64_to_ktime (* ts ), mode );
5696+ return 0 ;
5697+ }
5698+
56745699static int io_timeout_remove_prep (struct io_kiocb * req ,
56755700 const struct io_uring_sqe * sqe )
56765701{
5702+ struct io_timeout_rem * tr = & req -> timeout_rem ;
5703+
56775704 if (unlikely (req -> ctx -> flags & IORING_SETUP_IOPOLL ))
56785705 return - EINVAL ;
56795706 if (unlikely (req -> flags & (REQ_F_FIXED_FILE | REQ_F_BUFFER_SELECT )))
56805707 return - EINVAL ;
5681- if (sqe -> ioprio || sqe -> buf_index || sqe -> len || sqe -> timeout_flags )
5708+ if (sqe -> ioprio || sqe -> buf_index || sqe -> len )
5709+ return - EINVAL ;
5710+
5711+ tr -> addr = READ_ONCE (sqe -> addr );
5712+ tr -> flags = READ_ONCE (sqe -> timeout_flags );
5713+ if (tr -> flags & IORING_TIMEOUT_UPDATE ) {
5714+ if (tr -> flags & ~(IORING_TIMEOUT_UPDATE |IORING_TIMEOUT_ABS ))
5715+ return - EINVAL ;
5716+ if (get_timespec64 (& tr -> ts , u64_to_user_ptr (sqe -> addr2 )))
5717+ return - EFAULT ;
5718+ } else if (tr -> flags ) {
5719+ /* timeout removal doesn't support flags */
56825720 return - EINVAL ;
5721+ }
56835722
5684- req -> timeout_rem .addr = READ_ONCE (sqe -> addr );
56855723 return 0 ;
56865724}
56875725
@@ -5690,11 +5728,19 @@ static int io_timeout_remove_prep(struct io_kiocb *req,
56905728 */
56915729static int io_timeout_remove (struct io_kiocb * req )
56925730{
5731+ struct io_timeout_rem * tr = & req -> timeout_rem ;
56935732 struct io_ring_ctx * ctx = req -> ctx ;
56945733 int ret ;
56955734
56965735 spin_lock_irq (& ctx -> completion_lock );
5697- ret = io_timeout_cancel (ctx , req -> timeout_rem .addr );
5736+ if (req -> timeout_rem .flags & IORING_TIMEOUT_UPDATE ) {
5737+ enum hrtimer_mode mode = (tr -> flags & IORING_TIMEOUT_ABS )
5738+ ? HRTIMER_MODE_ABS : HRTIMER_MODE_REL ;
5739+
5740+ ret = io_timeout_update (ctx , tr -> addr , & tr -> ts , mode );
5741+ } else {
5742+ ret = io_timeout_cancel (ctx , tr -> addr );
5743+ }
56985744
56995745 io_cqring_fill_event (req , ret );
57005746 io_commit_cqring (ctx );
0 commit comments