forked from mirrors/linux
		
	hrtimer: Report offline hrtimer enqueue
The hrtimers migration on CPU-down hotplug process has been moved
earlier, before the CPU actually goes to die. This leaves a small window
of opportunity to queue an hrtimer in a blind spot, leaving it ignored.
For example a practical case has been reported with RCU waking up a
SCHED_FIFO task right before the CPUHP_AP_IDLE_DEAD stage, queuing that
way a sched/rt timer to the local offline CPU.
Make sure such situations never go unnoticed and warn when that happens.
Fixes: 5c0930ccaa ("hrtimers: Push pending hrtimers away from outgoing CPU earlier")
Reported-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20240129235646.3171983-4-boqun.feng@gmail.com
			
			
This commit is contained in:
		
							parent
							
								
									54be6c6c5a
								
							
						
					
					
						commit
						dad6a09f31
					
				
					 2 changed files with 6 additions and 1 deletions
				
			
		|  | @ -157,6 +157,7 @@ enum  hrtimer_base_type { | |||
|  * @max_hang_time:	Maximum time spent in hrtimer_interrupt | ||||
|  * @softirq_expiry_lock: Lock which is taken while softirq based hrtimer are | ||||
|  *			 expired | ||||
|  * @online:		CPU is online from an hrtimers point of view | ||||
|  * @timer_waiters:	A hrtimer_cancel() invocation waits for the timer | ||||
|  *			callback to finish. | ||||
|  * @expires_next:	absolute time of the next event, is required for remote | ||||
|  | @ -179,7 +180,8 @@ struct hrtimer_cpu_base { | |||
| 	unsigned int			hres_active		: 1, | ||||
| 					in_hrtirq		: 1, | ||||
| 					hang_detected		: 1, | ||||
| 					softirq_activated       : 1; | ||||
| 					softirq_activated       : 1, | ||||
| 					online			: 1; | ||||
| #ifdef CONFIG_HIGH_RES_TIMERS | ||||
| 	unsigned int			nr_events; | ||||
| 	unsigned short			nr_retries; | ||||
|  |  | |||
|  | @ -1085,6 +1085,7 @@ static int enqueue_hrtimer(struct hrtimer *timer, | |||
| 			   enum hrtimer_mode mode) | ||||
| { | ||||
| 	debug_activate(timer, mode); | ||||
| 	WARN_ON_ONCE(!base->cpu_base->online); | ||||
| 
 | ||||
| 	base->cpu_base->active_bases |= 1 << base->index; | ||||
| 
 | ||||
|  | @ -2183,6 +2184,7 @@ int hrtimers_prepare_cpu(unsigned int cpu) | |||
| 	cpu_base->softirq_next_timer = NULL; | ||||
| 	cpu_base->expires_next = KTIME_MAX; | ||||
| 	cpu_base->softirq_expires_next = KTIME_MAX; | ||||
| 	cpu_base->online = 1; | ||||
| 	hrtimer_cpu_base_init_expiry_lock(cpu_base); | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -2250,6 +2252,7 @@ int hrtimers_cpu_dying(unsigned int dying_cpu) | |||
| 	smp_call_function_single(ncpu, retrigger_next_event, NULL, 0); | ||||
| 
 | ||||
| 	raw_spin_unlock(&new_base->lock); | ||||
| 	old_base->online = 0; | ||||
| 	raw_spin_unlock(&old_base->lock); | ||||
| 
 | ||||
| 	return 0; | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Frederic Weisbecker
						Frederic Weisbecker