Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Mladek <pmladek@suse.com>2019-09-30 10:59:20 +0200
committerPetr Mladek <pmladek@suse.com>2019-09-30 16:36:21 +0200
commitfdaa896e840a8788a2186a3d071d17f5140c7e96 (patch)
tree434ebdf4e14a357ab7fbac45115a662eeb310db8
parentd120b01076aa6e8ce6a151909f9bc90057d90848 (diff)
printk/panic: Avoid deadlock in printk() after stopping CPUs
by NMI (bsc#1148712). suse-commit: dd62e61de51a3a38ea762c4c47227a298594a1dc
-rw-r--r--arch/x86/kernel/crash.c1
-rw-r--r--include/linux/printk.h6
-rw-r--r--kernel/printk/printk.c16
3 files changed, 23 insertions, 0 deletions
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 2bf70a2fed90..90cc72d38dda 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -99,6 +99,7 @@ static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
void kdump_nmi_shootdown_cpus(void)
{
nmi_shootdown_cpus(kdump_nmi_callback);
+ printk_bust_locks();
disable_local_APIC();
}
diff --git a/include/linux/printk.h b/include/linux/printk.h
index cefd374c47b1..63c1ecaf227b 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -194,6 +194,8 @@ devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write, void __user *buf,
extern void wake_up_klogd(void);
+void printk_bust_locks(void);
+
char *log_buf_addr_get(void);
u32 log_buf_len_get(void);
void log_buf_vmcoreinfo_setup(void);
@@ -235,6 +237,10 @@ static inline void wake_up_klogd(void)
{
}
+static void printk_bust_locks(void)
+{
+}
+
static inline char *log_buf_addr_get(void)
{
return NULL;
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index ffeb1cb99603..674ba0c2552e 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1626,6 +1626,22 @@ static struct task_struct *console_owner;
static bool console_waiter;
/**
+ * printk_bust_locks - forcibly reset all printk-related locks
+ *
+ * This function can be used after CPUs were stopped using NMI.
+ * It is especially useful in kdump_nmi_shootdown_cpus() that
+ * uses NMI but it does not modify the online CPU mask.
+ */
+void printk_bust_locks(void)
+{
+ debug_locks_off();
+ raw_spin_lock_init(&logbuf_lock);
+ raw_spin_lock_init(&console_owner_lock);
+ console_owner = NULL;
+ console_waiter = false;
+}
+
+/**
* console_lock_spinning_enable - mark beginning of code where another
* thread might safely busy wait
*