#include <linux/kallsyms.h>
 #include <linux/security.h>
 #include <linux/seq_file.h>
-#include <linux/notifier.h>
 #include <linux/irqflags.h>
 #include <linux/debugfs.h>
 #include <linux/tracefs.h>
 
 fs_initcall(tracer_init_tracefs);
 
-static int trace_panic_handler(struct notifier_block *this,
-                              unsigned long event, void *unused)
-{
-       if (ftrace_dump_on_oops)
-               ftrace_dump(ftrace_dump_on_oops);
-       return NOTIFY_OK;
-}
+static int trace_die_panic_handler(struct notifier_block *self,
+                               unsigned long ev, void *unused);
 
 static struct notifier_block trace_panic_notifier = {
-       .notifier_call  = trace_panic_handler,
-       .next           = NULL,
-       .priority       = 150   /* priority: INT_MAX >= x >= 0 */
+       .notifier_call = trace_die_panic_handler,
+       .priority = INT_MAX - 1,
 };
 
-static int trace_die_handler(struct notifier_block *self,
-                            unsigned long val,
-                            void *data)
-{
-       switch (val) {
-       case DIE_OOPS:
-               if (ftrace_dump_on_oops)
-                       ftrace_dump(ftrace_dump_on_oops);
-               break;
-       default:
-               break;
-       }
-       return NOTIFY_OK;
-}
-
 static struct notifier_block trace_die_notifier = {
-       .notifier_call = trace_die_handler,
-       .priority = 200
+       .notifier_call = trace_die_panic_handler,
+       .priority = INT_MAX - 1,
 };
 
+/*
+ * The idea is to execute the following die/panic callback early, in order
+ * to avoid showing irrelevant information in the trace (like other panic
+ * notifier functions); we are the 2nd to run, after hung_task/rcu_stall
+ * warnings get disabled (to prevent potential log flooding).
+ */
+static int trace_die_panic_handler(struct notifier_block *self,
+                               unsigned long ev, void *unused)
+{
+       if (!ftrace_dump_on_oops)
+               return NOTIFY_DONE;
+
+       /* The die notifier requires DIE_OOPS to trigger */
+       if (self == &trace_die_notifier && ev != DIE_OOPS)
+               return NOTIFY_DONE;
+
+       ftrace_dump(ftrace_dump_on_oops);
+
+       return NOTIFY_DONE;
+}
+
 /*
  * printk is set to max of 1024, we really don't need it that big.
  * Nothing should be printing 1000 characters anyway.