This is a pretty trivial addition on top of the relative timeouts we have now, but it's handy for ensuring tighter timing for those that are building scheduling primitives on top of io_uring.
Unified · Split
| @@ -1978,13 +1978,17 @@ static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe) · 1977 unmodified lines | |||
| 1978 | unsigned count; | 1978 | unsigned count; |
| 1979 | struct io_ring_ctx *ctx = req->ctx; | 1979 | struct io_ring_ctx *ctx = req->ctx; |
| 1980 | struct list_head *entry; | 1980 | struct list_head *entry; |
| 1981 | enum hrtimer_mode mode; | ||
| 1981 | struct timespec64 ts; | 1982 | struct timespec64 ts; |
| 1982 | unsigned span = 0; | 1983 | unsigned span = 0; |
| 1984 | unsigned flags; | ||
| 1983 | 1985 | ||
| 1984 | if (unlikely(ctx->flags & IORING_SETUP_IOPOLL)) | 1986 | if (unlikely(ctx->flags & IORING_SETUP_IOPOLL)) |
| 1985 | return -EINVAL; | 1987 | return -EINVAL; |
| 1986 | if (sqe->flags || sqe->ioprio || sqe->buf_index || sqe->timeout_flags || | 1988 | if (sqe->flags || sqe->ioprio || sqe->buf_index || sqe->len != 1) |
| 1987 | sqe->len != 1) | 1989 | return -EINVAL; |
| 1990 | flags = READ_ONCE(sqe->timeout_flags); | ||
| 1991 | if (flags & ~IORING_TIMEOUT_ABS) | ||
| 1988 | return -EINVAL; | 1992 | return -EINVAL; |
| 1989 | 1993 | ||
| 1990 | if (get_timespec64(&ts, u64_to_user_ptr(sqe->addr))) | 1994 | if (get_timespec64(&ts, u64_to_user_ptr(sqe->addr))) |
| @@ -2042,10 +2046,13 @@ static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe) · 51 unmodified lines | |||
| 2042 | list_add(&req->list, entry); | 2046 | list_add(&req->list, entry); |
| 2043 | spin_unlock_irq(&ctx->completion_lock); | 2047 | spin_unlock_irq(&ctx->completion_lock); |
| 2044 | 2048 | ||
| 2045 | hrtimer_init(&req->timeout.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | 2049 | if (flags & IORING_TIMEOUT_ABS) |
| 2050 | mode = HRTIMER_MODE_ABS; | ||
| 2051 | else | ||
| 2052 | mode = HRTIMER_MODE_REL; | ||
| 2053 | hrtimer_init(&req->timeout.timer, CLOCK_MONOTONIC, mode); | ||
| 2046 | req->timeout.timer.function = io_timeout_fn; | 2054 | req->timeout.timer.function = io_timeout_fn; |
| 2047 | hrtimer_start(&req->timeout.timer, timespec64_to_ktime(ts), | 2055 | hrtimer_start(&req->timeout.timer, timespec64_to_ktime(ts), mode); |
| 2048 | HRTIMER_MODE_REL); | ||
| 2049 | return 0; | 2056 | return 0; |
| 2050 | } | 2057 | } |
| 2051 | 2058 | ||
| @@ -70,6 +70,11 @@ struct io_uring_sqe { · 69 unmodified lines | |||
| 70 | */ | 70 | */ |
| 71 | #define IORING_FSYNC_DATASYNC (1U << 0) | 71 | #define IORING_FSYNC_DATASYNC (1U << 0) |
| 72 | 72 | ||
| 73 | /* | ||
| 74 | * sqe->timeout_flags | ||
| 75 | */ | ||
| 76 | #define IORING_TIMEOUT_ABS (1U << 0) | ||
| 77 | |||
| 73 | /* | 78 | /* |
| 74 | * IO completion data structure (Completion Queue Entry) | 79 | * IO completion data structure (Completion Queue Entry) |
| 75 | */ | 80 | */ |