mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	cpumask/hotplug: Fix cpu_dying() state tracking
Vincent reported that for states with a NULL startup/teardown function we do not call cpuhp_invoke_callback() (because there is none) and as such we'll not update the cpu_dying() state. The stale cpu_dying() can eventually lead to triggering BUG(). Rectify this by updating cpu_dying() in the exact same places the hotplug machinery tracks its directional state, namely cpuhp_set_state() and cpuhp_reset_state(). Reported-by: Vincent Donnefort <vincent.donnefort@arm.com> Suggested-by: Vincent Donnefort <vincent.donnefort@arm.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Vincent Donnefort <vincent.donnefort@arm.com> Reviewed-by: Valentin Schneider <valentin.schneider@arm.com> Link: https://lkml.kernel.org/r/YH7r+AoQEReSvxBI@hirez.programming.kicks-ass.net
This commit is contained in:
		
							parent
							
								
									3a7956e25e
								
							
						
					
					
						commit
						2ea46c6fc9
					
				
					 1 changed files with 11 additions and 5 deletions
				
			
		
							
								
								
									
										16
									
								
								kernel/cpu.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								kernel/cpu.c
									
									
									
									
									
								
							|  | @ -63,6 +63,7 @@ struct cpuhp_cpu_state { | ||||||
| 	bool			rollback; | 	bool			rollback; | ||||||
| 	bool			single; | 	bool			single; | ||||||
| 	bool			bringup; | 	bool			bringup; | ||||||
|  | 	int			cpu; | ||||||
| 	struct hlist_node	*node; | 	struct hlist_node	*node; | ||||||
| 	struct hlist_node	*last; | 	struct hlist_node	*last; | ||||||
| 	enum cpuhp_state	cb_state; | 	enum cpuhp_state	cb_state; | ||||||
|  | @ -160,9 +161,6 @@ static int cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state state, | ||||||
| 	int (*cb)(unsigned int cpu); | 	int (*cb)(unsigned int cpu); | ||||||
| 	int ret, cnt; | 	int ret, cnt; | ||||||
| 
 | 
 | ||||||
| 	if (cpu_dying(cpu) != !bringup) |  | ||||||
| 		set_cpu_dying(cpu, !bringup); |  | ||||||
| 
 |  | ||||||
| 	if (st->fail == state) { | 	if (st->fail == state) { | ||||||
| 		st->fail = CPUHP_INVALID; | 		st->fail = CPUHP_INVALID; | ||||||
| 		return -EAGAIN; | 		return -EAGAIN; | ||||||
|  | @ -467,13 +465,16 @@ static inline enum cpuhp_state | ||||||
| cpuhp_set_state(struct cpuhp_cpu_state *st, enum cpuhp_state target) | cpuhp_set_state(struct cpuhp_cpu_state *st, enum cpuhp_state target) | ||||||
| { | { | ||||||
| 	enum cpuhp_state prev_state = st->state; | 	enum cpuhp_state prev_state = st->state; | ||||||
|  | 	bool bringup = st->state < target; | ||||||
| 
 | 
 | ||||||
| 	st->rollback = false; | 	st->rollback = false; | ||||||
| 	st->last = NULL; | 	st->last = NULL; | ||||||
| 
 | 
 | ||||||
| 	st->target = target; | 	st->target = target; | ||||||
| 	st->single = false; | 	st->single = false; | ||||||
| 	st->bringup = st->state < target; | 	st->bringup = bringup; | ||||||
|  | 	if (cpu_dying(st->cpu) != !bringup) | ||||||
|  | 		set_cpu_dying(st->cpu, !bringup); | ||||||
| 
 | 
 | ||||||
| 	return prev_state; | 	return prev_state; | ||||||
| } | } | ||||||
|  | @ -481,6 +482,8 @@ cpuhp_set_state(struct cpuhp_cpu_state *st, enum cpuhp_state target) | ||||||
| static inline void | static inline void | ||||||
| cpuhp_reset_state(struct cpuhp_cpu_state *st, enum cpuhp_state prev_state) | cpuhp_reset_state(struct cpuhp_cpu_state *st, enum cpuhp_state prev_state) | ||||||
| { | { | ||||||
|  | 	bool bringup = !st->bringup; | ||||||
|  | 
 | ||||||
| 	st->target = prev_state; | 	st->target = prev_state; | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
|  | @ -503,7 +506,9 @@ cpuhp_reset_state(struct cpuhp_cpu_state *st, enum cpuhp_state prev_state) | ||||||
| 			st->state++; | 			st->state++; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	st->bringup = !st->bringup; | 	st->bringup = bringup; | ||||||
|  | 	if (cpu_dying(st->cpu) != !bringup) | ||||||
|  | 		set_cpu_dying(st->cpu, !bringup); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Regular hotplug invocation of the AP hotplug thread */ | /* Regular hotplug invocation of the AP hotplug thread */ | ||||||
|  | @ -693,6 +698,7 @@ static void cpuhp_create(unsigned int cpu) | ||||||
| 
 | 
 | ||||||
| 	init_completion(&st->done_up); | 	init_completion(&st->done_up); | ||||||
| 	init_completion(&st->done_down); | 	init_completion(&st->done_down); | ||||||
|  | 	st->cpu = cpu; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int cpuhp_should_run(unsigned int cpu) | static int cpuhp_should_run(unsigned int cpu) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Peter Zijlstra
						Peter Zijlstra