debug: turn ignore_loglevel into an early param
[sfrench/cifs-2.6.git] / kernel / printk.c
index a30fe33de395a7964f68e237c73de7344190b18a..29ae1e99cde08b247aa106a2939496abf3b3c871 100644 (file)
 
 #include <asm/uaccess.h>
 
+/*
+ * Architectures can override it:
+ */
+void __attribute__((weak)) early_printk(const char *fmt, ...)
+{
+}
+
 #define __LOG_BUF_LEN  (1 << CONFIG_LOG_BUF_SHIFT)
 
 /* printk's without a loglevel use this.. */
@@ -448,10 +455,10 @@ static int __init ignore_loglevel_setup(char *str)
        ignore_loglevel = 1;
        printk(KERN_INFO "debug: ignoring loglevel setting.\n");
 
-       return 1;
+       return 0;
 }
 
-__setup("ignore_loglevel", ignore_loglevel_setup);
+early_param("ignore_loglevel", ignore_loglevel_setup);
 
 /*
  * Write out chars from start to end - 1 inclusive
@@ -573,11 +580,6 @@ static int __init printk_time_setup(char *str)
 
 __setup("time", printk_time_setup);
 
-__attribute__((weak)) unsigned long long printk_clock(void)
-{
-       return sched_clock();
-}
-
 /* Check if we have any console registered that can be called early in boot. */
 static int have_callable_console(void)
 {
@@ -628,30 +630,57 @@ asmlinkage int printk(const char *fmt, ...)
 /* cpu currently holding logbuf_lock */
 static volatile unsigned int printk_cpu = UINT_MAX;
 
+const char printk_recursion_bug_msg [] =
+                       KERN_CRIT "BUG: recent printk recursion!\n";
+static int printk_recursion_bug;
+
 asmlinkage int vprintk(const char *fmt, va_list args)
 {
+       static int log_level_unknown = 1;
+       static char printk_buf[1024];
+
        unsigned long flags;
-       int printed_len;
+       int printed_len = 0;
+       int this_cpu;
        char *p;
-       static char printk_buf[1024];
-       static int log_level_unknown = 1;
 
        boot_delay_msec();
 
        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 */
        raw_local_irq_save(flags);
+       this_cpu = smp_processor_id();
+
+       /*
+        * Ouch, printk recursed into itself!
+        */
+       if (unlikely(printk_cpu == this_cpu)) {
+               /*
+                * If a crash is occurring during printk() on this CPU,
+                * then try to get the crash message out but make sure
+                * we can't deadlock. Otherwise just return to avoid the
+                * recursion and return - but flag the recursion so that
+                * it can be printed at the next appropriate moment:
+                */
+               if (!oops_in_progress) {
+                       printk_recursion_bug = 1;
+                       goto out_restore_irqs;
+               }
+               zap_locks();
+       }
+
        lockdep_off();
        spin_lock(&logbuf_lock);
-       printk_cpu = smp_processor_id();
+       printk_cpu = this_cpu;
 
+       if (printk_recursion_bug) {
+               printk_recursion_bug = 0;
+               strcpy(printk_buf, printk_recursion_bug_msg);
+               printed_len = sizeof(printk_recursion_bug_msg);
+       }
        /* Emit the output into the temporary buffer */
-       printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
+       printed_len += vscnprintf(printk_buf + printed_len,
+                                 sizeof(printk_buf), fmt, args);
 
        /*
         * Copy the output into log_buf.  If the caller didn't provide
@@ -680,7 +709,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
                                        loglev_char = default_message_loglevel
                                                + '0';
                                }
-                               t = printk_clock();
+                               t = cpu_clock(printk_cpu);
                                nanosec_rem = do_div(t, 1000000000);
                                tlen = sprintf(tbuf,
                                                "<%c>[%5lu.%06lu] ",
@@ -744,6 +773,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
                printk_cpu = UINT_MAX;
                spin_unlock(&logbuf_lock);
                lockdep_on();
+out_restore_irqs:
                raw_local_irq_restore(flags);
        }
 
@@ -817,7 +847,7 @@ __setup("console=", console_setup);
  * 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)
+int add_preferred_console(char *name, int idx, char *options)
 {
        struct console_cmdline *c;
        int i;