Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.6.24-git7 /kernel/printk.c

Filename:/kernel/printk.c
Lines Added:39
Lines Deleted:16
Also changed in: (Previous) 2.6.24-git6  2.6.24-git5  2.6.24-git4  2.6.24-git3  2.6.24-git2  2.6.24 
(Following) 2.6.24-git8  2.6.24-git9  2.6.24-git10  2.6.24-git11  2.6.24-git12  2.6.24-git13 

Location
[  2.6.24-git7
  [  kernel
     o  printk.c

Patch

diff --git a/kernel/printk.c b/kernel/printk.c
index 89011bf..3b7c968 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -573,11 +573,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 +623,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 +702,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 +766,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);
    }
 


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.