* [PATCH rcu 0/4] Reduce lock contention during RCU CPU stall warnings
@ 2024-08-23 21:14 Paul E. McKenney
2024-08-23 21:15 ` [PATCH rcu 1/4] rcu: Defer printing stall-warning backtrace when holding rcu_node lock Paul E. McKenney
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Paul E. McKenney @ 2024-08-23 21:14 UTC (permalink / raw)
To: rcu; +Cc: linux-kernel, kernel-team, rostedt, riel
Hello!
This patch series reduces lock contention during RCU CPU stall warnings,
especially on systems having slow consoles. It does this first by
deferring printk() output, second by refraining from emitting stack
backtraces if the grace period should end partway through, and third
by using a lockless check in order to avoid ever acquiring the lock for
leaf rcu_node structures not associated with a stalled CPU. In the case
where a given rcu_node structure is associated with multiple stalled CPUs,
the lock is also dropped and reacquired for each stalled CPU.
While in the area, get rid of a function that is no longer used.
1. Defer printing stall-warning backtrace when holding rcu_node lock.
2. Delete unused rcu_gp_might_be_stalled() function.
3. Stop stall warning from dumping stacks if grace period ends.
4. Finer-grained grace-period-end checks in rcu_dump_cpu_stacks().
Thanx, Paul
------------------------------------------------------------------------
b/include/linux/rcutiny.h | 1
b/include/linux/rcutree.h | 1
b/kernel/rcu/tree_stall.h | 2 +
kernel/rcu/tree_stall.h | 65 +++++++++++++++-------------------------------
4 files changed, 24 insertions(+), 45 deletions(-)
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH rcu 1/4] rcu: Defer printing stall-warning backtrace when holding rcu_node lock
2024-08-23 21:14 [PATCH rcu 0/4] Reduce lock contention during RCU CPU stall warnings Paul E. McKenney
@ 2024-08-23 21:15 ` Paul E. McKenney
2024-08-23 21:15 ` [PATCH rcu 2/4] rcu: Delete unused rcu_gp_might_be_stalled() function Paul E. McKenney
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Paul E. McKenney @ 2024-08-23 21:15 UTC (permalink / raw)
To: rcu; +Cc: linux-kernel, kernel-team, rostedt, riel, Paul E. McKenney
The rcu_dump_cpu_stacks() holds the leaf rcu_node structure's ->lock
when dumping the stakcks of any CPUs stalling the current grace period.
This lock is held to prevent confusion that would otherwise occur when
the stalled CPU reported its quiescent state (and then went on to do
unrelated things) just as the backtrace NMI was heading towards it.
This has worked well, but on larger systems has recently been observed
to cause severe lock contention resulting in CSD-lock stalls and other
general unhappiness.
This commit therefore does printk_deferred_enter() before acquiring
the lock and printk_deferred_exit() after releasing it, thus deferring
the overhead of actually outputting the stack trace out of that lock's
critical section.
Reported-by: Rik van Riel <riel@surriel.com>
Suggested-by: Rik van Riel <riel@surriel.com>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
---
kernel/rcu/tree_stall.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h
index cf8e5c6ed50ac..2fb40ec4b2aea 100644
--- a/kernel/rcu/tree_stall.h
+++ b/kernel/rcu/tree_stall.h
@@ -371,6 +371,7 @@ static void rcu_dump_cpu_stacks(void)
struct rcu_node *rnp;
rcu_for_each_leaf_node(rnp) {
+ printk_deferred_enter();
raw_spin_lock_irqsave_rcu_node(rnp, flags);
for_each_leaf_node_possible_cpu(rnp, cpu)
if (rnp->qsmask & leaf_node_cpu_bit(rnp, cpu)) {
@@ -380,6 +381,7 @@ static void rcu_dump_cpu_stacks(void)
dump_cpu_task(cpu);
}
raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
+ printk_deferred_exit();
}
}
--
2.40.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH rcu 2/4] rcu: Delete unused rcu_gp_might_be_stalled() function
2024-08-23 21:14 [PATCH rcu 0/4] Reduce lock contention during RCU CPU stall warnings Paul E. McKenney
2024-08-23 21:15 ` [PATCH rcu 1/4] rcu: Defer printing stall-warning backtrace when holding rcu_node lock Paul E. McKenney
@ 2024-08-23 21:15 ` Paul E. McKenney
2024-08-23 21:15 ` [PATCH rcu 3/4] rcu: Stop stall warning from dumping stacks if grace period ends Paul E. McKenney
2024-08-23 21:15 ` [PATCH rcu 4/4] rcu: Finer-grained grace-period-end checks in rcu_dump_cpu_stacks() Paul E. McKenney
3 siblings, 0 replies; 5+ messages in thread
From: Paul E. McKenney @ 2024-08-23 21:15 UTC (permalink / raw)
To: rcu; +Cc: linux-kernel, kernel-team, rostedt, riel, Paul E. McKenney
The rcu_gp_might_be_stalled() function is no longer used, so this commit
removes it.
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
---
include/linux/rcutiny.h | 1 -
include/linux/rcutree.h | 1 -
kernel/rcu/tree_stall.h | 30 ------------------------------
3 files changed, 32 deletions(-)
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
index cf2b5a188f783..ca43525474a9e 100644
--- a/include/linux/rcutiny.h
+++ b/include/linux/rcutiny.h
@@ -160,7 +160,6 @@ static inline bool rcu_inkernel_boot_has_ended(void) { return true; }
static inline bool rcu_is_watching(void) { return true; }
static inline void rcu_momentary_eqs(void) { }
static inline void kfree_rcu_scheduler_running(void) { }
-static inline bool rcu_gp_might_be_stalled(void) { return false; }
/* Avoid RCU read-side critical sections leaking across. */
static inline void rcu_all_qs(void) { barrier(); }
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index 7dbde2b6f714a..da14ad1141263 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -39,7 +39,6 @@ void kvfree_call_rcu(struct rcu_head *head, void *ptr);
void rcu_barrier(void);
void rcu_momentary_eqs(void);
void kfree_rcu_scheduler_running(void);
-bool rcu_gp_might_be_stalled(void);
struct rcu_gp_oldstate {
unsigned long rgos_norm;
diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h
index 2fb40ec4b2aea..ed065e3ce5c33 100644
--- a/kernel/rcu/tree_stall.h
+++ b/kernel/rcu/tree_stall.h
@@ -75,36 +75,6 @@ int rcu_jiffies_till_stall_check(void)
}
EXPORT_SYMBOL_GPL(rcu_jiffies_till_stall_check);
-/**
- * rcu_gp_might_be_stalled - Is it likely that the grace period is stalled?
- *
- * Returns @true if the current grace period is sufficiently old that
- * it is reasonable to assume that it might be stalled. This can be
- * useful when deciding whether to allocate memory to enable RCU-mediated
- * freeing on the one hand or just invoking synchronize_rcu() on the other.
- * The latter is preferable when the grace period is stalled.
- *
- * Note that sampling of the .gp_start and .gp_seq fields must be done
- * carefully to avoid false positives at the beginnings and ends of
- * grace periods.
- */
-bool rcu_gp_might_be_stalled(void)
-{
- unsigned long d = rcu_jiffies_till_stall_check() / RCU_STALL_MIGHT_DIV;
- unsigned long j = jiffies;
-
- if (d < RCU_STALL_MIGHT_MIN)
- d = RCU_STALL_MIGHT_MIN;
- smp_mb(); // jiffies before .gp_seq to avoid false positives.
- if (!rcu_gp_in_progress())
- return false;
- // Long delays at this point avoids false positive, but a delay
- // of ULONG_MAX/4 jiffies voids your no-false-positive warranty.
- smp_mb(); // .gp_seq before second .gp_start
- // And ditto here.
- return !time_before(j, READ_ONCE(rcu_state.gp_start) + d);
-}
-
/* Don't do RCU CPU stall warnings during long sysrq printouts. */
void rcu_sysrq_start(void)
{
--
2.40.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH rcu 3/4] rcu: Stop stall warning from dumping stacks if grace period ends
2024-08-23 21:14 [PATCH rcu 0/4] Reduce lock contention during RCU CPU stall warnings Paul E. McKenney
2024-08-23 21:15 ` [PATCH rcu 1/4] rcu: Defer printing stall-warning backtrace when holding rcu_node lock Paul E. McKenney
2024-08-23 21:15 ` [PATCH rcu 2/4] rcu: Delete unused rcu_gp_might_be_stalled() function Paul E. McKenney
@ 2024-08-23 21:15 ` Paul E. McKenney
2024-08-23 21:15 ` [PATCH rcu 4/4] rcu: Finer-grained grace-period-end checks in rcu_dump_cpu_stacks() Paul E. McKenney
3 siblings, 0 replies; 5+ messages in thread
From: Paul E. McKenney @ 2024-08-23 21:15 UTC (permalink / raw)
To: rcu; +Cc: linux-kernel, kernel-team, rostedt, riel, Paul E. McKenney
Currently, once an RCU CPU stall warning decides to dump the stalling
CPUs' stacks, the rcu_dump_cpu_stacks() function persists until it
has gone through the full list. Unfortunately, if the stalled grace
periods ends midway through, this function will be dumping stacks of
innocent-bystander CPUs that happen to be blocking not the old grace
period, but instead the new one. This can cause serious confusion.
This commit therefore stops dumping stacks if and when the stalled grace
period ends.
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
---
kernel/rcu/tree_stall.h | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h
index ed065e3ce5c33..9c8eb4b8dfb33 100644
--- a/kernel/rcu/tree_stall.h
+++ b/kernel/rcu/tree_stall.h
@@ -334,13 +334,17 @@ static int rcu_print_task_stall(struct rcu_node *rnp, unsigned long flags)
* that don't support NMI-based stack dumps. The NMI-triggered stack
* traces are more accurate because they are printed by the target CPU.
*/
-static void rcu_dump_cpu_stacks(void)
+static void rcu_dump_cpu_stacks(unsigned long gp_seq)
{
int cpu;
unsigned long flags;
struct rcu_node *rnp;
rcu_for_each_leaf_node(rnp) {
+ if (gp_seq != rcu_state.gp_seq) {
+ pr_err("INFO: Stall ended during stack backtracing.\n");
+ return;
+ }
printk_deferred_enter();
raw_spin_lock_irqsave_rcu_node(rnp, flags);
for_each_leaf_node_possible_cpu(rnp, cpu)
@@ -605,7 +609,7 @@ static void print_other_cpu_stall(unsigned long gp_seq, unsigned long gps)
(long)rcu_seq_current(&rcu_state.gp_seq), totqlen,
data_race(rcu_state.n_online_cpus)); // Diagnostic read
if (ndetected) {
- rcu_dump_cpu_stacks();
+ rcu_dump_cpu_stacks(gp_seq);
/* Complain about tasks blocking the grace period. */
rcu_for_each_leaf_node(rnp)
@@ -635,7 +639,7 @@ static void print_other_cpu_stall(unsigned long gp_seq, unsigned long gps)
rcu_force_quiescent_state(); /* Kick them all. */
}
-static void print_cpu_stall(unsigned long gps)
+static void print_cpu_stall(unsigned long gp_seq, unsigned long gps)
{
int cpu;
unsigned long flags;
@@ -670,7 +674,7 @@ static void print_cpu_stall(unsigned long gps)
rcu_check_gp_kthread_expired_fqs_timer();
rcu_check_gp_kthread_starvation();
- rcu_dump_cpu_stacks();
+ rcu_dump_cpu_stacks(gp_seq);
raw_spin_lock_irqsave_rcu_node(rnp, flags);
/* Rewrite if needed in case of slow consoles. */
@@ -750,7 +754,8 @@ static void check_cpu_stall(struct rcu_data *rdp)
gs2 = READ_ONCE(rcu_state.gp_seq);
if (gs1 != gs2 ||
ULONG_CMP_LT(j, js) ||
- ULONG_CMP_GE(gps, js))
+ ULONG_CMP_GE(gps, js) ||
+ !rcu_seq_state(gs2))
return; /* No stall or GP completed since entering function. */
rnp = rdp->mynode;
jn = jiffies + ULONG_MAX / 2;
@@ -771,7 +776,7 @@ static void check_cpu_stall(struct rcu_data *rdp)
pr_err("INFO: %s detected stall, but suppressed full report due to a stuck CSD-lock.\n", rcu_state.name);
} else if (self_detected) {
/* We haven't checked in, so go dump stack. */
- print_cpu_stall(gps);
+ print_cpu_stall(gs2, gps);
} else {
/* They had a few time units to dump stack, so complain. */
print_other_cpu_stall(gs2, gps);
--
2.40.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH rcu 4/4] rcu: Finer-grained grace-period-end checks in rcu_dump_cpu_stacks()
2024-08-23 21:14 [PATCH rcu 0/4] Reduce lock contention during RCU CPU stall warnings Paul E. McKenney
` (2 preceding siblings ...)
2024-08-23 21:15 ` [PATCH rcu 3/4] rcu: Stop stall warning from dumping stacks if grace period ends Paul E. McKenney
@ 2024-08-23 21:15 ` Paul E. McKenney
3 siblings, 0 replies; 5+ messages in thread
From: Paul E. McKenney @ 2024-08-23 21:15 UTC (permalink / raw)
To: rcu; +Cc: linux-kernel, kernel-team, rostedt, riel, Paul E. McKenney
This commit pushes the grace-period-end checks further down into
rcu_dump_cpu_stacks(), and also uses lockless checks coupled with
finer-grained locking.
The result is that the current leaf rcu_node structure's ->lock is
acquired only if a stack backtrace might be needed from the current CPU,
and is held across only that CPU's backtrace. As a result, if there are
no stalled CPUs associated with a given rcu_node structure, then its
->lock will not be acquired at all. On large systems, it is usually
(though not always) the case that a small number of CPUs are stalling
the current grace period, which means that the ->lock need be acquired
only for a small fraction of the rcu_node structures.
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
---
kernel/rcu/tree_stall.h | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h
index 9c8eb4b8dfb33..ab6848baba4f6 100644
--- a/kernel/rcu/tree_stall.h
+++ b/kernel/rcu/tree_stall.h
@@ -341,20 +341,24 @@ static void rcu_dump_cpu_stacks(unsigned long gp_seq)
struct rcu_node *rnp;
rcu_for_each_leaf_node(rnp) {
- if (gp_seq != rcu_state.gp_seq) {
- pr_err("INFO: Stall ended during stack backtracing.\n");
- return;
- }
printk_deferred_enter();
- raw_spin_lock_irqsave_rcu_node(rnp, flags);
- for_each_leaf_node_possible_cpu(rnp, cpu)
+ for_each_leaf_node_possible_cpu(rnp, cpu) {
+ if (gp_seq != data_race(rcu_state.gp_seq)) {
+ printk_deferred_exit();
+ pr_err("INFO: Stall ended during stack backtracing.\n");
+ return;
+ }
+ if (!(data_race(rnp->qsmask) & leaf_node_cpu_bit(rnp, cpu)))
+ continue;
+ raw_spin_lock_irqsave_rcu_node(rnp, flags);
if (rnp->qsmask & leaf_node_cpu_bit(rnp, cpu)) {
if (cpu_is_offline(cpu))
pr_err("Offline CPU %d blocking current GP.\n", cpu);
else
dump_cpu_task(cpu);
+ raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
}
- raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
+ }
printk_deferred_exit();
}
}
--
2.40.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-08-23 21:15 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-23 21:14 [PATCH rcu 0/4] Reduce lock contention during RCU CPU stall warnings Paul E. McKenney
2024-08-23 21:15 ` [PATCH rcu 1/4] rcu: Defer printing stall-warning backtrace when holding rcu_node lock Paul E. McKenney
2024-08-23 21:15 ` [PATCH rcu 2/4] rcu: Delete unused rcu_gp_might_be_stalled() function Paul E. McKenney
2024-08-23 21:15 ` [PATCH rcu 3/4] rcu: Stop stall warning from dumping stacks if grace period ends Paul E. McKenney
2024-08-23 21:15 ` [PATCH rcu 4/4] rcu: Finer-grained grace-period-end checks in rcu_dump_cpu_stacks() Paul E. McKenney
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox