Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

cgroup/cpuset: Don't fail cpuset.cpus change in v2

Commit fe8cd2736e75 ("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 <longman@redhat.com>
Reviewed-by: Chen Ridong <chenridong@huawei.com>
Signed-off-by: Tejun Heo <tj@kernel.org>

authored by

Waiman Long and committed by
Tejun Heo
6e6f13f6 a1a01793

+19 -19
+4 -4
Documentation/admin-guide/cgroup-v2.rst
··· 2561 2561 Users can manually set it to a value that is different from 2562 2562 "cpuset.cpus". One constraint in setting it is that the list of 2563 2563 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. 2568 2568 2569 2569 For a parent cgroup, any one of its exclusive CPUs can only 2570 2570 be distributed to at most one of its child cgroups. Having an
+15 -15
kernel/cgroup/cpuset.c
··· 609 609 610 610 /** 611 611 * 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 614 615 * 615 616 * Returns: true if CPU exclusivity conflict exists, false otherwise 616 617 * 617 618 * Conflict detection rules: 618 619 * 1. If either cpuset is CPU exclusive, they must be mutually exclusive 619 620 * 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 621 622 */ 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) 623 625 { 624 626 /* 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); 627 629 628 630 /* Exclusive_cpus cannot intersect */ 629 - if (cpumask_intersects(cs1->exclusive_cpus, cs2->exclusive_cpus)) 631 + if (cpumask_intersects(trial->exclusive_cpus, sibling->exclusive_cpus)) 630 632 return true; 631 633 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)) 639 637 return true; 640 638 641 639 return false; ··· 670 672 { 671 673 struct cgroup_subsys_state *css; 672 674 struct cpuset *c, *par; 675 + bool xcpus_changed; 673 676 int ret = 0; 674 677 675 678 rcu_read_lock(); ··· 727 728 * overlap. exclusive_cpus cannot overlap with each other if set. 728 729 */ 729 730 ret = -EINVAL; 731 + xcpus_changed = !cpumask_equal(cur->exclusive_cpus, trial->exclusive_cpus); 730 732 cpuset_for_each_child(c, css, par) { 731 733 if (c == cur) 732 734 continue; 733 - if (cpus_excl_conflict(trial, c)) 735 + if (cpus_excl_conflict(trial, c, xcpus_changed)) 734 736 goto out; 735 737 if (mems_excl_conflict(trial, c)) 736 738 goto out;