Linux cgroups development
 help / color / mirror / Atom feed
From: Guopeng Zhang <guopeng.zhang@linux.dev>
To: longman@redhat.com, cgroups@vger.kernel.org
Cc: ridong.chen@linux.dev, tj@kernel.org, hannes@cmpxchg.org,
	mkoutny@suse.com, shuah@kernel.org,
	linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org,
	Guopeng Zhang <zhangguopeng@kylinos.cn>
Subject: [PATCH 10/17] cgroup/cpuset: Fix isolated accounting on direct child invalidation
Date: Thu, 20 Aug 2026 20:41:55 +0800	[thread overview]
Message-ID: <20260820124202.517160-11-guopeng.zhang@linux.dev> (raw)
In-Reply-To: <20260820124202.517160-1-guopeng.zhang@linux.dev>

From: Guopeng Zhang <zhangguopeng@kylinos.cn>

compute_partition_effective_cpumask() can invalidate a child whose CPUs
no longer fit in the parent or would leave a populated parent without an
active CPU. make_partition_invalid() changes the child state without
updating isolated_cpus for the CPUs returned by the child.

Keep the unfiltered result of compute_excpus() so that offline CPUs are
included in isolation accounting. For each CPU released by the child, use
the parent's state when the parent remains valid and owns the CPU.
Otherwise use the state of the nearest valid partition ancestor.

Fixes: 11e5f407b64a ("cgroup/cpuset: Keep track of CPUs in isolated partitions")
Signed-off-by: Guopeng Zhang <zhangguopeng@kylinos.cn>
---
 kernel/cgroup/cpuset.c | 43 +++++++++++++++++++++++++++++++++++-------
 1 file changed, 36 insertions(+), 7 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index a616012927be..b9faadf4af6d 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1281,6 +1281,17 @@ static bool isolated_cpu_update(int new_prs, int cpu)
 	return true;
 }
 
+/* Return the valid partition that owns CPUs released by @cs. */
+static struct cpuset *partition_owner(struct cpuset *cs)
+{
+	struct cpuset *owner = parent_cs(cs);
+
+	lockdep_assert_held(&cpuset_mutex);
+	while (!is_partition_valid(owner))
+		owner = parent_cs(owner);
+	return owner;
+}
+
 /*
  * isolated_cpus_update - Update the isolated_cpus mask
  * @old_prs: old partition_root_state
@@ -2089,6 +2100,7 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
  * compute_partition_effective_cpumask - compute effective_cpus for partition
  * @cs: partition root cpuset
  * @new_ecpus: previously computed effective_cpus to be updated
+ * @new_xcpus: scratch mask for the new effective_xcpus
  *
  * Compute the effective_cpus of a partition root by scanning effective_xcpus
  * of child partition roots and excluding their effective_xcpus.
@@ -2102,7 +2114,8 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
  * Note that rcu_read_lock() is assumed to be held.
  */
 static void compute_partition_effective_cpumask(struct cpuset *cs,
-						struct cpumask *new_ecpus)
+						struct cpumask *new_ecpus,
+						struct cpumask *new_xcpus)
 {
 	struct cgroup_subsys_state *css;
 	struct cpuset *child;
@@ -2116,8 +2129,8 @@ static void compute_partition_effective_cpumask(struct cpuset *cs,
 	 *  2) All the effective_cpus will be used up and cp
 	 *     has tasks
 	 */
-	compute_excpus(cs, new_ecpus);
-	cpumask_and(new_ecpus, new_ecpus, cpu_active_mask);
+	compute_excpus(cs, new_xcpus);
+	cpumask_and(new_ecpus, new_xcpus, cpu_active_mask);
 
 	rcu_read_lock();
 	cpuset_for_each_child(child, css, cs) {
@@ -2139,11 +2152,27 @@ static void compute_partition_effective_cpumask(struct cpuset *cs,
 
 		if (child->prs_err) {
 			int old_prs = child->partition_root_state;
+			int parent_prs = cs->partition_root_state;
+			int owner_prs = partition_owner(cs)->partition_root_state;
+			int cpu;
 
 			/*
-			 * Invalidate child partition
+			 * CPUs in the parent's new exclusive mask return to the
+			 * parent. The other CPUs have already been released to the
+			 * partition that owns the parent. Account both destinations
+			 * before invalidating the child.
 			 */
 			spin_lock_irq(&callback_lock);
+			for_each_cpu(cpu, child->effective_xcpus) {
+				int new_prs = parent_prs > 0 &&
+					      cpumask_test_cpu(cpu, new_xcpus)
+					      ? parent_prs : owner_prs;
+
+				if (old_prs == new_prs)
+					continue;
+				if (isolated_cpu_update(new_prs, cpu))
+					update_housekeeping = true;
+			}
 			make_partition_invalid(child);
 			spin_unlock_irq(&callback_lock);
 			notify_partition_change(child, old_prs);
@@ -2231,7 +2260,7 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp,
 		}
 
 		if (remote || (is_partition_valid(parent) && is_partition_valid(cp)))
-			compute_partition_effective_cpumask(cp, tmp->new_cpus);
+			compute_partition_effective_cpumask(cp, tmp->new_cpus, tmp->addmask);
 		else
 			compute_effective_cpumask(tmp->new_cpus, cp, parent);
 
@@ -3996,7 +4025,7 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp)
 	 */
 	remote = is_remote_partition(cs);
 	if (remote || (is_partition_valid(cs) && is_partition_valid(parent)))
-		compute_partition_effective_cpumask(cs, &new_cpus);
+		compute_partition_effective_cpumask(cs, &new_cpus, tmp->addmask);
 
 	if (remote && (cpumask_empty(subpartitions_cpus) ||
 			(cpumask_empty(&new_cpus) &&
@@ -4031,7 +4060,7 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp)
 	if (partcmd >= 0) {
 		update_parent_effective_cpumask(cs, partcmd, NULL, tmp);
 		if ((partcmd == partcmd_invalidate) || is_partition_valid(cs)) {
-			compute_partition_effective_cpumask(cs, &new_cpus);
+			compute_partition_effective_cpumask(cs, &new_cpus, tmp->addmask);
 			cpuset_force_rebuild();
 		}
 	}
-- 
2.43.0


  parent reply	other threads:[~2026-08-20 12:43 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-20 12:41 [PATCH 00/17] cgroup/cpuset: Fix partition CPU ownership and isolation accounting Guopeng Zhang
2026-08-20 12:41 ` [PATCH 01/17] selftests/cgroup: Drop invalid boot isolation comparison Guopeng Zhang
2026-08-20 12:41 ` [PATCH 02/17] cgroup/cpuset: Preserve boot-isolated CPUs on partition release Guopeng Zhang
2026-08-20 12:41 ` [PATCH 03/17] selftests/cgroup: Test boot-isolated CPU " Guopeng Zhang
2026-08-20 12:41 ` [PATCH 04/17] cgroup/cpuset: Limit type-change accounting to owned CPUs Guopeng Zhang
2026-08-20 12:41 ` [PATCH 05/17] selftests/cgroup: Test isolated CPU accounting on type changes Guopeng Zhang
2026-08-20 12:41 ` [PATCH 06/17] cgroup/cpuset: Validate type changes against owned CPUs Guopeng Zhang
2026-08-20 12:41 ` [PATCH 07/17] selftests/cgroup: Test type-change validation with child-owned CPUs Guopeng Zhang
2026-08-20 12:41 ` [PATCH 08/17] cgroup/cpuset: Release CPUs when a type change is rejected Guopeng Zhang
2026-08-20 12:41 ` [PATCH 09/17] selftests/cgroup: Test rejected partition type changes Guopeng Zhang
2026-08-20 12:41 ` Guopeng Zhang [this message]
2026-08-20 12:41 ` [PATCH 11/17] selftests/cgroup: Test isolation accounting on direct child invalidation Guopeng Zhang
2026-08-20 12:41 ` [PATCH 12/17] cgroup/cpuset: Invalidate children outside the new CPU mask Guopeng Zhang
2026-08-20 12:41 ` [PATCH 13/17] selftests/cgroup: Test child invalidation after shrinking cpuset.cpus Guopeng Zhang
2026-08-20 12:41 ` [PATCH 14/17] cgroup/cpuset: Publish cpus_allowed before partition updates Guopeng Zhang
2026-08-20 12:42 ` [PATCH 15/17] selftests/cgroup: Test shrinking cpuset.cpus in a remote partition Guopeng Zhang
2026-08-20 12:42 ` [PATCH 16/17] cgroup/cpuset: Fix isolated accounting on propagated invalidation Guopeng Zhang
2026-08-20 12:42 ` [PATCH 17/17] selftests/cgroup: Test isolation " Guopeng Zhang

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=20260820124202.517160-11-guopeng.zhang@linux.dev \
    --to=guopeng.zhang@linux.dev \
    --cc=cgroups@vger.kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=longman@redhat.com \
    --cc=mkoutny@suse.com \
    --cc=ridong.chen@linux.dev \
    --cc=shuah@kernel.org \
    --cc=tj@kernel.org \
    --cc=zhangguopeng@kylinos.cn \
    /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