[RFC PATCH v2 2/8] timekeeping: Account for clawback adjustment in ntp_error
From: David Woodhouse
Date: Sun May 17 2026 - 18:03:52 EST
From: David Woodhouse <dwmw@xxxxxxxxxxxx>
timekeeping_apply_adjustment() modifies xtime_nsec to maintain vDSO
monotonicity when mult changes:
xtime_nsec -= offset
This ensures that the time reported to userspace doesn't jump when the
multiplier is adjusted. However, ntp_error — which tracks the difference
between intended and actual clock position — was not updated to reflect
this change.
After a mult change, xtime_nsec has moved but ntp_error still reflects
the old position. For the normal ±1 dithering this is negligible (the
adjustments cancel over time), but for larger mult changes — such as
when an external reference clock sets a new frequency — the one-time
uncompensated offset is significant (~38ns for a 700-count mult change).
Fix by adjusting ntp_error by the same amount:
ntp_error += offset << ntp_error_shift
This keeps ntp_error consistent with the actual xtime_nsec position
after the clawback.
Fixes: 1b1b3e2a3671 ("timekeeping: Rework frequency adjustments to work better w/ nohz")
Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx>
---
kernel/time/timekeeping.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 3da7167ceb0d..050123fc179b 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2317,6 +2317,7 @@ static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk,
tk->tkr_mono.mult += mult_adj;
tk->xtime_interval += interval;
tk->tkr_mono.xtime_nsec -= offset;
+ tk->ntp_error += offset << tk->ntp_error_shift;
}
/*
--
2.51.0