X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=kernel%2Fprintk.c;h=9b1f825bc570877355bd7a577cf2182cd30794e1;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=3b74688184a8d4c7d423a730baeef2804e892937;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/kernel/printk.c b/kernel/printk.c index 3b7468818..9b1f825bc 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -247,7 +248,10 @@ int do_syslog(int type, char __user * buf, int len) unsigned long i, j, limit, count; int do_clear = 0; char c; - int error = 0; + int error = -EPERM; + + if (!vx_check(0, VX_ADMIN|VX_WATCH)) + return error; error = security_syslog(type); if (error) @@ -471,6 +475,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. * @@ -493,12 +518,8 @@ asmlinkage int printk(const char *fmt, ...) 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)) + zap_locks(); /* This stops the holder of console_sem just where we want him */ spin_lock_irqsave(&logbuf_lock, flags); @@ -666,6 +687,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