Linux cgroups development
 help / color / mirror / Atom feed
* [PATCH -next 00/21] cpuset: rework local partition logic
@ 2025-11-17  2:46 Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 01/21] cpuset: add early empty cpumask check in partition_xcpus_add/del Chen Ridong
                   ` (21 more replies)
  0 siblings, 22 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

The current local partition implementation consolidates all operations
(enable, disable, invalidate, and update) within the large
update_parent_effective_cpumask() function, which exceeds 300 lines.
This monolithic approach has become increasingly difficult to understand
and maintain. Additionally, partition-related fields are updated in
multiple locations, leading to redundant code and potential corner case
oversights.

This patch series refactors the local partition logic by separating
operations into dedicated functions: local_partition_enable(),
local_partition_disable(), and local_partition_update(), creating
symmetry with the existing remote partition infrastructure.

The series is organized as follows:

1. Infrastructure Preparation (Patches 1-2):
   - Code cleanup and preparation for the refactoring work

2. Introduce partition operation helpers (Patches 3-5):
   - Introduce out partition_enable(), partition_disable(), and
     partition_update() functions.

3. Use new helpers for remote partition (Patches 6-8)

4. Local Partition Implementation (Patches 9-12):
   - Separate update_parent_effective_cpumask() into dedicated functions:
     * local_partition_enable()
     * local_partition_disable()
     * local_partition_update()

5. Optimization and Cleanup (Patches 13-21):
   - Remove redundant partition-related operations
   - Additional optimizations based on the new architecture

base-commit: 6d7e7251d03f98f26f2ee0dfd21bb0a0480a2178

---

Changes from RFC v2:
1. Dropped the bugfix (already merged/fixed upstream)
2. Rebased onto next
3. Introduced partition_switch to handle root state switches
4. Directly use local_partition_disable()—no longer first introduce
   local_partition_invalidate() before unifying the two
5. Incorporated modifications based on Longman's suggestions

Changes in RFC v1:
1. Added bugfix for root partition isolcpus at series start.
2. Completed helper function implementations when first introduced.
3. Split larger patches into smaller, more reviewable units.
4. Incorporated feedback from Longman.

Chen Ridong (21):
  cpuset: add early empty cpumask check in partition_xcpus_add/del
  cpuset: generalize the validate_partition() interface
  cpuset: introduce partition_enable()
  cpuset: introduce partition_disable()
  cpuset: introduce partition_update()
  cpuset: use partition_enable() for remote partition enablement
  cpuset: use partition_disable() for remote partition disablement
  cpuset: use partition_update() for remote partition update
  cpuset: introduce local_partition_enable()
  cpuset: introduce local_partition_disable()
  cpuset: user local_partition_disable() to invalidate local partition
  cpuset: introduce local_partition_update()
  cpuset: remove update_parent_effective_cpumask
  cpuset: remove redundant partition field updates
  cpuset: simplify partition update logic for hotplug tasks
  cpuset: use partition_disable for compute_partition_effective_cpumask
  cpuset: use validate_local_partition in local_partition_enable
  cpuset: introduce validate_remote_partition
  cpuset: simplify the update_prstate() function
  cpuset: remove prs_err clear when notify_partition_change
  cpuset: Remove unnecessary validation in partition_cpus_change

 kernel/cgroup/cpuset.c | 1014 ++++++++++++++++++----------------------
 1 file changed, 453 insertions(+), 561 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH -next 01/21] cpuset: add early empty cpumask check in partition_xcpus_add/del
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 02/21] cpuset: generalize the validate_partition() interface Chen Ridong
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

Add a check for an empty cpumask at the start of partition_xcpus_add()
and partition_xcpus_del(). This allows the functions to return early,
avoiding unnecessary computation when there is no work to be done. With
these changes, partition_xcpus_add() and partition_xcpus_del() can be
called even if xcpus is empty. The caller no longer needs to check whether
xcpus is empty, eliminating many conditional statements.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 8bf7c38ba320..0b7545ca4c18 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1367,10 +1367,13 @@ static void partition_xcpus_add(int new_prs, struct cpuset *parent,
 {
 	WARN_ON_ONCE(new_prs < 0);
 	lockdep_assert_held(&callback_lock);
+
+	if (cpumask_empty(xcpus))
+		return;
+
 	if (!parent)
 		parent = &top_cpuset;
 
-
 	if (parent == &top_cpuset)
 		cpumask_or(subpartitions_cpus, subpartitions_cpus, xcpus);
 
@@ -1394,6 +1397,10 @@ static void partition_xcpus_del(int old_prs, struct cpuset *parent,
 {
 	WARN_ON_ONCE(old_prs < 0);
 	lockdep_assert_held(&callback_lock);
+
+	if (cpumask_empty(xcpus))
+		return;
+
 	if (!parent)
 		parent = &top_cpuset;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 02/21] cpuset: generalize the validate_partition() interface
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 01/21] cpuset: add early empty cpumask check in partition_xcpus_add/del Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 03/21] cpuset: introduce partition_enable() Chen Ridong
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

Refactor validate_partition() to accept a more generic parameter set,
making the interface flexible enough to handle both local and remote
partition validation scenarios. Additionally, a check for whether
isolated CPUs can be updated has been added to validate_partition().

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 87 +++++++++++++++++++-----------------------
 1 file changed, 40 insertions(+), 47 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 0b7545ca4c18..392a0436a19d 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1603,6 +1603,41 @@ static inline bool is_local_partition(struct cpuset *cs)
 	return is_partition_valid(cs) && !is_remote_partition(cs);
 }
 
+/**
+ * validate_partition - Validate a cpuset partition configuration
+ * @cs: The cpuset to validate
+ * @new_prs: The proposed new partition root state
+ * @new_excpus: The new effective exclusive CPUs mask to validate
+ * @add: exclusive CPUs to be added
+ * @del: exclusive CPUs to be deleted
+ *
+ * Return: PRS error code (0 if valid, non-zero error code if invalid)
+ */
+static enum prs_errcode validate_partition(struct cpuset *cs, int new_prs,
+	struct cpumask *new_excpus, struct cpumask *add, struct cpumask *del)
+{
+	struct cpuset *parent = parent_cs(cs);
+	int parent_prs = parent->partition_root_state;
+
+	if (new_prs == PRS_MEMBER)
+		return PERR_NONE;
+
+	if (cpumask_empty(new_excpus))
+		return PERR_INVCPUS;
+
+	if (prstate_housekeeping_conflict(new_prs, new_excpus))
+		return PERR_HKEEPING;
+
+	if ((new_prs == PRS_ISOLATED) && (new_prs != parent_prs) &&
+	    !isolated_cpus_can_update(add, del))
+		return PERR_HKEEPING;
+
+	if (tasks_nocpu_error(parent, cs, new_excpus))
+		return PERR_NOCPUS;
+
+	return PERR_NONE;
+}
+
 /*
  * remote_partition_enable - Enable current cpuset as a remote partition root
  * @cs: the cpuset to update
@@ -1872,22 +1907,9 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
 			WARN_ON_ONCE(!cpumask_empty(cs->exclusive_cpus));
 		new_prs = (cmd == partcmd_enable) ? PRS_ROOT : PRS_ISOLATED;
 
-		/*
-		 * Enabling partition root is not allowed if its
-		 * effective_xcpus is empty.
-		 */
-		if (cpumask_empty(xcpus))
-			return PERR_INVCPUS;
-
-		if (prstate_housekeeping_conflict(new_prs, xcpus))
-			return PERR_HKEEPING;
-
-		if ((new_prs == PRS_ISOLATED) && (new_prs != parent_prs) &&
-		    !isolated_cpus_can_update(xcpus, NULL))
-			return PERR_HKEEPING;
-
-		if (tasks_nocpu_error(parent, cs, xcpus))
-			return PERR_NOCPUS;
+		part_error = validate_partition(cs, new_prs, xcpus, xcpus, NULL);
+		if (part_error)
+			return part_error;
 
 		/*
 		 * This function will only be called when all the preliminary
@@ -2448,36 +2470,6 @@ static int parse_cpuset_cpulist(const char *buf, struct cpumask *out_mask)
 	return 0;
 }
 
-/**
- * validate_partition - Validate a cpuset partition configuration
- * @cs: The cpuset to validate
- * @trialcs: The trial cpuset containing proposed configuration changes
- *
- * If any validation check fails, the appropriate error code is set in the
- * cpuset's prs_err field.
- *
- * Return: PRS error code (0 if valid, non-zero error code if invalid)
- */
-static enum prs_errcode validate_partition(struct cpuset *cs, struct cpuset *trialcs)
-{
-	struct cpuset *parent = parent_cs(cs);
-
-	if (cs_is_member(trialcs))
-		return PERR_NONE;
-
-	if (cpumask_empty(trialcs->effective_xcpus))
-		return PERR_INVCPUS;
-
-	if (prstate_housekeeping_conflict(trialcs->partition_root_state,
-					  trialcs->effective_xcpus))
-		return PERR_HKEEPING;
-
-	if (tasks_nocpu_error(parent, cs, trialcs->effective_xcpus))
-		return PERR_NOCPUS;
-
-	return PERR_NONE;
-}
-
 static int cpus_allowed_validate_change(struct cpuset *cs, struct cpuset *trialcs,
 					struct tmpmasks *tmp)
 {
@@ -2532,7 +2524,8 @@ static void partition_cpus_change(struct cpuset *cs, struct cpuset *trialcs,
 	if (cs_is_member(cs))
 		return;
 
-	prs_err = validate_partition(cs, trialcs);
+	prs_err = validate_partition(cs, trialcs->partition_root_state,
+			trialcs->effective_xcpus, trialcs->effective_xcpus, NULL);
 	if (prs_err)
 		trialcs->prs_err = cs->prs_err = prs_err;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 03/21] cpuset: introduce partition_enable()
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 01/21] cpuset: add early empty cpumask check in partition_xcpus_add/del Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 02/21] cpuset: generalize the validate_partition() interface Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 04/21] cpuset: introduce partition_disable() Chen Ridong
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

Add partition_enable() to consolidate updates to key cpuset structures
during partition enablement, including:
1. remote_partition
2. effective_xcpus
3. partition_root_state
4. prs_err

Key operations performed:
1. Invokes partition_xcpus_add() to assign exclusive CPUs
2. Maintains remote partition flag
3. Syncs the effective_xcpus mask
4. Updates partition_root_state and prs_err
5. Triggers scheduler domain rebuilds
6. Sends partition change notifications

This helper enables transitions between root and isolated states. All
fields except remote_sibling are reassigned during the transition.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 48 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 392a0436a19d..b917f2c55767 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1638,6 +1638,54 @@ static enum prs_errcode validate_partition(struct cpuset *cs, int new_prs,
 	return PERR_NONE;
 }
 
+static void partition_state_update(struct cpuset *cs, int new_prs,
+				   enum prs_errcode prs_err)
+{
+	lockdep_assert_held(&callback_lock);
+
+	cs->partition_root_state = new_prs;
+	WRITE_ONCE(cs->prs_err, prs_err);
+	if (!is_partition_valid(cs))
+		reset_partition_data(cs);
+}
+
+/**
+ * partition_enable - Transitions a cpuset to a partition root
+ * @cs: The cpuset to enable partition for
+ * @parent: Parent cpuset of @cs, NULL for remote parent
+ * @new_prs: New partition state to set
+ * @new_excpus: New effective exclusive CPUs mask for the partition
+ *
+ * Transitions a cpuset to a partition root, only for v2.
+ * It supports the transition between root and isolated partition.
+ */
+static void partition_enable(struct cpuset *cs, struct cpuset *parent,
+			     int new_prs, struct cpumask *new_excpus)
+{
+	int old_prs;
+
+	lockdep_assert_held(&cpuset_mutex);
+	WARN_ON_ONCE(new_prs <= 0);
+	WARN_ON_ONCE(!cpuset_v2());
+
+	if (cs->partition_root_state == new_prs)
+		return;
+
+	old_prs = cs->partition_root_state;
+	spin_lock_irq(&callback_lock);
+	/* enable partition should only add exclusive cpus */
+	partition_xcpus_add(new_prs, parent, new_excpus);
+	/* enable remote partition */
+	if (!parent)
+		cs->remote_partition = true;
+	cpumask_copy(cs->effective_xcpus, new_excpus);
+	partition_state_update(cs, new_prs, PERR_NONE);
+	spin_unlock_irq(&callback_lock);
+	update_isolation_cpumasks();
+	cpuset_force_rebuild();
+	notify_partition_change(cs, old_prs);
+}
+
 /*
  * remote_partition_enable - Enable current cpuset as a remote partition root
  * @cs: the cpuset to update
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 04/21] cpuset: introduce partition_disable()
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (2 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 03/21] cpuset: introduce partition_enable() Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 05/21] cpuset: introduce partition_update() Chen Ridong
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

Add partition_disable() to consolidate updates to key cpuset structures
during partition disablement, including:
1. remote_partition
2. effective_xcpus
3. partition_root_state
4. prs_err

Key operations performed:
1. Cleaning up remote_partition
2. Removing exclusive CPUs via partition_xcpus_del()
3. Recomputing effective exclusive CPUs mask
4. Updating partition state and error status
5. Triggering required scheduler domain rebuilds
6. Clear exclusive flag.
7. Sends partition change notifications

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index b917f2c55767..a85f9619c982 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1686,6 +1686,39 @@ static void partition_enable(struct cpuset *cs, struct cpuset *parent,
 	notify_partition_change(cs, old_prs);
 }
 
+/**
+ * partition_disable - Disable partition root state for a cpuset
+ * @cs: The cpuset to disable partition for
+ * @parent: Parent cpuset of @cs, NULL for remote parent
+ * @new_prs: New partition root state (should be non-positive)
+ * @prs_err: Error code to set if disabling due to validation failure
+ */
+static void partition_disable(struct cpuset *cs, struct cpuset *parent,
+			      int new_prs, enum prs_errcode prs_err)
+{
+	int old_prs;
+
+	lockdep_assert_held(&cpuset_mutex);
+	WARN_ON_ONCE(new_prs > 0);
+	WARN_ON_ONCE(!cpuset_v2());
+
+	old_prs = cs->partition_root_state;
+	spin_lock_irq(&callback_lock);
+	cs->remote_partition = false;
+	/* disable a partition should only delete exclusive cpus */
+	partition_xcpus_del(cs->partition_root_state,
+			    parent, cs->effective_xcpus);
+	/* effective_xcpus may need to be changed */
+	compute_excpus(cs, cs->effective_xcpus);
+	partition_state_update(cs, new_prs, prs_err);
+	spin_unlock_irq(&callback_lock);
+	update_isolation_cpumasks();
+	cpuset_force_rebuild();
+	/* Clear exclusive flag; no errors are expected */
+	update_partition_exclusive_flag(cs, new_prs);
+	notify_partition_change(cs, old_prs);
+}
+
 /*
  * remote_partition_enable - Enable current cpuset as a remote partition root
  * @cs: the cpuset to update
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 05/21] cpuset: introduce partition_update()
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (3 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 04/21] cpuset: introduce partition_disable() Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 06/21] cpuset: use partition_enable() for remote partition enablement Chen Ridong
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

Introduce partition_update() to centralize updates to key cpuset structures
during a partition update, including:
1. effective_xcpus
2. exclusive_cpus

Key operations performed:
1. Adding and removing exclusive CPUs via partition_xcpus_add()/del()
2. Synchronizing the effective exclusive CPUs mask
3. Updating the exclusive CPUs mask when modification is required
4. Triggering necessary system updates and workqueue synchronization
5. Updating the partition's exclusive flag
6. Sending partition change notifications

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 45 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index a85f9619c982..97e3bcd3d073 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1719,6 +1719,51 @@ static void partition_disable(struct cpuset *cs, struct cpuset *parent,
 	notify_partition_change(cs, old_prs);
 }
 
+/**
+ * partition_update - Update an existing partition configuration
+ * @cs: The cpuset to update
+ * @prs: Partition root state (must be positive)
+ * @xcpus: New exclusive CPUs mask for the partition (NULL to keep current)
+ * @excpus: New effective exclusive CPUs mask
+ * @tmp: Temporary masks
+ *
+ * Updates partition-related fields. The tmp->addmask is the CPU mask that
+ * will be added to the subpartitions_cpus and removed from parent's
+ * effective_cpus, and the tmp->delmask vice versa.
+ */
+static void partition_update(struct cpuset *cs, int prs, struct cpumask *xcpus,
+				  struct cpumask *excpus, struct tmpmasks *tmp)
+{
+	struct cpuset *parent;
+	int old_prs;
+
+	lockdep_assert_held(&cpuset_mutex);
+	WARN_ON_ONCE(!cpuset_v2());
+	WARN_ON_ONCE(prs <= 0);
+
+	if (cpumask_empty(tmp->addmask) &&
+	    cpumask_empty(tmp->delmask))
+		return;
+
+	parent = is_remote_partition(cs) ? NULL : parent_cs(cs);
+	old_prs = cs->partition_root_state;
+	spin_lock_irq(&callback_lock);
+	partition_xcpus_add(prs, parent, tmp->addmask);
+	partition_xcpus_del(prs, parent, tmp->delmask);
+	/*
+	 * Need to update effective_xcpus and exclusive_cpus now as
+	 * update_sibling_cpumasks() below may iterate back to the same cs.
+	 */
+	cpumask_copy(cs->effective_xcpus, excpus);
+	if (xcpus)
+		cpumask_copy(cs->exclusive_cpus, xcpus);
+	spin_unlock_irq(&callback_lock);
+	update_isolation_cpumasks();
+	cpuset_force_rebuild();
+	update_partition_exclusive_flag(cs, prs);
+	notify_partition_change(cs, old_prs);
+}
+
 /*
  * remote_partition_enable - Enable current cpuset as a remote partition root
  * @cs: the cpuset to update
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 06/21] cpuset: use partition_enable() for remote partition enablement
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (4 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 05/21] cpuset: introduce partition_update() Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 07/21] cpuset: use partition_disable() for remote partition disablement Chen Ridong
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

Now that the partition_enable() helper is available, replace the
existing implementation for remote partition enablement with this
centralized function to unify the enablement logic.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 97e3bcd3d073..31c7b967c81d 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1803,15 +1803,7 @@ static int remote_partition_enable(struct cpuset *cs, int new_prs,
 	    prstate_housekeeping_conflict(new_prs, tmp->new_cpus))
 		return PERR_HKEEPING;
 
-	spin_lock_irq(&callback_lock);
-	partition_xcpus_add(new_prs, NULL, tmp->new_cpus);
-	cs->remote_partition = true;
-	cpumask_copy(cs->effective_xcpus, tmp->new_cpus);
-	spin_unlock_irq(&callback_lock);
-	update_isolation_cpumasks();
-	cpuset_force_rebuild();
-	cs->prs_err = 0;
-
+	partition_enable(cs, NULL, new_prs, tmp->new_cpus);
 	/*
 	 * Propagate changes in top_cpuset's effective_cpus down the hierarchy.
 	 */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 07/21] cpuset: use partition_disable() for remote partition disablement
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (5 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 06/21] cpuset: use partition_enable() for remote partition enablement Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 08/21] cpuset: use partition_update() for remote partition update Chen Ridong
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

Now that the partition_disable() helper is available, replace the
existing implementation for remote partition disablement with this
centralized function to unify the disablement logic.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 18 ++++--------------
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 31c7b967c81d..1482c501a49c 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1823,23 +1823,13 @@ static int remote_partition_enable(struct cpuset *cs, int new_prs,
  */
 static void remote_partition_disable(struct cpuset *cs, struct tmpmasks *tmp)
 {
+	int new_prs;
+
 	WARN_ON_ONCE(!is_remote_partition(cs));
 	WARN_ON_ONCE(!cpumask_subset(cs->effective_xcpus, subpartitions_cpus));
 
-	spin_lock_irq(&callback_lock);
-	cs->remote_partition = false;
-	partition_xcpus_del(cs->partition_root_state, NULL, cs->effective_xcpus);
-	if (cs->prs_err)
-		cs->partition_root_state = -cs->partition_root_state;
-	else
-		cs->partition_root_state = PRS_MEMBER;
-
-	/* effective_xcpus may need to be changed */
-	compute_excpus(cs, cs->effective_xcpus);
-	reset_partition_data(cs);
-	spin_unlock_irq(&callback_lock);
-	update_isolation_cpumasks();
-	cpuset_force_rebuild();
+	new_prs = cs->prs_err ? -cs->partition_root_state : PRS_MEMBER;
+	partition_disable(cs, NULL, new_prs, cs->prs_err);
 
 	/*
 	 * Propagate changes in top_cpuset's effective_cpus down the hierarchy.
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 08/21] cpuset: use partition_update() for remote partition update
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (6 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 07/21] cpuset: use partition_disable() for remote partition disablement Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 09/21] cpuset: introduce local_partition_enable() Chen Ridong
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

Now that the partition_update() helper is available, use it to replace
the existing remote partition update logic. This unifies the update
path through a single centralized function.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 25 ++++---------------------
 1 file changed, 4 insertions(+), 21 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 1482c501a49c..392b01f95e62 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1851,7 +1851,6 @@ static void remote_partition_disable(struct cpuset *cs, struct tmpmasks *tmp)
 static void remote_cpus_update(struct cpuset *cs, struct cpumask *xcpus,
 			       struct cpumask *excpus, struct tmpmasks *tmp)
 {
-	bool adding, deleting;
 	int prs = cs->partition_root_state;
 
 	if (WARN_ON_ONCE(!is_remote_partition(cs)))
@@ -1864,15 +1863,15 @@ static void remote_cpus_update(struct cpuset *cs, struct cpumask *xcpus,
 		goto invalidate;
 	}
 
-	adding   = cpumask_andnot(tmp->addmask, excpus, cs->effective_xcpus);
-	deleting = cpumask_andnot(tmp->delmask, cs->effective_xcpus, excpus);
+	cpumask_andnot(tmp->addmask, excpus, cs->effective_xcpus);
+	cpumask_andnot(tmp->delmask, cs->effective_xcpus, excpus);
 
 	/*
 	 * Additions of remote CPUs is only allowed if those CPUs are
 	 * not allocated to other partitions and there are effective_cpus
 	 * left in the top cpuset.
 	 */
-	if (adding) {
+	if (!cpumask_empty(tmp->addmask)) {
 		WARN_ON_ONCE(cpumask_intersects(tmp->addmask, subpartitions_cpus));
 		if (!capable(CAP_SYS_ADMIN))
 			cs->prs_err = PERR_ACCESS;
@@ -1886,23 +1885,7 @@ static void remote_cpus_update(struct cpuset *cs, struct cpumask *xcpus,
 			goto invalidate;
 	}
 
-	spin_lock_irq(&callback_lock);
-	if (adding)
-		partition_xcpus_add(prs, NULL, tmp->addmask);
-	if (deleting)
-		partition_xcpus_del(prs, NULL, tmp->delmask);
-	/*
-	 * Need to update effective_xcpus and exclusive_cpus now as
-	 * update_sibling_cpumasks() below may iterate back to the same cs.
-	 */
-	cpumask_copy(cs->effective_xcpus, excpus);
-	if (xcpus)
-		cpumask_copy(cs->exclusive_cpus, xcpus);
-	spin_unlock_irq(&callback_lock);
-	update_isolation_cpumasks();
-	if (adding || deleting)
-		cpuset_force_rebuild();
-
+	partition_update(cs, cs->partition_root_state, xcpus, excpus, tmp);
 	/*
 	 * Propagate changes in top_cpuset's effective_cpus down the hierarchy.
 	 */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 09/21] cpuset: introduce local_partition_enable()
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (7 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 08/21] cpuset: use partition_update() for remote partition update Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 10/21] cpuset: introduce local_partition_disable() Chen Ridong
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

The partition_enable() function introduced in the previous patch can be
reused to enable local partitions.

The local_partition_enable() function is introduced, which factors out the
local partition enablement logic from update_parent_effective_cpumask().
After passing local partition validation checks, it delegates to
partition_enable() to complete the partition setup.

This refactoring creates a clear separation between local and remote
partition operations while maintaining code reuse through the shared
partition_enable() infrastructure.

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

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 392b01f95e62..3c1e8431c234 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1897,6 +1897,52 @@ static void remote_cpus_update(struct cpuset *cs, struct cpumask *xcpus,
 	remote_partition_disable(cs, tmp);
 }
 
+/**
+ * local_partition_enable - Enable local partition for a cpuset
+ * @cs: Target cpuset to become a local partition root
+ * @new_prs: New partition root state to apply
+ * @tmp: Temporary masks for CPU calculations
+ *
+ * Return: 0 on success, error code on failure
+ */
+static int local_partition_enable(struct cpuset *cs,
+				int new_prs, struct tmpmasks *tmp)
+{
+	struct cpuset *parent = parent_cs(cs);
+	enum prs_errcode err;
+
+	lockdep_assert_held(&cpuset_mutex);
+	WARN_ON_ONCE(is_remote_partition(cs));	/* For local partition only */
+
+	/*
+	 * The parent must be a partition root.
+	 * The new cpumask, if present, or the current cpus_allowed must
+	 * not be empty.
+	 */
+	if (!is_partition_valid(parent)) {
+		return is_partition_invalid(parent)
+			? PERR_INVPARENT : PERR_NOTPART;
+	}
+
+	/*
+	 * Need to call compute_excpus() in case
+	 * exclusive_cpus not set. Sibling conflict should only happen
+	 * if exclusive_cpus isn't set.
+	 */
+	if (compute_excpus(cs, tmp->new_cpus))
+		WARN_ON_ONCE(!cpumask_empty(cs->exclusive_cpus));
+
+	err = validate_partition(cs, new_prs, tmp->new_cpus, tmp->new_cpus, NULL);
+	if (err)
+		return err;
+
+	partition_enable(cs, parent, new_prs, tmp->new_cpus);
+
+	cpuset_update_tasks_cpumask(parent, tmp->addmask);
+	update_sibling_cpumasks(parent, cs, tmp);
+	return 0;
+}
+
 /**
  * update_parent_effective_cpumask - update effective_cpus mask of parent cpuset
  * @cs:      The cpuset that requests change in partition root state
@@ -1987,35 +2033,7 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
 
 	nocpu = tasks_nocpu_error(parent, cs, xcpus);
 
-	if ((cmd == partcmd_enable) || (cmd == partcmd_enablei)) {
-		/*
-		 * Need to call compute_excpus() in case
-		 * exclusive_cpus not set. Sibling conflict should only happen
-		 * if exclusive_cpus isn't set.
-		 */
-		xcpus = tmp->delmask;
-		if (compute_excpus(cs, xcpus))
-			WARN_ON_ONCE(!cpumask_empty(cs->exclusive_cpus));
-		new_prs = (cmd == partcmd_enable) ? PRS_ROOT : PRS_ISOLATED;
-
-		part_error = validate_partition(cs, new_prs, xcpus, xcpus, NULL);
-		if (part_error)
-			return part_error;
-
-		/*
-		 * This function will only be called when all the preliminary
-		 * checks have passed. At this point, the following condition
-		 * should hold.
-		 *
-		 * (cs->effective_xcpus & cpu_active_mask) ⊆ parent->effective_cpus
-		 *
-		 * Warn if it is not the case.
-		 */
-		cpumask_and(tmp->new_cpus, xcpus, cpu_active_mask);
-		WARN_ON_ONCE(!cpumask_subset(tmp->new_cpus, parent->effective_cpus));
-
-		deleting = true;
-	} else if (cmd == partcmd_disable) {
+	if (cmd == partcmd_disable) {
 		/*
 		 * May need to add cpus back to parent's effective_cpus
 		 * (and maybe removed from subpartitions_cpus/isolated_cpus)
@@ -3147,14 +3165,10 @@ static int update_prstate(struct cpuset *cs, int new_prs)
 		 * If parent is valid partition, enable local partiion.
 		 * Otherwise, enable a remote partition.
 		 */
-		if (is_partition_valid(parent)) {
-			enum partition_cmd cmd = (new_prs == PRS_ROOT)
-					       ? partcmd_enable : partcmd_enablei;
-
-			err = update_parent_effective_cpumask(cs, cmd, NULL, &tmpmask);
-		} else {
+		if (is_partition_valid(parent))
+			err = local_partition_enable(cs, new_prs, &tmpmask);
+		else
 			err = remote_partition_enable(cs, new_prs, &tmpmask);
-		}
 	} else if (old_prs && new_prs) {
 		/*
 		 * A change in load balance state only, no change in cpumasks.
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 10/21] cpuset: introduce local_partition_disable()
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (8 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 09/21] cpuset: introduce local_partition_enable() Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 11/21] cpuset: user local_partition_disable() to invalidate local partition Chen Ridong
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

The partition_disable() function introduced earlier can be extended to
handle local partition disablement.

The local_partition_disable() functions is introduced, which extracts the
local partition disable logic from update_parent_effective_cpumask(). It
calls partition_disable() to complete the disablement process.

This refactoring establishes a clear separation between local and remote
partition operations while promoting code reuse through the shared
partition_disable() infrastructure.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 43 ++++++++++++++++++++++++++----------------
 1 file changed, 27 insertions(+), 16 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 3c1e8431c234..fe166d7ed49d 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1943,6 +1943,31 @@ static int local_partition_enable(struct cpuset *cs,
 	return 0;
 }
 
+/**
+ * local_partition_disable - Disable a local partition
+ * @cs: Target cpuset (local partition root) to disable
+ * @part_error: partition error when @cs is disabled
+ * @tmp: Temporary masks for CPU calculations
+ */
+static void local_partition_disable(struct cpuset *cs, enum prs_errcode part_error,
+				    struct tmpmasks *tmp)
+{
+	struct cpuset *parent = parent_cs(cs);
+	int new_prs;
+
+	lockdep_assert_held(&cpuset_mutex);
+	WARN_ON_ONCE(is_remote_partition(cs));	/* For local partition only */
+
+	if (!is_partition_valid(cs))
+		return;
+
+	new_prs = part_error ? -cs->partition_root_state : 0;
+	partition_disable(cs, parent, new_prs, part_error);
+
+	cpuset_update_tasks_cpumask(parent, tmp->addmask);
+	update_sibling_cpumasks(parent, cs, tmp);
+}
+
 /**
  * update_parent_effective_cpumask - update effective_cpus mask of parent cpuset
  * @cs:      The cpuset that requests change in partition root state
@@ -2033,19 +2058,7 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
 
 	nocpu = tasks_nocpu_error(parent, cs, xcpus);
 
-	if (cmd == partcmd_disable) {
-		/*
-		 * May need to add cpus back to parent's effective_cpus
-		 * (and maybe removed from subpartitions_cpus/isolated_cpus)
-		 * for valid partition root. xcpus may contain CPUs that
-		 * shouldn't be removed from the two global cpumasks.
-		 */
-		if (is_partition_valid(cs)) {
-			cpumask_copy(tmp->addmask, cs->effective_xcpus);
-			adding = true;
-		}
-		new_prs = PRS_MEMBER;
-	} else if (newmask) {
+	if (newmask) {
 		/*
 		 * Empty cpumask is not allowed
 		 */
@@ -3188,9 +3201,7 @@ static int update_prstate(struct cpuset *cs, int new_prs)
 		if (is_remote_partition(cs))
 			remote_partition_disable(cs, &tmpmask);
 		else
-			update_parent_effective_cpumask(cs, partcmd_disable,
-							NULL, &tmpmask);
-
+			local_partition_disable(cs, PERR_NONE, &tmpmask);
 		/*
 		 * Invalidation of child partitions will be done in
 		 * update_cpumasks_hier().
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 11/21] cpuset: user local_partition_disable() to invalidate local partition
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (9 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 10/21] cpuset: introduce local_partition_disable() Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 12/21] cpuset: introduce local_partition_update() Chen Ridong
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

Build on the local_partition_disable() infrastructure introduced in the
previous patch to handle local partition invalidation.

Additionally, correct the transition logic in cpuset_hotplug_update_tasks()
when determining whether to transition an invalid partition root, the check
should be based on non-empty user_xcpus rather than non-empty
effective_xcpus. This correction addresses the scenario where
exclusive_cpus is not set but cpus_allowed is configured. In this case,
effective_xcpus may be empty even though the partition should be considered
for re-enablement. The user_xcpus based check ensures proper partition
state transitions under these conditions.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 32 +++++++++-----------------------
 1 file changed, 9 insertions(+), 23 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index fe166d7ed49d..770a28491cb7 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2028,22 +2028,6 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
 	adding = deleting = false;
 	old_prs = new_prs = cs->partition_root_state;
 
-	if (cmd == partcmd_invalidate) {
-		if (is_partition_invalid(cs))
-			return 0;
-
-		/*
-		 * Make the current partition invalid.
-		 */
-		if (is_partition_valid(parent))
-			adding = cpumask_and(tmp->addmask,
-					     xcpus, parent->effective_xcpus);
-		if (old_prs > 0)
-			new_prs = -old_prs;
-
-		goto write_error;
-	}
-
 	/*
 	 * The parent must be a partition root.
 	 * The new cpumask, if present, or the current cpus_allowed must
@@ -2619,7 +2603,7 @@ static int cpus_allowed_validate_change(struct cpuset *cs, struct cpuset *trialc
 			if (is_partition_valid(cp) &&
 			    cpumask_intersects(xcpus, cp->effective_xcpus)) {
 				rcu_read_unlock();
-				update_parent_effective_cpumask(cp, partcmd_invalidate, NULL, tmp);
+				local_partition_disable(cp, PERR_NOTEXCL, tmp);
 				rcu_read_lock();
 			}
 		}
@@ -2659,8 +2643,7 @@ static void partition_cpus_change(struct cpuset *cs, struct cpuset *trialcs,
 					   trialcs->effective_xcpus, tmp);
 	} else {
 		if (trialcs->prs_err)
-			update_parent_effective_cpumask(cs, partcmd_invalidate,
-							NULL, tmp);
+			local_partition_disable(cs, trialcs->prs_err, tmp);
 		else
 			update_parent_effective_cpumask(cs, partcmd_update,
 							trialcs->effective_xcpus, tmp);
@@ -4104,18 +4087,21 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp)
 	 *    partitions.
 	 */
 	if (is_local_partition(cs) && (!is_partition_valid(parent) ||
-				tasks_nocpu_error(parent, cs, &new_cpus)))
+				tasks_nocpu_error(parent, cs, &new_cpus))) {
 		partcmd = partcmd_invalidate;
+		local_partition_disable(cs, cs->prs_err, tmp);
+	}
 	/*
 	 * On the other hand, an invalid partition root may be transitioned
-	 * back to a regular one with a non-empty effective xcpus.
+	 * back to a regular one with a non-empty user xcpus.
 	 */
 	else if (is_partition_valid(parent) && is_partition_invalid(cs) &&
-		 !cpumask_empty(cs->effective_xcpus))
+		 !cpumask_empty(user_xcpus(cs))) {
 		partcmd = partcmd_update;
+		update_parent_effective_cpumask(cs, partcmd, NULL, 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);
 			cpuset_force_rebuild();
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 12/21] cpuset: introduce local_partition_update()
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (10 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 11/21] cpuset: user local_partition_disable() to invalidate local partition Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 13/21] cpuset: remove update_parent_effective_cpumask Chen Ridong
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

The local_partition_update() function replaces the command partcmd_update
previously handled within update_parent_effective_cpumask(). The update
logic follows a state-based approach:

1. Validation check: First verify if the local partition is currently valid
2. Invalidation handling: If the partition is invalid, trigger invalidation
3. State transition: If an invalid partition has no errors, transition to
   valid
4. cpumask updates: For local partition that only cpu maks changes, use
   partition_update() to handle partition change.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 151 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 146 insertions(+), 5 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 770a28491cb7..d1f0824bc7c9 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1897,6 +1897,62 @@ static void remote_cpus_update(struct cpuset *cs, struct cpumask *xcpus,
 	remote_partition_disable(cs, tmp);
 }
 
+static bool is_user_xcpus_exclusive(struct cpuset *cs)
+{
+	struct cpuset *parent = parent_cs(cs);
+	struct cgroup_subsys_state *css;
+	struct cpuset *child;
+	bool exclusive = true;
+
+	rcu_read_lock();
+	cpuset_for_each_child(child, css, parent) {
+		if (child == cs)
+			continue;
+		if (!cpusets_are_exclusive(cs, child)) {
+			exclusive = false;
+			break;
+		}
+	}
+	rcu_read_unlock();
+	return exclusive;
+}
+
+/**
+ * validate_local_partition - Validate for local partition
+ * @cs: Target cpuset to validate
+ * @new_prs: New partition root state to validate
+ * @excpus: New exclusive effectuve CPUs mask to validate
+ * @excl_check: Flag to enable exclusive CPUs ownership validation
+ * @tmp: Temporary masks
+ *
+ * Return: PERR_NONE if validation passes, appropriate error code otherwise
+ *
+ * Important: The caller must ensure that @cs's cpu mask is updated before
+ * invoking this function when exclusive CPU validation is required.
+ */
+static enum prs_errcode validate_local_partition(struct cpuset *cs, int new_prs,
+			struct cpumask *excpus, bool excl_check, struct tmpmasks *tmp)
+{
+	struct cpuset *parent = parent_cs(cs);
+
+	/*
+	 * The parent must be a partition root.
+	 * The new cpumask, if present, or the current cpus_allowed must
+	 * not be empty.
+	 */
+	if (!is_partition_valid(parent)) {
+		return is_partition_invalid(parent)
+			? PERR_INVPARENT : PERR_NOTPART;
+	}
+
+	if (excl_check && !is_user_xcpus_exclusive(cs))
+		return PERR_NOTEXCL;
+
+	if (!tmp)
+		return validate_partition(cs, new_prs, excpus, excpus, NULL);
+	return validate_partition(cs, new_prs, excpus, tmp->addmask, tmp->delmask);
+}
+
 /**
  * local_partition_enable - Enable local partition for a cpuset
  * @cs: Target cpuset to become a local partition root
@@ -1968,6 +2024,85 @@ static void local_partition_disable(struct cpuset *cs, enum prs_errcode part_err
 	update_sibling_cpumasks(parent, cs, tmp);
 }
 
+/**
+ * __local_partition_update - Update local partition configuration
+ * @cs: Target cpuset to update
+ * @xcpus: New exclusive CPU mask
+ * @excpus: New effective exclusive CPU mask
+ * @tmp: Temporary mask storage for intermediate calculations
+ * @excl_check: Flag to enable exclusivity validation
+ *
+ * Handles updates to local CPU partition configurations by validating
+ * changes, managing state transitions, and propagating updates through
+ * the cpuset hierarchy.
+ *
+ * Note on exclusivity checking: Exclusivity validation is required when
+ * transitioning from an invalid to valid partition state. However, when
+ * updating cpus_allowed or exclusive_cpus, exclusivity should have already
+ * been verified by validate_change(). In such cases, excl_check must be
+ * false since the cs cpumasks are not yet updated.
+ *
+ * Return: Partition error code (PERR_NONE indicates success)
+ */
+static int __local_partition_update(struct cpuset *cs, struct cpumask *xcpus,
+				  struct cpumask *excpus, struct tmpmasks *tmp,
+				  bool excl_check)
+{
+	struct cpuset *parent = parent_cs(cs);
+	int part_error = PERR_NONE;	/* Partition error? */
+	int old_prs, new_prs;
+
+	lockdep_assert_held(&cpuset_mutex);
+	/* For local partition only */
+	if (WARN_ON_ONCE(is_remote_partition(cs) || cs_is_member(cs)))
+		return PERR_NONE;
+
+	old_prs = cs->partition_root_state;
+	/*
+	 * If new_prs < 0, it might transition to valid partition state.
+	 * Use absolute value for validation checks.
+	 */
+	new_prs = old_prs < 0 ? -old_prs : old_prs;
+	cpumask_andnot(tmp->addmask, excpus, cs->effective_xcpus);
+	cpumask_andnot(tmp->delmask, cs->effective_xcpus, excpus);
+	part_error = validate_local_partition(cs, new_prs, excpus,
+					      excl_check, tmp);
+	if (part_error) {
+		local_partition_disable(cs, part_error, tmp);
+		return part_error;
+	}
+
+	/* Nothing changes, return PERR_NONE */
+	if (new_prs == old_prs &&
+	    (cpumask_empty(tmp->addmask) && cpumask_empty(tmp->delmask)))
+		return PERR_NONE;
+
+	/*
+	 * If partition was previously invalid but now passes checks,
+	 * re-enable it and update related flags.
+	 * Otherwise, partition state doesn't change, only cpumasks change.
+	 */
+	if (is_partition_invalid(cs)) {
+		partition_enable(cs, parent, new_prs, excpus);
+		update_partition_exclusive_flag(cs, new_prs);
+		update_partition_sd_lb(cs, old_prs);
+	} else {
+		partition_update(cs, new_prs, xcpus, excpus, tmp);
+	}
+
+	cpuset_update_tasks_cpumask(parent, tmp->addmask);
+	update_sibling_cpumasks(parent, cs, tmp);
+	return PERR_NONE;
+}
+
+static int local_partition_update(struct cpuset *cs, struct tmpmasks *tmp)
+{
+	struct cpuset *parent = parent_cs(cs);
+
+	cpumask_and(tmp->new_cpus, user_xcpus(cs), parent->effective_xcpus);
+	return __local_partition_update(cs, NULL, tmp->new_cpus, tmp, true);
+}
+
 /**
  * update_parent_effective_cpumask - update effective_cpus mask of parent cpuset
  * @cs:      The cpuset that requests change in partition root state
@@ -2445,9 +2580,16 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp,
 		if (!css_tryget_online(&cp->css))
 			continue;
 		rcu_read_unlock();
+		/*
+		 * The tmp->new_cpus may by modified.
+		 * Update effective_cpus before passing tmp to other functions.
+		 */
+		spin_lock_irq(&callback_lock);
+		cpumask_copy(cp->effective_cpus, tmp->new_cpus);
+		spin_unlock_irq(&callback_lock);
 
 		if (update_parent) {
-			update_parent_effective_cpumask(cp, partcmd_update, NULL, tmp);
+			local_partition_update(cp, tmp);
 			/*
 			 * The cpuset partition_root_state may become
 			 * invalid. Capture it.
@@ -2456,7 +2598,6 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp,
 		}
 
 		spin_lock_irq(&callback_lock);
-		cpumask_copy(cp->effective_cpus, tmp->new_cpus);
 		cp->partition_root_state = new_prs;
 		if (!cpumask_empty(cp->exclusive_cpus) && (cp != cs))
 			compute_excpus(cp, cp->effective_xcpus);
@@ -2645,8 +2786,8 @@ static void partition_cpus_change(struct cpuset *cs, struct cpuset *trialcs,
 		if (trialcs->prs_err)
 			local_partition_disable(cs, trialcs->prs_err, tmp);
 		else
-			update_parent_effective_cpumask(cs, partcmd_update,
-							trialcs->effective_xcpus, tmp);
+			__local_partition_update(cs, trialcs->exclusive_cpus,
+						 trialcs->effective_xcpus, tmp, false);
 	}
 }
 
@@ -4098,7 +4239,7 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp)
 	else if (is_partition_valid(parent) && is_partition_invalid(cs) &&
 		 !cpumask_empty(user_xcpus(cs))) {
 		partcmd = partcmd_update;
-		update_parent_effective_cpumask(cs, partcmd, NULL, tmp);
+		local_partition_update(cs, tmp);
 	}
 
 	if (partcmd >= 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 13/21] cpuset: remove update_parent_effective_cpumask
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (11 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 12/21] cpuset: introduce local_partition_update() Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 14/21] cpuset: remove redundant partition field updates Chen Ridong
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

Clean up by removing the update_parent_effective_cpumask() function.
Its logic has now been fully replaced and centralized by the new
helper functions.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 282 -----------------------------------------
 1 file changed, 282 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index d1f0824bc7c9..65430e12b58f 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2103,288 +2103,6 @@ static int local_partition_update(struct cpuset *cs, struct tmpmasks *tmp)
 	return __local_partition_update(cs, NULL, tmp->new_cpus, tmp, true);
 }
 
-/**
- * update_parent_effective_cpumask - update effective_cpus mask of parent cpuset
- * @cs:      The cpuset that requests change in partition root state
- * @cmd:     Partition root state change command
- * @newmask: Optional new cpumask for partcmd_update
- * @tmp:     Temporary addmask and delmask
- * Return:   0 or a partition root state error code
- *
- * For partcmd_enable*, the cpuset is being transformed from a non-partition
- * root to a partition root. The effective_xcpus (cpus_allowed if
- * effective_xcpus not set) mask of the given cpuset will be taken away from
- * parent's effective_cpus. The function will return 0 if all the CPUs listed
- * in effective_xcpus can be granted or an error code will be returned.
- *
- * For partcmd_disable, the cpuset is being transformed from a partition
- * root back to a non-partition root. Any CPUs in effective_xcpus will be
- * given back to parent's effective_cpus. 0 will always be returned.
- *
- * For partcmd_update, if the optional newmask is specified, the cpu list is
- * to be changed from effective_xcpus to newmask. Otherwise, effective_xcpus is
- * assumed to remain the same. The cpuset should either be a valid or invalid
- * partition root. The partition root state may change from valid to invalid
- * or vice versa. An error code will be returned if transitioning from
- * invalid to valid violates the exclusivity rule.
- *
- * For partcmd_invalidate, the current partition will be made invalid.
- *
- * The partcmd_enable* and partcmd_disable commands are used by
- * update_prstate(). An error code may be returned and the caller will check
- * for error.
- *
- * The partcmd_update command is used by update_cpumasks_hier() with newmask
- * NULL and update_cpumask() with newmask set. The partcmd_invalidate is used
- * by update_cpumask() with NULL newmask. In both cases, the callers won't
- * check for error and so partition_root_state and prs_err will be updated
- * directly.
- */
-static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
-					   struct cpumask *newmask,
-					   struct tmpmasks *tmp)
-{
-	struct cpuset *parent = parent_cs(cs);
-	int adding;	/* Adding cpus to parent's effective_cpus	*/
-	int deleting;	/* Deleting cpus from parent's effective_cpus	*/
-	int old_prs, new_prs;
-	int part_error = PERR_NONE;	/* Partition error? */
-	struct cpumask *xcpus = user_xcpus(cs);
-	int parent_prs = parent->partition_root_state;
-	bool nocpu;
-
-	lockdep_assert_held(&cpuset_mutex);
-	WARN_ON_ONCE(is_remote_partition(cs));	/* For local partition only */
-
-	/*
-	 * new_prs will only be changed for the partcmd_update and
-	 * partcmd_invalidate commands.
-	 */
-	adding = deleting = false;
-	old_prs = new_prs = cs->partition_root_state;
-
-	/*
-	 * The parent must be a partition root.
-	 * The new cpumask, if present, or the current cpus_allowed must
-	 * not be empty.
-	 */
-	if (!is_partition_valid(parent)) {
-		return is_partition_invalid(parent)
-		       ? PERR_INVPARENT : PERR_NOTPART;
-	}
-	if (!newmask && xcpus_empty(cs))
-		return PERR_CPUSEMPTY;
-
-	nocpu = tasks_nocpu_error(parent, cs, xcpus);
-
-	if (newmask) {
-		/*
-		 * Empty cpumask is not allowed
-		 */
-		if (cpumask_empty(newmask)) {
-			part_error = PERR_CPUSEMPTY;
-			goto write_error;
-		}
-
-		/* Check newmask again, whether cpus are available for parent/cs */
-		nocpu |= tasks_nocpu_error(parent, cs, newmask);
-
-		/*
-		 * partcmd_update with newmask:
-		 *
-		 * Compute add/delete mask to/from effective_cpus
-		 *
-		 * For valid partition:
-		 *   addmask = exclusive_cpus & ~newmask
-		 *			      & parent->effective_xcpus
-		 *   delmask = newmask & ~exclusive_cpus
-		 *		       & parent->effective_xcpus
-		 *
-		 * For invalid partition:
-		 *   delmask = newmask & parent->effective_xcpus
-		 *   The partition may become valid soon.
-		 */
-		if (is_partition_invalid(cs)) {
-			adding = false;
-			deleting = cpumask_and(tmp->delmask,
-					newmask, parent->effective_xcpus);
-		} else {
-			cpumask_andnot(tmp->addmask, xcpus, newmask);
-			adding = cpumask_and(tmp->addmask, tmp->addmask,
-					     parent->effective_xcpus);
-
-			cpumask_andnot(tmp->delmask, newmask, xcpus);
-			deleting = cpumask_and(tmp->delmask, tmp->delmask,
-					       parent->effective_xcpus);
-		}
-
-		/*
-		 * TBD: Invalidate a currently valid child root partition may
-		 * still break isolated_cpus_can_update() rule if parent is an
-		 * isolated partition.
-		 */
-		if (is_partition_valid(cs) && (old_prs != parent_prs)) {
-			if ((parent_prs == PRS_ROOT) &&
-			    /* Adding to parent means removing isolated CPUs */
-			    !isolated_cpus_can_update(tmp->delmask, tmp->addmask))
-				part_error = PERR_HKEEPING;
-			if ((parent_prs == PRS_ISOLATED) &&
-			    /* Adding to parent means adding isolated CPUs */
-			    !isolated_cpus_can_update(tmp->addmask, tmp->delmask))
-				part_error = PERR_HKEEPING;
-		}
-
-		/*
-		 * The new CPUs to be removed from parent's effective CPUs
-		 * must be present.
-		 */
-		if (deleting) {
-			cpumask_and(tmp->new_cpus, tmp->delmask, cpu_active_mask);
-			WARN_ON_ONCE(!cpumask_subset(tmp->new_cpus, parent->effective_cpus));
-		}
-
-		/*
-		 * Make partition invalid if parent's effective_cpus could
-		 * become empty and there are tasks in the parent.
-		 */
-		if (nocpu && (!adding ||
-		    !cpumask_intersects(tmp->addmask, cpu_active_mask))) {
-			part_error = PERR_NOCPUS;
-			deleting = false;
-			adding = cpumask_and(tmp->addmask,
-					     xcpus, parent->effective_xcpus);
-		}
-	} else {
-		/*
-		 * partcmd_update w/o newmask
-		 *
-		 * delmask = effective_xcpus & parent->effective_cpus
-		 *
-		 * This can be called from:
-		 * 1) update_cpumasks_hier()
-		 * 2) cpuset_hotplug_update_tasks()
-		 *
-		 * Check to see if it can be transitioned from valid to
-		 * invalid partition or vice versa.
-		 *
-		 * A partition error happens when parent has tasks and all
-		 * its effective CPUs will have to be distributed out.
-		 */
-		if (nocpu) {
-			part_error = PERR_NOCPUS;
-			if (is_partition_valid(cs))
-				adding = cpumask_and(tmp->addmask,
-						xcpus, parent->effective_xcpus);
-		} else if (is_partition_invalid(cs) && !cpumask_empty(xcpus) &&
-			   cpumask_subset(xcpus, parent->effective_xcpus)) {
-			struct cgroup_subsys_state *css;
-			struct cpuset *child;
-			bool exclusive = true;
-
-			/*
-			 * Convert invalid partition to valid has to
-			 * pass the cpu exclusivity test.
-			 */
-			rcu_read_lock();
-			cpuset_for_each_child(child, css, parent) {
-				if (child == cs)
-					continue;
-				if (!cpusets_are_exclusive(cs, child)) {
-					exclusive = false;
-					break;
-				}
-			}
-			rcu_read_unlock();
-			if (exclusive)
-				deleting = cpumask_and(tmp->delmask,
-						xcpus, parent->effective_cpus);
-			else
-				part_error = PERR_NOTEXCL;
-		}
-	}
-
-write_error:
-	if (part_error)
-		WRITE_ONCE(cs->prs_err, part_error);
-
-	if (cmd == partcmd_update) {
-		/*
-		 * Check for possible transition between valid and invalid
-		 * partition root.
-		 */
-		switch (cs->partition_root_state) {
-		case PRS_ROOT:
-		case PRS_ISOLATED:
-			if (part_error)
-				new_prs = -old_prs;
-			break;
-		case PRS_INVALID_ROOT:
-		case PRS_INVALID_ISOLATED:
-			if (!part_error)
-				new_prs = -old_prs;
-			break;
-		}
-	}
-
-	if (!adding && !deleting && (new_prs == old_prs))
-		return 0;
-
-	/*
-	 * Transitioning between invalid to valid or vice versa may require
-	 * changing CS_CPU_EXCLUSIVE. In the case of partcmd_update,
-	 * validate_change() has already been successfully called and
-	 * CPU lists in cs haven't been updated yet. So defer it to later.
-	 */
-	if ((old_prs != new_prs) && (cmd != partcmd_update))  {
-		int err = update_partition_exclusive_flag(cs, new_prs);
-
-		if (err)
-			return err;
-	}
-
-	/*
-	 * Change the parent's effective_cpus & effective_xcpus (top cpuset
-	 * only).
-	 *
-	 * Newly added CPUs will be removed from effective_cpus and
-	 * newly deleted ones will be added back to effective_cpus.
-	 */
-	spin_lock_irq(&callback_lock);
-	if (old_prs != new_prs)
-		cs->partition_root_state = new_prs;
-
-	/*
-	 * Adding to parent's effective_cpus means deletion CPUs from cs
-	 * and vice versa.
-	 */
-	if (adding)
-		partition_xcpus_del(old_prs, parent, tmp->addmask);
-	if (deleting)
-		partition_xcpus_add(new_prs, parent, tmp->delmask);
-
-	spin_unlock_irq(&callback_lock);
-	update_isolation_cpumasks();
-
-	if ((old_prs != new_prs) && (cmd == partcmd_update))
-		update_partition_exclusive_flag(cs, new_prs);
-
-	if (adding || deleting) {
-		cpuset_update_tasks_cpumask(parent, tmp->addmask);
-		update_sibling_cpumasks(parent, cs, tmp);
-	}
-
-	/*
-	 * For partcmd_update without newmask, it is being called from
-	 * cpuset_handle_hotplug(). Update the load balance flag and
-	 * scheduling domain accordingly.
-	 */
-	if ((cmd == partcmd_update) && !newmask)
-		update_partition_sd_lb(cs, old_prs);
-
-	notify_partition_change(cs, old_prs);
-	return 0;
-}
-
 /**
  * compute_partition_effective_cpumask - compute effective_cpus for partition
  * @cs: partition root cpuset
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 14/21] cpuset: remove redundant partition field updates
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (12 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 13/21] cpuset: remove update_parent_effective_cpumask Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 15/21] cpuset: simplify partition update logic for hotplug tasks Chen Ridong
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

With the previous patch series, partition-related fields are now properly
managed during partition enable, disable, and update operations. There
should be no need to set these fields outside of these dedicated partition
operations.

This patch removes the redundant partition field updates from the cpumask
setting code path. However, one exception remains: when setting
cpuset.cpus.exclusive on a non-partition cpuset, update_exclusive_cpumask()
must still set effective_xcpus directly. This is necessary because no
partition operation is invoked in this scenario, yet effective_xcpus needs
to be properly initialized.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 65430e12b58f..43d5ea7d84a4 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2551,9 +2551,6 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
 
 	spin_lock_irq(&callback_lock);
 	cpumask_copy(cs->cpus_allowed, trialcs->cpus_allowed);
-	cpumask_copy(cs->effective_xcpus, trialcs->effective_xcpus);
-	if ((old_prs > 0) && !is_partition_valid(cs))
-		reset_partition_data(cs);
 	spin_unlock_irq(&callback_lock);
 
 	/* effective_cpus/effective_xcpus will be updated here */
@@ -2617,8 +2614,6 @@ static int update_exclusive_cpumask(struct cpuset *cs, struct cpuset *trialcs,
 	spin_lock_irq(&callback_lock);
 	cpumask_copy(cs->exclusive_cpus, trialcs->exclusive_cpus);
 	cpumask_copy(cs->effective_xcpus, trialcs->effective_xcpus);
-	if ((old_prs > 0) && !is_partition_valid(cs))
-		reset_partition_data(cs);
 	spin_unlock_irq(&callback_lock);
 
 	/*
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 15/21] cpuset: simplify partition update logic for hotplug tasks
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (13 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 14/21] cpuset: remove redundant partition field updates Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 16/21] cpuset: use partition_disable for compute_partition_effective_cpumask Chen Ridong
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

Simplify the partition update logic in cpuset_hotplug_update_tasks() by
calling the unified local_partition_update() interface.

For local partitions, the previous patch introduced local_partition_update
which handles both validation state transitions:
- Invalidates local partitions that fail validation checks
- Transitions invalid partitions to valid state when no errors are detected

This eliminates the need for separate transition logic
in cpuset_hotplug_update_tasks(), which can now simply call
local_partition_update() to handle all local partition changes.

For remote partitions, the logic is adjusted to always proceed to
update_tasks regardless of whether the partition was disabled, as the
original skip condition was not valid for remote partitions. This change
maintains existing functionality while simplifying the code path.

The partition_cmd emum type can now be safely removed as it is no longer
referenced by any code paths after the partition update logic
simplification.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 64 +++++++++++++++---------------------------
 1 file changed, 23 insertions(+), 41 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 43d5ea7d84a4..4e68e8edc827 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1237,17 +1237,6 @@ static void compute_effective_cpumask(struct cpumask *new_cpus,
 	cpumask_and(new_cpus, cs->cpus_allowed, parent->effective_cpus);
 }
 
-/*
- * Commands for update_parent_effective_cpumask
- */
-enum partition_cmd {
-	partcmd_enable,		/* Enable partition root	  */
-	partcmd_enablei,	/* Enable isolated partition root */
-	partcmd_disable,	/* Disable partition root	  */
-	partcmd_update,		/* Update parent's effective_cpus */
-	partcmd_invalidate,	/* Make partition invalid	  */
-};
-
 static void update_sibling_cpumasks(struct cpuset *parent, struct cpuset *cs,
 				    struct tmpmasks *tmp);
 
@@ -3893,8 +3882,6 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp)
 	static nodemask_t new_mems;
 	bool cpus_updated;
 	bool mems_updated;
-	bool remote;
-	int partcmd = -1;
 	struct cpuset *parent;
 retry:
 	wait_event(cpuset_attach_wq, cs->attach_in_progress == 0);
@@ -3921,16 +3908,15 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp)
 	 * Compute effective_cpus for valid partition root, may invalidate
 	 * child partition roots if necessary.
 	 */
-	remote = is_remote_partition(cs);
-	if (remote || (is_partition_valid(cs) && is_partition_valid(parent)))
+	if (is_remote_partition(cs)) {
 		compute_partition_effective_cpumask(cs, &new_cpus);
-
-	if (remote && cpumask_empty(&new_cpus) &&
-	    partition_is_populated(cs, NULL)) {
-		cs->prs_err = PERR_HOTPLUG;
-		remote_partition_disable(cs, tmp);
-		compute_effective_cpumask(&new_cpus, cs, parent);
-		remote = false;
+		if (cpumask_empty(&new_cpus) &&
+		    partition_is_populated(cs, NULL)) {
+			cs->prs_err = PERR_HOTPLUG;
+			remote_partition_disable(cs, tmp);
+			compute_effective_cpumask(&new_cpus, cs, parent);
+		}
+		goto update_tasks;
 	}
 
 	/*
@@ -3938,29 +3924,25 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp)
 	 * the following conditions hold:
 	 * 1) empty effective cpus but not valid empty partition.
 	 * 2) parent is invalid or doesn't grant any cpus to child
-	 *    partitions.
-	 */
-	if (is_local_partition(cs) && (!is_partition_valid(parent) ||
-				tasks_nocpu_error(parent, cs, &new_cpus))) {
-		partcmd = partcmd_invalidate;
-		local_partition_disable(cs, cs->prs_err, tmp);
-	}
-	/*
+	 *  partitions.
+	 *
 	 * On the other hand, an invalid partition root may be transitioned
 	 * back to a regular one with a non-empty user xcpus.
+	 *
+	 * local_partition_update can handle these cases.
 	 */
-	else if (is_partition_valid(parent) && is_partition_invalid(cs) &&
-		 !cpumask_empty(user_xcpus(cs))) {
-		partcmd = partcmd_update;
-		local_partition_update(cs, tmp);
-	}
+	local_partition_update(cs, tmp);
+
+	/*
+	 * Recompute effective CPU mask after partition state update:
+	 * - For valid partitions: calculate partition-specific effective CPUs
+	 * - For invalid partitions: compute member effective CPU mask
+	 */
+	if (is_partition_valid(cs))
+		compute_partition_effective_cpumask(cs, &new_cpus);
+	else
+		compute_effective_cpumask(&new_cpus, cs, parent);
 
-	if (partcmd >= 0) {
-		if ((partcmd == partcmd_invalidate) || is_partition_valid(cs)) {
-			compute_partition_effective_cpumask(cs, &new_cpus);
-			cpuset_force_rebuild();
-		}
-	}
 
 update_tasks:
 	cpus_updated = !cpumask_equal(&new_cpus, cs->effective_cpus);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 16/21] cpuset: use partition_disable for compute_partition_effective_cpumask
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (14 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 15/21] cpuset: simplify partition update logic for hotplug tasks Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 17/21] cpuset: use validate_local_partition in local_partition_enable Chen Ridong
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

Replace the partition invalidation logic in the
compute_partition_effective_cpumask() with a call to partition_disable().

This centralizes partition state management and ensures consistent
handling of partition disable operations throughout the cpuset subsystem.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 29 +++++++----------------------
 1 file changed, 7 insertions(+), 22 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 4e68e8edc827..af2966cd685d 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -174,15 +174,6 @@ static inline bool cs_is_member(const struct cpuset *cs)
 	return cs->partition_root_state == PRS_MEMBER;
 }
 
-/*
- * Callers should hold callback_lock to modify partition_root_state.
- */
-static inline void make_partition_invalid(struct cpuset *cs)
-{
-	if (cs->partition_root_state > 0)
-		cs->partition_root_state = -cs->partition_root_state;
-}
-
 /*
  * Send notification event of whenever partition_root_state changes.
  */
@@ -2114,6 +2105,7 @@ static void compute_partition_effective_cpumask(struct cpuset *cs,
 	struct cgroup_subsys_state *css;
 	struct cpuset *child;
 	bool populated = partition_is_populated(cs, NULL);
+	enum prs_errcode prs_err;
 
 	/*
 	 * Check child partition roots to see if they should be
@@ -2136,24 +2128,17 @@ static void compute_partition_effective_cpumask(struct cpuset *cs,
 		 * partition root.
 		 */
 		WARN_ON_ONCE(is_remote_partition(child));
-		child->prs_err = 0;
+		prs_err = 0;
 		if (!cpumask_subset(child->effective_xcpus,
 				    cs->effective_xcpus))
-			child->prs_err = PERR_INVCPUS;
+			prs_err = PERR_INVCPUS;
 		else if (populated &&
 			 cpumask_subset(new_ecpus, child->effective_xcpus))
-			child->prs_err = PERR_NOCPUS;
-
-		if (child->prs_err) {
-			int old_prs = child->partition_root_state;
+			prs_err = PERR_NOCPUS;
 
-			/*
-			 * Invalidate child partition
-			 */
-			spin_lock_irq(&callback_lock);
-			make_partition_invalid(child);
-			spin_unlock_irq(&callback_lock);
-			notify_partition_change(child, old_prs);
+		if (prs_err) {
+			partition_disable(child, cs, -child->partition_root_state,
+					  prs_err);
 			continue;
 		}
 		cpumask_andnot(new_ecpus, new_ecpus,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 17/21] cpuset: use validate_local_partition in local_partition_enable
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (15 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 16/21] cpuset: use partition_disable for compute_partition_effective_cpumask Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 18/21] cpuset: introduce validate_remote_partition Chen Ridong
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

Replace the partition error checks within `local_partition_enable()` by
utilizing the common `validate_local_partition()` function.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index af2966cd685d..b75d27a59ba9 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1950,16 +1950,6 @@ static int local_partition_enable(struct cpuset *cs,
 	lockdep_assert_held(&cpuset_mutex);
 	WARN_ON_ONCE(is_remote_partition(cs));	/* For local partition only */
 
-	/*
-	 * The parent must be a partition root.
-	 * The new cpumask, if present, or the current cpus_allowed must
-	 * not be empty.
-	 */
-	if (!is_partition_valid(parent)) {
-		return is_partition_invalid(parent)
-			? PERR_INVPARENT : PERR_NOTPART;
-	}
-
 	/*
 	 * Need to call compute_excpus() in case
 	 * exclusive_cpus not set. Sibling conflict should only happen
@@ -1968,7 +1958,7 @@ static int local_partition_enable(struct cpuset *cs,
 	if (compute_excpus(cs, tmp->new_cpus))
 		WARN_ON_ONCE(!cpumask_empty(cs->exclusive_cpus));
 
-	err = validate_partition(cs, new_prs, tmp->new_cpus, tmp->new_cpus, NULL);
+	err = validate_local_partition(cs, new_prs, tmp->new_cpus, false, NULL);
 	if (err)
 		return err;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 18/21] cpuset: introduce validate_remote_partition
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (16 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 17/21] cpuset: use validate_local_partition in local_partition_enable Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 19/21] cpuset: simplify the update_prstate() function Chen Ridong
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

This introduces validate_remote_partition() to consolidate validation
logic for remote partition operations. It will be used by both
remote_partition_enable() and remote_partition_disable().

The new function performs the following checks:
1. Privilege requirement: only CAP_SYS_ADMIN can add CPUs to a
   remote partition.
2. Conflict check: ensure added CPUs are not in any existing
   sub-partitions and that there is at least one online CPU in the
   excluded mask.
3. Resource check: prevent allocating all top cpuset's effective CPUs
   to remote partitions.
4. Common partition validation.

Additionally, this patch adds error handling for remote_partition_disable()
so that cs->prs_err can be updated centrally.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 118 +++++++++++++++++++++--------------------
 1 file changed, 60 insertions(+), 58 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index b75d27a59ba9..8690f144b208 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1744,6 +1744,47 @@ static void partition_update(struct cpuset *cs, int prs, struct cpumask *xcpus,
 	notify_partition_change(cs, old_prs);
 }
 
+/**
+ * validate_remote_partition - Validate for remote partition
+ * @cs: Target cpuset to validate
+ * @new_prs: New partition root state to validate
+ * @excpus: New exclusive effectuve CPUs mask to validate
+ * @add: exclusive CPUs to be added
+ * @del: exclusive CPUs to be deleted, can be NULL
+ *
+ * Return: PERR_NONE if validation passes, appropriate error code otherwise
+ */
+static enum prs_errcode validate_remote_partition(struct cpuset *cs,
+	int new_prs, struct cpumask *excpus, struct cpumask *add, struct cpumask *del)
+{
+	/*
+	 * The user must have sysadmin privilege.
+	 */
+	if (!cpumask_empty(add) && !capable(CAP_SYS_ADMIN))
+		return PERR_ACCESS;
+
+	/*
+	 * Additions of remote CPUs is only allowed if those CPUs are
+	 * not allocated to other partitions and there are effective_cpus
+	 * left in the top cpuset.
+	 *
+	 * The effective_xcpus mask can contain offline CPUs, but there must
+	 * be at least one or more online CPUs present before it can be enabled.
+	 */
+	if (cpumask_intersects(add, subpartitions_cpus) ||
+	    !cpumask_intersects(excpus, cpu_active_mask))
+		return PERR_INVCPUS;
+
+	/*
+	 * It is not allowed that all effective_cpus of top_cpuset are
+	 * distributed remote partition
+	 */
+	if (cpumask_subset(top_cpuset.effective_cpus, excpus))
+		return PERR_NOCPUS;
+
+	return validate_partition(cs, new_prs, excpus, add, del);
+}
+
 /*
  * remote_partition_enable - Enable current cpuset as a remote partition root
  * @cs: the cpuset to update
@@ -1757,31 +1798,15 @@ static void partition_update(struct cpuset *cs, int prs, struct cpumask *xcpus,
 static int remote_partition_enable(struct cpuset *cs, int new_prs,
 				   struct tmpmasks *tmp)
 {
-	/*
-	 * The user must have sysadmin privilege.
-	 */
-	if (!capable(CAP_SYS_ADMIN))
-		return PERR_ACCESS;
 
-	/*
-	 * The requested exclusive_cpus must not be allocated to other
-	 * partitions and it can't use up all the root's effective_cpus.
-	 *
-	 * The effective_xcpus mask can contain offline CPUs, but there must
-	 * be at least one or more online CPUs present before it can be enabled.
-	 *
-	 * Note that creating a remote partition with any local partition root
-	 * above it or remote partition root underneath it is not allowed.
-	 */
+	enum prs_errcode err;
+
 	compute_excpus(cs, tmp->new_cpus);
 	WARN_ON_ONCE(cpumask_intersects(tmp->new_cpus, subpartitions_cpus));
-	if (!cpumask_intersects(tmp->new_cpus, cpu_active_mask) ||
-	    cpumask_subset(top_cpuset.effective_cpus, tmp->new_cpus))
-		return PERR_INVCPUS;
-	if (((new_prs == PRS_ISOLATED) &&
-	     !isolated_cpus_can_update(tmp->new_cpus, NULL)) ||
-	    prstate_housekeeping_conflict(new_prs, tmp->new_cpus))
-		return PERR_HKEEPING;
+	err = validate_remote_partition(cs, new_prs, tmp->new_cpus,
+					tmp->new_cpus, NULL);
+	if (err)
+		return err;
 
 	partition_enable(cs, NULL, new_prs, tmp->new_cpus);
 	/*
@@ -1801,15 +1826,16 @@ static int remote_partition_enable(struct cpuset *cs, int new_prs,
  *
  * cpuset_mutex must be held by the caller.
  */
-static void remote_partition_disable(struct cpuset *cs, struct tmpmasks *tmp)
+static void remote_partition_disable(struct cpuset *cs,
+			enum prs_errcode prs_err, struct tmpmasks *tmp)
 {
 	int new_prs;
 
 	WARN_ON_ONCE(!is_remote_partition(cs));
 	WARN_ON_ONCE(!cpumask_subset(cs->effective_xcpus, subpartitions_cpus));
 
-	new_prs = cs->prs_err ? -cs->partition_root_state : PRS_MEMBER;
-	partition_disable(cs, NULL, new_prs, cs->prs_err);
+	new_prs = prs_err ? -cs->partition_root_state : PRS_MEMBER;
+	partition_disable(cs, NULL, new_prs, prs_err);
 
 	/*
 	 * Propagate changes in top_cpuset's effective_cpus down the hierarchy.
@@ -1831,39 +1857,19 @@ static void remote_partition_disable(struct cpuset *cs, struct tmpmasks *tmp)
 static void remote_cpus_update(struct cpuset *cs, struct cpumask *xcpus,
 			       struct cpumask *excpus, struct tmpmasks *tmp)
 {
-	int prs = cs->partition_root_state;
+	enum prs_errcode err;
 
 	if (WARN_ON_ONCE(!is_remote_partition(cs)))
 		return;
 
 	WARN_ON_ONCE(!cpumask_subset(cs->effective_xcpus, subpartitions_cpus));
-
-	if (cpumask_empty(excpus)) {
-		cs->prs_err = PERR_CPUSEMPTY;
-		goto invalidate;
-	}
-
 	cpumask_andnot(tmp->addmask, excpus, cs->effective_xcpus);
 	cpumask_andnot(tmp->delmask, cs->effective_xcpus, excpus);
 
-	/*
-	 * Additions of remote CPUs is only allowed if those CPUs are
-	 * not allocated to other partitions and there are effective_cpus
-	 * left in the top cpuset.
-	 */
-	if (!cpumask_empty(tmp->addmask)) {
-		WARN_ON_ONCE(cpumask_intersects(tmp->addmask, subpartitions_cpus));
-		if (!capable(CAP_SYS_ADMIN))
-			cs->prs_err = PERR_ACCESS;
-		else if (cpumask_intersects(tmp->addmask, subpartitions_cpus) ||
-			 cpumask_subset(top_cpuset.effective_cpus, tmp->addmask))
-			cs->prs_err = PERR_NOCPUS;
-		else if ((prs == PRS_ISOLATED) &&
-			 !isolated_cpus_can_update(tmp->addmask, tmp->delmask))
-			cs->prs_err = PERR_HKEEPING;
-		if (cs->prs_err)
-			goto invalidate;
-	}
+	err = validate_remote_partition(cs, cs->partition_root_state, excpus,
+					tmp->addmask, tmp->delmask);
+	if (err)
+		return remote_partition_disable(cs, err, tmp);
 
 	partition_update(cs, cs->partition_root_state, xcpus, excpus, tmp);
 	/*
@@ -1872,9 +1878,6 @@ static void remote_cpus_update(struct cpuset *cs, struct cpumask *xcpus,
 	cpuset_update_tasks_cpumask(&top_cpuset, tmp->new_cpus);
 	update_sibling_cpumasks(&top_cpuset, NULL, tmp);
 	return;
-
-invalidate:
-	remote_partition_disable(cs, tmp);
 }
 
 static bool is_user_xcpus_exclusive(struct cpuset *cs)
@@ -2456,11 +2459,11 @@ static void partition_cpus_change(struct cpuset *cs, struct cpuset *trialcs,
 	prs_err = validate_partition(cs, trialcs->partition_root_state,
 			trialcs->effective_xcpus, trialcs->effective_xcpus, NULL);
 	if (prs_err)
-		trialcs->prs_err = cs->prs_err = prs_err;
+		trialcs->prs_err = prs_err;
 
 	if (is_remote_partition(cs)) {
 		if (trialcs->prs_err)
-			remote_partition_disable(cs, tmp);
+			remote_partition_disable(cs, trialcs->prs_err, tmp);
 		else
 			remote_cpus_update(cs, trialcs->exclusive_cpus,
 					   trialcs->effective_xcpus, tmp);
@@ -3000,7 +3003,7 @@ static int update_prstate(struct cpuset *cs, int new_prs)
 		 * disables child partitions.
 		 */
 		if (is_remote_partition(cs))
-			remote_partition_disable(cs, &tmpmask);
+			remote_partition_disable(cs, PERR_NONE, &tmpmask);
 		else
 			local_partition_disable(cs, PERR_NONE, &tmpmask);
 		/*
@@ -3887,8 +3890,7 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp)
 		compute_partition_effective_cpumask(cs, &new_cpus);
 		if (cpumask_empty(&new_cpus) &&
 		    partition_is_populated(cs, NULL)) {
-			cs->prs_err = PERR_HOTPLUG;
-			remote_partition_disable(cs, tmp);
+			remote_partition_disable(cs, PERR_HOTPLUG, tmp);
 			compute_effective_cpumask(&new_cpus, cs, parent);
 		}
 		goto update_tasks;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 19/21] cpuset: simplify the update_prstate() function
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (17 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 18/21] cpuset: introduce validate_remote_partition Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 20/21] cpuset: remove prs_err clear when notify_partition_change Chen Ridong
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

This patch introduces partition_switch to handle both local partition
and remote partition root state switches between "root" and "isolated".
It first validates the partition viavalidate_partition() to check its
validity. If validation fails, it returns an error and disables the
partition; if validation passes, it enables the partition with the new
root state.

With partition_switch introduced, update_prstate() can be simplified. The
partition-related assignments in update_prstate() are redundant, as these
operations are already handled by partition_enable() and
partition_disable(). They are therefore removed.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 58 +++++++++++++++++-------------------------
 1 file changed, 23 insertions(+), 35 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 8690f144b208..333bd6476370 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1699,6 +1699,24 @@ static void partition_disable(struct cpuset *cs, struct cpuset *parent,
 	notify_partition_change(cs, old_prs);
 }
 
+static int partition_switch(struct cpuset *cs, int new_prs)
+{
+	enum prs_errcode err;
+	struct cpuset *parent;
+
+	lockdep_assert_held(&cpuset_mutex);
+	WARN_ON_ONCE(new_prs < 0 || !is_partition_valid(cs));
+	WARN_ON_ONCE(!cpuset_v2());
+
+	err = validate_partition(cs, new_prs, cs->effective_cpus,
+				 cs->effective_cpus, NULL);
+	if (err)
+		return err;
+	parent = is_remote_partition(cs) ? NULL : parent_cs(cs);
+	partition_enable(cs, parent, new_prs, cs->effective_cpus);
+	return 0;
+}
+
 /**
  * partition_update - Update an existing partition configuration
  * @cs: The cpuset to update
@@ -2938,7 +2956,6 @@ 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;
-	bool isolcpus_updated = false;
 
 	if (old_prs == new_prs)
 		return 0;
@@ -2987,16 +3004,8 @@ static int update_prstate(struct cpuset *cs, int new_prs)
 		else
 			err = remote_partition_enable(cs, new_prs, &tmpmask);
 	} else if (old_prs && new_prs) {
-		/*
-		 * A change in load balance state only, no change in cpumasks.
-		 * Need to update isolated_cpus.
-		 */
-		if (((new_prs == PRS_ISOLATED) &&
-		     !isolated_cpus_can_update(cs->effective_xcpus, NULL)) ||
-		    prstate_housekeeping_conflict(new_prs, cs->effective_xcpus))
-			err = PERR_HKEEPING;
-		else
-			isolcpus_updated = true;
+		/* Root state switches, eg, root --> isolated */
+		err = partition_switch(cs, new_prs);
 	} else {
 		/*
 		 * Switching back to member is always allowed even if it
@@ -3012,36 +3021,15 @@ static int update_prstate(struct cpuset *cs, int new_prs)
 		 */
 	}
 out:
-	/*
-	 * Make partition invalid & disable CS_CPU_EXCLUSIVE if an error
-	 * happens.
-	 */
-	if (err) {
-		new_prs = -new_prs;
-		update_partition_exclusive_flag(cs, new_prs);
-	}
-
-	spin_lock_irq(&callback_lock);
-	cs->partition_root_state = new_prs;
-	WRITE_ONCE(cs->prs_err, err);
-	if (!is_partition_valid(cs))
-		reset_partition_data(cs);
-	else if (isolcpus_updated)
-		isolated_cpus_update(old_prs, new_prs, cs->effective_xcpus);
-	spin_unlock_irq(&callback_lock);
-	update_isolation_cpumasks();
+	/* Make partition invalid if an error happens */
+	if (err)
+		partition_disable(cs, parent, -new_prs, err);
 
 	/* Force update if switching back to member & update effective_xcpus */
 	update_cpumasks_hier(cs, &tmpmask, !new_prs);
 
-	/* A newly created partition must have effective_xcpus set */
-	WARN_ON_ONCE(!old_prs && (new_prs > 0)
-			      && cpumask_empty(cs->effective_xcpus));
-
 	/* Update sched domains and load balance flag */
 	update_partition_sd_lb(cs, old_prs);
-
-	notify_partition_change(cs, old_prs);
 	if (force_sd_rebuild)
 		rebuild_sched_domains_locked();
 	free_tmpmasks(&tmpmask);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 20/21] cpuset: remove prs_err clear when notify_partition_change
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (18 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 19/21] cpuset: simplify the update_prstate() function Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-17  2:46 ` [PATCH -next 21/21] cpuset: Remove unnecessary validation in partition_cpus_change Chen Ridong
  2025-11-25  0:49 ` [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

The prs_err should be properly set when partition state is set, it
does't have to reset in the notify_partition_change, just remove it.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 333bd6476370..b795af41eff8 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -182,10 +182,6 @@ static inline void notify_partition_change(struct cpuset *cs, int old_prs)
 	if (old_prs == cs->partition_root_state)
 		return;
 	cgroup_file_notify(&cs->partition_file);
-
-	/* Reset prs_err if not invalid */
-	if (is_partition_valid(cs))
-		WRITE_ONCE(cs->prs_err, PERR_NONE);
 }
 
 /*
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH -next 21/21] cpuset: Remove unnecessary validation in partition_cpus_change
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (19 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 20/21] cpuset: remove prs_err clear when notify_partition_change Chen Ridong
@ 2025-11-17  2:46 ` Chen Ridong
  2025-11-25  0:49 ` [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
  21 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-17  2:46 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong

From: Chen Ridong <chenridong@huawei.com>

When user-configured CPUs (including cpuset.cpus and cpuset.cpus.exclusive)
are modified, the partition may either be disabled or updated. Both local
and remote partitions update can fully validate their own validity: if the
validation fails, the partition will be disabled. Therefore, the
validationin partition_cpus_change is redundant and can be removed.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
 kernel/cgroup/cpuset.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index b795af41eff8..59c1592280b0 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2465,16 +2465,9 @@ static int cpus_allowed_validate_change(struct cpuset *cs, struct cpuset *trialc
 static void partition_cpus_change(struct cpuset *cs, struct cpuset *trialcs,
 					struct tmpmasks *tmp)
 {
-	enum prs_errcode prs_err;
-
 	if (cs_is_member(cs))
 		return;
 
-	prs_err = validate_partition(cs, trialcs->partition_root_state,
-			trialcs->effective_xcpus, trialcs->effective_xcpus, NULL);
-	if (prs_err)
-		trialcs->prs_err = prs_err;
-
 	if (is_remote_partition(cs)) {
 		if (trialcs->prs_err)
 			remote_partition_disable(cs, trialcs->prs_err, tmp);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH -next 00/21] cpuset: rework local partition logic
  2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
                   ` (20 preceding siblings ...)
  2025-11-17  2:46 ` [PATCH -next 21/21] cpuset: Remove unnecessary validation in partition_cpus_change Chen Ridong
@ 2025-11-25  0:49 ` Chen Ridong
  2025-11-25  1:09   ` Waiman Long
  21 siblings, 1 reply; 27+ messages in thread
From: Chen Ridong @ 2025-11-25  0:49 UTC (permalink / raw)
  To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong



On 2025/11/17 10:46, Chen Ridong wrote:
> From: Chen Ridong <chenridong@huawei.com>
> 
> The current local partition implementation consolidates all operations
> (enable, disable, invalidate, and update) within the large
> update_parent_effective_cpumask() function, which exceeds 300 lines.
> This monolithic approach has become increasingly difficult to understand
> and maintain. Additionally, partition-related fields are updated in
> multiple locations, leading to redundant code and potential corner case
> oversights.
> 
> This patch series refactors the local partition logic by separating
> operations into dedicated functions: local_partition_enable(),
> local_partition_disable(), and local_partition_update(), creating
> symmetry with the existing remote partition infrastructure.
> 
> The series is organized as follows:
> 
> 1. Infrastructure Preparation (Patches 1-2):
>    - Code cleanup and preparation for the refactoring work
> 
> 2. Introduce partition operation helpers (Patches 3-5):
>    - Introduce out partition_enable(), partition_disable(), and
>      partition_update() functions.
> 
> 3. Use new helpers for remote partition (Patches 6-8)
> 
> 4. Local Partition Implementation (Patches 9-12):
>    - Separate update_parent_effective_cpumask() into dedicated functions:
>      * local_partition_enable()
>      * local_partition_disable()
>      * local_partition_update()
> 
> 5. Optimization and Cleanup (Patches 13-21):
>    - Remove redundant partition-related operations
>    - Additional optimizations based on the new architecture
> 
> base-commit: 6d7e7251d03f98f26f2ee0dfd21bb0a0480a2178
> 
> ---
> 
> Changes from RFC v2:
> 1. Dropped the bugfix (already merged/fixed upstream)
> 2. Rebased onto next
> 3. Introduced partition_switch to handle root state switches
> 4. Directly use local_partition_disable()—no longer first introduce
>    local_partition_invalidate() before unifying the two
> 5. Incorporated modifications based on Longman's suggestions
> 
> Changes in RFC v1:
> 1. Added bugfix for root partition isolcpus at series start.
> 2. Completed helper function implementations when first introduced.
> 3. Split larger patches into smaller, more reviewable units.
> 4. Incorporated feedback from Longman.
> 
> Chen Ridong (21):
>   cpuset: add early empty cpumask check in partition_xcpus_add/del
>   cpuset: generalize the validate_partition() interface
>   cpuset: introduce partition_enable()
>   cpuset: introduce partition_disable()
>   cpuset: introduce partition_update()
>   cpuset: use partition_enable() for remote partition enablement
>   cpuset: use partition_disable() for remote partition disablement
>   cpuset: use partition_update() for remote partition update
>   cpuset: introduce local_partition_enable()
>   cpuset: introduce local_partition_disable()
>   cpuset: user local_partition_disable() to invalidate local partition
>   cpuset: introduce local_partition_update()
>   cpuset: remove update_parent_effective_cpumask
>   cpuset: remove redundant partition field updates
>   cpuset: simplify partition update logic for hotplug tasks
>   cpuset: use partition_disable for compute_partition_effective_cpumask
>   cpuset: use validate_local_partition in local_partition_enable
>   cpuset: introduce validate_remote_partition
>   cpuset: simplify the update_prstate() function
>   cpuset: remove prs_err clear when notify_partition_change
>   cpuset: Remove unnecessary validation in partition_cpus_change
> 
>  kernel/cgroup/cpuset.c | 1014 ++++++++++++++++++----------------------
>  1 file changed, 453 insertions(+), 561 deletions(-)
> 

Hi Longman,

I would greatly appreciate it if you could review this series when you are available.

-- 
Best regards,
Ridong


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH -next 00/21] cpuset: rework local partition logic
  2025-11-25  0:49 ` [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
@ 2025-11-25  1:09   ` Waiman Long
  2025-11-25  1:17     ` Chen Ridong
                       ` (2 more replies)
  0 siblings, 3 replies; 27+ messages in thread
From: Waiman Long @ 2025-11-25  1:09 UTC (permalink / raw)
  To: Chen Ridong, tj, hannes, mkoutny
  Cc: cgroups, linux-kernel, lujialin4, chenridong

On 11/24/25 7:49 PM, Chen Ridong wrote:
>
> On 2025/11/17 10:46, Chen Ridong wrote:
>> From: Chen Ridong <chenridong@huawei.com>
>>
>> The current local partition implementation consolidates all operations
>> (enable, disable, invalidate, and update) within the large
>> update_parent_effective_cpumask() function, which exceeds 300 lines.
>> This monolithic approach has become increasingly difficult to understand
>> and maintain. Additionally, partition-related fields are updated in
>> multiple locations, leading to redundant code and potential corner case
>> oversights.
>>
>> This patch series refactors the local partition logic by separating
>> operations into dedicated functions: local_partition_enable(),
>> local_partition_disable(), and local_partition_update(), creating
>> symmetry with the existing remote partition infrastructure.
>>
>> The series is organized as follows:
>>
>> 1. Infrastructure Preparation (Patches 1-2):
>>     - Code cleanup and preparation for the refactoring work
>>
>> 2. Introduce partition operation helpers (Patches 3-5):
>>     - Introduce out partition_enable(), partition_disable(), and
>>       partition_update() functions.
>>
>> 3. Use new helpers for remote partition (Patches 6-8)
>>
>> 4. Local Partition Implementation (Patches 9-12):
>>     - Separate update_parent_effective_cpumask() into dedicated functions:
>>       * local_partition_enable()
>>       * local_partition_disable()
>>       * local_partition_update()
>>
>> 5. Optimization and Cleanup (Patches 13-21):
>>     - Remove redundant partition-related operations
>>     - Additional optimizations based on the new architecture
>>
>> base-commit: 6d7e7251d03f98f26f2ee0dfd21bb0a0480a2178
>>
>> ---
>>
>> Changes from RFC v2:
>> 1. Dropped the bugfix (already merged/fixed upstream)
>> 2. Rebased onto next
>> 3. Introduced partition_switch to handle root state switches
>> 4. Directly use local_partition_disable()—no longer first introduce
>>     local_partition_invalidate() before unifying the two
>> 5. Incorporated modifications based on Longman's suggestions
>>
>> Changes in RFC v1:
>> 1. Added bugfix for root partition isolcpus at series start.
>> 2. Completed helper function implementations when first introduced.
>> 3. Split larger patches into smaller, more reviewable units.
>> 4. Incorporated feedback from Longman.
>>
>> Chen Ridong (21):
>>    cpuset: add early empty cpumask check in partition_xcpus_add/del
>>    cpuset: generalize the validate_partition() interface
>>    cpuset: introduce partition_enable()
>>    cpuset: introduce partition_disable()
>>    cpuset: introduce partition_update()
>>    cpuset: use partition_enable() for remote partition enablement
>>    cpuset: use partition_disable() for remote partition disablement
>>    cpuset: use partition_update() for remote partition update
>>    cpuset: introduce local_partition_enable()
>>    cpuset: introduce local_partition_disable()
>>    cpuset: user local_partition_disable() to invalidate local partition
>>    cpuset: introduce local_partition_update()
>>    cpuset: remove update_parent_effective_cpumask
>>    cpuset: remove redundant partition field updates
>>    cpuset: simplify partition update logic for hotplug tasks
>>    cpuset: use partition_disable for compute_partition_effective_cpumask
>>    cpuset: use validate_local_partition in local_partition_enable
>>    cpuset: introduce validate_remote_partition
>>    cpuset: simplify the update_prstate() function
>>    cpuset: remove prs_err clear when notify_partition_change
>>    cpuset: Remove unnecessary validation in partition_cpus_change
>>
>>   kernel/cgroup/cpuset.c | 1014 ++++++++++++++++++----------------------
>>   1 file changed, 453 insertions(+), 561 deletions(-)
>>
> Hi Longman,
>
> I would greatly appreciate it if you could review this series when you are available.
>
I was expecting a v3 and so I had probably missed it. Will take a look 
sometimes this week.

Cheers,
Longman


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH -next 00/21] cpuset: rework local partition logic
  2025-11-25  1:09   ` Waiman Long
@ 2025-11-25  1:17     ` Chen Ridong
  2025-12-02  0:43     ` Chen Ridong
  2025-12-15 13:15     ` Chen Ridong
  2 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-11-25  1:17 UTC (permalink / raw)
  To: Waiman Long, tj, hannes, mkoutny
  Cc: cgroups, linux-kernel, lujialin4, chenridong



On 2025/11/25 9:09, Waiman Long wrote:
> On 11/24/25 7:49 PM, Chen Ridong wrote:
>>
>> On 2025/11/17 10:46, Chen Ridong wrote:
>>> From: Chen Ridong <chenridong@huawei.com>
>>>
>>> The current local partition implementation consolidates all operations
>>> (enable, disable, invalidate, and update) within the large
>>> update_parent_effective_cpumask() function, which exceeds 300 lines.
>>> This monolithic approach has become increasingly difficult to understand
>>> and maintain. Additionally, partition-related fields are updated in
>>> multiple locations, leading to redundant code and potential corner case
>>> oversights.
>>>
>>> This patch series refactors the local partition logic by separating
>>> operations into dedicated functions: local_partition_enable(),
>>> local_partition_disable(), and local_partition_update(), creating
>>> symmetry with the existing remote partition infrastructure.
>>>
>>> The series is organized as follows:
>>>
>>> 1. Infrastructure Preparation (Patches 1-2):
>>>     - Code cleanup and preparation for the refactoring work
>>>
>>> 2. Introduce partition operation helpers (Patches 3-5):
>>>     - Introduce out partition_enable(), partition_disable(), and
>>>       partition_update() functions.
>>>
>>> 3. Use new helpers for remote partition (Patches 6-8)
>>>
>>> 4. Local Partition Implementation (Patches 9-12):
>>>     - Separate update_parent_effective_cpumask() into dedicated functions:
>>>       * local_partition_enable()
>>>       * local_partition_disable()
>>>       * local_partition_update()
>>>
>>> 5. Optimization and Cleanup (Patches 13-21):
>>>     - Remove redundant partition-related operations
>>>     - Additional optimizations based on the new architecture
>>>
>>> base-commit: 6d7e7251d03f98f26f2ee0dfd21bb0a0480a2178
>>>
>>> ---
>>>
>>> Changes from RFC v2:
>>> 1. Dropped the bugfix (already merged/fixed upstream)
>>> 2. Rebased onto next
>>> 3. Introduced partition_switch to handle root state switches
>>> 4. Directly use local_partition_disable()—no longer first introduce
>>>     local_partition_invalidate() before unifying the two
>>> 5. Incorporated modifications based on Longman's suggestions
>>>
>>> Changes in RFC v1:
>>> 1. Added bugfix for root partition isolcpus at series start.
>>> 2. Completed helper function implementations when first introduced.
>>> 3. Split larger patches into smaller, more reviewable units.
>>> 4. Incorporated feedback from Longman.
>>>
>>> Chen Ridong (21):
>>>    cpuset: add early empty cpumask check in partition_xcpus_add/del
>>>    cpuset: generalize the validate_partition() interface
>>>    cpuset: introduce partition_enable()
>>>    cpuset: introduce partition_disable()
>>>    cpuset: introduce partition_update()
>>>    cpuset: use partition_enable() for remote partition enablement
>>>    cpuset: use partition_disable() for remote partition disablement
>>>    cpuset: use partition_update() for remote partition update
>>>    cpuset: introduce local_partition_enable()
>>>    cpuset: introduce local_partition_disable()
>>>    cpuset: user local_partition_disable() to invalidate local partition
>>>    cpuset: introduce local_partition_update()
>>>    cpuset: remove update_parent_effective_cpumask
>>>    cpuset: remove redundant partition field updates
>>>    cpuset: simplify partition update logic for hotplug tasks
>>>    cpuset: use partition_disable for compute_partition_effective_cpumask
>>>    cpuset: use validate_local_partition in local_partition_enable
>>>    cpuset: introduce validate_remote_partition
>>>    cpuset: simplify the update_prstate() function
>>>    cpuset: remove prs_err clear when notify_partition_change
>>>    cpuset: Remove unnecessary validation in partition_cpus_change
>>>
>>>   kernel/cgroup/cpuset.c | 1014 ++++++++++++++++++----------------------
>>>   1 file changed, 453 insertions(+), 561 deletions(-)
>>>
>> Hi Longman,
>>
>> I would greatly appreciate it if you could review this series when you are available.
>>
> I was expecting a v3 and so I had probably missed it. Will take a look sometimes this week.
> 

Thank you very much.

-- 
Best regards,
Ridong


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH -next 00/21] cpuset: rework local partition logic
  2025-11-25  1:09   ` Waiman Long
  2025-11-25  1:17     ` Chen Ridong
@ 2025-12-02  0:43     ` Chen Ridong
  2025-12-15 13:15     ` Chen Ridong
  2 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-12-02  0:43 UTC (permalink / raw)
  To: Waiman Long, tj, hannes, mkoutny
  Cc: cgroups, linux-kernel, lujialin4, chenridong



On 2025/11/25 9:09, Waiman Long wrote:
> On 11/24/25 7:49 PM, Chen Ridong wrote:
>>
>> On 2025/11/17 10:46, Chen Ridong wrote:
>>> From: Chen Ridong <chenridong@huawei.com>
>>>
>>> The current local partition implementation consolidates all operations
>>> (enable, disable, invalidate, and update) within the large
>>> update_parent_effective_cpumask() function, which exceeds 300 lines.
>>> This monolithic approach has become increasingly difficult to understand
>>> and maintain. Additionally, partition-related fields are updated in
>>> multiple locations, leading to redundant code and potential corner case
>>> oversights.
>>>
>>> This patch series refactors the local partition logic by separating
>>> operations into dedicated functions: local_partition_enable(),
>>> local_partition_disable(), and local_partition_update(), creating
>>> symmetry with the existing remote partition infrastructure.
>>>
>>> The series is organized as follows:
>>>
>>> 1. Infrastructure Preparation (Patches 1-2):
>>>     - Code cleanup and preparation for the refactoring work
>>>
>>> 2. Introduce partition operation helpers (Patches 3-5):
>>>     - Introduce out partition_enable(), partition_disable(), and
>>>       partition_update() functions.
>>>
>>> 3. Use new helpers for remote partition (Patches 6-8)
>>>
>>> 4. Local Partition Implementation (Patches 9-12):
>>>     - Separate update_parent_effective_cpumask() into dedicated functions:
>>>       * local_partition_enable()
>>>       * local_partition_disable()
>>>       * local_partition_update()
>>>
>>> 5. Optimization and Cleanup (Patches 13-21):
>>>     - Remove redundant partition-related operations
>>>     - Additional optimizations based on the new architecture
>>>
>>> base-commit: 6d7e7251d03f98f26f2ee0dfd21bb0a0480a2178
>>>
>>> ---
>>>
>>> Changes from RFC v2:
>>> 1. Dropped the bugfix (already merged/fixed upstream)
>>> 2. Rebased onto next
>>> 3. Introduced partition_switch to handle root state switches
>>> 4. Directly use local_partition_disable()—no longer first introduce
>>>     local_partition_invalidate() before unifying the two
>>> 5. Incorporated modifications based on Longman's suggestions
>>>
>>> Changes in RFC v1:
>>> 1. Added bugfix for root partition isolcpus at series start.
>>> 2. Completed helper function implementations when first introduced.
>>> 3. Split larger patches into smaller, more reviewable units.
>>> 4. Incorporated feedback from Longman.
>>>
>>> Chen Ridong (21):
>>>    cpuset: add early empty cpumask check in partition_xcpus_add/del
>>>    cpuset: generalize the validate_partition() interface
>>>    cpuset: introduce partition_enable()
>>>    cpuset: introduce partition_disable()
>>>    cpuset: introduce partition_update()
>>>    cpuset: use partition_enable() for remote partition enablement
>>>    cpuset: use partition_disable() for remote partition disablement
>>>    cpuset: use partition_update() for remote partition update
>>>    cpuset: introduce local_partition_enable()
>>>    cpuset: introduce local_partition_disable()
>>>    cpuset: user local_partition_disable() to invalidate local partition
>>>    cpuset: introduce local_partition_update()
>>>    cpuset: remove update_parent_effective_cpumask
>>>    cpuset: remove redundant partition field updates
>>>    cpuset: simplify partition update logic for hotplug tasks
>>>    cpuset: use partition_disable for compute_partition_effective_cpumask
>>>    cpuset: use validate_local_partition in local_partition_enable
>>>    cpuset: introduce validate_remote_partition
>>>    cpuset: simplify the update_prstate() function
>>>    cpuset: remove prs_err clear when notify_partition_change
>>>    cpuset: Remove unnecessary validation in partition_cpus_change
>>>
>>>   kernel/cgroup/cpuset.c | 1014 ++++++++++++++++++----------------------
>>>   1 file changed, 453 insertions(+), 561 deletions(-)
>>>
>> Hi Longman,
>>
>> I would greatly appreciate it if you could review this series when you are available.
>>
> I was expecting a v3 and so I had probably missed it. Will take a look sometimes this week.
> 

Hi Longman,

Looking forward to your review. :)

-- 
Best regards,
Ridong


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH -next 00/21] cpuset: rework local partition logic
  2025-11-25  1:09   ` Waiman Long
  2025-11-25  1:17     ` Chen Ridong
  2025-12-02  0:43     ` Chen Ridong
@ 2025-12-15 13:15     ` Chen Ridong
  2 siblings, 0 replies; 27+ messages in thread
From: Chen Ridong @ 2025-12-15 13:15 UTC (permalink / raw)
  To: Waiman Long, tj, hannes, mkoutny
  Cc: cgroups, linux-kernel, lujialin4, chenridong



On 2025/11/25 9:09, Waiman Long wrote:
> On 11/24/25 7:49 PM, Chen Ridong wrote:
>>
>> On 2025/11/17 10:46, Chen Ridong wrote:
>>> From: Chen Ridong <chenridong@huawei.com>
>>>
>>> The current local partition implementation consolidates all operations
>>> (enable, disable, invalidate, and update) within the large
>>> update_parent_effective_cpumask() function, which exceeds 300 lines.
>>> This monolithic approach has become increasingly difficult to understand
>>> and maintain. Additionally, partition-related fields are updated in
>>> multiple locations, leading to redundant code and potential corner case
>>> oversights.
>>>
>>> This patch series refactors the local partition logic by separating
>>> operations into dedicated functions: local_partition_enable(),
>>> local_partition_disable(), and local_partition_update(), creating
>>> symmetry with the existing remote partition infrastructure.
>>>
>>> The series is organized as follows:
>>>
>>> 1. Infrastructure Preparation (Patches 1-2):
>>>     - Code cleanup and preparation for the refactoring work
>>>
>>> 2. Introduce partition operation helpers (Patches 3-5):
>>>     - Introduce out partition_enable(), partition_disable(), and
>>>       partition_update() functions.
>>>
>>> 3. Use new helpers for remote partition (Patches 6-8)
>>>
>>> 4. Local Partition Implementation (Patches 9-12):
>>>     - Separate update_parent_effective_cpumask() into dedicated functions:
>>>       * local_partition_enable()
>>>       * local_partition_disable()
>>>       * local_partition_update()
>>>
>>> 5. Optimization and Cleanup (Patches 13-21):
>>>     - Remove redundant partition-related operations
>>>     - Additional optimizations based on the new architecture
>>>
>>> base-commit: 6d7e7251d03f98f26f2ee0dfd21bb0a0480a2178
>>>
>>> ---
>>>
>>> Changes from RFC v2:
>>> 1. Dropped the bugfix (already merged/fixed upstream)
>>> 2. Rebased onto next
>>> 3. Introduced partition_switch to handle root state switches
>>> 4. Directly use local_partition_disable()—no longer first introduce
>>>     local_partition_invalidate() before unifying the two
>>> 5. Incorporated modifications based on Longman's suggestions
>>>
>>> Changes in RFC v1:
>>> 1. Added bugfix for root partition isolcpus at series start.
>>> 2. Completed helper function implementations when first introduced.
>>> 3. Split larger patches into smaller, more reviewable units.
>>> 4. Incorporated feedback from Longman.
>>>
>>> Chen Ridong (21):
>>>    cpuset: add early empty cpumask check in partition_xcpus_add/del
>>>    cpuset: generalize the validate_partition() interface
>>>    cpuset: introduce partition_enable()
>>>    cpuset: introduce partition_disable()
>>>    cpuset: introduce partition_update()
>>>    cpuset: use partition_enable() for remote partition enablement
>>>    cpuset: use partition_disable() for remote partition disablement
>>>    cpuset: use partition_update() for remote partition update
>>>    cpuset: introduce local_partition_enable()
>>>    cpuset: introduce local_partition_disable()
>>>    cpuset: user local_partition_disable() to invalidate local partition
>>>    cpuset: introduce local_partition_update()
>>>    cpuset: remove update_parent_effective_cpumask
>>>    cpuset: remove redundant partition field updates
>>>    cpuset: simplify partition update logic for hotplug tasks
>>>    cpuset: use partition_disable for compute_partition_effective_cpumask
>>>    cpuset: use validate_local_partition in local_partition_enable
>>>    cpuset: introduce validate_remote_partition
>>>    cpuset: simplify the update_prstate() function
>>>    cpuset: remove prs_err clear when notify_partition_change
>>>    cpuset: Remove unnecessary validation in partition_cpus_change
>>>
>>>   kernel/cgroup/cpuset.c | 1014 ++++++++++++++++++----------------------
>>>   1 file changed, 453 insertions(+), 561 deletions(-)
>>>
>> Hi Longman,
>>
>> I would greatly appreciate it if you could review this series when you are available.
>>
> I was expecting a v3 and so I had probably missed it. Will take a look sometimes this week.
> 

Hi Longman,

Just a gentle reminder about this series whenever you have a moment, in case it got buried.

-- 
Best regards,
Ridong


^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2025-12-15 13:15 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-17  2:46 [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
2025-11-17  2:46 ` [PATCH -next 01/21] cpuset: add early empty cpumask check in partition_xcpus_add/del Chen Ridong
2025-11-17  2:46 ` [PATCH -next 02/21] cpuset: generalize the validate_partition() interface Chen Ridong
2025-11-17  2:46 ` [PATCH -next 03/21] cpuset: introduce partition_enable() Chen Ridong
2025-11-17  2:46 ` [PATCH -next 04/21] cpuset: introduce partition_disable() Chen Ridong
2025-11-17  2:46 ` [PATCH -next 05/21] cpuset: introduce partition_update() Chen Ridong
2025-11-17  2:46 ` [PATCH -next 06/21] cpuset: use partition_enable() for remote partition enablement Chen Ridong
2025-11-17  2:46 ` [PATCH -next 07/21] cpuset: use partition_disable() for remote partition disablement Chen Ridong
2025-11-17  2:46 ` [PATCH -next 08/21] cpuset: use partition_update() for remote partition update Chen Ridong
2025-11-17  2:46 ` [PATCH -next 09/21] cpuset: introduce local_partition_enable() Chen Ridong
2025-11-17  2:46 ` [PATCH -next 10/21] cpuset: introduce local_partition_disable() Chen Ridong
2025-11-17  2:46 ` [PATCH -next 11/21] cpuset: user local_partition_disable() to invalidate local partition Chen Ridong
2025-11-17  2:46 ` [PATCH -next 12/21] cpuset: introduce local_partition_update() Chen Ridong
2025-11-17  2:46 ` [PATCH -next 13/21] cpuset: remove update_parent_effective_cpumask Chen Ridong
2025-11-17  2:46 ` [PATCH -next 14/21] cpuset: remove redundant partition field updates Chen Ridong
2025-11-17  2:46 ` [PATCH -next 15/21] cpuset: simplify partition update logic for hotplug tasks Chen Ridong
2025-11-17  2:46 ` [PATCH -next 16/21] cpuset: use partition_disable for compute_partition_effective_cpumask Chen Ridong
2025-11-17  2:46 ` [PATCH -next 17/21] cpuset: use validate_local_partition in local_partition_enable Chen Ridong
2025-11-17  2:46 ` [PATCH -next 18/21] cpuset: introduce validate_remote_partition Chen Ridong
2025-11-17  2:46 ` [PATCH -next 19/21] cpuset: simplify the update_prstate() function Chen Ridong
2025-11-17  2:46 ` [PATCH -next 20/21] cpuset: remove prs_err clear when notify_partition_change Chen Ridong
2025-11-17  2:46 ` [PATCH -next 21/21] cpuset: Remove unnecessary validation in partition_cpus_change Chen Ridong
2025-11-25  0:49 ` [PATCH -next 00/21] cpuset: rework local partition logic Chen Ridong
2025-11-25  1:09   ` Waiman Long
2025-11-25  1:17     ` Chen Ridong
2025-12-02  0:43     ` Chen Ridong
2025-12-15 13:15     ` Chen Ridong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox