]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
rcu/nocb: Consolidate rcu_nocb_cpu_offload/deoffload functions
authorJoel Fernandes <joelagnelf@nvidia.com>
Sat, 3 Jan 2026 15:37:54 +0000 (10:37 -0500)
committerJoel Fernandes <joelagnelf@nvidia.com>
Mon, 30 Mar 2026 19:48:14 +0000 (15:48 -0400)
The rcu_nocb_cpu_offload() and rcu_nocb_cpu_deoffload() functions are
nearly duplicates.

Therefore, extract the common logic into rcu_nocb_cpu_toggle_offload()
which takes an 'offload' boolean, and make both exported functions
simple wrappers.

This eliminates a bunch of duplicate code at the call sites, namely
mutex locking, CPU hotplug locking and CPU online checks.

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
kernel/rcu/tree_nocb.h

index b3337c7231ccb887e8acad455ee6f0f397661eac..d5e4d23090e8e86c6dd2a92c6463aaa0e68a19fc 100644 (file)
@@ -1081,30 +1081,6 @@ static int rcu_nocb_rdp_deoffload(struct rcu_data *rdp)
        return 0;
 }
 
-int rcu_nocb_cpu_deoffload(int cpu)
-{
-       struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
-       int ret = 0;
-
-       cpus_read_lock();
-       mutex_lock(&rcu_state.nocb_mutex);
-       if (rcu_rdp_is_offloaded(rdp)) {
-               if (!cpu_online(cpu)) {
-                       ret = rcu_nocb_rdp_deoffload(rdp);
-                       if (!ret)
-                               cpumask_clear_cpu(cpu, rcu_nocb_mask);
-               } else {
-                       pr_info("NOCB: Cannot CB-deoffload online CPU %d\n", rdp->cpu);
-                       ret = -EINVAL;
-               }
-       }
-       mutex_unlock(&rcu_state.nocb_mutex);
-       cpus_read_unlock();
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(rcu_nocb_cpu_deoffload);
-
 static bool rcu_nocb_rdp_offload_wait_cond(struct rcu_data *rdp)
 {
        unsigned long flags;
@@ -1149,28 +1125,52 @@ static int rcu_nocb_rdp_offload(struct rcu_data *rdp)
        return 0;
 }
 
-int rcu_nocb_cpu_offload(int cpu)
+/* Common helper for CPU offload/deoffload operations. */
+static int rcu_nocb_cpu_toggle_offload(int cpu, bool offload)
 {
        struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
        int ret = 0;
 
        cpus_read_lock();
        mutex_lock(&rcu_state.nocb_mutex);
-       if (!rcu_rdp_is_offloaded(rdp)) {
-               if (!cpu_online(cpu)) {
-                       ret = rcu_nocb_rdp_offload(rdp);
-                       if (!ret)
-                               cpumask_set_cpu(cpu, rcu_nocb_mask);
-               } else {
-                       pr_info("NOCB: Cannot CB-offload online CPU %d\n", rdp->cpu);
-                       ret = -EINVAL;
-               }
+
+       /* Already in desired state, nothing to do. */
+       if (rcu_rdp_is_offloaded(rdp) == offload)
+               goto out_unlock;
+
+       if (cpu_online(cpu)) {
+               pr_info("NOCB: Cannot CB-%soffload online CPU %d\n",
+                       offload ? "" : "de", rdp->cpu);
+               ret = -EINVAL;
+               goto out_unlock;
        }
+
+       if (offload) {
+               ret = rcu_nocb_rdp_offload(rdp);
+               if (!ret)
+                       cpumask_set_cpu(cpu, rcu_nocb_mask);
+       } else {
+               ret = rcu_nocb_rdp_deoffload(rdp);
+               if (!ret)
+                       cpumask_clear_cpu(cpu, rcu_nocb_mask);
+       }
+
+out_unlock:
        mutex_unlock(&rcu_state.nocb_mutex);
        cpus_read_unlock();
-
        return ret;
 }
+
+int rcu_nocb_cpu_deoffload(int cpu)
+{
+       return rcu_nocb_cpu_toggle_offload(cpu, false /* de-offload */);
+}
+EXPORT_SYMBOL_GPL(rcu_nocb_cpu_deoffload);
+
+int rcu_nocb_cpu_offload(int cpu)
+{
+       return rcu_nocb_cpu_toggle_offload(cpu, true /* offload */);
+}
 EXPORT_SYMBOL_GPL(rcu_nocb_cpu_offload);
 
 #ifdef CONFIG_RCU_LAZY