X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=kernel%2Fprintk.c;h=11c6681ad944ea3b7bee4f67fe630ec6117c75a2;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=bb5ac824d4e19f12a34f3018f77d68d6637d8219;hpb=a8e794ca871505c8ea96cc102f4ad555c5231d7f;p=linux-2.6.git diff --git a/kernel/printk.c b/kernel/printk.c index bb5ac824d..11c6681ad 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -192,6 +193,8 @@ static int __init log_buf_len_setup(char *str) unsigned long size = memparse(str, &str); unsigned long flags; + if (size) + size = roundup_pow_of_two(size); if (size > log_buf_len) { unsigned long start, dest_idx, offset; char * new_log_buf; @@ -474,6 +477,27 @@ static void emit_log_char(char c) 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. * @@ -490,26 +514,34 @@ static void emit_log_char(char c) asmlinkage int printk(const char *fmt, ...) { va_list args; + int r; + + va_start(args, fmt); + r = vprintk(fmt, args); + va_end(args); + + return r; +} + +static volatile int printk_cpu = -1; + +asmlinkage int vprintk(const char *fmt, va_list args) +{ unsigned long flags; int printed_len; char *p; static char printk_buf[1024]; static int log_level_unknown = 1; - if (oops_in_progress) { - /* 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); - } + if (unlikely(oops_in_progress && printk_cpu == smp_processor_id())) + zap_locks(); /* This stops the holder of console_sem just where we want him */ spin_lock_irqsave(&logbuf_lock, flags); + printk_cpu = smp_processor_id(); /* Emit the output into the temporary buffer */ - va_start(args, fmt); printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args); - va_end(args); /* * Copy the output into log_buf. If the caller didn't provide @@ -561,6 +593,7 @@ out: return printed_len; } EXPORT_SYMBOL(printk); +EXPORT_SYMBOL(vprintk); /** * acquire_console_sem - lock the console system for exclusive use. @@ -669,6 +702,47 @@ void console_unblank(void) } EXPORT_SYMBOL(console_unblank); +/* + * Return the console tty driver structure and its associated index + */ +struct tty_driver *console_device(int *index) +{ + struct console *c; + struct tty_driver *driver = NULL; + + acquire_console_sem(); + for (c = console_drivers; c != NULL; c = c->next) { + if (!c->device) + continue; + driver = c->device(c, index); + if (driver) + break; + } + release_console_sem(); + return driver; +} + +/* + * Prevent further output on the passed console device so that (for example) + * serial drivers can disable console output before suspending a port, and can + * re-enable output afterwards. + */ +void console_stop(struct console *console) +{ + acquire_console_sem(); + console->flags &= ~CON_ENABLED; + release_console_sem(); +} +EXPORT_SYMBOL(console_stop); + +void console_start(struct console *console) +{ + acquire_console_sem(); + console->flags |= CON_ENABLED; + release_console_sem(); +} +EXPORT_SYMBOL(console_start); + /* * The console driver calls this routine during kernel initialization * to register the console printing procedure with printk() and to