Skip to content

Commit

Permalink
printk() - do not merge continuation lines of different threads
Browse files Browse the repository at this point in the history
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: Kay Sievers <kay@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Kay Sievers authored and Greg Kroah-Hartman committed May 10, 2012
1 parent 7f3a781 commit 5c5d5ca
Showing 1 changed file with 10 additions and 9 deletions.
19 changes: 10 additions & 9 deletions kernel/printk.c
Original file line number Diff line number Diff line change
Expand Up @@ -1230,12 +1230,13 @@ asmlinkage int vprintk_emit(int facility, int level,
static size_t buflen;
static int buflevel;
static char textbuf[LOG_LINE_MAX];
static struct task_struct *cont;
char *text = textbuf;
size_t textlen;
unsigned long flags;
int this_cpu;
bool newline = false;
bool cont = false;
bool prefix = false;
int printed_len = 0;

boot_delay_msec();
Expand Down Expand Up @@ -1295,20 +1296,16 @@ asmlinkage int vprintk_emit(int facility, int level,
case '0' ... '7':
if (level == -1)
level = text[1] - '0';
text += 3;
textlen -= 3;
break;
case 'c': /* KERN_CONT */
cont = true;
case 'd': /* KERN_DEFAULT */
prefix = true;
case 'c': /* KERN_CONT */
text += 3;
textlen -= 3;
break;
}
}

if (buflen && (!cont || dict)) {
/* no continuation; flush existing buffer */
if (buflen && (prefix || dict || cont != current)) {
/* flush existing buffer */
log_store(facility, buflevel, NULL, 0, buf, buflen);
printed_len += buflen;
buflen = 0;
Expand Down Expand Up @@ -1342,6 +1339,10 @@ asmlinkage int vprintk_emit(int facility, int level,
dict, dictlen, text, textlen);
printed_len += textlen;
}
cont = NULL;
} else {
/* remember thread which filled the buffer */
cont = current;
}

/*
Expand Down

0 comments on commit 5c5d5ca

Please sign in to comment.