From: Frederic Weisbecker <frederic@kernel.org>
To: LKML <linux-kernel@vger.kernel.org>
Cc: Frederic Weisbecker <frederic@kernel.org>,
Tejun Heo <tj@kernel.org>, Peter Zijlstra <peterz@infradead.org>,
"Paul E . McKenney" <paulmck@kernel.org>,
Paul Gortmaker <paul.gortmaker@windriver.com>,
Johannes Weiner <hannes@cmpxchg.org>,
Marcelo Tosatti <mtosatti@redhat.com>,
Phil Auld <pauld@redhat.com>, Zefan Li <lizefan.x@bytedance.com>,
Waiman Long <longman@redhat.com>,
Daniel Bristot de Oliveira <bristot@kernel.org>,
Nicolas Saenz Julienne <nsaenz@kernel.org>,
rcu@vger.kernel.org
Subject: [PATCH 1/4] rcu/nocb: Pass a cpumask instead of a single CPU to offload/deoffload
Date: Thu, 26 May 2022 00:10:52 +0200 [thread overview]
Message-ID: <20220525221055.1152307-2-frederic@kernel.org> (raw)
In-Reply-To: <20220525221055.1152307-1-frederic@kernel.org>
Currently the interface to toggle callbacks offloading state only takes
a single CPU per call. Now driving RCU NOCB through cpusets requires
to be able to change the offloading state of a whole set of CPUs.
To make it easier, extend the (de-)offloading interface to support a
cpumask.
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Cc: Zefan Li <lizefan.x@bytedance.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Paul E. McKenney <paulmck@kernel.org>
Cc: Phil Auld <pauld@redhat.com>
Cc: Nicolas Saenz Julienne <nsaenz@kernel.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Waiman Long <longman@redhat.com>
Cc: Daniel Bristot de Oliveira <bristot@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
---
include/linux/rcupdate.h | 9 ++--
kernel/rcu/rcutorture.c | 4 +-
kernel/rcu/tree_nocb.h | 102 ++++++++++++++++++++++++++-------------
3 files changed, 76 insertions(+), 39 deletions(-)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index f9f75a3cfeb8..dc8bb7cc893a 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -114,13 +114,14 @@ static inline void rcu_user_exit(void) { }
#ifdef CONFIG_RCU_NOCB_CPU
void rcu_init_nohz(void);
-int rcu_nocb_cpu_offload(int cpu);
-int rcu_nocb_cpu_deoffload(int cpu);
+int rcu_nocb_cpumask_update(struct cpumask *cpumask, bool offload);
void rcu_nocb_flush_deferred_wakeup(void);
#else /* #ifdef CONFIG_RCU_NOCB_CPU */
static inline void rcu_init_nohz(void) { }
-static inline int rcu_nocb_cpu_offload(int cpu) { return -EINVAL; }
-static inline int rcu_nocb_cpu_deoffload(int cpu) { return 0; }
+static inline int rcu_nocb_cpumask_update(struct cpumask *cpumask, bool offload)
+{
+ return -EINVAL;
+}
static inline void rcu_nocb_flush_deferred_wakeup(void) { }
#endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index faf6b4c7a757..f912ff4869b3 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -1887,10 +1887,10 @@ static int rcu_nocb_toggle(void *arg)
r = torture_random(&rand);
cpu = (r >> 4) % (maxcpu + 1);
if (r & 0x1) {
- rcu_nocb_cpu_offload(cpu);
+ rcu_nocb_cpumask_update(cpumask_of(cpu), true);
atomic_long_inc(&n_nocb_offload);
} else {
- rcu_nocb_cpu_deoffload(cpu);
+ rcu_nocb_cpumask_update(cpumask_of(cpu), false);
atomic_long_inc(&n_nocb_deoffload);
}
toggle_delay = torture_random(&rand) % toggle_fuzz + toggle_interval;
diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h
index fa8e4f82e60c..428571ad11e3 100644
--- a/kernel/rcu/tree_nocb.h
+++ b/kernel/rcu/tree_nocb.h
@@ -1084,29 +1084,23 @@ static long rcu_nocb_rdp_deoffload(void *arg)
return 0;
}
-int rcu_nocb_cpu_deoffload(int cpu)
+static 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.barrier_mutex);
- if (rcu_rdp_is_offloaded(rdp)) {
- if (cpu_online(cpu)) {
- ret = work_on_cpu(cpu, rcu_nocb_rdp_deoffload, rdp);
- if (!ret)
- cpumask_clear_cpu(cpu, rcu_nocb_mask);
- } else {
- pr_info("NOCB: Can't CB-deoffload an offline CPU\n");
- ret = -EINVAL;
- }
- }
- mutex_unlock(&rcu_state.barrier_mutex);
- cpus_read_unlock();
+ if (cpu_is_offline(cpu))
+ return -EINVAL;
+
+ if (!rcu_rdp_is_offloaded(rdp))
+ return 0;
+
+ ret = work_on_cpu(cpu, rcu_nocb_rdp_deoffload, rdp);
+ if (!ret)
+ cpumask_clear_cpu(cpu, rcu_nocb_mask);
return ret;
}
-EXPORT_SYMBOL_GPL(rcu_nocb_cpu_deoffload);
static long rcu_nocb_rdp_offload(void *arg)
{
@@ -1117,12 +1111,6 @@ static long rcu_nocb_rdp_offload(void *arg)
struct rcu_data *rdp_gp = rdp->nocb_gp_rdp;
WARN_ON_ONCE(rdp->cpu != raw_smp_processor_id());
- /*
- * For now we only support re-offload, ie: the rdp must have been
- * offloaded on boot first.
- */
- if (!rdp->nocb_gp_rdp)
- return -EINVAL;
if (WARN_ON_ONCE(!rdp_gp->nocb_gp_kthread))
return -EINVAL;
@@ -1169,29 +1157,77 @@ static long rcu_nocb_rdp_offload(void *arg)
return 0;
}
-int rcu_nocb_cpu_offload(int cpu)
+static int rcu_nocb_cpu_offload(int cpu)
{
struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
- int ret = 0;
+ int ret;
+
+ if (cpu_is_offline(cpu))
+ return -EINVAL;
+
+ if (rcu_rdp_is_offloaded(rdp))
+ return 0;
+
+ ret = work_on_cpu(cpu, rcu_nocb_rdp_offload, rdp);
+ if (!ret)
+ cpumask_set_cpu(cpu, rcu_nocb_mask);
+
+ return ret;
+}
+
+int rcu_nocb_cpumask_update(struct cpumask *cpumask, bool offload)
+{
+ int cpu;
+ int err = 0;
+ int err_cpu;
+ cpumask_var_t saved_nocb_mask;
+
+ if (!alloc_cpumask_var(&saved_nocb_mask, GFP_KERNEL))
+ return -ENOMEM;
+
+ cpumask_copy(saved_nocb_mask, rcu_nocb_mask);
cpus_read_lock();
mutex_lock(&rcu_state.barrier_mutex);
- if (!rcu_rdp_is_offloaded(rdp)) {
- if (cpu_online(cpu)) {
- ret = work_on_cpu(cpu, rcu_nocb_rdp_offload, rdp);
- if (!ret)
- cpumask_set_cpu(cpu, rcu_nocb_mask);
+ for_each_cpu(cpu, cpumask) {
+ if (offload) {
+ err = rcu_nocb_cpu_offload(cpu);
+ if (err < 0) {
+ err_cpu = cpu;
+ pr_err("NOCB: offload cpu %d failed (%d)\n", cpu, err);
+ break;
+ }
} else {
- pr_info("NOCB: Can't CB-offload an offline CPU\n");
- ret = -EINVAL;
+ err = rcu_nocb_cpu_deoffload(cpu);
+ if (err < 0) {
+ err_cpu = cpu;
+ pr_err("NOCB: deoffload cpu %d failed (%d)\n", cpu, err);
+ break;
+ }
}
}
+
+ /* Rollback in case of error */
+ if (err < 0) {
+ err_cpu = cpu;
+ for_each_cpu(cpu, cpumask) {
+ if (err_cpu == cpu)
+ break;
+ if (cpumask_test_cpu(cpu, saved_nocb_mask))
+ WARN_ON_ONCE(rcu_nocb_cpu_offload(cpu));
+ else
+ WARN_ON_ONCE(rcu_nocb_cpu_deoffload(cpu));
+ }
+ }
+
mutex_unlock(&rcu_state.barrier_mutex);
cpus_read_unlock();
- return ret;
+ free_cpumask_var(saved_nocb_mask);
+
+ return err;
}
-EXPORT_SYMBOL_GPL(rcu_nocb_cpu_offload);
+EXPORT_SYMBOL_GPL(rcu_nocb_cpumask_update);
void __init rcu_init_nohz(void)
{
--
2.25.1
next prev parent reply other threads:[~2022-05-25 22:11 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-25 22:10 [PATCH 0/4] rcu/cpuset: Control RCU_NOCB offloading through cpusets Frederic Weisbecker
2022-05-25 22:10 ` Frederic Weisbecker [this message]
2022-05-25 22:19 ` [PATCH 1/4] rcu/nocb: Pass a cpumask instead of a single CPU to offload/deoffload Frederic Weisbecker
2022-05-25 22:42 ` Paul E. McKenney
2022-05-25 22:10 ` [PATCH 2/4] rcu/nocb: Prepare to change nocb cpumask from CPU-hotplug protected cpuset caller Frederic Weisbecker
2022-05-25 22:10 ` [PATCH 3/4] sched/isolation: Infrastructure to support rcu nocb cpumask changes Frederic Weisbecker
2022-08-19 7:12 ` Tobias Huschle
2022-05-25 22:10 ` [RFC PATCH 4/4] cpuset: Support RCU-NOCB toggle on v2 root partitions Frederic Weisbecker
2022-05-26 18:21 ` Tejun Heo
2022-05-26 22:51 ` Frederic Weisbecker
2022-05-26 23:02 ` Tejun Heo
2022-05-27 0:28 ` Waiman Long
2022-05-27 0:37 ` Tejun Heo
2022-05-27 8:30 ` Juri Lelli
2022-05-27 8:45 ` Tejun Heo
2022-05-27 12:58 ` Phil Auld
2022-05-28 14:24 ` Peter Zijlstra
2022-05-30 0:40 ` Frederic Weisbecker
2022-05-30 8:11 ` Peter Zijlstra
2022-05-30 10:56 ` Frederic Weisbecker
2022-05-30 13:16 ` Peter Zijlstra
2022-05-30 14:13 ` Juri Lelli
2022-05-30 21:35 ` Frederic Weisbecker
2022-05-31 0:57 ` Tejun Heo
2022-05-31 14:21 ` Waiman Long
2022-05-30 14:29 ` nicolas saenz julienne
2022-05-30 14:49 ` Paul E. McKenney
2022-05-30 22:36 ` Alison Chaiken
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220525221055.1152307-2-frederic@kernel.org \
--to=frederic@kernel.org \
--cc=bristot@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lizefan.x@bytedance.com \
--cc=longman@redhat.com \
--cc=mtosatti@redhat.com \
--cc=nsaenz@kernel.org \
--cc=paul.gortmaker@windriver.com \
--cc=pauld@redhat.com \
--cc=paulmck@kernel.org \
--cc=peterz@infradead.org \
--cc=rcu@vger.kernel.org \
--cc=tj@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.