diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 53e81a61be57..74e8b8e4cd7f 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -281,6 +281,9 @@ enum { * and take masks of ancestors with non-empty cpus/mems, instead of * being moved to an ancestor. * + * - cpuset: a task can be moved into an empty cpuset, and again it + * takes masks of ancestors. + * * - memcg: use_hierarchy is on by default and the cgroup file for * the flag is not created. * diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 3473dd2580d1..3b3fdfdd4d78 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -479,7 +479,7 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial) */ ret = -ENOSPC; if ((cgroup_task_count(cur->css.cgroup) || cur->attach_in_progress) && - (cpumask_empty(trial->cpus_allowed) || + (cpumask_empty(trial->cpus_allowed) && nodes_empty(trial->mems_allowed))) goto out; @@ -1466,8 +1466,13 @@ static int cpuset_can_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) mutex_lock(&cpuset_mutex); + /* + * We allow to move tasks into an empty cpuset if sane_behavior + * flag is set. + */ ret = -ENOSPC; - if (cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)) + if (!cgroup_sane_behavior(cgrp) && + (cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed))) goto out_unlock; cgroup_taskset_for_each(task, cgrp, tset) {