console: make printk() line continuation tracking per-CPU
authorJan Beulich <jbeulich@suse.com>
Wed, 25 Nov 2015 16:18:21 +0000 (17:18 +0100)
committerJan Beulich <jbeulich@suse.com>
Wed, 25 Nov 2015 16:18:21 +0000 (17:18 +0100)
This avoids cases where split messages (with other than the initial
part not carrying a log level; single line messages only of course)
issued on multiple CPUs interfere with each other, causing messages to
be issued which are supposed to be suppressed due to the log level
setting. E.g.

CPU A CPU B
XENLOG_G_DEBUG "abc"
XENLOG_G_DEBUG "def\n"
"xyz\n"

would cause the last message to be logged despite this obviously not
being intended (at default log levels).

Suggested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Tested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
xen/drivers/char/console.c

index 4362400130a7afb6ada0dad5cf724e701c328012..e0083f1cd47d2f878e8067ebd3ea1a877717fb5c 100644 (file)
@@ -620,15 +620,18 @@ static void printk_start_of_line(const char *prefix)
 
 static void vprintk_common(const char *prefix, const char *fmt, va_list args)
 {
+    struct vps {
+        bool_t continued, do_print;
+    }            *state;
+    static DEFINE_PER_CPU(struct vps, state);
     static char   buf[1024];
-    static int    start_of_line = 1, do_print;
-
     char         *p, *q;
     unsigned long flags;
 
     /* console_lock can be acquired recursively from __printk_ratelimit(). */
     local_irq_save(flags);
     spin_lock_recursive(&console_lock);
+    state = &this_cpu(state);
 
     (void)vsnprintf(buf, sizeof(buf), fmt, args);
 
@@ -637,30 +640,30 @@ static void vprintk_common(const char *prefix, const char *fmt, va_list args)
     while ( (q = strchr(p, '\n')) != NULL )
     {
         *q = '\0';
-        if ( start_of_line )
-            do_print = printk_prefix_check(p, &p);
-        if ( do_print )
+        if ( !state->continued )
+            state->do_print = printk_prefix_check(p, &p);
+        if ( state->do_print )
         {
-            if ( start_of_line )
+            if ( !state->continued )
                 printk_start_of_line(prefix);
             __putstr(p);
             __putstr("\n");
         }
-        start_of_line = 1;
+        state->continued = 0;
         p = q + 1;
     }
 
     if ( *p != '\0' )
     {
-        if ( start_of_line )
-            do_print = printk_prefix_check(p, &p);
-        if ( do_print )
+        if ( !state->continued )
+            state->do_print = printk_prefix_check(p, &p);
+        if ( state->do_print )
         {
-            if ( start_of_line )
+            if ( !state->continued )
                 printk_start_of_line(prefix);
             __putstr(p);
         }
-        start_of_line = 0;
+        state->continued = 1;
     }
 
     spin_unlock_recursive(&console_lock);