Skip to content

Commit 6e6f13f

Browse files
Waiman-Longhtejun
authored andcommitted
cgroup/cpuset: Don't fail cpuset.cpus change in v2
Commit fe8cd27 ("cgroup/cpuset: Delay setting of CS_CPU_EXCLUSIVE until valid partition") introduced a new check to disallow the setting of a new cpuset.cpus.exclusive value that is a superset of a sibling's cpuset.cpus value so that there will at least be one CPU left in the sibling in case the cpuset becomes a valid partition root. This new check does have the side effect of failing a cpuset.cpus change that make it a subset of a sibling's cpuset.cpus.exclusive value. With v2, users are supposed to be allowed to set whatever value they want in cpuset.cpus without failure. To maintain this rule, the check is now restricted to only when cpuset.cpus.exclusive is being changed not when cpuset.cpus is changed. The cgroup-v2.rst doc file is also updated to reflect this change. Signed-off-by: Waiman Long <[email protected]> Reviewed-by: Chen Ridong <[email protected]> Signed-off-by: Tejun Heo <[email protected]>
1 parent a1a0179 commit 6e6f13f

2 files changed

Lines changed: 19 additions & 19 deletions

File tree

Documentation/admin-guide/cgroup-v2.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2561,10 +2561,10 @@ Cpuset Interface Files
25612561
Users can manually set it to a value that is different from
25622562
"cpuset.cpus". One constraint in setting it is that the list of
25632563
CPUs must be exclusive with respect to "cpuset.cpus.exclusive"
2564-
of its sibling. If "cpuset.cpus.exclusive" of a sibling cgroup
2565-
isn't set, its "cpuset.cpus" value, if set, cannot be a subset
2566-
of it to leave at least one CPU available when the exclusive
2567-
CPUs are taken away.
2564+
and "cpuset.cpus.exclusive.effective" of its siblings. Another
2565+
constraint is that it cannot be a superset of "cpuset.cpus"
2566+
of its sibling in order to leave at least one CPU available to
2567+
that sibling when the exclusive CPUs are taken away.
25682568

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

kernel/cgroup/cpuset.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -609,33 +609,31 @@ static inline bool cpusets_are_exclusive(struct cpuset *cs1, struct cpuset *cs2)
609609

610610
/**
611611
* cpus_excl_conflict - Check if two cpusets have exclusive CPU conflicts
612-
* @cs1: first cpuset to check
613-
* @cs2: second cpuset to check
612+
* @trial: the trial cpuset to be checked
613+
* @sibling: a sibling cpuset to be checked against
614+
* @xcpus_changed: set if exclusive_cpus has been set
614615
*
615616
* Returns: true if CPU exclusivity conflict exists, false otherwise
616617
*
617618
* Conflict detection rules:
618619
* 1. If either cpuset is CPU exclusive, they must be mutually exclusive
619620
* 2. exclusive_cpus masks cannot intersect between cpusets
620-
* 3. The allowed CPUs of one cpuset cannot be a subset of another's exclusive CPUs
621+
* 3. The allowed CPUs of a sibling cpuset cannot be a subset of the new exclusive CPUs
621622
*/
622-
static inline bool cpus_excl_conflict(struct cpuset *cs1, struct cpuset *cs2)
623+
static inline bool cpus_excl_conflict(struct cpuset *trial, struct cpuset *sibling,
624+
bool xcpus_changed)
623625
{
624626
/* If either cpuset is exclusive, check if they are mutually exclusive */
625-
if (is_cpu_exclusive(cs1) || is_cpu_exclusive(cs2))
626-
return !cpusets_are_exclusive(cs1, cs2);
627+
if (is_cpu_exclusive(trial) || is_cpu_exclusive(sibling))
628+
return !cpusets_are_exclusive(trial, sibling);
627629

628630
/* Exclusive_cpus cannot intersect */
629-
if (cpumask_intersects(cs1->exclusive_cpus, cs2->exclusive_cpus))
631+
if (cpumask_intersects(trial->exclusive_cpus, sibling->exclusive_cpus))
630632
return true;
631633

632-
/* The cpus_allowed of one cpuset cannot be a subset of another cpuset's exclusive_cpus */
633-
if (!cpumask_empty(cs1->cpus_allowed) &&
634-
cpumask_subset(cs1->cpus_allowed, cs2->exclusive_cpus))
635-
return true;
636-
637-
if (!cpumask_empty(cs2->cpus_allowed) &&
638-
cpumask_subset(cs2->cpus_allowed, cs1->exclusive_cpus))
634+
/* The cpus_allowed of a sibling cpuset cannot be a subset of the new exclusive_cpus */
635+
if (xcpus_changed && !cpumask_empty(sibling->cpus_allowed) &&
636+
cpumask_subset(sibling->cpus_allowed, trial->exclusive_cpus))
639637
return true;
640638

641639
return false;
@@ -672,6 +670,7 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
672670
{
673671
struct cgroup_subsys_state *css;
674672
struct cpuset *c, *par;
673+
bool xcpus_changed;
675674
int ret = 0;
676675

677676
rcu_read_lock();
@@ -728,10 +727,11 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
728727
* overlap. exclusive_cpus cannot overlap with each other if set.
729728
*/
730729
ret = -EINVAL;
730+
xcpus_changed = !cpumask_equal(cur->exclusive_cpus, trial->exclusive_cpus);
731731
cpuset_for_each_child(c, css, par) {
732732
if (c == cur)
733733
continue;
734-
if (cpus_excl_conflict(trial, c))
734+
if (cpus_excl_conflict(trial, c, xcpus_changed))
735735
goto out;
736736
if (mems_excl_conflict(trial, c))
737737
goto out;

0 commit comments

Comments
 (0)