Commit c570d667 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Fix the mangled-oops-output-on-SMP problem

From: Ingo Molnar <mingo@elte.hu>

printk currently does

	if (oops_in_progres)
		bust_printk_locks();

which means that once we oops, the printk locking is 100% ineffective and
multiple CPUs make an unreadable mess on a serial console.  It's a significant
development hassle.

Fix that up by only popping locks once per ten seconds.

akpm@osdl.org did:

  - Bump the timeout to 30 seconds - 9600 baud is slow.

  - Handle jiffy wraps: change the logic so that we only skip the lockbust
    if the current time is within 30 seconds of the previous lockbusting
    attempt.
parent ed8d9961
...@@ -471,6 +471,27 @@ static void emit_log_char(char c) ...@@ -471,6 +471,27 @@ static void emit_log_char(char c)
logged_chars++; logged_chars++;
} }
/*
* Zap console related locks when oopsing. Only zap at most once
* every 10 seconds, to leave time for slow consoles to print a
* full oops.
*/
static void zap_locks(void)
{
static unsigned long oops_timestamp;
if (time_after_eq(jiffies, oops_timestamp) &&
!time_after(jiffies, oops_timestamp + 30*HZ))
return;
oops_timestamp = jiffies;
/* If a crash is occurring, make sure we can't deadlock */
spin_lock_init(&logbuf_lock);
/* And make sure that we print immediately */
init_MUTEX(&console_sem);
}
/* /*
* This is printk. It can be called from any context. We want it to work. * This is printk. It can be called from any context. We want it to work.
* *
...@@ -493,12 +514,8 @@ asmlinkage int printk(const char *fmt, ...) ...@@ -493,12 +514,8 @@ asmlinkage int printk(const char *fmt, ...)
static char printk_buf[1024]; static char printk_buf[1024];
static int log_level_unknown = 1; static int log_level_unknown = 1;
if (oops_in_progress) { if (unlikely(oops_in_progress))
/* If a crash is occurring, make sure we can't deadlock */ zap_locks();
spin_lock_init(&logbuf_lock);
/* And make sure that we print immediately */
init_MUTEX(&console_sem);
}
/* This stops the holder of console_sem just where we want him */ /* This stops the holder of console_sem just where we want him */
spin_lock_irqsave(&logbuf_lock, flags); spin_lock_irqsave(&logbuf_lock, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment