All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hui Peng <benquike@gmail.com>
To: Ridong Chen <ridong.chen@linux.dev>
Cc: longman@redhat.com, tj@kernel.org, hannes@cmpxchg.org,
	mkoutny@suse.com, cgroups@vger.kernel.org,
	linux-kernel@vger.kernel.org, Hui Peng <benquike@gmail.com>
Subject: Re: [PATCH] cgroup/cpuset: prevent overlapping local and remote partition creation
Date: Sun, 20 Sep 2026 03:04:58 +0000	[thread overview]
Message-ID: <20260920030458.1800040-1-benquike@gmail.com> (raw)
In-Reply-To: <139d9231-4723-4365-9af7-8142e6581ede@linux.dev>

On Sun, Sep 20, 2026 at 09:22:09AM +0800, Ridong Chen wrote:
> Could you please first describe what the issue is and how it can be triggered?
> Or is there any reproducer?

Hi Ridong,

Thanks for taking a look. Below is a detailed description of both
scenarios, how each is triggered in the current code, the dmesg
WARNINGs produced on 7.3.0-rc3, and the minimized shell reproducers.

------------------------------------------------------------------------
Scenario 1: Enabling a remote partition underneath an ancestor local
            partition root (remote_partition_enable)
------------------------------------------------------------------------

How it happens:
1. Suppose top-level cgroup "A" is a valid local partition root owning
   CPU 1 (cpuset.cpus = 1, cpuset.cpus.exclusive = 1,
   cpuset.cpus.partition = root). Enabling "A" calls
   partition_xcpus_add(..., &top_cpuset, {1}), which adds CPU 1 to
   subpartitions_cpus.
2. Child "A/B" is a normal non-partition member (cpuset.cpus.partition =
   member) with cpuset.cpus = 1 and cpuset.cpus.exclusive = 1.
3. Grandchild "A/B/D" has cpuset.cpus = 1, cpuset.cpus.exclusive = 1.
   When "root" is written to "A/B/D/cpuset.cpus.partition",
   update_prstate() checks is_partition_valid(parent) on A/B (which is
   false because A/B is PRS_MEMBER) and therefore calls
   remote_partition_enable(D, PRS_ROOT, &tmpmask).
4. In remote_partition_enable(), compute_excpus(D, tmp->new_cpus) walks
   up D -> B -> A and computes tmp->new_cpus = {1}. Because ancestor "A"
   is already a valid local partition root, CPU 1 is already present in
   subpartitions_cpus.
5. remote_partition_enable() hits:
     WARN_ON_ONCE(cpumask_intersects(tmp->new_cpus, subpartitions_cpus));
   at kernel/cgroup/cpuset.c:1594 and continues without returning an
   error, enabling "A/B/D" as a valid remote partition on CPU 1 while
   ancestor "A" is simultaneously a valid local partition on CPU 1,
   which then also triggers a second WARNING in
   rebuild_sched_domains_locked() (kernel/cgroup/cpuset.c:906).

Minimized reproducer (Scenario 1):
  #!/bin/sh
  mkdir -p /tmp/cg1
  mount -t cgroup2 none /tmp/cg1
  echo "+cpuset" > /tmp/cg1/cgroup.subtree_control

  mkdir /tmp/cg1/A
  echo 1 > /tmp/cg1/A/cpuset.cpus
  echo 1 > /tmp/cg1/A/cpuset.cpus.exclusive
  echo root > /tmp/cg1/A/cpuset.cpus.partition
  echo "+cpuset" > /tmp/cg1/A/cgroup.subtree_control

  mkdir /tmp/cg1/A/B
  echo 1 > /tmp/cg1/A/B/cpuset.cpus
  echo 1 > /tmp/cg1/A/B/cpuset.cpus.exclusive
  echo "+cpuset" > /tmp/cg1/A/B/cgroup.subtree_control

  mkdir /tmp/cg1/A/B/D
  echo 1 > /tmp/cg1/A/B/D/cpuset.cpus
  echo 1 > /tmp/cg1/A/B/D/cpuset.cpus.exclusive
  echo root > /tmp/cg1/A/B/D/cpuset.cpus.partition

dmesg output on 7.3.0-rc3:
  WARNING: kernel/cgroup/cpuset.c:1594 at update_prstate+0xbef/0xd70, CPU#2
  Call Trace:
   cpuset_partition_write+0x112/0x140
  WARNING: kernel/cgroup/cpuset.c:906 at rebuild_sched_domains_locked+0x4f2/0x710, CPU#2
  Call Trace:
   cpuset_partition_write+0x112/0x140

------------------------------------------------------------------------
Scenario 2: Invalid top-level local partition transitioning to valid
            over an active remote child partition (validate_partition)
------------------------------------------------------------------------

How it happens:
1. Suppose top-level cgroup "A" is configured as a partition root
   (echo root > A/cpuset.cpus.partition) and given all online CPUs
   (e.g., echo 0-3 > A/cpuset.cpus.exclusive on a 4-CPU system), which
   transitions "A" to PRS_INVALID_ROOT ("root invalid (Parent unable to
   distribute cpu downstream)").
2. Because "A" is invalid (!is_partition_valid(A)), creating child "A/R"
   with cpuset.cpus = 1, cpuset.cpus.exclusive = 1, and
   cpuset.cpus.partition = root succeeds via remote_partition_enable(),
   making "A/R" a valid remote partition on CPU 1 (adding CPU 1 to
   subpartitions_cpus and removing CPU 1 from top_cpuset.effective_cpus).
3. Next, shrinking "A/cpuset.cpus.exclusive" from "0-3" to "1" calls
   update_exclusive_cpumask() -> partition_cpus_change(A, trialcs, &tmp)
   -> validate_partition(A, trialcs).
4. Unlike update_prstate() (which checks (parent == &top_cpuset) &&
   cpumask_intersects(..., subpartitions_cpus) and returns PERR_REMOTE),
   validate_partition() omits the subpartitions_cpus check and returns
   PERR_NONE (0).
5. partition_cpus_change() then calls update_parent_effective_cpumask(A,
   partcmd_update, trialcs->effective_xcpus, &tmp) to activate "A" on
   CPU 1, which is already removed from top_cpuset.effective_cpus by
   "A/R", triggering WARN_ON_ONCE(!cpumask_subset(tmp->new_cpus,
   parent->effective_cpus)) at kernel/cgroup/cpuset.c:1943 and
   WARN_ON_ONCE(old_prs < 0) in partition_xcpus_del() at
   kernel/cgroup/cpuset.c:1342.

Minimized reproducer (Scenario 2, on a 4-CPU VM):
  #!/bin/sh
  mkdir -p /tmp/cg2
  mount -t cgroup2 none /tmp/cg2
  echo "+cpuset" > /tmp/cg2/cgroup.subtree_control

  mkdir /tmp/cg2/A
  echo root > /tmp/cg2/A/cpuset.cpus.partition
  echo 0-3 > /tmp/cg2/A/cpuset.cpus.exclusive
  echo "+cpuset" > /tmp/cg2/A/cgroup.subtree_control

  mkdir /tmp/cg2/A/R
  echo 1 > /tmp/cg2/A/R/cpuset.cpus
  echo 1 > /tmp/cg2/A/R/cpuset.cpus.exclusive
  echo root > /tmp/cg2/A/R/cpuset.cpus.partition

  # Shrink A's exclusive_cpus to 1
  echo 1 > /tmp/cg2/A/cpuset.cpus.exclusive

dmesg output on 7.3.0-rc3:
  WARNING: kernel/cgroup/cpuset.c:1943 at update_parent_effective_cpumask+0x189b/0x1fd0
  Call Trace:
   cpuset_write_resmask+0xcf2/0x1690
  WARNING: kernel/cgroup/cpuset.c:1342 at partition_xcpus_del+0x15b/0x1b0
  Call Trace:
   update_parent_effective_cpumask+0x118c/0x1fd0
   cpuset_write_resmask+0xcf2/0x1690

Also, in v2 of the patch, I will refine the check in validate_partition()
to exclude cs's own existing effective_xcpus when cs is already a valid
local partition (!is_partition_valid(cs)), and split the two scenarios
into separate patches with these reproducers in the commit messages if
you prefer.

Best regards,
Hui Peng

  reply	other threads:[~2026-09-20  3:05 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-19 22:17 [PATCH] cgroup/cpuset: prevent overlapping local and remote partition creation Hui Peng
2026-09-20  1:22 ` Ridong Chen
2026-09-20  3:04   ` Hui Peng [this message]
2026-09-20  8:23   ` [PATCH v2 1/2] cgroup/cpuset: return PERR_NOCPUS in remote_partition_enable() on subpartitions_cpus conflict Hui Peng
2026-09-20  8:23     ` [PATCH v2 2/2] cgroup/cpuset: prevent local partition activation over remote partition and sibling xcpus conflict Hui Peng
2026-09-20  8:57       ` Guopeng Zhang
2026-09-20 18:14         ` Hui Peng
2026-09-20 18:14         ` [PATCH v3 1/3] cgroup/cpuset: return PERR_NOCPUS in remote_partition_enable() Hui Peng
2026-09-20 18:14           ` [PATCH v3 2/3] cgroup/cpuset: prevent activating local partition over remote one Hui Peng
2026-09-22 20:21             ` Waiman Long
2026-09-20 18:14           ` [PATCH v3 3/3] cgroup/cpuset: check sibling effective_xcpus in cpus_excl_conflict() Hui Peng
2026-09-21  7:08           ` [PATCH v3 1/3] cgroup/cpuset: return PERR_NOCPUS in remote_partition_enable() Ridong Chen
2026-09-22  8:00             ` Hui Peng
2026-09-22 20:04               ` Waiman Long
2026-09-20  6:30 ` [PATCH] cgroup/cpuset: prevent overlapping local and remote partition creation Guopeng Zhang
2026-09-20  8:23   ` Hui Peng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260920030458.1800040-1-benquike@gmail.com \
    --to=benquike@gmail.com \
    --cc=cgroups@vger.kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=longman@redhat.com \
    --cc=mkoutny@suse.com \
    --cc=ridong.chen@linux.dev \
    --cc=tj@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.