[PATCH] time/hrtimer: Embed hrtimer mode into hrtimer_sleeper

From: Juri Lelli
Date: Tue Jun 14 2022 - 04:58:51 EST


Changes to hrtimer mode (potentially made by __hrtimer_init_sleeper() on
PREEMPT_RT) are not visible to do_nanosleep(), thus not accounted for
by hrtimer_start_expires() call paths.

Embed hrtimer mode into hrtimer_sleeper struct, so that the same mode is
used by code following hrtimer_sleeper initialization.

Signed-off-by: Juri Lelli <juri.lelli@xxxxxxxxxx>
---
block/blk-mq.c | 2 +-
include/linux/hrtimer.h | 1 +
include/linux/wait.h | 2 +-
kernel/futex/pi.c | 2 +-
kernel/time/hrtimer.c | 7 ++++---
net/core/pktgen.c | 2 +-
6 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/block/blk-mq.c b/block/blk-mq.c
index 03235ed3a792..429d5f08a7c4 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -4672,7 +4672,7 @@ static bool blk_mq_poll_hybrid(struct request_queue *q, blk_qc_t qc)
if (blk_mq_rq_state(rq) == MQ_RQ_COMPLETE)
break;
set_current_state(TASK_UNINTERRUPTIBLE);
- hrtimer_sleeper_start_expires(&hs, mode);
+ hrtimer_sleeper_start_expires(&hs, hs.mode);
if (hs.task)
io_schedule();
hrtimer_cancel(&hs.timer);
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index d22418264bec..90f79b4e20c8 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -140,6 +140,7 @@ struct hrtimer {
struct hrtimer_sleeper {
struct hrtimer timer;
struct task_struct *task;
+ enum hrtimer_mode mode;
};

#ifdef CONFIG_64BIT
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 2d0df57c9902..b7499818f2c7 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -521,7 +521,7 @@ do { \
if ((timeout) != KTIME_MAX) \
hrtimer_start_range_ns(&__t.timer, timeout, \
current->timer_slack_ns, \
- HRTIMER_MODE_REL); \
+ __t.mode); \
\
__ret = ___wait_event(wq_head, condition, state, 0, 0, \
if (!__t.task) { \
diff --git a/kernel/futex/pi.c b/kernel/futex/pi.c
index 183b28c32c83..c576e84d96c9 100644
--- a/kernel/futex/pi.c
+++ b/kernel/futex/pi.c
@@ -1034,7 +1034,7 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl
}

if (unlikely(to))
- hrtimer_sleeper_start_expires(to, HRTIMER_MODE_ABS);
+ hrtimer_sleeper_start_expires(to, to->mode);

ret = rt_mutex_wait_proxy_lock(&q.pi_state->pi_mutex, to, &rt_waiter);

diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 0ea8702eb516..0019c802e2e8 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1996,6 +1996,7 @@ static void __hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
__hrtimer_init(&sl->timer, clock_id, mode);
sl->timer.function = hrtimer_wakeup;
sl->task = current;
+ sl->mode = mode;
}

/**
@@ -2075,7 +2076,7 @@ static long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
hrtimer_init_sleeper_on_stack(&t, restart->nanosleep.clockid,
HRTIMER_MODE_ABS);
hrtimer_set_expires_tv64(&t.timer, restart->nanosleep.expires);
- ret = do_nanosleep(&t, HRTIMER_MODE_ABS);
+ ret = do_nanosleep(&t, t.mode);
destroy_hrtimer_on_stack(&t.timer);
return ret;
}
@@ -2094,7 +2095,7 @@ long hrtimer_nanosleep(ktime_t rqtp, const enum hrtimer_mode mode,

hrtimer_init_sleeper_on_stack(&t, clockid, mode);
hrtimer_set_expires_range_ns(&t.timer, rqtp, slack);
- ret = do_nanosleep(&t, mode);
+ ret = do_nanosleep(&t, t.mode);
if (ret != -ERESTART_RESTARTBLOCK)
goto out;

@@ -2299,7 +2300,7 @@ schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta,

hrtimer_init_sleeper_on_stack(&t, clock_id, mode);
hrtimer_set_expires_range_ns(&t.timer, *expires, delta);
- hrtimer_sleeper_start_expires(&t, mode);
+ hrtimer_sleeper_start_expires(&t, t.mode);

if (likely(t.task))
schedule();
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 82c016e8c196..51eddba28c03 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2169,7 +2169,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
} else {
do {
set_current_state(TASK_INTERRUPTIBLE);
- hrtimer_sleeper_start_expires(&t, HRTIMER_MODE_ABS);
+ hrtimer_sleeper_start_expires(&t, t.mode);

if (likely(t.task))
schedule();
--
2.36.1