Commit 22833966 authored by Jens Axboe's avatar Jens Axboe

io_uring: don't convert to jiffies for waiting on timeouts

If an application calls io_uring_enter(2) with a timespec passed in,
convert that timespec to ktime_t rather than jiffies. The latter does
not provide the granularity the application may expect, and may in
fact provided different granularity on different systems, depending
on what the HZ value is configured at.

Turn the timespec into an absolute ktime_t, and use that with
schedule_hrtimeout() instead.

Link: https://github.com/axboe/liburing/issues/531
Cc: stable@vger.kernel.org
Reported-by: default avatarBob Chen <chenbo.chen@alibaba-inc.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent f240762f
...@@ -7694,7 +7694,7 @@ static int io_run_task_work_sig(void) ...@@ -7694,7 +7694,7 @@ static int io_run_task_work_sig(void)
/* when returns >0, the caller should retry */ /* when returns >0, the caller should retry */
static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx, static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx,
struct io_wait_queue *iowq, struct io_wait_queue *iowq,
signed long *timeout) ktime_t timeout)
{ {
int ret; int ret;
...@@ -7706,8 +7706,9 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx, ...@@ -7706,8 +7706,9 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx,
if (test_bit(0, &ctx->check_cq_overflow)) if (test_bit(0, &ctx->check_cq_overflow))
return 1; return 1;
*timeout = schedule_timeout(*timeout); if (!schedule_hrtimeout(&timeout, HRTIMER_MODE_ABS))
return !*timeout ? -ETIME : 1; return -ETIME;
return 1;
} }
/* /*
...@@ -7720,7 +7721,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, ...@@ -7720,7 +7721,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
{ {
struct io_wait_queue iowq; struct io_wait_queue iowq;
struct io_rings *rings = ctx->rings; struct io_rings *rings = ctx->rings;
signed long timeout = MAX_SCHEDULE_TIMEOUT; ktime_t timeout = KTIME_MAX;
int ret; int ret;
do { do {
...@@ -7736,7 +7737,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, ...@@ -7736,7 +7737,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
if (get_timespec64(&ts, uts)) if (get_timespec64(&ts, uts))
return -EFAULT; return -EFAULT;
timeout = timespec64_to_jiffies(&ts); timeout = ktime_add_ns(timespec64_to_ktime(ts), ktime_get_ns());
} }
if (sig) { if (sig) {
...@@ -7768,7 +7769,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, ...@@ -7768,7 +7769,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
} }
prepare_to_wait_exclusive(&ctx->cq_wait, &iowq.wq, prepare_to_wait_exclusive(&ctx->cq_wait, &iowq.wq,
TASK_INTERRUPTIBLE); TASK_INTERRUPTIBLE);
ret = io_cqring_wait_schedule(ctx, &iowq, &timeout); ret = io_cqring_wait_schedule(ctx, &iowq, timeout);
finish_wait(&ctx->cq_wait, &iowq.wq); finish_wait(&ctx->cq_wait, &iowq.wq);
cond_resched(); cond_resched();
} while (ret > 0); } while (ret > 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment