From: Takenori Nagano <t-nagano@ah.jp.nec.com>
Subject: [PATCH] Add dump_after_notifier sysctl
Patch-mainline: never
References: 265764

This patch adds dump_after_notifier sysctl to execute kdump after the notifier
call chain. This basically makes it possible to execute KDB before kdump.

Signed-off-by: Takenori Nagano <t-nagano@ah.jp.nec.com>
Acked-by: Bernhard Walle <bwalle@suse.de>

---
 include/linux/kexec.h  |    2 ++
 include/linux/sysctl.h |    1 +
 kernel/kexec.c         |   29 +++++++++++++++++++++++++++++
 kernel/panic.c         |    5 ++++-
 kernel/sysctl_check.c  |    1 +
 5 files changed, 37 insertions(+), 1 deletion(-)

--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -158,6 +158,7 @@ unsigned long paddr_vmcoreinfo_note(void
 
 extern struct kimage *kexec_image;
 extern struct kimage *kexec_crash_image;
+extern int dump_after_notifier;
 
 #ifndef kexec_flush_icache_page
 #define kexec_flush_icache_page(page)
@@ -212,5 +213,6 @@ struct pt_regs;
 struct task_struct;
 static inline void crash_kexec(struct pt_regs *regs) { }
 static inline int kexec_should_crash(struct task_struct *p) { return 0; }
+#define dump_after_notifier 0
 #endif /* CONFIG_KEXEC */
 #endif /* LINUX_KEXEC_H */
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -162,6 +162,7 @@ enum
 	KERN_MAX_LOCK_DEPTH=74,
 	KERN_NMI_WATCHDOG=75, /* int: enable/disable nmi watchdog */
 	KERN_PANIC_ON_NMI=76, /* int: whether we will panic on an unrecovered */
+	KERN_DUMP_AFTER_NOTIFIER=78, /* int: kdump after panic_notifier (SUSE only) */
 	KERN_PANIC_ON_IO_NMI=79, /* int: whether we will panic on an io NMI */
 };
 
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/console.h>
 #include <linux/vmalloc.h>
+#include <linux/sysctl.h>
 
 #include <asm/page.h>
 #include <asm/uaccess.h>
@@ -46,6 +47,7 @@
 
 /* Per cpu memory for storing cpu states in case of system crash. */
 note_buf_t* crash_notes;
+int dump_after_notifier;
 
 /* vmcoreinfo stuff */
 static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
@@ -1152,6 +1154,30 @@ void crash_save_cpu(struct pt_regs *regs
 	final_note(buf);
 }
 
+#ifdef CONFIG_SYSCTL
+static ctl_table dump_after_notifier_table[] = {
+	{
+		.ctl_name = KERN_DUMP_AFTER_NOTIFIER,
+		.procname = "dump_after_notifier",
+		.data = &dump_after_notifier,
+		.maxlen = sizeof(int),
+		.mode = 0644,
+		.proc_handler = &proc_dointvec,
+	},
+	{ .ctl_name = 0 }
+};
+
+static ctl_table kexec_sys_table[] = {
+	{
+		.ctl_name = CTL_KERN,
+		.procname = "kernel",
+		.mode = 0555,
+		.child = dump_after_notifier_table,
+	},
+	{ .ctl_name = 0 }
+};
+#endif
+
 static int __init crash_notes_memory_init(void)
 {
 	/* Allocate memory for saving cpu registers. */
@@ -1161,6 +1187,9 @@ static int __init crash_notes_memory_ini
 		" states failed\n");
 		return -ENOMEM;
 	}
+#ifdef CONFIG_SYSCTL
+	register_sysctl_table(kexec_sys_table);
+#endif
 	return 0;
 }
 module_init(crash_notes_memory_init)
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -87,7 +87,8 @@ NORET_TYPE void panic(const char * fmt,
 	 * everything else.
 	 * Do we want to call this before we try to display a message?
 	 */
-	crash_kexec(NULL);
+	if (!dump_after_notifier)
+		crash_kexec(NULL);
 
 	/*
 	 * Note smp_send_stop is the usual smp shutdown function, which
@@ -98,6 +99,8 @@ NORET_TYPE void panic(const char * fmt,
 
 	atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
 
+	crash_kexec(NULL);
+
 	bust_spinlocks(0);
 
 	if (!panic_blink)
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -106,6 +106,7 @@ static const struct trans_ctl_table tran
 	{ KERN_PANIC_ON_NMI,		"panic_on_unrecovered_nmi" },
 	{ KERN_PANIC_ON_IO_NMI,		"panic_on_io_nmi" },
 	{ KERN_SETUID_DUMPABLE,		"suid_dumpable" },
+	{ KERN_DUMP_AFTER_NOTIFIER,	"dump_after_notifier" },
 	{}
 };
 
