From: Guopeng Zhang <[email protected]>

When cpuset.cpus changes, compute_partition_effective_cpumask() builds a
new exclusive mask but checks child partitions against
cs->effective_xcpus. That field still contains the old mask, so a child
that no longer fits can remain valid.

Use new_xcpus for the check. A later partcmd_update() may revisit the
newly invalid child. Report PERR_INVCPUS if the child CPUs are outside
the parent effective exclusive mask so that this visit does not make the
child valid again.

Fixes: 0c7f293efc87 ("cgroup/cpuset: Add cpuset.cpus.exclusive.effective for 
v2")
Signed-off-by: Guopeng Zhang <[email protected]>
---
 kernel/cgroup/cpuset.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index b9faadf4af6d..b3e749ede7d1 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1987,12 +1987,16 @@ static int update_parent_effective_cpumask(struct 
cpuset *cs, int cmd,
                                adding = cpumask_and(tmp->addmask,
                                                     cs->effective_xcpus,
                                                     parent->effective_xcpus);
-               } else if (is_partition_invalid(cs) && !cpumask_empty(xcpus) &&
-                          cpumask_subset(xcpus, parent->effective_xcpus)) {
+               } else if (is_partition_invalid(cs) && !cpumask_empty(xcpus)) {
                        struct cgroup_subsys_state *css;
                        struct cpuset *child;
                        bool exclusive = true;
 
+                       if (!cpumask_subset(xcpus, parent->effective_xcpus)) {
+                               part_error = PERR_INVCPUS;
+                               goto write_error;
+                       }
+
                        /*
                         * Convert invalid partition to valid has to
                         * pass the cpu exclusivity test.
@@ -2144,7 +2148,7 @@ static void compute_partition_effective_cpumask(struct 
cpuset *cs,
                WARN_ON_ONCE(is_remote_partition(child));
                WRITE_ONCE(child->prs_err, 0);
                if (!cpumask_subset(child->effective_xcpus,
-                                   cs->effective_xcpus))
+                                   new_xcpus))
                        WRITE_ONCE(child->prs_err, PERR_INVCPUS);
                else if (populated &&
                         cpumask_subset(new_ecpus, child->effective_xcpus))
-- 
2.43.0


Reply via email to