#define REQ_F_TIMEOUT         1024    /* timeout request */
  #define REQ_F_ISREG           2048    /* regular file */
  #define REQ_F_MUST_PUNT               4096    /* must be punted even for NONBLOCK */
 -#define REQ_F_INFLIGHT                8192    /* on inflight list */
 -#define REQ_F_COMP_LOCKED     16384   /* completion under lock */
 +#define REQ_F_TIMEOUT_NOSEQ   8192    /* no timeout sequence */
++#define REQ_F_INFLIGHT                16384   /* on inflight list */
++#define REQ_F_COMP_LOCKED     32768   /* completion under lock */
        u64                     user_data;
        u32                     result;
        u32                     sequence;
        struct io_kiocb *req;
  
        req = list_first_entry_or_null(&ctx->timeout_list, struct io_kiocb, list);
 -      if (req && !__req_need_defer(req)) {
 -              list_del_init(&req->list);
 -              return req;
 +      if (req) {
 +              if (req->flags & REQ_F_TIMEOUT_NOSEQ)
 +                      return NULL;
-               if (!__io_sequence_defer(ctx, req)) {
++              if (!__req_need_defer(req)) {
 +                      list_del_init(&req->list);
 +                      return req;
 +              }
        }
  
        return NULL;
        if (get_timespec64(&ts, u64_to_user_ptr(sqe->addr)))
                return -EFAULT;
  
+       if (flags & IORING_TIMEOUT_ABS)
+               mode = HRTIMER_MODE_ABS;
+       else
+               mode = HRTIMER_MODE_REL;
+ 
+       hrtimer_init(&req->timeout.timer, CLOCK_MONOTONIC, mode);
 +      req->flags |= REQ_F_TIMEOUT;
  
        /*
         * sqe->off holds how many events that need to occur for this
                nxt->sequence++;
        }
        req->sequence -= span;
 +add:
        list_add(&req->list, entry);
+       req->timeout.timer.function = io_timeout_fn;
+       hrtimer_start(&req->timeout.timer, timespec64_to_ktime(ts), mode);
        spin_unlock_irq(&ctx->completion_lock);
+       return 0;
+ }
  
-       hrtimer_init(&req->timeout.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       req->timeout.timer.function = io_timeout_fn;
-       hrtimer_start(&req->timeout.timer, timespec64_to_ktime(ts),
-                       HRTIMER_MODE_REL);
+ static bool io_cancel_cb(struct io_wq_work *work, void *data)
+ {
+       struct io_kiocb *req = container_of(work, struct io_kiocb, work);
+ 
+       return req->user_data == (unsigned long) data;
+ }
+ 
+ static int io_async_cancel_one(struct io_ring_ctx *ctx, void *sqe_addr)
+ {
+       enum io_wq_cancel cancel_ret;
+       int ret = 0;
+ 
+       cancel_ret = io_wq_cancel_cb(ctx->io_wq, io_cancel_cb, sqe_addr);
+       switch (cancel_ret) {
+       case IO_WQ_CANCEL_OK:
+               ret = 0;
+               break;
+       case IO_WQ_CANCEL_RUNNING:
+               ret = -EALREADY;
+               break;
+       case IO_WQ_CANCEL_NOTFOUND:
+               ret = -ENOENT;
+               break;
+       }
+ 
+       return ret;
+ }
+ 
+ static void io_async_find_and_cancel(struct io_ring_ctx *ctx,
+                                    struct io_kiocb *req, __u64 sqe_addr,
+                                    struct io_kiocb **nxt)
+ {
+       unsigned long flags;
+       int ret;
+ 
+       ret = io_async_cancel_one(ctx, (void *) (unsigned long) sqe_addr);
+       if (ret != -ENOENT) {
+               spin_lock_irqsave(&ctx->completion_lock, flags);
+               goto done;
+       }
+ 
+       spin_lock_irqsave(&ctx->completion_lock, flags);
+       ret = io_timeout_cancel(ctx, sqe_addr);
+       if (ret != -ENOENT)
+               goto done;
+       ret = io_poll_cancel(ctx, sqe_addr);
+ done:
+       io_cqring_fill_event(req, ret);
+       io_commit_cqring(ctx);
+       spin_unlock_irqrestore(&ctx->completion_lock, flags);
+       io_cqring_ev_posted(ctx);
+ 
+       if (ret < 0 && (req->flags & REQ_F_LINK))
+               req->flags |= REQ_F_FAIL_LINK;
+       io_put_req_find_next(req, nxt);
+ }
+ 
+ static int io_async_cancel(struct io_kiocb *req, const struct io_uring_sqe *sqe,
+                          struct io_kiocb **nxt)
+ {
+       struct io_ring_ctx *ctx = req->ctx;
+ 
+       if (unlikely(ctx->flags & IORING_SETUP_IOPOLL))
+               return -EINVAL;
+       if (sqe->flags || sqe->ioprio || sqe->off || sqe->len ||
+           sqe->cancel_flags)
+               return -EINVAL;
+ 
+       io_async_find_and_cancel(ctx, req, READ_ONCE(sqe->addr), NULL);
        return 0;
  }