Commit 4873fa07 authored by John Stultz's avatar John Stultz Committed by Thomas Gleixner

timekeeping: Fix leapsecond triggered load spike issue

The timekeeping code misses an update of the hrtimer subsystem after a
leap second happened. Due to that timers based on CLOCK_REALTIME are
either expiring a second early or late depending on whether a leap
second has been inserted or deleted until an operation is initiated
which causes that update. Unless the update happens by some other
means this discrepancy between the timekeeping and the hrtimer data
stays forever and timers are expired either early or late.

The reported immediate workaround - $ data -s "`date`" - is causing a
call to clock_was_set() which updates the hrtimer data structures.
See: http://www.sheeri.com/content/mysql-and-leap-second-high-cpu-and-fix

Add the missing clock_was_set() call to update_wall_time() in case of
a leap second event. The actual update is deferred to softirq context
as the necessary smp function call cannot be invoked from hard
interrupt context.
Signed-off-by: default avatarJohn Stultz <johnstul@us.ibm.com>
Reported-by: default avatarJan Engelhardt <jengelh@inai.de>
Reviewed-by: default avatarIngo Molnar <mingo@kernel.org>
Acked-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: default avatarPrarit Bhargava <prarit@redhat.com>
Cc: stable@vger.kernel.org
Link: http://lkml.kernel.org/r/1341960205-56738-3-git-send-email-johnstul@us.ibm.comSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent f55a6faa
...@@ -963,6 +963,8 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) ...@@ -963,6 +963,8 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift)
leap = second_overflow(timekeeper.xtime.tv_sec); leap = second_overflow(timekeeper.xtime.tv_sec);
timekeeper.xtime.tv_sec += leap; timekeeper.xtime.tv_sec += leap;
timekeeper.wall_to_monotonic.tv_sec -= leap; timekeeper.wall_to_monotonic.tv_sec -= leap;
if (leap)
clock_was_set_delayed();
} }
/* Accumulate raw time */ /* Accumulate raw time */
...@@ -1079,6 +1081,8 @@ static void update_wall_time(void) ...@@ -1079,6 +1081,8 @@ static void update_wall_time(void)
leap = second_overflow(timekeeper.xtime.tv_sec); leap = second_overflow(timekeeper.xtime.tv_sec);
timekeeper.xtime.tv_sec += leap; timekeeper.xtime.tv_sec += leap;
timekeeper.wall_to_monotonic.tv_sec -= leap; timekeeper.wall_to_monotonic.tv_sec -= leap;
if (leap)
clock_was_set_delayed();
} }
timekeeping_update(false); timekeeping_update(false);
......
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