All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ridong Chen <ridong.chen@linux.dev>
To: Waiman Long <longman@redhat.com>, Tejun Heo <tj@kernel.org>,
	Johannes Weiner <hannes@cmpxchg.org>,
	"Michal Koutn?" <mkoutny@suse.com>
Cc: Guopeng Zhang <guopeng.zhang@linux.dev>,
	Ridong Chen <ridong.chen@linux.dev>,
	cgroups@vger.kernel.org, linux-kernel@vger.kernel.org,
	Ridong Chen <chenridong@xiaomi.com>
Subject: [RFC PATCH -v4 02/22] cpuset: settle isolation state when CPUs are given back to parent
Date: Sun,  1 Nov 2026 19:41:46 +0800	[thread overview]
Message-ID: <20261101114206.2434398-3-ridong.chen@linux.dev> (raw)
In-Reply-To: <20261101114206.2434398-1-ridong.chen@linux.dev>

From: Ridong Chen <chenridong@xiaomi.com>

partition_xcpus_del() only updates isolated_cpus when the partition that
gives back the CPUs has a different state than its parent. CPUs that were
further distributed to descendant isolated partitions are not taken into
account, so isolated_cpus_release() has to be called afterwards in
several places to walk up the ancestors and fix isolated_cpus.

Make partition_xcpus_del() always set the isolation state of the given
back CPUs to the state of the parent that receives them. As the
effective_xcpus of a partition covers the CPUs distributed to its
descendants, the isolation state of those CPUs is settled at the same
time. Boot-time isolated CPUs are still preserved by isolated_cpu_update().

compute_partition_effective_cpumask() invalidates a child partition
without going through partition_xcpus_del(), so do the same there: the
CPUs of the invalidated child take the isolation state of its parent.

isolated_cpus_release() is no longer needed and is removed.

Signed-off-by: Ridong Chen <chenridong@xiaomi.com>
---
 kernel/cgroup/cpuset.c | 86 ++++++++++++------------------------------
 1 file changed, 24 insertions(+), 62 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 72e1df1295e1..df9fc126e391 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1264,42 +1264,21 @@ static void isolated_cpus_update(int old_prs, int new_prs, struct cpumask *xcpus
 }
 
 /*
- * isolated_cpus_release - Remove the relevant CPUs in @xcpus from isolated_cpus
- * @cs: the current cpuset
- * @xcpus: the set of effective xcpus to be considered for removal
- *
- * This function is called when an isolated partition is invalidated or when
- * some of its effective xcpus are to be removed from isolated_cpus due to
- * changes in parent cpuset. The given @xcpus must be modifiable as the function
- * will update its value to determine the right set of CPUs to be removed.
+ * isolated_cpus_set_state - Set the isolation state of @xcpus
+ * @prs: partition root state that @xcpus will belong to
+ * @xcpus: exclusive CPUs whose isolation state may change
  */
-static void isolated_cpus_release(struct cpuset *cs, struct cpumask *xcpus)
+static void isolated_cpus_set_state(int prs, struct cpumask *xcpus)
 {
-	struct cpuset *ancestor = parent_cs(cs);
-	struct cpuset *iancestor = NULL;
-
-	/*
-	 * Search the furthest isolated partition root ancestor available
-	 * until top_cpuset or a remote partition root is hit.
-	 */
-	for (; ancestor; ancestor = parent_cs(ancestor)) {
-		if (ancestor->partition_root_state == PRS_ISOLATED)
-			iancestor = ancestor;
-		if (is_remote_partition(ancestor))
-			break;
-	}
-
-	/*
-	 * If a furthest isolated partition acnestor is found, use it to
-	 * determine which of the CPUs in @xcpus should be removed from
-	 * isolated_cpus. Otherwise, all of them will be removed.
-	 */
-	if (iancestor && !cpumask_andnot(xcpus, xcpus, iancestor->effective_xcpus))
-		return; /* No CPU should be removed from isolated_cpus */
+	bool updated = false;
+	int cpu;
 
-	spin_lock_irq(&callback_lock);
-	isolated_cpus_update(PRS_ISOLATED, PRS_ROOT, xcpus);
-	spin_unlock_irq(&callback_lock);
+	lockdep_assert_held(&callback_lock);
+	lockdep_assert_held(&cpuset_mutex);
+	for_each_cpu(cpu, xcpus)
+		updated |= isolated_cpu_update(prs, cpu);
+	if (updated)
+		update_housekeeping = true;
 }
 
 /*
@@ -1355,9 +1334,12 @@ static void partition_xcpus_del(int old_prs, struct cpuset *parent,
 	if (parent == &top_cpuset)
 		cpumask_andnot(subpartitions_cpus, subpartitions_cpus, xcpus);
 
-	if (old_prs != parent->partition_root_state)
-		isolated_cpus_update(old_prs, parent->partition_root_state,
-				     xcpus);
+	/*
+	 * CPUs given back to parent take the parent's isolation state. This
+	 * also covers CPUs that were further distributed to descendant
+	 * isolated partitions.
+	 */
+	isolated_cpus_set_state(parent->partition_root_state, xcpus);
 
 	cpumask_or(parent->effective_cpus, parent->effective_cpus, xcpus);
 	cpumask_and(parent->effective_cpus, parent->effective_cpus, cpu_active_mask);
@@ -1640,14 +1622,13 @@ static void compute_partition_effective_cpumask(struct cpuset *cs,
 			int parent_prs = cs->partition_root_state;
 
 			/*
-			 * Invalidate child partition and update isolated_cpus
-			 * if necessary.
+			 * Invalidate child partition. Its CPUs, including those
+			 * further distributed to its descendants, take the
+			 * isolation state of cs.
 			 */
 			spin_lock_irq(&callback_lock);
 			WRITE_ONCE(child->prs_err, PERR_NOCPUS);
-			if ((old_prs == PRS_ISOLATED) && (parent_prs == PRS_ROOT))
-				isolated_cpus_update(PRS_ISOLATED, PRS_ROOT,
-						     child->effective_xcpus);
+			isolated_cpus_set_state(parent_prs, child->effective_xcpus);
 			child->partition_root_state = -old_prs;
 			spin_unlock_irq(&callback_lock);
 			notify_partition_change(child, old_prs);
@@ -2090,21 +2071,8 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
 		 *
 		 * A partition error happens when parent has tasks and all
 		 * its effective CPUs will have to be distributed out.
-		 *
-		 * For an isolated partition with a shrunk root partition parent
-		 * we may need to return some or all of its isolated CPUs.
 		 */
 		nocpu |= cpumask_empty(tmp->delmask);
-		if ((parent_prs == PRS_ROOT) && (old_prs == PRS_ISOLATED)) {
-			cpumask_clear(tmp->addmask);
-			if (nocpu)
-				cpumask_copy(tmp->addmask, cs->effective_xcpus);
-			else if (!cpumask_subset(cs->effective_xcpus, parent->effective_xcpus))
-				cpumask_andnot(tmp->addmask, cs->effective_xcpus,
-							     parent->effective_xcpus);
-			if (!cpumask_empty(tmp->addmask))
-				isolated_cpus_release(cs, tmp->addmask);
-		}
 		if (nocpu) {
 			part_error = PERR_NOCPUS;
 			if (is_partition_valid(cs))
@@ -2327,18 +2295,12 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp,
 				/*
 				 * When parent is not a valid partition root,
 				 * child partition roots become invalid too.
-				 *
-				 * For a to be invalidated isolated partition,
-				 * call return_isolated_cpus() to remove the
-				 * relevant CPUs from isolated_cpus.
+				 * The isolation state of their CPUs has been
+				 * settled when the parent gave them back.
 				 */
 				if (is_partition_valid(cp))
 					new_prs = -old_prs;
 
-				if (old_prs == PRS_ISOLATED) {
-					cpumask_copy(tmp->delmask, cp->effective_xcpus);
-					isolated_cpus_release(cp, tmp->delmask);
-				}
 				WRITE_ONCE(cp->prs_err,
 					   is_partition_invalid(parent)
 					   ? PERR_INVPARENT : PERR_NOTPART);
-- 
2.34.1


  parent reply	other threads:[~2026-11-01 11:42 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-01 11:41 [RFC PATCH -v4 00/22] cpuset: rework local partition logic Ridong Chen
2026-11-01 11:41 ` [RFC PATCH -v4 01/22] cpuset: add early empty cpumask check in partition_xcpus_add/del Ridong Chen
2026-11-01 11:41 ` Ridong Chen [this message]
2026-11-01 11:41 ` [RFC PATCH -v4 03/22] cpuset: generalize the validate_partition() interface Ridong Chen
2026-11-01 11:41 ` [RFC PATCH -v4 04/22] cpuset: introduce partition_enable() Ridong Chen
2026-11-01 11:41 ` [RFC PATCH -v4 05/22] cpuset: introduce partition_disable() Ridong Chen
2026-11-01 11:41 ` [RFC PATCH -v4 06/22] cpuset: introduce partition_update() Ridong Chen
2026-11-01 11:41 ` [RFC PATCH -v4 07/22] cpuset: use partition_enable() for remote partition enablement Ridong Chen
2026-11-01 11:41 ` [RFC PATCH -v4 08/22] cpuset: use partition_disable() for remote partition disablement Ridong Chen
2026-11-01 11:41 ` [RFC PATCH -v4 09/22] cpuset: use partition_update() for remote partition update Ridong Chen
2026-11-01 11:41 ` [RFC PATCH -v4 10/22] cpuset: introduce local_partition_enable() Ridong Chen
2026-11-01 11:41 ` [RFC PATCH -v4 11/22] cpuset: introduce local_partition_disable() Ridong Chen
2026-11-01 11:41 ` [RFC PATCH -v4 12/22] cpuset: use local_partition_disable() to invalidate local partition Ridong Chen
2026-11-01 11:41 ` [RFC PATCH -v4 13/22] cpuset: introduce local_partition_update() Ridong Chen
2026-11-01 11:41 ` [RFC PATCH -v4 14/22] cpuset: remove update_parent_effective_cpumask Ridong Chen
2026-11-01 11:41 ` [RFC PATCH -v4 15/22] cpuset: remove redundant partition field updates Ridong Chen
2026-11-01 11:42 ` [RFC PATCH -v4 16/22] cpuset: simplify partition update logic for hotplug tasks Ridong Chen
2026-11-01 11:42 ` [RFC PATCH -v4 17/22] cpuset: use partition_disable for compute_partition_effective_cpumask Ridong Chen
2026-11-01 11:42 ` [RFC PATCH -v4 18/22] cpuset: use validate_local_partition in local_partition_enable Ridong Chen
2026-11-01 11:42 ` [RFC PATCH -v4 19/22] cpuset: introduce validate_remote_partition Ridong Chen
2026-11-01 11:42 ` [RFC PATCH -v4 20/22] cpuset: simplify the update_prstate() function Ridong Chen
2026-11-01 11:42 ` [RFC PATCH -v4 21/22] cpuset: remove prs_err clear when notify_partition_change Ridong Chen
2026-11-01 11:42 ` [RFC PATCH -v4 22/22] cpuset: remove unnecessary validation in partition_cpus_change Ridong Chen

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=20261101114206.2434398-3-ridong.chen@linux.dev \
    --to=ridong.chen@linux.dev \
    --cc=cgroups@vger.kernel.org \
    --cc=chenridong@xiaomi.com \
    --cc=guopeng.zhang@linux.dev \
    --cc=hannes@cmpxchg.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=longman@redhat.com \
    --cc=mkoutny@suse.com \
    --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.