#include <linux/smp.h>
#include <linux/security.h>
#include <linux/bootmem.h>
+#include <linux/vs_base.h>
#include <asm/uaccess.h>
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;
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)
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.
*
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
return printed_len;
}
EXPORT_SYMBOL(printk);
+EXPORT_SYMBOL(vprintk);
/**
* acquire_console_sem - lock the console system for exclusive use.
}
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