Commit d556d326 authored by John Stultz's avatar John Stultz Committed by Willy Tarreau

2.6.32.y: timekeeping: Fix nohz issue with commit 61b76840

Commit 61b76840 ("time: Avoid
making adjustments if we haven't accumulated anything")
introduced a regression with nohz.

Basically with kernels between 2.6.20-something to 2.6.32,
we accumulate time in half second chunks, rather then every
timer-tick. This was added because when NOHZ landed, if you
were idle for a few seconds, you had to spin for every tick
we skipped in the accumulation loop, which created some bad
latencies.

However, this required that we create the xtime_cache() which
was still updated each tick, so that filesystem timestamps,
etc continued to see time increment normally.

Of course, the xtime_cache is updated at the bottom of
update_wall_time(). So the early return on
(offset < timekeeper.cycle_interval), added by the problematic
commit causes the xtime_cache to not be updated.

This can cause code using current_kernel_time() (like the mqueue
code) or hrtimer_get_softirq_time(), which uses the non-updated
xtime_cache, to see timers to fire with very coarse half-second
granularity.

Many thanks to Romain for describing the issue clearly,
providing test case to reproduce it and helping with testing
the solution.

This change is for 2.6.32-stable ONLY!

Cc: stable@vger.kernel.org
Cc: Willy Tarreau <w@1wt.eu>
Cc: Romain Francoise <romain@orebokech.com>
Reported-by: default avatarRomain Francoise <romain@orebokech.com>
Tested-by: default avatarRomain Francoise <romain@orebokech.com>
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
parent ec2826bc
...@@ -809,7 +809,7 @@ void update_wall_time(void) ...@@ -809,7 +809,7 @@ void update_wall_time(void)
#endif #endif
/* Check if there's really nothing to do */ /* Check if there's really nothing to do */
if (offset < timekeeper.cycle_interval) if (offset < timekeeper.cycle_interval)
return; goto out;
timekeeper.xtime_nsec = (s64)xtime.tv_nsec << timekeeper.shift; timekeeper.xtime_nsec = (s64)xtime.tv_nsec << timekeeper.shift;
...@@ -881,6 +881,7 @@ void update_wall_time(void) ...@@ -881,6 +881,7 @@ void update_wall_time(void)
timekeeper.ntp_error += timekeeper.xtime_nsec << timekeeper.ntp_error += timekeeper.xtime_nsec <<
timekeeper.ntp_error_shift; timekeeper.ntp_error_shift;
out:
nsecs = clocksource_cyc2ns(offset, timekeeper.mult, timekeeper.shift); nsecs = clocksource_cyc2ns(offset, timekeeper.mult, timekeeper.shift);
update_xtime_cache(nsecs); update_xtime_cache(nsecs);
......
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