[PATCH v2 04/10] rcu: Add running and boosted indications to RCU task stall dump

From: Paul E. McKenney

Date: Wed Oct 07 2026 - 16:45:53 EST


Currently, rcu_print_task_stall() will dump out the PID, RCU reader
nesting level, the rcu_special structure's flags, and whether or not
that reader is on the ->blkd_tasks list. When debugging RCU priority
boosting, it is also good to know whether the stalled RCU reader is
currently running and whether it is currently being RCU priority boosted.
This commit therefore adds this information to the output.

[ paulmck: Apply kernel test robot feedback. ]
[ paulmck: Apply feedback from Arnd Bergmann and kernel test robot. ]

Link: https://lore.kernel.org/all/20260925133922.1356404-1-arnd@xxxxxxxxxx/
Link: https://lore.kernel.org/all/202609261005.GrnaXBXT-lkp@xxxxxxxxx/
Signed-off-by: Paul E. McKenney <paulmck@xxxxxxxxxx>
Reviewed-by: Bradley Morgan <brads@xxxxxxxxxxxxxx>
Reviewed-by: Kunwu Chan <kunwu.chan@xxxxxxxxx>
Tested-by: Kunwu Chan <kunwu.chan@xxxxxxxxx>
---
kernel/rcu/tree_plugin.h | 2 --
kernel/rcu/tree_stall.h | 24 ++++++++++++++++++++++--
2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 743c16247fc05..ae5d21bae7bc0 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -11,8 +11,6 @@
* Paul E. McKenney <paulmck@xxxxxxxxxxxxx>
*/

-#include "../locking/rtmutex_common.h"
-
static bool rcu_rdp_is_offloaded(struct rcu_data *rdp)
{
/*
diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h
index 93ba31a619b67..803a56af3259f 100644
--- a/kernel/rcu/tree_stall.h
+++ b/kernel/rcu/tree_stall.h
@@ -11,6 +11,8 @@
#include <linux/kvm_para.h>
#include <linux/rcu_notifier.h>
#include <linux/smp.h>
+#include <linux/rtmutex.h>
+#include "../locking/rtmutex_common.h"

//////////////////////////////////////////////////////////////////////////////
//
@@ -305,6 +307,8 @@ struct rcu_stall_chk_rdr {
int nesting;
union rcu_special rs;
bool on_blkd_list;
+ bool rcu_rdr_running;
+ int rcu_rdr_boosted;
};

/*
@@ -313,6 +317,7 @@ struct rcu_stall_chk_rdr {
*/
static int check_slow_task(struct task_struct *t, void *arg)
{
+ struct rcu_node *rnp;
struct rcu_stall_chk_rdr *rscrp = arg;

if (task_curr(t))
@@ -320,6 +325,19 @@ static int check_slow_task(struct task_struct *t, void *arg)
rscrp->nesting = t->rcu_read_lock_nesting;
rscrp->rs = t->rcu_read_unlock_special;
rscrp->on_blkd_list = !list_empty(&t->rcu_node_entry);
+ rscrp->rcu_rdr_running = task_curr(t);
+ rscrp->rcu_rdr_boosted = 0;
+ if (rscrp->on_blkd_list) {
+ rnp = READ_ONCE(t->rcu_blocked_node);
+ raw_spin_lock_rcu_node(rnp); /* irqs already disabled. */
+ if (rnp == READ_ONCE(t->rcu_blocked_node)) {
+ if (rt_mutex_owner(&rnp->boost_mtx.rtmutex) == t)
+ rscrp->rcu_rdr_boosted = 1;
+ } else {
+ rscrp->rcu_rdr_boosted = 2;
+ }
+ raw_spin_unlock_rcu_node(rnp); /* irqs remain disabled. */
+ }
return 0;
}

@@ -357,12 +375,14 @@ static int rcu_print_task_stall(struct rcu_node *rnp, unsigned long flags)
if (task_call_func(t, check_slow_task, &rscr))
pr_cont(" P%d", t->pid);
else
- pr_cont(" P%d/%d:%c%c%c%c",
+ pr_cont(" P%d/%d:%c%c%c%c%c%c",
t->pid, rscr.nesting,
".b"[rscr.rs.b.blocked],
".q"[rscr.rs.b.need_qs],
".e"[rscr.rs.b.exp_hint],
- ".l"[rscr.on_blkd_list]);
+ ".l"[rscr.on_blkd_list],
+ ".R"[rscr.rcu_rdr_running],
+ ".B?"[rscr.rcu_rdr_boosted]);
lockdep_assert_irqs_disabled();
put_task_struct(t);
ndetected++;
--
2.40.1