Skip to content

Commit 42a11bf

Browse files
Waiman-Longhtejun
authored andcommitted
cgroup/cpuset: Make cpuset_fork() handle CLONE_INTO_CGROUP properly
By default, the clone(2) syscall spawn a child process into the same cgroup as its parent. With the use of the CLONE_INTO_CGROUP flag introduced by commit ef2c41c ("clone3: allow spawning processes into cgroups"), the child will be spawned into a different cgroup which is somewhat similar to writing the child's tid into "cgroup.threads". The current cpuset_fork() method does not properly handle the CLONE_INTO_CGROUP case where the cpuset of the child may be different from that of its parent. Update the cpuset_fork() method to treat the CLONE_INTO_CGROUP case similar to cpuset_attach(). Since the newly cloned task has not been running yet, its actual memory usage isn't known. So it is not necessary to make change to mm in cpuset_fork(). Fixes: ef2c41c ("clone3: allow spawning processes into cgroups") Reported-by: Giuseppe Scrivano <gscrivan@redhat.com> Signed-off-by: Waiman Long <longman@redhat.com> Cc: stable@vger.kernel.org # v5.7+ Signed-off-by: Tejun Heo <tj@kernel.org>
1 parent ba9182a commit 42a11bf

1 file changed

Lines changed: 42 additions & 20 deletions

File tree

kernel/cgroup/cpuset.c

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2515,16 +2515,33 @@ static void cpuset_cancel_attach(struct cgroup_taskset *tset)
25152515
}
25162516

25172517
/*
2518-
* Protected by cpuset_rwsem. cpus_attach is used only by cpuset_attach()
2518+
* Protected by cpuset_rwsem. cpus_attach is used only by cpuset_attach_task()
25192519
* but we can't allocate it dynamically there. Define it global and
25202520
* allocate from cpuset_init().
25212521
*/
25222522
static cpumask_var_t cpus_attach;
2523+
static nodemask_t cpuset_attach_nodemask_to;
2524+
2525+
static void cpuset_attach_task(struct cpuset *cs, struct task_struct *task)
2526+
{
2527+
percpu_rwsem_assert_held(&cpuset_rwsem);
2528+
2529+
if (cs != &top_cpuset)
2530+
guarantee_online_cpus(task, cpus_attach);
2531+
else
2532+
cpumask_copy(cpus_attach, task_cpu_possible_mask(task));
2533+
/*
2534+
* can_attach beforehand should guarantee that this doesn't
2535+
* fail. TODO: have a better way to handle failure here
2536+
*/
2537+
WARN_ON_ONCE(set_cpus_allowed_ptr(task, cpus_attach));
2538+
2539+
cpuset_change_task_nodemask(task, &cpuset_attach_nodemask_to);
2540+
cpuset_update_task_spread_flags(cs, task);
2541+
}
25232542

25242543
static void cpuset_attach(struct cgroup_taskset *tset)
25252544
{
2526-
/* static buf protected by cpuset_rwsem */
2527-
static nodemask_t cpuset_attach_nodemask_to;
25282545
struct task_struct *task;
25292546
struct task_struct *leader;
25302547
struct cgroup_subsys_state *css;
@@ -2555,20 +2572,8 @@ static void cpuset_attach(struct cgroup_taskset *tset)
25552572

25562573
guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
25572574

2558-
cgroup_taskset_for_each(task, css, tset) {
2559-
if (cs != &top_cpuset)
2560-
guarantee_online_cpus(task, cpus_attach);
2561-
else
2562-
cpumask_copy(cpus_attach, task_cpu_possible_mask(task));
2563-
/*
2564-
* can_attach beforehand should guarantee that this doesn't
2565-
* fail. TODO: have a better way to handle failure here
2566-
*/
2567-
WARN_ON_ONCE(set_cpus_allowed_ptr(task, cpus_attach));
2568-
2569-
cpuset_change_task_nodemask(task, &cpuset_attach_nodemask_to);
2570-
cpuset_update_task_spread_flags(cs, task);
2571-
}
2575+
cgroup_taskset_for_each(task, css, tset)
2576+
cpuset_attach_task(cs, task);
25722577

25732578
/*
25742579
* Change mm for all threadgroup leaders. This is expensive and may
@@ -3266,11 +3271,28 @@ static void cpuset_bind(struct cgroup_subsys_state *root_css)
32663271
*/
32673272
static void cpuset_fork(struct task_struct *task)
32683273
{
3269-
if (task_css_is_root(task, cpuset_cgrp_id))
3274+
struct cpuset *cs;
3275+
bool same_cs;
3276+
3277+
rcu_read_lock();
3278+
cs = task_cs(task);
3279+
same_cs = (cs == task_cs(current));
3280+
rcu_read_unlock();
3281+
3282+
if (same_cs) {
3283+
if (cs == &top_cpuset)
3284+
return;
3285+
3286+
set_cpus_allowed_ptr(task, current->cpus_ptr);
3287+
task->mems_allowed = current->mems_allowed;
32703288
return;
3289+
}
32713290

3272-
set_cpus_allowed_ptr(task, current->cpus_ptr);
3273-
task->mems_allowed = current->mems_allowed;
3291+
/* CLONE_INTO_CGROUP */
3292+
percpu_down_write(&cpuset_rwsem);
3293+
guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
3294+
cpuset_attach_task(cs, task);
3295+
percpu_up_write(&cpuset_rwsem);
32743296
}
32753297

32763298
struct cgroup_subsys cpuset_cgrp_subsys = {

0 commit comments

Comments
 (0)