]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
cgroup/cpuset: Fix error handling in remote_partition_disable()
authorWaiman Long <longman@redhat.com>
Sun, 30 Mar 2025 21:52:41 +0000 (17:52 -0400)
committerTejun Heo <tj@kernel.org>
Mon, 31 Mar 2025 23:25:38 +0000 (13:25 -1000)
When remote_partition_disable() is called to disable a remote partition,
it always sets the partition to an invalid partition state. It should
only do so if an error code (prs_err) has been set. Correct that and
add proper error code in places where remote_partition_disable() is
called due to error.

Fixes: 181c8e091aae ("cgroup/cpuset: Introduce remote partition")
Signed-off-by: Waiman Long <longman@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
kernel/cgroup/cpuset.c

index 2c49d80f2a01391d62826b7e2f7b6a9688acce8a..e457b4b1db5d15fa891c750d73495bab933c1176 100644 (file)
@@ -1406,6 +1406,7 @@ static int remote_partition_enable(struct cpuset *cs, int new_prs,
        list_add(&cs->remote_sibling, &remote_children);
        spin_unlock_irq(&callback_lock);
        update_unbound_workqueue_cpumask(isolcpus_updated);
+       cs->prs_err = 0;
 
        /*
         * Propagate changes in top_cpuset's effective_cpus down the hierarchy.
@@ -1436,9 +1437,11 @@ static void remote_partition_disable(struct cpuset *cs, struct tmpmasks *tmp)
        list_del_init(&cs->remote_sibling);
        isolcpus_updated = partition_xcpus_del(cs->partition_root_state,
                                               NULL, tmp->new_cpus);
-       cs->partition_root_state = -cs->partition_root_state;
-       if (!cs->prs_err)
-               cs->prs_err = PERR_INVCPUS;
+       if (cs->prs_err)
+               cs->partition_root_state = -cs->partition_root_state;
+       else
+               cs->partition_root_state = PRS_MEMBER;
+
        reset_partition_data(cs);
        spin_unlock_irq(&callback_lock);
        update_unbound_workqueue_cpumask(isolcpus_updated);
@@ -1471,8 +1474,10 @@ static void remote_cpus_update(struct cpuset *cs, struct cpumask *newmask,
 
        WARN_ON_ONCE(!cpumask_subset(cs->effective_xcpus, subpartitions_cpus));
 
-       if (cpumask_empty(newmask))
+       if (cpumask_empty(newmask)) {
+               cs->prs_err = PERR_CPUSEMPTY;
                goto invalidate;
+       }
 
        adding   = cpumask_andnot(tmp->addmask, newmask, cs->effective_xcpus);
        deleting = cpumask_andnot(tmp->delmask, cs->effective_xcpus, newmask);
@@ -1482,10 +1487,15 @@ static void remote_cpus_update(struct cpuset *cs, struct cpumask *newmask,
         * not allocated to other partitions and there are effective_cpus
         * left in the top cpuset.
         */
-       if (adding && (!capable(CAP_SYS_ADMIN) ||
-                      cpumask_intersects(tmp->addmask, subpartitions_cpus) ||
-                      cpumask_subset(top_cpuset.effective_cpus, tmp->addmask)))
-               goto invalidate;
+       if (adding) {
+               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;
+               if (cs->prs_err)
+                       goto invalidate;
+       }
 
        spin_lock_irq(&callback_lock);
        if (adding)
@@ -1601,7 +1611,7 @@ static bool prstate_housekeeping_conflict(int prstate, struct cpumask *new_cpus)
  * 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_error will be updated
+ * 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,
@@ -3739,6 +3749,7 @@ retry:
 
        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;