在 2026/10/14 22:05, Waiman Long 写道:
> Although it is not typical for real users to create a complicated nested
> partition hierarchy, it is currently allowed to create nested root and
> isolated partitions. In addition, disabling or invalidating a partition
> should always be allowed especially when the cpuset is being deleted.
> 
> With a nested root and isolated partition hierarchy, it is possible
> that all active housekeeping CPUs can be exhausted when disabling or
> invalidating a root partition and returning its CPUs to the isolated
> parent.
> 
> One way to avoid this problem is to disallow the creation of a root
> partition under an isolated parent. It is indeed a new limitation imposed
> on the existing cpuset partition functionality. However an isolated
> partition is usually a left node where scheduling and some other kernel
> noises are disabled. It doesn't make much sense to create a child root
> partition under an isolated parent and remove some CPUs from the set
> of isolated CPUs again. Creation of a child isolated partition under a
> root or isolated parent is still allowed.
> 
> The cgroup-v2 documentation is also updated to reflect this new
> limitation. New test cases are added to test_cpuset_prs.sh to verify
> this new behavior. Some existing test cases are also updated accordingly.
> 
> Signed-off-by: Waiman Long <[email protected]>
> ---
>  Documentation/admin-guide/cgroup-v2.rst           |  4 +++-
>  kernel/cgroup/cpuset-internal.h                   |  1 +
>  kernel/cgroup/cpuset.c                            | 13 +++++++++++++
>  tools/testing/selftests/cgroup/test_cpuset_prs.sh | 14 ++++++++------
>  4 files changed, 25 insertions(+), 7 deletions(-)
> 
> diff --git a/Documentation/admin-guide/cgroup-v2.rst 
> b/Documentation/admin-guide/cgroup-v2.rst
> index bd8c80f3bbc9..2c445829e24d 100644
> --- a/Documentation/admin-guide/cgroup-v2.rst
> +++ b/Documentation/admin-guide/cgroup-v2.rst
> @@ -2767,7 +2767,9 @@ Cpuset Interface Files
>       be retained, but behaves more like a "member".
>  
>       All possible state transitions among "member", "root" and
> -     "isolated" are allowed.
> +     "isolated" are allowed with the exception that a local child
> +     "root" partition is not allowed to be created under an "isolated"
> +     parent partition.
>  
>       On read, the "cpuset.cpus.partition" file can show the following
>       values.
> diff --git a/kernel/cgroup/cpuset-internal.h b/kernel/cgroup/cpuset-internal.h
> index 5da9c91295b0..2e44dc8634dc 100644
> --- a/kernel/cgroup/cpuset-internal.h
> +++ b/kernel/cgroup/cpuset-internal.h
> @@ -35,6 +35,7 @@ enum prs_errcode {
>       PERR_HKEEPING,
>       PERR_ACCESS,
>       PERR_REMOTE,
> +     PERR_ISOPARENT,
>  };
>  
>  /* bits in struct cpuset flags field */
> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
> index 40c004386af0..681701ba46e1 100644
> --- a/kernel/cgroup/cpuset.c
> +++ b/kernel/cgroup/cpuset.c
> @@ -60,6 +60,7 @@ static const char * const perr_strings[] = {
>       [PERR_HKEEPING]  = "partition config conflicts with housekeeping setup",
>       [PERR_ACCESS]    = "Enable partition not permitted",
>       [PERR_REMOTE]    = "Have remote partition underneath",
> +     [PERR_ISOPARENT] = "Root partition is not allowed with isolated parent",
>  };
>  
>  /*
> @@ -2865,6 +2866,7 @@ static int update_prstate(struct cpuset *cs, int 
> new_prs)
>       int err = PERR_NONE, old_prs = cs->partition_root_state;
>       struct cpuset *parent = parent_cs(cs);
>       struct tmpmasks tmpmask;
> +     int parent_prs = parent->partition_root_state;
>       bool isolcpus_updated = false;
>       bool disable_partition = false;
>  
> @@ -2910,6 +2912,14 @@ static int update_prstate(struct cpuset *cs, int 
> new_prs)
>                       enum partition_cmd cmd = (new_prs == PRS_ROOT)
>                                              ? partcmd_enable : 
> partcmd_enablei;
>  
> +                     /*
> +                      * It is not allowed to create a root partition under
> +                      * an isolated parent partition.
> +                      */
> +                     if ((new_prs == PRS_ROOT) && (parent_prs == 
> PRS_ISOLATED)) {
> +                             err = PERR_ISOPARENT;
> +                             goto out;
> +                     }

I tested the following case. Writing root initially leaves C invalid, but
updating its cpuset.cpus makes it valid again.

CPUs 0-15 are online, with nohz_full=2-15 and no isolcpus:

    # cd /sys/fs/cgroup
    # echo +cpuset > cgroup.subtree_control
    # mkdir A
    # echo 1-2 > A/cpuset.cpus
    # echo isolated > A/cpuset.cpus.partition
    # echo +cpuset > A/cgroup.subtree_control
    # mkdir A/C
    # echo 1 > A/C/cpuset.cpus
    # echo root > A/C/cpuset.cpus.partition
    # cat A/C/cpuset.cpus.partition
    root invalid (Root partition is not allowed with isolated parent)
    # echo 1-2 > A/C/cpuset.cpus
    # cat A/C/cpuset.cpus.partition
    root

C becomes a valid root partition.

Thanks,
Guopeng

>                       err = update_parent_effective_cpumask(cs, cmd, NULL, 
> &tmpmask);
>               } else {
>                       err = remote_partition_enable(cs, new_prs, &tmpmask);
> @@ -2922,6 +2932,9 @@ static int update_prstate(struct cpuset *cs, int 
> new_prs)
>               if (prstate_housekeeping_conflict(new_prs, 
> cs->effective_xcpus)) {
>                       disable_partition = true;
>                       err = PERR_HKEEPING;
> +             } else if (parent_prs == PRS_ISOLATED) {
> +                     disable_partition = true;
> +                     err = PERR_ISOPARENT;
>               } else {
>                       isolcpus_updated = true;
>               }
> diff --git a/tools/testing/selftests/cgroup/test_cpuset_prs.sh 
> b/tools/testing/selftests/cgroup/test_cpuset_prs.sh
> index 874a8a161236..85a4f87840b4 100755
> --- a/tools/testing/selftests/cgroup/test_cpuset_prs.sh
> +++ b/tools/testing/selftests/cgroup/test_cpuset_prs.sh
> @@ -288,16 +288,12 @@ TEST_MATRIX=(
>                                                                      
> A1:P0|A2:P1|A3:P0|B1:P1"
>       "   C0-3    C1-3   C3     C4    X2-3  X2-3:P1   P2     P1    0 
> A1:0-1|A2:2|A3:3|B1:4 \
>                                                                      
> A1:P0|A2:P1|A3:P2|B1:P1 2-4|3"
> -     "   C0-4    C1-4  C2-4     .    X2-4  X2-4:P2  X4:P1    .    0 
> A1:0-1|A2:2-3|A3:4 \
> -                                                                    
> A1:P0|A2:P2|A3:P1 2-4|2-3"
> -     "   C0-4    C1-4  C2-4     .    X2-4  X2-4:P2 X3-4:P1   .    0 
> A1:0-1|A2:2|A3:3-4 \
> -                                                                    
> A1:P0|A2:P2|A3:P1 2"
>       " C0-4:X2-4 C1-4:X2-4:P1 C2-4:X4:P2 \
>                                  .      .      X5      .      .    0 
> A1:0-4|A2:1-4|A3:2-4 \
>                                                                      
> A1:P0|A2:P-1|A3:P-2 ."
> -     " C0-4:X2-4 C1-4:X2-4:P2 C2-4:X4:P1 \
> +     " C0-4:X2-4 C1-4:X2-4:P1 C2-4:X4:P2 \
>                                  .      .      .      X1      .    0 
> A1:0-1|A2:2-4|A3:2-4 \
> -                                                                    
> A1:P0|A2:P2|A3:P-1 2-4"
> +                                                                    
> A1:P0|A2:P1|A3:P-2 ."
>       " CX1-3:P1 CX1-3  CX1-3    .      .      .      P1      .    0 
> A1:1-3|A2:1-3|A3:1-3 \
>                                                                      
> A1:P1|A2:P0|A3:P-1"
>  
> @@ -430,6 +426,12 @@ TEST_MATRIX=(
>       # cpuset.cpus can become empty with task in it as it inherits parent's 
> effective CPUs
>       "   C1-3    C2      .      .       .    T:C     .      .     0 
> A1:1-3|A2:1-3"
>  
> +     # Creation of root partition under an isolated partition is not allowed
> +     "  C1-3:P2  C2      .      .       .     P1     .      .     0 
> A1:1-3|A2:2 A1:P2|A2:P-1 1-3"
> +     "  C1-3:P2  C2      .      .       .     P2     .      .     0 
> A1:1,3|A2:2 A1:P2|A2:P2  1-3"
> +     "  C1-3:P2 C2:P2    .      .       .     P1     .      .     0 
> A1:1-3|A2:2 A1:P2|A2:P-1 1-3"
> +
> +     #
>       #  old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs 
> Pstate ISOLCPUS
>       #  ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- 
> ------ --------
>       # Failure cases:


Reply via email to