History

cgroup/cpuset: Make child cpusets restrict parents on v1 hierarchy

The commit 1f1562fcd04a ("cgroup/cpuset: Don't let child cpusets restrict parent in default hierarchy") inteded to relax the check only on the default hierarchy (or v2 mode) but it dropped the check in v1 too. This patch returns and separates the legacy-only validations so that they can be considered only in the v1 mode, which should enforce the old constraints for the sake of compatibility.

Michal Koutný committed 4 years ago

Commit d068eeb1 parent daadb3b1 file · +40 −12Browse files

Showing the changes to kernel (1 of 1 file). Show all

Unified · Split

kernel/cgroup/cpuset.c+40−12
@@ -590,6 +590,35 @@ static inline void free_cpuset(struct cpuset *cs) · 589 unmodified lines
590 kfree(cs);590 kfree(cs);
591}591}
592 592
593/*
594 * validate_change_legacy() - Validate conditions specific to legacy (v1)
595 * behavior.
596 */
597static int validate_change_legacy(struct cpuset *cur, struct cpuset *trial)
598{
599 struct cgroup_subsys_state *css;
600 struct cpuset *c, *par;
601 int ret;
602
603 WARN_ON_ONCE(!rcu_read_lock_held());
604
605 /* Each of our child cpusets must be a subset of us */
606 ret = -EBUSY;
607 cpuset_for_each_child(c, css, cur)
608 if (!is_cpuset_subset(c, trial))
609 goto out;
610
611 /* On legacy hierarchy, we must be a subset of our parent cpuset. */
612 ret = -EACCES;
613 par = parent_cs(cur);
614 if (par && !is_cpuset_subset(trial, par))
615 goto out;
616
617 ret = 0;
618out:
619 return ret;
620}
621
593/*622/*
594 * validate_change() - Used to validate that any proposed cpuset change623 * validate_change() - Used to validate that any proposed cpuset change
595 * follows the structural rules for cpusets.624 * follows the structural rules for cpusets.
@@ -614,20 +643,21 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial) · 18 unmodified lines
614{643{
615 struct cgroup_subsys_state *css;644 struct cgroup_subsys_state *css;
616 struct cpuset *c, *par;645 struct cpuset *c, *par;
617 int ret;646 int ret = 0;
618
619 /* The checks don't apply to root cpuset */
620 if (cur == &top_cpuset)
621 return 0;
622 647
623 rcu_read_lock();648 rcu_read_lock();
624 par = parent_cs(cur);
625 649
626 /* On legacy hierarchy, we must be a subset of our parent cpuset. */650 if (!is_in_v2_mode())
627 ret = -EACCES;651 ret = validate_change_legacy(cur, trial);
628 if (!is_in_v2_mode() && !is_cpuset_subset(trial, par))652 if (ret)
653 goto out;
654
655 /* Remaining checks don't apply to root cpuset */
656 if (cur == &top_cpuset)
629 goto out;657 goto out;
630 658
659 par = parent_cs(cur);
660
631 /*661 /*
632 * If either I or some sibling (!= me) is exclusive, we can't662 * If either I or some sibling (!= me) is exclusive, we can't
633 * overlap663 * overlap
@@ -1175,9 +1205,7 @@ enum subparts_cmd { · 541 unmodified lines
1175 *1205 *
1176 * Because of the implicit cpu exclusive nature of a partition root,1206 * Because of the implicit cpu exclusive nature of a partition root,
1177 * cpumask changes that violates the cpu exclusivity rule will not be1207 * cpumask changes that violates the cpu exclusivity rule will not be
1178 * permitted when checked by validate_change(). The validate_change()1208 * permitted when checked by validate_change().
1179 * function will also prevent any changes to the cpu list if it is not
1180 * a superset of children's cpu lists.
1181 */1209 */
1182static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd,1210static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd,
1183 struct cpumask *newmask,1211 struct cpumask *newmask,