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
590590 kfree(cs);
591591 }
592592
593+/*
594+ * validate_change_legacy() - Validate conditions specific to legacy (v1)
595+ * behavior.
596+ */
597+static 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;
618+out:
619+ return ret;
620+}
621+
593622 /*
594623 * validate_change() - Used to validate that any proposed cpuset change
595624 * follows the structural rules for cpusets.
@@ -614,20 +643,21 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial) · 18 unmodified lines
614643 {
615644 struct cgroup_subsys_state *css;
616645 struct cpuset *c, *par;
617− int ret;
618−
619− /* The checks don't apply to root cpuset */
620− if (cur == &top_cpuset)
621− return 0;
646+ int ret = 0;
622647
623648 rcu_read_lock();
624− par = parent_cs(cur);
625649
626− /* On legacy hierarchy, we must be a subset of our parent cpuset. */
627− ret = -EACCES;
628− if (!is_in_v2_mode() && !is_cpuset_subset(trial, par))
650+ if (!is_in_v2_mode())
651+ ret = validate_change_legacy(cur, trial);
652+ if (ret)
653+ goto out;
654+
655+ /* Remaining checks don't apply to root cpuset */
656+ if (cur == &top_cpuset)
629657 goto out;
630658
659+ par = parent_cs(cur);
660+
631661 /*
632662 * If either I or some sibling (!= me) is exclusive, we can't
633663 * overlap
@@ -1175,9 +1205,7 @@ enum subparts_cmd { · 541 unmodified lines
11751205 *
11761206 * Because of the implicit cpu exclusive nature of a partition root,
11771207 * cpumask changes that violates the cpu exclusivity rule will not be
1178− * permitted when checked by validate_change(). The 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.
1208+ * permitted when checked by validate_change().
11811209 */
11821210 static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd,
11831211 struct cpumask *newmask,