X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=kernel%2Fprintk.c;h=c46a20a19a153f06e938d469bf760ee893b63114;hb=bcc5c7d2b692e5319db00b0dd020ce98723103b1;hp=29ae1e99cde08b247aa106a2939496abf3b3c871;hpb=c1f3ee120bb61045b1c0a3ead620d1d65af47130;p=linux-2.6 diff --git a/kernel/printk.c b/kernel/printk.c index 29ae1e99cd..c46a20a19a 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -32,7 +32,6 @@ #include #include #include -#include #include @@ -93,16 +92,16 @@ static int console_locked, console_suspended; */ static DEFINE_SPINLOCK(logbuf_lock); -#define LOG_BUF_MASK (log_buf_len-1) +#define LOG_BUF_MASK (log_buf_len-1) #define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK]) /* * The indices into log_buf are not constrained to log_buf_len - they * must be masked before subscripting */ -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 log_start; /* Index into log_buf: next char to be read by syslog() */ +static unsigned con_start; /* Index into log_buf: next char to be sent to consoles */ +static unsigned log_end; /* Index into log_buf: most-recently-written-char + 1 */ /* * Array of consoles built from command line options (console=) @@ -128,17 +127,17 @@ static int console_may_schedule; 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 */ +static unsigned logged_chars; /* Number of chars produced since last read+clear operation */ static int __init log_buf_len_setup(char *str) { - unsigned long size = memparse(str, &str); + unsigned 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; + unsigned start, dest_idx, offset; char *new_log_buf; new_log_buf = alloc_bootmem(size); @@ -295,7 +294,7 @@ int log_buf_read(int idx) */ int do_syslog(int type, char __user *buf, int len) { - unsigned long i, j, limit, count; + unsigned i, j, limit, count; int do_clear = 0; char c; int error = 0; @@ -436,7 +435,7 @@ asmlinkage long sys_syslog(int type, char __user *buf, int len) /* * Call the console drivers on a range of log_buf */ -static void __call_console_drivers(unsigned long start, unsigned long end) +static void __call_console_drivers(unsigned start, unsigned end) { struct console *con; @@ -463,8 +462,8 @@ early_param("ignore_loglevel", ignore_loglevel_setup); /* * Write out chars from start to end - 1 inclusive */ -static void _call_console_drivers(unsigned long start, - unsigned long end, int msg_log_level) +static void _call_console_drivers(unsigned start, + unsigned end, int msg_log_level) { if ((msg_log_level < console_loglevel || ignore_loglevel) && console_drivers && start != end) { @@ -484,12 +483,12 @@ static void _call_console_drivers(unsigned long start, * log_buf[start] to log_buf[end - 1]. * The console_sem must be held. */ -static void call_console_drivers(unsigned long start, unsigned long end) +static void call_console_drivers(unsigned start, unsigned end) { - unsigned long cur_index, start_print; + unsigned cur_index, start_print; static int msg_level = -1; - BUG_ON(((long)(start - end)) > 0); + BUG_ON(((int)(start - end)) > 0); cur_index = start; start_print = start; @@ -567,19 +566,6 @@ static int printk_time = 0; #endif module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR); -static int __init printk_time_setup(char *str) -{ - if (*str) - return 0; - printk_time = 1; - printk(KERN_NOTICE "The 'time' option is deprecated and " - "is scheduled for removal in early 2008\n"); - printk(KERN_NOTICE "Use 'printk.time=' instead\n"); - return 1; -} - -__setup("time", printk_time_setup); - /* Check if we have any console registered that can be called early in boot. */ static int have_callable_console(void) { @@ -630,6 +616,40 @@ asmlinkage int printk(const char *fmt, ...) /* cpu currently holding logbuf_lock */ static volatile unsigned int printk_cpu = UINT_MAX; +/* + * Can we actually use the console at this time on this cpu? + * + * Console drivers may assume that per-cpu resources have + * been allocated. So unless they're explicitly marked as + * being able to cope (CON_ANYTIME) don't call them until + * this CPU is officially up. + */ +static inline int can_use_console(unsigned int cpu) +{ + return cpu_online(cpu) || have_callable_console(); +} + +/* + * Try to get console ownership to actually show the kernel + * messages from a 'printk'. Return true (and with the + * console_semaphore held, and 'console_locked' set) if it + * is successful, false otherwise. + * + * This gets called with the 'logbuf_lock' spinlock held and + * interrupts disabled. It should return with 'lockbuf_lock' + * released but interrupts still disabled. + */ +static int acquire_console_semaphore_for_printk(unsigned int cpu) +{ + int retval = 0; + + if (can_use_console(cpu)) + retval = !try_acquire_console_sem(); + printk_cpu = UINT_MAX; + spin_unlock(&logbuf_lock); + return retval; +} + const char printk_recursion_bug_msg [] = KERN_CRIT "BUG: recent printk recursion!\n"; static int printk_recursion_bug; @@ -680,7 +700,7 @@ asmlinkage int vprintk(const char *fmt, va_list args) } /* Emit the output into the temporary buffer */ printed_len += vscnprintf(printk_buf + printed_len, - sizeof(printk_buf), fmt, args); + sizeof(printk_buf) - printed_len, fmt, args); /* * Copy the output into log_buf. If the caller didn't provide @@ -739,43 +759,22 @@ asmlinkage int vprintk(const char *fmt, va_list args) log_level_unknown = 1; } - if (!down_trylock(&console_sem)) { - /* - * We own the drivers. We can drop the spinlock and - * let release_console_sem() print the text, maybe ... - */ - console_locked = 1; - printk_cpu = UINT_MAX; - spin_unlock(&logbuf_lock); + /* + * Try to acquire and then immediately release the + * console semaphore. The release will do all the + * actual magic (print out buffers, wake up klogd, + * etc). + * + * The acquire_console_semaphore_for_printk() function + * will release 'logbuf_lock' regardless of whether it + * actually gets the semaphore or not. + */ + if (acquire_console_semaphore_for_printk(this_cpu)) + release_console_sem(); - /* - * Console drivers may assume that per-cpu resources have - * been allocated. So unless they're explicitly marked as - * being able to cope (CON_ANYTIME) don't call them until - * this CPU is officially up. - */ - if (cpu_online(smp_processor_id()) || have_callable_console()) { - console_may_schedule = 0; - release_console_sem(); - } else { - /* Release by hand to avoid flushing the buffer. */ - console_locked = 0; - up(&console_sem); - } - lockdep_on(); - raw_local_irq_restore(flags); - } else { - /* - * Someone else owns the drivers. We drop the spinlock, which - * 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(&logbuf_lock); - lockdep_on(); + lockdep_on(); out_restore_irqs: - raw_local_irq_restore(flags); - } + raw_local_irq_restore(flags); preempt_enable(); return printed_len; @@ -790,7 +789,7 @@ asmlinkage long sys_syslog(int type, char __user *buf, int len) return -ENOSYS; } -static void call_console_drivers(unsigned long start, unsigned long end) +static void call_console_drivers(unsigned start, unsigned end) { } @@ -983,8 +982,8 @@ void wake_up_klogd(void) void release_console_sem(void) { unsigned long flags; - unsigned long _con_start, _log_end; - unsigned long wake_klogd = 0; + unsigned _con_start, _log_end; + unsigned wake_klogd = 0; if (console_suspended) { up(&secondary_console_sem); @@ -1265,6 +1264,7 @@ void tty_write_message(struct tty_struct *tty, char *msg) return; } +#if defined CONFIG_PRINTK /* * printk rate limiting, lifted from the networking subsystem. * @@ -1275,7 +1275,7 @@ void tty_write_message(struct tty_struct *tty, char *msg) int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst) { static DEFINE_SPINLOCK(ratelimit_lock); - static unsigned long toks = 10 * 5 * HZ; + static unsigned toks = 10 * 5 * HZ; static unsigned long last_msg; static int missed; unsigned long flags; @@ -1334,3 +1334,4 @@ bool printk_timed_ratelimit(unsigned long *caller_jiffies, return false; } EXPORT_SYMBOL(printk_timed_ratelimit); +#endif