diff options
author | John Stultz <john.stultz@linaro.org> | 2013-01-28 12:01:40 -0800 |
---|---|---|
committer | Willy Tarreau <w@1wt.eu> | 2013-06-10 11:42:12 +0200 |
commit | d556d3262945a9f7733c0c2cf70be5ac0c358254 (patch) | |
tree | 1dc8f2bac25c21e51244b87fc52a0b5e2e714d30 /kernel | |
parent | ec2826bc2f8c9874284080a9cda657c4c1dc948e (diff) |
2.6.32.y: timekeeping: Fix nohz issue with commit 61b76840ddee647c0c223365378c3f394355b7d7
Commit 61b76840ddee647c0c223365378c3f394355b7d7 ("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: Romain Francoise <romain@orebokech.com>
Tested-by: Romain Francoise <romain@orebokech.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/time/timekeeping.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 3d35af308f6b..f65a0fb37251 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -809,7 +809,7 @@ void update_wall_time(void) #endif /* Check if there's really nothing to do */ if (offset < timekeeper.cycle_interval) - return; + goto out; timekeeper.xtime_nsec = (s64)xtime.tv_nsec << timekeeper.shift; @@ -881,6 +881,7 @@ void update_wall_time(void) timekeeper.ntp_error += timekeeper.xtime_nsec << timekeeper.ntp_error_shift; +out: nsecs = clocksource_cyc2ns(offset, timekeeper.mult, timekeeper.shift); update_xtime_cache(nsecs); |