io_uring: correct timeout req sequence when inserting a new entry
authorzhangyi (F) <yi.zhang@huawei.com>
Wed, 23 Oct 2019 07:10:09 +0000 (15:10 +0800)
committerJens Axboe <axboe@kernel.dk>
Thu, 24 Oct 2019 04:09:56 +0000 (22:09 -0600)
The sequence number of the timeout req (req->sequence) indicate the
expected completion request. Because of each timeout req consume a
sequence number, so the sequence of each timeout req on the timeout
list shouldn't be the same. But now, we may get the same number (also
incorrect) if we insert a new entry before the last one, such as submit
such two timeout reqs on a new ring instance below.

                    req->sequence
 req_1 (count = 2):       2
 req_2 (count = 1):       2

Then, if we submit a nop req, req_2 will still timeout even the nop req
finished. This patch fix this problem by adjust the sequence number of
each reordered reqs when inserting a new entry.

Signed-off-by: zhangyi (F) <yi.zhang@huawei.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/io_uring.c

index b65a685..1b46c72 100644 (file)
@@ -1912,6 +1912,7 @@ static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        struct io_ring_ctx *ctx = req->ctx;
        struct list_head *entry;
        struct timespec64 ts;
+       unsigned span = 0;
 
        if (unlikely(ctx->flags & IORING_SETUP_IOPOLL))
                return -EINVAL;
@@ -1960,9 +1961,17 @@ static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe)
                if (ctx->cached_sq_head < nxt_sq_head)
                        tmp += UINT_MAX;
 
-               if (tmp >= tmp_nxt)
+               if (tmp > tmp_nxt)
                        break;
+
+               /*
+                * Sequence of reqs after the insert one and itself should
+                * be adjusted because each timeout req consumes a slot.
+                */
+               span++;
+               nxt->sequence++;
        }
+       req->sequence -= span;
        list_add(&req->list, entry);
        spin_unlock_irq(&ctx->completion_lock);