]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
rcu: sysctl: Panic on RCU Stall
authorDaniel Bristot de Oliveira <bristot@redhat.com>
Thu, 2 Jun 2016 16:51:41 +0000 (13:51 -0300)
committerSomasundaram Krishnasamy <somasundaram.krishnasamy@oracle.com>
Fri, 8 Sep 2017 14:07:38 +0000 (07:07 -0700)
Orabug: 26338027

It is not always easy to determine the cause of an RCU stall just by
analysing the RCU stall messages, mainly when the problem is caused
by the indirect starvation of rcu threads. For example, when preempt_rcu
is not awakened due to the starvation of a timer softirq.

We have been hard coding panic() in the RCU stall functions for
some time while testing the kernel-rt. But this is not possible in
some scenarios, like when supporting customers.

This patch implements the sysctl kernel.panic_on_rcu_stall. If
set to 1, the system will panic() when an RCU stall takes place,
enabling the capture of a vmcore. The vmcore provides a way to analyze
all kernel/tasks states, helping out to point to the culprit and the
solution for the stall.

The kernel.panic_on_rcu_stall sysctl is disabled by default.

Changes from v1:
- Fixed a typo in the git log
- The if(sysctl_panic_on_rcu_stall) panic() is in a static function
- Fixed the CONFIG_TINY_RCU compilation issue
- The var sysctl_panic_on_rcu_stall is now __read_mostly

Cc: Jonathan Corbet <corbet@lwn.net>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Cc: Josh Triplett <josh@joshtriplett.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Lai Jiangshan <jiangshanlai@gmail.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Reviewed-by: Arnaldo Carvalho de Melo <acme@kernel.org>
Tested-by: "Luis Claudio R. Goncalves" <lgoncalv@redhat.com>
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
(cherry picked from commit 088e9d253d3a4ab7e058dd84bb532c32dadf1882)
Signed-off-by: Somasundaram Krishnasamy <somasundaram.krishnasamy@oracle.com>
Reviewed-by: Jack Vogel <jack.vogel@oracle.com>
Conflicts:
Documentation/sysctl/kernel.txt

Documentation/sysctl/kernel.txt
include/linux/kernel.h
kernel/rcu/tree.c
kernel/sysctl.c

index 5a4962cd5e1fe7ea154f14b4a277912a787ae013..bbc7c531aaff04e5b13095f3595e946aa84284e3 100644 (file)
@@ -58,6 +58,7 @@ show up in /proc/sys/kernel:
 - panic_on_stackoverflow
 - panic_on_unrecovered_nmi
 - panic_on_warn
+- panic_on_rcu_stall
 - pid_max
 - powersave-nap               [ PPC only ]
 - printk
@@ -598,6 +599,17 @@ a kernel rebuild when attempting to kdump at the location of a WARN().
 
 ==============================================================
 
+panic_on_rcu_stall:
+
+When set to 1, calls panic() after RCU stall detection messages. This
+is useful to define the root cause of RCU stalls using a vmcore.
+
+0: do not panic() when RCU stall takes place, default behavior.
+
+1: panic() after printing RCU stall messages.
+
+==============================================================
+
 perf_cpu_time_max_percent:
 
 Hints to the kernel how much CPU time it should be allowed to
index fd9fed4ab265ea410f8c5c2ad4faab52aaf359ee..624c1ae8292851737de7665a45f90f6fa7fda5d5 100644 (file)
@@ -438,6 +438,7 @@ extern int panic_on_oops;
 extern int panic_on_unrecovered_nmi;
 extern int panic_on_io_nmi;
 extern int panic_on_warn;
+extern int sysctl_panic_on_rcu_stall;
 extern int sysctl_panic_on_stackoverflow;
 /*
  * panic_cpu is used for synchronizing panic() and crash_kexec() execution. It
index 8cf7304b2867f5a113807afb0bd5dc0a3bd3cfc0..2f944207f6cebba16fe59b6bab57b3c1bd18cc45 100644 (file)
@@ -125,6 +125,8 @@ static int num_rcu_lvl[] = {  /* Number of rcu_nodes at specified level. */
        NUM_RCU_LVL_4,
 };
 int rcu_num_nodes __read_mostly = NUM_RCU_NODES; /* Total # rcu_nodes in use. */
+/* panic() on RCU Stall sysctl. */
+int sysctl_panic_on_rcu_stall __read_mostly;
 
 /*
  * The rcu_scheduler_active variable transitions from zero to one just
@@ -1159,6 +1161,12 @@ static void rcu_dump_cpu_stacks(struct rcu_state *rsp)
        }
 }
 
+static inline void panic_on_rcu_stall(void)
+{
+       if (sysctl_panic_on_rcu_stall)
+               panic("RCU Stall\n");
+}
+
 static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum)
 {
        int cpu;
@@ -1232,6 +1240,8 @@ static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum)
 
        rcu_check_gp_kthread_starvation(rsp);
 
+       panic_on_rcu_stall();
+
        force_quiescent_state(rsp);  /* Kick them all. */
 }
 
@@ -1267,6 +1277,8 @@ static void print_cpu_stall(struct rcu_state *rsp)
                                     3 * rcu_jiffies_till_stall_check() + 3;
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
 
+       panic_on_rcu_stall();
+
        /*
         * Attempt to revive the RCU machinery by forcing a context switch.
         *
index 9b0850cbf85351688444bcf302297441f326ab77..accc394915f9d1c22a07ec1002105df12398f7d3 100644 (file)
@@ -1159,6 +1159,17 @@ static struct ctl_table kern_table[] = {
                .mode           = 0555,
                .child          = ksplice_sysctls,
        },
+#endif
+#if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU)
+       {
+               .procname       = "panic_on_rcu_stall",
+               .data           = &sysctl_panic_on_rcu_stall,
+               .maxlen         = sizeof(sysctl_panic_on_rcu_stall),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
 #endif
        { }
 };