From: Waiman Long <longman@redhat.com>
To: "Ridong Chen" <ridong.chen@linux.dev>,
"Tejun Heo" <tj@kernel.org>,
"Johannes Weiner" <hannes@cmpxchg.org>,
"Michal Koutný" <mkoutny@suse.com>,
"Shuah Khan" <shuah@kernel.org>
Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-kselftest@vger.kernel.org,
Guopeng Zhang <guopeng.zhang@linux.dev>,
Waiman Long <longman@redhat.com>,
Sashiko <sashiko-bot@kernel.org>
Subject: [PATCH-next v3 3/3] cgroup/cpuset: Check remote partition underneath before making an invalid partition valid
Date: Tue, 10 Nov 2026 21:02:04 -0500 [thread overview]
Message-ID: <20261111020204.1660055-4-longman@redhat.com> (raw)
In-Reply-To: <20261111020204.1660055-1-longman@redhat.com>
When re-evaluating an invalid local partition via partcmd_update,
update_parent_effective_cpumask() does not check whether a descendant
remote partition is using its exclusive CPUs, promoting the cpuset to a
valid partition root over the remote partition. This condition should only
be possible if parent is the top_cpuset and exclusive_cpus isn't empty.
This leaves an active remote partition underneath a valid
local partition root with overlapping exclusive CPUs, breaking
scheduler domain partitioning and triggering warnings in
compute_partition_effective_cpumask() and generate_sched_domains().
Fix that by checking the effective_xcpus against subpartitions_cpus
when an underneath remote partition is possible to make sure that all
the exclusive CPUs are available before allowing the invalid partition
to be switched back to valid.
Also make sure that effective_xcpus is non-empty before swtiching an
invalid partition back to valid.
Add a test case in test_cpuset_prs.sh to verify that an invalid partition
with a remote partition underneath cannot be switched back to valid
with a hotplug event.
Fixes: 181c8e091aae ("cgroup/cpuset: Introduce remote partition")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://sashiko.dev/#/bug/linux-47715b89-d5fb-4731-b7c9-070773c6ff75
Signed-off-by: Waiman Long <longman@redhat.com>
---
kernel/cgroup/cpuset.c | 42 ++++++++++++-------
.../selftests/cgroup/test_cpuset_prs.sh | 4 ++
2 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 8b684361c94e..af5fd543fe88 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2034,11 +2034,7 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
* tasks_nocpu_error() with this very mask, and a failing
* write is routed to partcmd_invalidate instead.
*/
- if (is_partition_invalid(cs)) {
- adding = false;
- deleting = cpumask_and(tmp->delmask,
- newmask, parent->effective_xcpus);
- } else {
+ if (is_partition_valid(cs)) {
cpumask_andnot(tmp->addmask, cs->effective_xcpus, newmask);
adding = cpumask_and(tmp->addmask, tmp->addmask,
parent->effective_xcpus);
@@ -2046,6 +2042,17 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
cpumask_andnot(tmp->delmask, newmask, cs->effective_xcpus);
deleting = cpumask_and(tmp->delmask, tmp->delmask,
parent->effective_xcpus);
+ } else {
+ deleting = cpumask_and(tmp->delmask,
+ newmask, parent->effective_xcpus);
+
+ /* Check if a remote partition may be underneath */
+ if ((parent == &top_cpuset) &&
+ !cpumask_empty(cs->exclusive_cpus) &&
+ cpumask_intersects(tmp->delmask, subpartitions_cpus)) {
+ part_error = PERR_REMOTE;
+ deleting = false;
+ }
}
/*
@@ -2126,34 +2133,37 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
} else if (is_partition_invalid(cs)) {
struct cgroup_subsys_state *css;
struct cpuset *child;
- bool exclusive = true;
/*
* Convert invalid partition to valid has to pass the
- * cpu exclusivity test when cpuset.cpus.exclusive is
- * empty as well as the housekeeping check.
+ * following tests:
+ * 1) housekeeping CPU conflict check
+ * 2) cpu exclusivity test when cpuset.cpus.exclusive is
+ * empty.
+ * 3) if parent is top_cpuset, none of the effective_xcpus
+ * (tmp->delmask) are in subpartitions_cpus, if not a
+ * remote partition may be underneath.
*/
if (prstate_housekeeping_conflict(cs->partition_root_state,
parent_prs, tmp->delmask, NULL)) {
part_error = PERR_HKEEPING;
- goto write_error;
- }
- if (cpumask_empty(cs->exclusive_cpus)) {
+ } else if (cpumask_empty(cs->exclusive_cpus)) {
rcu_read_lock();
cpuset_for_each_child(child, css, parent) {
if (child == cs)
continue;
if (!cpusets_are_exclusive(cs, child)) {
- exclusive = false;
+ part_error = PERR_NOTEXCL;
break;
}
}
rcu_read_unlock();
+ } else if ((parent == &top_cpuset) &&
+ cpumask_intersects(tmp->delmask, subpartitions_cpus)) {
+ part_error = PERR_REMOTE;
}
- if (exclusive)
+ if (!part_error)
deleting = !cpumask_empty(tmp->delmask);
- else
- part_error = PERR_NOTEXCL;
}
}
@@ -2174,7 +2184,7 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
break;
case PRS_INVALID_ROOT:
case PRS_INVALID_ISOLATED:
- if (!part_error)
+ if (!part_error && deleting)
new_prs = -old_prs;
break;
}
diff --git a/tools/testing/selftests/cgroup/test_cpuset_prs.sh b/tools/testing/selftests/cgroup/test_cpuset_prs.sh
index 1e9e6b4c6f7b..3d873804abc2 100755
--- a/tools/testing/selftests/cgroup/test_cpuset_prs.sh
+++ b/tools/testing/selftests/cgroup/test_cpuset_prs.sh
@@ -563,6 +563,10 @@ TEST_MATRIX=(
" C1-6:P1 C3-6:P2 C5-6:P2 . . P1 . . 0 A1:1-2|A2:3-4|A3:5-6 \
A1:P1|A2:P1|A3:P2 5-6"
+ # A hotplug event will not incorrectly activate an invalid partition with
+ # a remote partition underneath.
+ " CX1-4 C3-4:P1 . . P1 O1=0 . . 0 A1:2|A2:3-4 A1:P-1|A2:P1"
+
#
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
--
2.56.0
prev parent reply other threads:[~2026-11-11 2:02 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-11 2:02 [PATCH-next v3 0/3] cgroup/cpuset: More fix patches Waiman Long
2026-11-11 2:02 ` [PATCH-next v3 1/3] cgroup/cpuset: Correctly set cpus_updated in cpuset_hotplug_update_tasks() Waiman Long
2026-11-11 2:02 ` [PATCH-next v3 2/3] cgroup/cpuset: Fix incorrect partition invalidation logic " Waiman Long
2026-11-11 2:02 ` Waiman Long [this message]
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=20261111020204.1660055-4-longman@redhat.com \
--to=longman@redhat.com \
--cc=cgroups@vger.kernel.org \
--cc=guopeng.zhang@linux.dev \
--cc=hannes@cmpxchg.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=mkoutny@suse.com \
--cc=ridong.chen@linux.dev \
--cc=sashiko-bot@kernel.org \
--cc=shuah@kernel.org \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®