kernel/time/timekeeping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
The addition of the bases argument to clock_was_set() fixed up all call
sites correctly except for do_adjtimex(). This uses CLOCK_REALTIME
instead of CLOCK_SET_WALL as argument. CLOCK_REALTIME is 0.
As a result the effect of that clock_was_set() notification is incomplete
and might result in timers expiring late because the hrtimer code does
not re-evaluate the affected clock bases.
Use CLOCK_SET_WALL instead of CLOCK_REALTIME to tell the hrtimers code
which clock bases need to be re-evaluated.
Fixes: 17a1b8826b45 ("hrtimer: Add bases argument to clock_was_set()")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <jstultz@google.com>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: stable@vger.kernel.org
---
kernel/time/timekeeping.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2606,7 +2606,7 @@ int do_adjtimex(struct __kernel_timex *t
clock_set |= timekeeping_advance(TK_ADV_FREQ);
if (clock_set)
- clock_was_set(CLOCK_REALTIME);
+ clock_was_set(CLOCK_SET_WALL);
ntp_notify_cmos_timer();
On Sat, Aug 3, 2024 at 8:07 AM Thomas Gleixner <tglx@linutronix.de> wrote: > > The addition of the bases argument to clock_was_set() fixed up all call > sites correctly except for do_adjtimex(). This uses CLOCK_REALTIME > instead of CLOCK_SET_WALL as argument. CLOCK_REALTIME is 0. > > As a result the effect of that clock_was_set() notification is incomplete > and might result in timers expiring late because the hrtimer code does > not re-evaluate the affected clock bases. > > Use CLOCK_SET_WALL instead of CLOCK_REALTIME to tell the hrtimers code > which clock bases need to be re-evaluated. Acked-by: John Stultz <jstultz@google.com> My only thought here is maybe renaming CLOCK_SET_WALL and CLOCK_SET_BOOT to something like: BASEMASK_WALL_CLOCK_SET and BASEMASK_BOOT_CLOCK_SET Just to avoid future naming mixups or confusion with clockids? thanks -john
On Mon, Aug 05 2024 at 10:50, John Stultz wrote:
> On Sat, Aug 3, 2024 at 8:07 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>>
>> The addition of the bases argument to clock_was_set() fixed up all call
>> sites correctly except for do_adjtimex(). This uses CLOCK_REALTIME
>> instead of CLOCK_SET_WALL as argument. CLOCK_REALTIME is 0.
>>
>> As a result the effect of that clock_was_set() notification is incomplete
>> and might result in timers expiring late because the hrtimer code does
>> not re-evaluate the affected clock bases.
>>
>> Use CLOCK_SET_WALL instead of CLOCK_REALTIME to tell the hrtimers code
>> which clock bases need to be re-evaluated.
>
> Acked-by: John Stultz <jstultz@google.com>
>
> My only thought here is maybe renaming CLOCK_SET_WALL and
> CLOCK_SET_BOOT to something like:
> BASEMASK_WALL_CLOCK_SET and BASEMASK_BOOT_CLOCK_SET
>
> Just to avoid future naming mixups or confusion with clockids?
Makes sense. Care to whip up a patch?
Thanks,
tglx
In commit 5916be8a53de ("timekeeping: Fix bogus clock_was_set()
invocation in do_adjtimex()"), Thomas fixed a bug where instead
of passing one of the CLOCK_SET_* values to clock_was_set(),a
conceptually related clockid (CLOCK_REALTIME) was incorrectly
passed.
Just to make this type of accident less likely, lets rename the
base masks used by clock_was_set() to something that doesn't
resemble a clockid.
Thus:
CLOCK_SET_WALL -> BASEMASK_WALL_CLOCK_SET
CLOCK_SET_BOOT -> BASEMASK_BOOT_CLOCK_SET
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Anna-Maria Behnsen <anna-maria@linutronix.de>
Cc: Frederic Weisbecker <frederic@kernel.org>
Signed-off-by: John Stultz <jstultz@google.com>
---
kernel/time/hrtimer.c | 2 +-
kernel/time/tick-internal.h | 4 ++--
kernel/time/timekeeping.c | 8 ++++----
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index b8ee320208d41..ca18a2a344294 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -980,7 +980,7 @@ void clock_was_set(unsigned int bases)
static void clock_was_set_work(struct work_struct *work)
{
- clock_was_set(CLOCK_SET_WALL);
+ clock_was_set(BASEMASK_WALL_CLOCK_SET);
}
static DECLARE_WORK(hrtimer_work, clock_was_set_work);
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index 5f2105e637bdf..59a6e50734f40 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -181,11 +181,11 @@ extern u64 get_next_timer_interrupt(unsigned long basej, u64 basem);
u64 timer_base_try_to_set_idle(unsigned long basej, u64 basem, bool *idle);
void timer_clear_idle(void);
-#define CLOCK_SET_WALL \
+#define BASEMASK_WALL_CLOCK_SET \
(BIT(HRTIMER_BASE_REALTIME) | BIT(HRTIMER_BASE_REALTIME_SOFT) | \
BIT(HRTIMER_BASE_TAI) | BIT(HRTIMER_BASE_TAI_SOFT))
-#define CLOCK_SET_BOOT \
+#define BASEMASK_BOOT_CLOCK_SET \
(BIT(HRTIMER_BASE_BOOTTIME) | BIT(HRTIMER_BASE_BOOTTIME_SOFT))
void clock_was_set(unsigned int bases);
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 5391e4167d602..c8108345438aa 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1471,7 +1471,7 @@ int do_settimeofday64(const struct timespec64 *ts)
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
/* Signal hrtimers about time change */
- clock_was_set(CLOCK_SET_WALL);
+ clock_was_set(BASEMASK_WALL_CLOCK_SET);
if (!ret) {
audit_tk_injoffset(ts_delta);
@@ -1521,7 +1521,7 @@ static int timekeeping_inject_offset(const struct timespec64 *ts)
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
/* Signal hrtimers about time change */
- clock_was_set(CLOCK_SET_WALL);
+ clock_was_set(BASEMASK_WALL_CLOCK_SET);
return ret;
}
@@ -1896,7 +1896,7 @@ void timekeeping_inject_sleeptime64(const struct timespec64 *delta)
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
/* Signal hrtimers about time change */
- clock_was_set(CLOCK_SET_WALL | CLOCK_SET_BOOT);
+ clock_was_set(BASEMASK_WALL_CLOCK_SET | BASEMASK_BOOT_CLOCK_SET);
}
#endif
@@ -2606,7 +2606,7 @@ int do_adjtimex(struct __kernel_timex *txc)
clock_set |= timekeeping_advance(TK_ADV_FREQ);
if (clock_set)
- clock_was_set(CLOCK_SET_WALL);
+ clock_was_set(BASEMASK_WALL_CLOCK_SET);
ntp_notify_cmos_timer();
--
2.46.0.184.g6999bdac58-goog
On Thu, Aug 15 2024 at 13:03, John Stultz wrote:
> In commit 5916be8a53de ("timekeeping: Fix bogus clock_was_set()
> invocation in do_adjtimex()"), Thomas fixed a bug where instead
> of passing one of the CLOCK_SET_* values to clock_was_set(),a
> conceptually related clockid (CLOCK_REALTIME) was incorrectly
> passed.
>
> Just to make this type of accident less likely, lets rename the
s/lets//
> base masks used by clock_was_set() to something that doesn't
> resemble a clockid.
>
> Thus:
> CLOCK_SET_WALL -> BASEMASK_WALL_CLOCK_SET
> CLOCK_SET_BOOT -> BASEMASK_BOOT_CLOCK_SET
I don't think that's the actual problem. What's the confusing part is
the function name itself clock_was_set().
Renaming that to at the same time to something unambiguous would be
helpful.
hrtimer_refresh_bases() or something like that should be descriptive
enough.
Thanks,
tglx
The following commit has been merged into the timers/urgent branch of tip:
Commit-ID: 5916be8a53de6401871bdd953f6c60237b47d6d3
Gitweb: https://git.kernel.org/tip/5916be8a53de6401871bdd953f6c60237b47d6d3
Author: Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sat, 03 Aug 2024 17:07:51 +02:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Mon, 05 Aug 2024 16:14:14 +02:00
timekeeping: Fix bogus clock_was_set() invocation in do_adjtimex()
The addition of the bases argument to clock_was_set() fixed up all call
sites correctly except for do_adjtimex(). This uses CLOCK_REALTIME
instead of CLOCK_SET_WALL as argument. CLOCK_REALTIME is 0.
As a result the effect of that clock_was_set() notification is incomplete
and might result in timers expiring late because the hrtimer code does
not re-evaluate the affected clock bases.
Use CLOCK_SET_WALL instead of CLOCK_REALTIME to tell the hrtimers code
which clock bases need to be re-evaluated.
Fixes: 17a1b8826b45 ("hrtimer: Add bases argument to clock_was_set()")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/all/877ccx7igo.ffs@tglx
---
kernel/time/timekeeping.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 2fa87dc..5391e41 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2606,7 +2606,7 @@ int do_adjtimex(struct __kernel_timex *txc)
clock_set |= timekeeping_advance(TK_ADV_FREQ);
if (clock_set)
- clock_was_set(CLOCK_REALTIME);
+ clock_was_set(CLOCK_SET_WALL);
ntp_notify_cmos_timer();
© 2016 - 2025 Red Hat, Inc.