diff options
Diffstat (limited to 'kernel/sched/core.c')
| -rw-r--r-- | kernel/sched/core.c | 28 | 
1 files changed, 19 insertions, 9 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 3a673a3b0c6..053dfd7692d 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1132,18 +1132,28 @@ EXPORT_SYMBOL_GPL(kick_process);   */  static int select_fallback_rq(int cpu, struct task_struct *p)  { -	const struct cpumask *nodemask = cpumask_of_node(cpu_to_node(cpu)); +	int nid = cpu_to_node(cpu); +	const struct cpumask *nodemask = NULL;  	enum { cpuset, possible, fail } state = cpuset;  	int dest_cpu; -	/* Look for allowed, online CPU in same node. */ -	for_each_cpu(dest_cpu, nodemask) { -		if (!cpu_online(dest_cpu)) -			continue; -		if (!cpu_active(dest_cpu)) -			continue; -		if (cpumask_test_cpu(dest_cpu, tsk_cpus_allowed(p))) -			return dest_cpu; +	/* +	 * If the node that the cpu is on has been offlined, cpu_to_node() +	 * will return -1. There is no cpu on the node, and we should +	 * select the cpu on the other node. +	 */ +	if (nid != -1) { +		nodemask = cpumask_of_node(nid); + +		/* Look for allowed, online CPU in same node. */ +		for_each_cpu(dest_cpu, nodemask) { +			if (!cpu_online(dest_cpu)) +				continue; +			if (!cpu_active(dest_cpu)) +				continue; +			if (cpumask_test_cpu(dest_cpu, tsk_cpus_allowed(p))) +				return dest_cpu; +		}  	}  	for (;;) {  |