Make printk() console semaphore accesses sensible
[sfrench/cifs-2.6.git] / kernel / printk.c
index 4a090621f3793fe705352565a41a022441e617b6..c46a20a19a153f06e938d469bf760ee893b63114 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/security.h>
 #include <linux/bootmem.h>
 #include <linux/syscalls.h>
-#include <linux/jiffies.h>
 
 #include <asm/uaccess.h>
 
@@ -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=<value>' 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;
@@ -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.
  *
@@ -1334,3 +1334,4 @@ bool printk_timed_ratelimit(unsigned long *caller_jiffies,
        return false;
 }
 EXPORT_SYMBOL(printk_timed_ratelimit);
+#endif