EXPORT_SYMBOL(console_printk);
+/*
+ * Low lever drivers may need that to know if they can schedule in
+ * their unblank() callback or not. So let's export it.
+ */
int oops_in_progress;
+EXPORT_SYMBOL(oops_in_progress);
/*
* console_sem protects the console_drivers list, and also
*/
static DEFINE_SPINLOCK(logbuf_lock);
-static char __log_buf[__LOG_BUF_LEN];
-static char *log_buf = __log_buf;
-static int log_buf_len = __LOG_BUF_LEN;
-
#define LOG_BUF_MASK (log_buf_len-1)
#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
static unsigned long log_start; /* Index into log_buf: next char to be read by syslog() */
static unsigned long con_start; /* Index into log_buf: next char to be sent to consoles */
static unsigned long log_end; /* Index into log_buf: most-recently-written-char + 1 */
-static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */
/*
* Array of consoles built from command line options (console=)
/* Flag: console code may call schedule() */
static int console_may_schedule;
+#ifdef CONFIG_PRINTK
+
+static char __log_buf[__LOG_BUF_LEN];
+static char *log_buf = __log_buf;
+static int log_buf_len = __LOG_BUF_LEN;
+static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */
+
/*
* Setup a list of consoles. Called from init/main.c
*/
__setup("console=", console_setup);
-/**
- * add_preferred_console - add a device to the list of preferred consoles.
- *
- * The last preferred console added will be used for kernel messages
- * and stdin/out/err for init. Normally this is used by console_setup
- * above to handle user-supplied console arguments; however it can also
- * be used by arch-specific code either to override the user or more
- * commonly to provide a default console (ie from PROM variables) when
- * the user has not supplied one.
- */
-int __init add_preferred_console(char *name, int idx, char *options)
-{
- struct console_cmdline *c;
- int i;
-
- /*
- * See if this tty is not yet registered, and
- * if we have a slot free.
- */
- for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
- if (strcmp(console_cmdline[i].name, name) == 0 &&
- console_cmdline[i].index == idx) {
- selected_console = i;
- return 0;
- }
- if (i == MAX_CMDLINECONSOLES)
- return -E2BIG;
- selected_console = i;
- c = &console_cmdline[i];
- memcpy(c->name, name, sizeof(c->name));
- c->name[sizeof(c->name) - 1] = 0;
- c->options = options;
- c->index = idx;
- return 0;
-}
-
static int __init log_buf_len_setup(char *str)
{
unsigned long size = memparse(str, &str);
error = 0;
if (!len)
goto out;
- error = verify_area(VERIFY_WRITE,buf,len);
- if (error)
+ if (!access_ok(VERIFY_WRITE, buf, len)) {
+ error = -EFAULT;
goto out;
+ }
}
if (!vx_check(0, VX_ADMIN|VX_WATCH))
return vx_do_syslog(type, buf, len);
init_MUTEX(&console_sem);
}
+#if defined(CONFIG_PRINTK_TIME)
+static int printk_time = 1;
+#else
+static int printk_time = 0;
+#endif
+
+static int __init printk_time_setup(char *str)
+{
+ if (*str)
+ return 0;
+ printk_time = 1;
+ return 1;
+}
+
+__setup("time", printk_time_setup);
+
/*
* This is printk. It can be called from any context. We want it to work.
*
* then changes console_loglevel may break. This is because console_loglevel
* is inspected when the actual printing occurs.
*/
+
asmlinkage int printk(const char *fmt, ...)
{
va_list args;
*/
for (p = printk_buf; *p; p++) {
if (log_level_unknown) {
- if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {
- emit_log_char('<');
- emit_log_char(default_message_loglevel + '0');
- emit_log_char('>');
+ /* log_level_unknown signals the start of a new line */
+ if (printk_time) {
+ int loglev_char;
+ char tbuf[50], *tp;
+ unsigned tlen;
+ unsigned long long t;
+ unsigned long nanosec_rem;
+
+ /*
+ * force the log level token to be
+ * before the time output.
+ */
+ if (p[0] == '<' && p[1] >='0' &&
+ p[1] <= '7' && p[2] == '>') {
+ loglev_char = p[1];
+ p += 3;
+ printed_len += 3;
+ } else {
+ loglev_char = default_message_loglevel
+ + '0';
+ }
+ t = sched_clock();
+ nanosec_rem = do_div(t, 1000000000);
+ tlen = sprintf(tbuf,
+ "<%c>[%5lu.%06lu] ",
+ loglev_char,
+ (unsigned long)t,
+ nanosec_rem/1000);
+
+ for (tp = tbuf; tp < tbuf + tlen; tp++)
+ emit_log_char(*tp);
+ printed_len += tlen - 3;
+ } else {
+ if (p[0] != '<' || p[1] < '0' ||
+ p[1] > '7' || p[2] != '>') {
+ emit_log_char('<');
+ emit_log_char(default_message_loglevel
+ + '0');
+ emit_log_char('>');
+ }
+ printed_len += 3;
}
log_level_unknown = 0;
+ if (!*p)
+ break;
}
emit_log_char(*p);
if (*p == '\n')
EXPORT_SYMBOL(printk);
EXPORT_SYMBOL(vprintk);
+#else
+
+asmlinkage long sys_syslog(int type, char __user * buf, int len)
+{
+ return 0;
+}
+
+int do_syslog(int type, char __user * buf, int len) { return 0; }
+static void call_console_drivers(unsigned long start, unsigned long end) {}
+
+#endif
+
+/**
+ * add_preferred_console - add a device to the list of preferred consoles.
+ *
+ * The last preferred console added will be used for kernel messages
+ * and stdin/out/err for init. Normally this is used by console_setup
+ * above to handle user-supplied console arguments; however it can also
+ * be used by arch-specific code either to override the user or more
+ * commonly to provide a default console (ie from PROM variables) when
+ * the user has not supplied one.
+ */
+int __init add_preferred_console(char *name, int idx, char *options)
+{
+ struct console_cmdline *c;
+ int i;
+
+ /*
+ * See if this tty is not yet registered, and
+ * if we have a slot free.
+ */
+ for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
+ if (strcmp(console_cmdline[i].name, name) == 0 &&
+ console_cmdline[i].index == idx) {
+ selected_console = i;
+ return 0;
+ }
+ if (i == MAX_CMDLINECONSOLES)
+ return -E2BIG;
+ selected_console = i;
+ c = &console_cmdline[i];
+ memcpy(c->name, name, sizeof(c->name));
+ c->name[sizeof(c->name) - 1] = 0;
+ c->options = options;
+ c->index = idx;
+ return 0;
+}
+
/**
* acquire_console_sem - lock the console system for exclusive use.
*
struct console *c;
/*
- * Try to get the console semaphore. If someone else owns it
- * we have to return without unblanking because console_unblank
- * may be called in interrupt context.
+ * console_unblank can no longer be called in interrupt context unless
+ * oops_in_progress is set to 1..
*/
- if (down_trylock(&console_sem) != 0)
- return;
+ if (oops_in_progress) {
+ if (down_trylock(&console_sem) != 0)
+ return;
+ } else
+ acquire_console_sem();
+
console_locked = 1;
console_may_schedule = 0;
for (c = console_drivers; c != NULL; c = c->next)
if (!(console->flags & CON_ENABLED))
return;
+ if (console_drivers && (console_drivers->flags & CON_BOOT)) {
+ unregister_console(console_drivers);
+ console->flags &= ~CON_PRINTBUFFER;
+ }
+
/*
* Put this console in the list - keep the
* preferred driver at the head of the list.
return res;
}
EXPORT_SYMBOL(unregister_console);
-
+
/**
* tty_write_message - write a message to a certain tty, not just the console.
*