Commit 5c5d5ca5 authored by Kay Sievers's avatar Kay Sievers Committed by Greg Kroah-Hartman

printk() - do not merge continuation lines of different threads

This prevents the merging of printk() continuation lines of different
threads, in the case they race against each other.

It should properly isolate "atomic" single-line printk() users from
continuation users, to make sure the single-line users will never be
merged with the racy continuation ones.

Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: default avatarKay Sievers <kay@vrfy.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7f3a781d
...@@ -1230,12 +1230,13 @@ asmlinkage int vprintk_emit(int facility, int level, ...@@ -1230,12 +1230,13 @@ asmlinkage int vprintk_emit(int facility, int level,
static size_t buflen; static size_t buflen;
static int buflevel; static int buflevel;
static char textbuf[LOG_LINE_MAX]; static char textbuf[LOG_LINE_MAX];
static struct task_struct *cont;
char *text = textbuf; char *text = textbuf;
size_t textlen; size_t textlen;
unsigned long flags; unsigned long flags;
int this_cpu; int this_cpu;
bool newline = false; bool newline = false;
bool cont = false; bool prefix = false;
int printed_len = 0; int printed_len = 0;
boot_delay_msec(); boot_delay_msec();
...@@ -1295,20 +1296,16 @@ asmlinkage int vprintk_emit(int facility, int level, ...@@ -1295,20 +1296,16 @@ asmlinkage int vprintk_emit(int facility, int level,
case '0' ... '7': case '0' ... '7':
if (level == -1) if (level == -1)
level = text[1] - '0'; level = text[1] - '0';
text += 3;
textlen -= 3;
break;
case 'c': /* KERN_CONT */
cont = true;
case 'd': /* KERN_DEFAULT */ case 'd': /* KERN_DEFAULT */
prefix = true;
case 'c': /* KERN_CONT */
text += 3; text += 3;
textlen -= 3; textlen -= 3;
break;
} }
} }
if (buflen && (!cont || dict)) { if (buflen && (prefix || dict || cont != current)) {
/* no continuation; flush existing buffer */ /* flush existing buffer */
log_store(facility, buflevel, NULL, 0, buf, buflen); log_store(facility, buflevel, NULL, 0, buf, buflen);
printed_len += buflen; printed_len += buflen;
buflen = 0; buflen = 0;
...@@ -1342,6 +1339,10 @@ asmlinkage int vprintk_emit(int facility, int level, ...@@ -1342,6 +1339,10 @@ asmlinkage int vprintk_emit(int facility, int level,
dict, dictlen, text, textlen); dict, dictlen, text, textlen);
printed_len += textlen; printed_len += textlen;
} }
cont = NULL;
} else {
/* remember thread which filled the buffer */
cont = current;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment