在 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


Reply via email to