mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	smp: have smp_call_function_single() detect invalid CPUs
Have smp_call_function_single() return invalid CPU indicies and return -ENXIO. This function is already executed inside a get_cpu()..put_cpu() which locks out CPU removal, so rather than having the higher layers doing another layer of locking to guard against unplugged CPUs do the test here. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
		
							parent
							
								
									2a61812af2
								
							
						
					
					
						commit
						f73be6dedf
					
				
					 1 changed files with 7 additions and 3 deletions
				
			
		
							
								
								
									
										10
									
								
								kernel/smp.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								kernel/smp.c
									
									
									
									
									
								
							| 
						 | 
					@ -210,8 +210,10 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct call_single_data d;
 | 
						struct call_single_data d;
 | 
				
			||||||
	unsigned long flags;
 | 
						unsigned long flags;
 | 
				
			||||||
	/* prevent preemption and reschedule on another processor */
 | 
						/* prevent preemption and reschedule on another processor,
 | 
				
			||||||
 | 
						   as well as CPU removal */
 | 
				
			||||||
	int me = get_cpu();
 | 
						int me = get_cpu();
 | 
				
			||||||
 | 
						int err = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Can deadlock when called with interrupts disabled */
 | 
						/* Can deadlock when called with interrupts disabled */
 | 
				
			||||||
	WARN_ON(irqs_disabled());
 | 
						WARN_ON(irqs_disabled());
 | 
				
			||||||
| 
						 | 
					@ -220,7 +222,7 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
 | 
				
			||||||
		local_irq_save(flags);
 | 
							local_irq_save(flags);
 | 
				
			||||||
		func(info);
 | 
							func(info);
 | 
				
			||||||
		local_irq_restore(flags);
 | 
							local_irq_restore(flags);
 | 
				
			||||||
	} else {
 | 
						} else if ((unsigned)cpu < NR_CPUS && cpu_online(cpu)) {
 | 
				
			||||||
		struct call_single_data *data = NULL;
 | 
							struct call_single_data *data = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!wait) {
 | 
							if (!wait) {
 | 
				
			||||||
| 
						 | 
					@ -236,10 +238,12 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
 | 
				
			||||||
		data->func = func;
 | 
							data->func = func;
 | 
				
			||||||
		data->info = info;
 | 
							data->info = info;
 | 
				
			||||||
		generic_exec_single(cpu, data);
 | 
							generic_exec_single(cpu, data);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							err = -ENXIO;	/* CPU not online */
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	put_cpu();
 | 
						put_cpu();
 | 
				
			||||||
	return 0;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(smp_call_function_single);
 | 
					EXPORT_SYMBOL(smp_call_function_single);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue