aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJohn Stultz <johnstul@us.ibm.com>2012-07-17 13:33:53 -0400
committerLuis Henriques <luis.henriques@canonical.com>2012-07-23 05:50:33 -0400
commited6c4786b2e96550384d5bb7ec0c1dc352c036ca (patch)
tree5adf656513a123d5d77669523885a40f04274dd9 /kernel
parent067f56551732041e4998152a070997060f5a65e5 (diff)
timekeeping: Fix leapsecond triggered load spike issue
BugLink: http://bugs.launchpad.net/bugs/1026850 This is a backport of 4873fa070ae84a4115f0b3c9dfabc224f1bc7c51 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: John Stultz <johnstul@us.ibm.com> Reported-by: Jan Engelhardt <jengelh@inai.de> Reviewed-by: Ingo Molnar <mingo@kernel.org> Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: Prarit Bhargava <prarit@redhat.com> Link: http://lkml.kernel.org/r/1341960205-56738-3-git-send-email-johnstul@us.ibm.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Prarit Bhargava <prarit@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: John Stultz <johnstul@us.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/time/timekeeping.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 0b582ebeb7c..92014744e52 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -827,6 +827,8 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift)
827 leap = second_overflow(xtime.tv_sec); 827 leap = second_overflow(xtime.tv_sec);
828 xtime.tv_sec += leap; 828 xtime.tv_sec += leap;
829 wall_to_monotonic.tv_sec -= leap; 829 wall_to_monotonic.tv_sec -= leap;
830 if (leap)
831 clock_was_set_delayed();
830 } 832 }
831 833
832 /* Accumulate raw time */ 834 /* Accumulate raw time */
@@ -938,6 +940,8 @@ static void update_wall_time(void)
938 leap = second_overflow(xtime.tv_sec); 940 leap = second_overflow(xtime.tv_sec);
939 xtime.tv_sec += leap; 941 xtime.tv_sec += leap;
940 wall_to_monotonic.tv_sec -= leap; 942 wall_to_monotonic.tv_sec -= leap;
943 if (leap)
944 clock_was_set_delayed();
941 } 945 }
942 946
943 timekeeping_update(false); 947 timekeeping_update(false);