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: 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> Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1341960205-56738-3-git-send-email-johnstul@us.ibm.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
		
					parent
					
						
							
								f55a6faa38
							
						
					
				
			
			
				commit
				
					
						4873fa070a
					
				
			
		
					 1 changed files with 4 additions and 0 deletions
				
			
		|  | @ -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) | ||||||
| 		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); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 John Stultz
				John Stultz