在 2026/8/25 23:11, Waiman Long 写道: > On 8/20/26 8:41 AM, Guopeng Zhang wrote: >> 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; >> + } >> + > A invalid partition means part_error should be set to some error code. This > change only makes sure the error code is PERR_INVCPUS. Other than that, I > don't see any other tangible change here. Thanks, Longman. I think there is a functional difference here. `part_error` is a local variable initialized to `PERR_NONE` on every call to `update_parent_effective_cpumask()`; it is not initialized from `cs->prs_err`. With the current condition: } else if (is_partition_invalid(cs) && !cpumask_empty(xcpus) && cpumask_subset(xcpus, parent->effective_xcpus)) { an invalid partition whose CPUs are no longer a subset of the parent's effective exclusive mask skips this branch entirely, leaving `part_error` as `PERR_NONE`. The later state transition then does: case PRS_INVALID_ROOT: case PRS_INVALID_ISOLATED: if (!part_error) new_prs = -old_prs; break; so the partition can be changed back to a valid state. Therefore, this change does more than set the error code to `PERR_INVCPUS`; it also prevents an out-of-mask invalid partition from being made valid again. >> /* >> * 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)) > > This hunk should probably be grouped into the same patch making change to > compute_partition_effective_cpumask(). I have included these changes in v4 and moved both changes from this patch into the earlier patch that modifies compute_partition_effective_cpumask(). I have also temporarily dropped all selftest patches, including those posted in v3, as the current test design needs some rework. Thanks, Guopeng

