console: make printk() line continuation tracking per-CPU 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 Signed-off-by: Jan Beulich Tested-by: Boris Ostrovsky --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -620,15 +620,18 @@ static void printk_start_of_line(const c 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 *p 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);