Skip to content

Commit 93bd25b

Browse files
committed
io_uring: make timeout sequence == 0 mean no sequence
Currently we make sequence == 0 be the same as sequence == 1, but that's not super useful if the intent is really to have a timeout that's just a pure timeout. If the user passes in sqe->off == 0, then don't apply any sequence logic to the request, let it purely be driven by the timeout specified. Reported-by: 李通洲 <[email protected]> Reviewed-by: 李通洲 <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 65de03e commit 93bd25b

File tree

1 file changed

+22
-7
lines changed

1 file changed

+22
-7
lines changed

fs/io_uring.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ struct io_kiocb {
326326
#define REQ_F_TIMEOUT 1024 /* timeout request */
327327
#define REQ_F_ISREG 2048 /* regular file */
328328
#define REQ_F_MUST_PUNT 4096 /* must be punted even for NONBLOCK */
329+
#define REQ_F_TIMEOUT_NOSEQ 8192 /* no timeout sequence */
329330
u64 user_data;
330331
u32 result;
331332
u32 sequence;
@@ -453,9 +454,13 @@ static struct io_kiocb *io_get_timeout_req(struct io_ring_ctx *ctx)
453454
struct io_kiocb *req;
454455

455456
req = list_first_entry_or_null(&ctx->timeout_list, struct io_kiocb, list);
456-
if (req && !__io_sequence_defer(ctx, req)) {
457-
list_del_init(&req->list);
458-
return req;
457+
if (req) {
458+
if (req->flags & REQ_F_TIMEOUT_NOSEQ)
459+
return NULL;
460+
if (!__io_sequence_defer(ctx, req)) {
461+
list_del_init(&req->list);
462+
return req;
463+
}
459464
}
460465

461466
return NULL;
@@ -1941,18 +1946,24 @@ static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe)
19411946
if (get_timespec64(&ts, u64_to_user_ptr(sqe->addr)))
19421947
return -EFAULT;
19431948

1949+
req->flags |= REQ_F_TIMEOUT;
1950+
19441951
/*
19451952
* sqe->off holds how many events that need to occur for this
1946-
* timeout event to be satisfied.
1953+
* timeout event to be satisfied. If it isn't set, then this is
1954+
* a pure timeout request, sequence isn't used.
19471955
*/
19481956
count = READ_ONCE(sqe->off);
1949-
if (!count)
1950-
count = 1;
1957+
if (!count) {
1958+
req->flags |= REQ_F_TIMEOUT_NOSEQ;
1959+
spin_lock_irq(&ctx->completion_lock);
1960+
entry = ctx->timeout_list.prev;
1961+
goto add;
1962+
}
19511963

19521964
req->sequence = ctx->cached_sq_head + count - 1;
19531965
/* reuse it to store the count */
19541966
req->submit.sequence = count;
1955-
req->flags |= REQ_F_TIMEOUT;
19561967

19571968
/*
19581969
* Insertion sort, ensuring the first entry in the list is always
@@ -1964,6 +1975,9 @@ static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe)
19641975
unsigned nxt_sq_head;
19651976
long long tmp, tmp_nxt;
19661977

1978+
if (nxt->flags & REQ_F_TIMEOUT_NOSEQ)
1979+
continue;
1980+
19671981
/*
19681982
* Since cached_sq_head + count - 1 can overflow, use type long
19691983
* long to store it.
@@ -1990,6 +2004,7 @@ static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe)
19902004
nxt->sequence++;
19912005
}
19922006
req->sequence -= span;
2007+
add:
19932008
list_add(&req->list, entry);
19942009
spin_unlock_irq(&ctx->completion_lock);
19952010

0 commit comments

Comments
 (0)