Skip to content

Commit 3fb906e

Browse files
Waiman-Longhtejun
authored andcommitted
cgroup/cpuset: Don't filter offline CPUs in cpuset_cpus_allowed() for top cpuset tasks
Since commit 8f9ea86 ("sched: Always preserve the user requested cpumask"), relax_compatible_cpus_allowed_ptr() is calling __sched_setaffinity() unconditionally. This helps to expose a bug in the current cpuset hotplug code where the cpumasks of the tasks in the top cpuset are not updated at all when some CPUs become online or offline. It is likely caused by the fact that some of the tasks in the top cpuset, like percpu kthreads, cannot have their cpu affinity changed. One way to reproduce this as suggested by Peter is: - boot machine - offline all CPUs except one - taskset -p ffffffff $$ - online all CPUs Fix this by allowing cpuset_cpus_allowed() to return a wider mask that includes offline CPUs for those tasks that are in the top cpuset. For tasks not in the top cpuset, the old rule applies and only online CPUs will be returned in the mask since hotplug events will update their cpumasks accordingly. Fixes: 8f9ea86 ("sched: Always preserve the user requested cpumask") Reported-by: Will Deacon <[email protected]> Originally-from: Peter Zijlstra (Intel) <[email protected]> Tested-by: Will Deacon <[email protected]> Signed-off-by: Waiman Long <[email protected]> Signed-off-by: Tejun Heo <[email protected]>
1 parent d2d11f3 commit 3fb906e

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

kernel/cgroup/cpuset.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3692,15 +3692,38 @@ void __init cpuset_init_smp(void)
36923692
* Description: Returns the cpumask_var_t cpus_allowed of the cpuset
36933693
* attached to the specified @tsk. Guaranteed to return some non-empty
36943694
* subset of cpu_online_mask, even if this means going outside the
3695-
* tasks cpuset.
3695+
* tasks cpuset, except when the task is in the top cpuset.
36963696
**/
36973697

36983698
void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask)
36993699
{
37003700
unsigned long flags;
3701+
struct cpuset *cs;
37013702

37023703
spin_lock_irqsave(&callback_lock, flags);
3703-
guarantee_online_cpus(tsk, pmask);
3704+
rcu_read_lock();
3705+
3706+
cs = task_cs(tsk);
3707+
if (cs != &top_cpuset)
3708+
guarantee_online_cpus(tsk, pmask);
3709+
/*
3710+
* Tasks in the top cpuset won't get update to their cpumasks
3711+
* when a hotplug online/offline event happens. So we include all
3712+
* offline cpus in the allowed cpu list.
3713+
*/
3714+
if ((cs == &top_cpuset) || cpumask_empty(pmask)) {
3715+
const struct cpumask *possible_mask = task_cpu_possible_mask(tsk);
3716+
3717+
/*
3718+
* We first exclude cpus allocated to partitions. If there is no
3719+
* allowable online cpu left, we fall back to all possible cpus.
3720+
*/
3721+
cpumask_andnot(pmask, possible_mask, top_cpuset.subparts_cpus);
3722+
if (!cpumask_intersects(pmask, cpu_online_mask))
3723+
cpumask_copy(pmask, possible_mask);
3724+
}
3725+
3726+
rcu_read_unlock();
37043727
spin_unlock_irqrestore(&callback_lock, flags);
37053728
}
37063729

0 commit comments

Comments
 (0)