mirror of
https://github.com/torvalds/linux.git
synced 2026-10-22 23:01:49 +02:00
cgroup: Fixes for v7.3-rc6
- During CPU offline, the active mask drops the CPU before cpuset updates the effective CPUs, so a task placement in that window could find no active CPU in the top cpuset and dereference NULL. Restore the NULL check. - The cpuset v2-mode test read the subsystem's root pointer, which is stale during a cgroup filesystem rebind, and the hotplug handler evaluated it before taking the cpuset mutex. Record the mode in a flag and test it under the mutex. -----BEGIN PGP SIGNATURE----- iIQEABYKACwWIQTfIjM1kS57o3GsC/uxYfJx3gVYGQUCasUtqA4cdGpAa2VybmVs Lm9yZwAKCRCxYfJx3gVYGf+HAP9wEWWAp5XQUuDFaWg6Ft8iPw4Tm+b1d2w4c5il j+EGQgD/ce2FLEIu2642xuvQB4XaScJMT7G+3XZplgBsT4/jrA4= =Qa2B -----END PGP SIGNATURE----- Merge tag 'cgroup-for-7.3-rc6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup Pull cgroup fixes from Tejun Heo: - During CPU offline, the active mask drops the CPU before cpuset updates the effective CPUs, so a task placement in that window could find no active CPU in the top cpuset and dereference NULL. Restore the NULL check. - The cpuset v2-mode test read the subsystem's root pointer, which is stale during a cgroup filesystem rebind, and the hotplug handler evaluated it before taking the cpuset mutex. Record the mode in a flag and test it under the mutex. * tag 'cgroup-for-7.3-rc6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: cgroup/cpuset: Call is_in_v2_mode() after acquiring cpuset_mutex in cpuset_handle_hotplug() cgroup/cpuset: Handle cpu hotplug race in guarantee_active_cpus() cgroup/cpuset: Don't access cpuset_cgrp_subsys.root in is_in_v2_mode()
This commit is contained in:
commit
0d32b3ec5f
|
|
@ -152,6 +152,12 @@ static cpumask_var_t isolated_cpus; /* CSCB */
|
|||
*/
|
||||
static bool update_housekeeping; /* RWCS */
|
||||
|
||||
/*
|
||||
* Set if "cpuset_v2_mode" mount option is used
|
||||
* Cached at bind time and not lock protected; accessed via {READ,WRITE}_ONCE
|
||||
*/
|
||||
static bool cpuset_v2_mode;
|
||||
|
||||
/*
|
||||
* Copy of isolated_cpus to be passed to housekeeping_update()
|
||||
*/
|
||||
|
|
@ -439,8 +445,7 @@ static inline bool cpuset_v2(void)
|
|||
*/
|
||||
static inline bool is_in_v2_mode(void)
|
||||
{
|
||||
return cpuset_v2() ||
|
||||
(cpuset_cgrp_subsys.root->flags & CGRP_ROOT_CPUSET_V2_MODE);
|
||||
return cpuset_v2() || READ_ONCE(cpuset_v2_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -513,10 +518,26 @@ static void guarantee_active_cpus(struct task_struct *tsk,
|
|||
rcu_read_lock();
|
||||
cs = task_cs(tsk);
|
||||
|
||||
while (!cpumask_intersects(cs->effective_cpus, pmask))
|
||||
while (!cpumask_intersects(cs->effective_cpus, pmask)) {
|
||||
cs = parent_cs(cs);
|
||||
|
||||
if (unlikely(!cs)) {
|
||||
/*
|
||||
* The top cpuset doesn't have any active cpu as a
|
||||
* consequence of a race between its caller and the cpu
|
||||
* hotplug operation where cpu_active_mask is updated
|
||||
* asynchronously before cpuset_handle_hotplug() is
|
||||
* being called to adjust the effective_cpus of the
|
||||
* affected cpusets. But we know the top cpuset's
|
||||
* effective_cpus is on its way to be identical to
|
||||
* cpu_active_mask minus the exclusive CPUs dedicated
|
||||
* to other valid cpuset partitions. Just pass back
|
||||
* the filtered cpu_active_mask in this case.
|
||||
*/
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
cpumask_and(pmask, pmask, cs->effective_cpus);
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
|
|
@ -3732,6 +3753,8 @@ static void cpuset_bind(struct cgroup_subsys_state *root_css)
|
|||
mutex_lock(&cpuset_mutex);
|
||||
spin_lock_irq(&callback_lock);
|
||||
|
||||
WRITE_ONCE(cpuset_v2_mode,
|
||||
!!(cpuset_cgrp_subsys.root->flags & CGRP_ROOT_CPUSET_V2_MODE));
|
||||
if (is_in_v2_mode()) {
|
||||
cpumask_copy(top_cpuset.cpus_allowed, cpu_possible_mask);
|
||||
cpumask_copy(top_cpuset.effective_xcpus, cpu_possible_mask);
|
||||
|
|
@ -4044,15 +4067,16 @@ static void cpuset_handle_hotplug(void)
|
|||
static cpumask_t new_cpus;
|
||||
static nodemask_t new_mems;
|
||||
bool cpus_updated, mems_updated;
|
||||
bool on_dfl = is_in_v2_mode();
|
||||
bool on_dfl;
|
||||
struct tmpmasks tmp, *ptmp = NULL;
|
||||
|
||||
if (on_dfl && !alloc_tmpmasks(&tmp))
|
||||
ptmp = &tmp;
|
||||
|
||||
lockdep_assert_cpus_held();
|
||||
mutex_lock(&cpuset_mutex);
|
||||
|
||||
on_dfl = is_in_v2_mode();
|
||||
if (on_dfl && !alloc_tmpmasks(&tmp))
|
||||
ptmp = &tmp;
|
||||
|
||||
/* fetch the available cpus/mems and find out which changed how */
|
||||
cpumask_copy(&new_cpus, cpu_active_mask);
|
||||
new_mems = node_states[N_MEMORY];
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user