* elsewhere, in preparation for a serial line console (someday).
* Ted Ts'o, 2/11/93.
* Modified for sysctl support, 1/8/97, Chris Horn.
- * Fixed SMP synchronization, 08/08/99, Manfred Spraul
- * manfreds@colorfullife.com
+ * Fixed SMP synchronization, 08/08/99, Manfred Spraul
+ * manfred@colorfullife.com
* Rewrote bits to get rid of console_lock
* 01Mar01 Andrew Morton <andrewm@uow.edu.au>
*/
if (!strcmp(str, "ttyb"))
strcpy(name, "ttyS1");
#endif
- for(s = name; *s; s++)
+ for (s = name; *s; s++)
if ((*s >= '0' && *s <= '9') || *s == ',')
break;
idx = simple_strtoul(s, NULL, 10);
size = roundup_pow_of_two(size);
if (size > log_buf_len) {
unsigned long start, dest_idx, offset;
- char * new_log_buf;
+ char *new_log_buf;
new_log_buf = alloc_bootmem(size);
if (!new_log_buf) {
- printk("log_buf_len: allocation failed\n");
+ printk(KERN_WARNING "log_buf_len: allocation failed\n");
goto out;
}
log_end -= offset;
spin_unlock_irqrestore(&logbuf_lock, flags);
- printk("log_buf_len: %d\n", log_buf_len);
+ printk(KERN_NOTICE "log_buf_len: %d\n", log_buf_len);
}
out:
-
return 1;
}
* 9 -- Return number of unread characters in the log buffer
* 10 -- Return size of the log buffer
*/
-int do_syslog(int type, char __user * buf, int len)
+int do_syslog(int type, char __user *buf, int len)
{
unsigned long i, j, limit, count;
int do_clear = 0;
error = -EFAULT;
goto out;
}
- error = wait_event_interruptible(log_wait, (log_start - log_end));
+ error = wait_event_interruptible(log_wait,
+ (log_start - log_end));
if (error)
goto out;
i = 0;
error = i;
break;
case 4: /* Read/clear last kernel messages */
- do_clear = 1;
+ do_clear = 1;
/* FALL THRU */
case 3: /* Read last kernel messages */
error = -EINVAL;
limit = log_end;
/*
* __put_user() could sleep, and while we sleep
- * printk() could overwrite the messages
+ * printk() could overwrite the messages
* we try to copy to user space. Therefore
* the messages are copied in reverse. <manfreds>
*/
- for(i = 0; i < count && !error; i++) {
+ for (i = 0; i < count && !error; i++) {
j = limit-1-i;
if (j + log_buf_len < log_end)
break;
if (error)
break;
error = i;
- if(i != count) {
+ if (i != count) {
int offset = count-error;
/* buffer overflow during copy, correct user buffer. */
- for(i=0;i<error;i++) {
+ for (i = 0; i < error; i++) {
if (__get_user(c,&buf[i+offset]) ||
__put_user(c,&buf[i])) {
error = -EFAULT;
return error;
}
-asmlinkage long sys_syslog(int type, char __user * buf, int len)
+asmlinkage long sys_syslog(int type, char __user *buf, int len)
{
return do_syslog(type, buf, len);
}
cur_index = start;
start_print = start;
while (cur_index != end) {
- if ( msg_level < 0 &&
- ((end - cur_index) > 2) &&
- LOG_BUF(cur_index + 0) == '<' &&
- LOG_BUF(cur_index + 1) >= '0' &&
- LOG_BUF(cur_index + 1) <= '7' &&
- LOG_BUF(cur_index + 2) == '>')
- {
+ if (msg_level < 0 && ((end - cur_index) > 2) &&
+ LOG_BUF(cur_index + 0) == '<' &&
+ LOG_BUF(cur_index + 1) >= '0' &&
+ LOG_BUF(cur_index + 1) <= '7' &&
+ LOG_BUF(cur_index + 2) == '>') {
msg_level = LOG_BUF(cur_index + 1) - '0';
cur_index += 3;
start_print = cur_index;
}
while (cur_index != end) {
char c = LOG_BUF(cur_index);
- cur_index++;
+ cur_index++;
if (c == '\n') {
if (msg_level < 0) {
/*
static unsigned long oops_timestamp;
if (time_after_eq(jiffies, oops_timestamp) &&
- !time_after(jiffies, oops_timestamp + 30*HZ))
+ !time_after(jiffies, oops_timestamp + 30 * HZ))
return;
oops_timestamp = jiffies;
__setup("time", printk_time_setup);
-/*
+__attribute__((weak)) unsigned long long printk_clock(void)
+{
+ return sched_clock();
+}
+
+/**
+ * printk - print a kernel message
+ * @fmt: format string
+ *
* This is printk. It can be called from any context. We want it to work.
- *
+ *
* We try to grab the console_sem. If we succeed, it's easy - we log the output and
* call the console drivers. If we fail to get the semaphore we place the output
* into the log buffer and return. The current holder of the console_sem will
* One effect of this deferred printing is that code which calls printk() and
* then changes console_loglevel may break. This is because console_loglevel
* is inspected when the actual printing occurs.
+ *
+ * See also:
+ * printf(3)
*/
asmlinkage int printk(const char *fmt, ...)
return r;
}
+/* cpu currently holding logbuf_lock */
+static volatile unsigned int printk_cpu = UINT_MAX;
+
asmlinkage int vprintk(const char *fmt, va_list args)
{
unsigned long flags;
static char printk_buf[1024];
static int log_level_unknown = 1;
- if (unlikely(oops_in_progress))
+ preempt_disable();
+ if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id())
+ /* If a crash is occurring during printk() on this CPU,
+ * make sure we can't deadlock */
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 */
printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
p[1] <= '7' && p[2] == '>') {
loglev_char = p[1];
p += 3;
- printed_len += 3;
+ printed_len -= 3;
} else {
loglev_char = default_message_loglevel
+ '0';
}
- t = sched_clock();
+ t = printk_clock();
nanosec_rem = do_div(t, 1000000000);
tlen = sprintf(tbuf,
"<%c>[%5lu.%06lu] ",
for (tp = tbuf; tp < tbuf + tlen; tp++)
emit_log_char(*tp);
- printed_len += tlen - 3;
+ printed_len += tlen;
} else {
if (p[0] != '<' || p[1] < '0' ||
p[1] > '7' || p[2] != '>') {
emit_log_char(default_message_loglevel
+ '0');
emit_log_char('>');
+ printed_len += 3;
}
- printed_len += 3;
}
log_level_unknown = 0;
if (!*p)
log_level_unknown = 1;
}
- if (!cpu_online(smp_processor_id()) &&
- system_state != SYSTEM_RUNNING) {
+ if (!cpu_online(smp_processor_id())) {
/*
* Some console drivers may assume that per-cpu resources have
* been allocated. So don't allow them to be called by this
* CPU until it is officially up. We shouldn't be calling into
* random console drivers on a CPU which doesn't exist yet..
*/
+ printk_cpu = UINT_MAX;
spin_unlock_irqrestore(&logbuf_lock, flags);
goto out;
}
* We own the drivers. We can drop the spinlock and let
* release_console_sem() print the text
*/
+ printk_cpu = UINT_MAX;
spin_unlock_irqrestore(&logbuf_lock, flags);
console_may_schedule = 0;
release_console_sem();
* allows the semaphore holder to proceed and to call the
* console drivers with the output which we just produced.
*/
+ printk_cpu = UINT_MAX;
spin_unlock_irqrestore(&logbuf_lock, flags);
}
out:
+ preempt_enable();
return printed_len;
}
EXPORT_SYMBOL(printk);
#else
-asmlinkage long sys_syslog(int type, char __user * buf, int len)
+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) {}
+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.
+ * @name: device name
+ * @idx: device index
+ * @options: options for this console
*
* The last preferred console added will be used for kernel messages
* and stdin/out/err for init. Normally this is used by console_setup
}
EXPORT_SYMBOL(release_console_sem);
-/** console_conditional_schedule - yield the CPU if required
+/**
+ * console_conditional_schedule - yield the CPU if required
*
* If the console code is currently allowed to sleep, and
* if this CPU should yield the CPU to another task, do
c->unblank();
release_console_sem();
}
-EXPORT_SYMBOL(console_unblank);
/*
* Return the console tty driver structure and its associated index
* print any messages that were printed by the kernel before the
* console driver was initialized.
*/
-void register_console(struct console * console)
+void register_console(struct console *console)
{
- int i;
+ int i;
unsigned long flags;
if (preferred_console < 0)
* See if this console matches one we selected on
* the command line.
*/
- for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) {
+ for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0];
+ i++) {
if (strcmp(console_cmdline[i].name, console->name) != 0)
continue;
if (console->index >= 0 &&
break;
console->flags |= CON_ENABLED;
console->index = console_cmdline[i].index;
- if (i == preferred_console)
+ if (i == selected_console) {
console->flags |= CON_CONSDEV;
+ preferred_console = selected_console;
+ }
break;
}
if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
console->next = console_drivers;
console_drivers = console;
+ if (console->next)
+ console->next->flags &= ~CON_CONSDEV;
} else {
console->next = console_drivers->next;
console_drivers->next = console;
}
EXPORT_SYMBOL(register_console);
-int unregister_console(struct console * console)
+int unregister_console(struct console *console)
{
- struct console *a,*b;
+ struct console *a, *b;
int res = 1;
acquire_console_sem();
if (console_drivers == console) {
console_drivers=console->next;
res = 0;
- } else {
+ } else if (console_drivers) {
for (a=console_drivers->next, b=console_drivers ;
a; b=a, a=b->next) {
if (a == console) {
b->next = a->next;
res = 0;
break;
- }
+ }
}
}
-
+
/* If last console is removed, we re-enable picking the first
* one that gets registered. Without that, pmac early boot console
* would prevent fbcon from taking over.
+ *
+ * If this isn't the last console and it has CON_CONSDEV set, we
+ * need to set it on the next preferred console.
*/
if (console_drivers == NULL)
preferred_console = selected_console;
-
+ else if (console->flags & CON_CONSDEV)
+ console_drivers->flags |= CON_CONSDEV;
release_console_sem();
return res;
/**
* tty_write_message - write a message to a certain tty, not just the console.
+ * @tty: the destination tty_struct
+ * @msg: the message to write
*
* This is used for messages that need to be redirected to a specific tty.
* We don't put it into the syslog queue right now maybe in the future if
int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst)
{
static DEFINE_SPINLOCK(ratelimit_lock);
- static unsigned long toks = 10*5*HZ;
+ static unsigned long toks = 10 * 5 * HZ;
static unsigned long last_msg;
static int missed;
unsigned long flags;
toks = ratelimit_burst * ratelimit_jiffies;
if (toks >= ratelimit_jiffies) {
int lost = missed;
+
missed = 0;
toks -= ratelimit_jiffies;
spin_unlock_irqrestore(&ratelimit_lock, flags);
EXPORT_SYMBOL(__printk_ratelimit);
/* minimum time in jiffies between messages */
-int printk_ratelimit_jiffies = 5*HZ;
+int printk_ratelimit_jiffies = 5 * HZ;
/* number of messages we send before ratelimiting */
int printk_ratelimit_burst = 10;