Skip to content

Commit fe8cd27

Browse files
Waiman-Longhtejun
authored andcommitted
cgroup/cpuset: Delay setting of CS_CPU_EXCLUSIVE until valid partition
The CS_CPU_EXCLUSIVE flag is currently set whenever cpuset.cpus.exclusive is set to make sure that the exclusivity test will be run to ensure its exclusiveness. At the same time, this flag can be changed whenever the partition root state is changed. For example, the CS_CPU_EXCLUSIVE flag will be reset whenever a partition root becomes invalid. This makes using CS_CPU_EXCLUSIVE to ensure exclusiveness a bit fragile. The current scheme also makes setting up a cpuset.cpus.exclusive hierarchy to enable remote partition harder as cpuset.cpus.exclusive cannot overlap with any cpuset.cpus of sibling cpusets if their cpuset.cpus.exclusive aren't set. Solve these issues by deferring the setting of CS_CPU_EXCLUSIVE flag until the cpuset become a valid partition root while adding new checks in validate_change() to ensure that cpuset.cpus.exclusive of sibling cpusets cannot overlap. An additional check is also added to validate_change() to make sure that cpuset.cpus of one cpuset cannot be a subset of cpuset.cpus.exclusive of a sibling cpuset to avoid the problem that none of those CPUs will be available when these exclusive CPUs are extracted out to a newly enabled partition root. The Documentation/admin-guide/cgroup-v2.rst file is updated to document the new constraints. Signed-off-by: Waiman Long <[email protected]> Signed-off-by: Tejun Heo <[email protected]>
1 parent 43ee401 commit fe8cd27

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

Documentation/admin-guide/cgroup-v2.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2359,8 +2359,12 @@ Cpuset Interface Files
23592359
is always a subset of it.
23602360

23612361
Users can manually set it to a value that is different from
2362-
"cpuset.cpus". The only constraint in setting it is that the
2363-
list of CPUs must be exclusive with respect to its sibling.
2362+
"cpuset.cpus". One constraint in setting it is that the list of
2363+
CPUs must be exclusive with respect to "cpuset.cpus.exclusive"
2364+
of its sibling. If "cpuset.cpus.exclusive" of a sibling cgroup
2365+
isn't set, its "cpuset.cpus" value, if set, cannot be a subset
2366+
of it to leave at least one CPU available when the exclusive
2367+
CPUs are taken away.
23642368

23652369
For a parent cgroup, any one of its exclusive CPUs can only
23662370
be distributed to at most one of its child cgroups. Having an

kernel/cgroup/cpuset.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -825,17 +825,41 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
825825

826826
/*
827827
* If either I or some sibling (!= me) is exclusive, we can't
828-
* overlap
828+
* overlap. exclusive_cpus cannot overlap with each other if set.
829829
*/
830830
ret = -EINVAL;
831831
cpuset_for_each_child(c, css, par) {
832-
if ((is_cpu_exclusive(trial) || is_cpu_exclusive(c)) &&
833-
c != cur) {
832+
bool txset, cxset; /* Are exclusive_cpus set? */
833+
834+
if (c == cur)
835+
continue;
836+
837+
txset = !cpumask_empty(trial->exclusive_cpus);
838+
cxset = !cpumask_empty(c->exclusive_cpus);
839+
if (is_cpu_exclusive(trial) || is_cpu_exclusive(c) ||
840+
(txset && cxset)) {
834841
if (!cpusets_are_exclusive(trial, c))
835842
goto out;
843+
} else if (txset || cxset) {
844+
struct cpumask *xcpus, *acpus;
845+
846+
/*
847+
* When just one of the exclusive_cpus's is set,
848+
* cpus_allowed of the other cpuset, if set, cannot be
849+
* a subset of it or none of those CPUs will be
850+
* available if these exclusive CPUs are activated.
851+
*/
852+
if (txset) {
853+
xcpus = trial->exclusive_cpus;
854+
acpus = c->cpus_allowed;
855+
} else {
856+
xcpus = c->exclusive_cpus;
857+
acpus = trial->cpus_allowed;
858+
}
859+
if (!cpumask_empty(acpus) && cpumask_subset(acpus, xcpus))
860+
goto out;
836861
}
837862
if ((is_mem_exclusive(trial) || is_mem_exclusive(c)) &&
838-
c != cur &&
839863
nodes_intersects(trial->mems_allowed, c->mems_allowed))
840864
goto out;
841865
}
@@ -1375,7 +1399,7 @@ static void update_sibling_cpumasks(struct cpuset *parent, struct cpuset *cs,
13751399
*/
13761400
static int update_partition_exclusive(struct cpuset *cs, int new_prs)
13771401
{
1378-
bool exclusive = (new_prs > 0);
1402+
bool exclusive = (new_prs > PRS_MEMBER);
13791403

13801404
if (exclusive && !is_cpu_exclusive(cs)) {
13811405
if (update_flag(CS_CPU_EXCLUSIVE, cs, 1))
@@ -2620,8 +2644,6 @@ static int update_exclusive_cpumask(struct cpuset *cs, struct cpuset *trialcs,
26202644
retval = cpulist_parse(buf, trialcs->exclusive_cpus);
26212645
if (retval < 0)
26222646
return retval;
2623-
if (!is_cpu_exclusive(cs))
2624-
set_bit(CS_CPU_EXCLUSIVE, &trialcs->flags);
26252647
}
26262648

26272649
/* Nothing to do if the CPUs didn't change */

0 commit comments

Comments
 (0)