aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/printk.c
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2012-05-09 22:32:53 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-09 23:29:59 -0400
commit5c5d5ca51abd728c8de3be43ffd6bb00f977bfcd (patch)
tree737f0efbb6971c7055d7b07dacc79a2922bd19c7 /kernel/printk.c
parent7f3a781d6fd81e397c3928c9af33f1fc63232db6 (diff)
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: Kay Sievers <kay@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel/printk.c')
-rw-r--r--kernel/printk.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index 7b432951f91e..301fb0f09fbf 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1230,12 +1230,13 @@ asmlinkage int vprintk_emit(int facility, int level,
1230 static size_t buflen; 1230 static size_t buflen;
1231 static int buflevel; 1231 static int buflevel;
1232 static char textbuf[LOG_LINE_MAX]; 1232 static char textbuf[LOG_LINE_MAX];
1233 static struct task_struct *cont;
1233 char *text = textbuf; 1234 char *text = textbuf;
1234 size_t textlen; 1235 size_t textlen;
1235 unsigned long flags; 1236 unsigned long flags;
1236 int this_cpu; 1237 int this_cpu;
1237 bool newline = false; 1238 bool newline = false;
1238 bool cont = false; 1239 bool prefix = false;
1239 int printed_len = 0; 1240 int printed_len = 0;
1240 1241
1241 boot_delay_msec(); 1242 boot_delay_msec();
@@ -1295,20 +1296,16 @@ asmlinkage int vprintk_emit(int facility, int level,
1295 case '0' ... '7': 1296 case '0' ... '7':
1296 if (level == -1) 1297 if (level == -1)
1297 level = text[1] - '0'; 1298 level = text[1] - '0';
1298 text += 3;
1299 textlen -= 3;
1300 break;
1301 case 'c': /* KERN_CONT */
1302 cont = true;
1303 case 'd': /* KERN_DEFAULT */ 1299 case 'd': /* KERN_DEFAULT */
1300 prefix = true;
1301 case 'c': /* KERN_CONT */
1304 text += 3; 1302 text += 3;
1305 textlen -= 3; 1303 textlen -= 3;
1306 break;
1307 } 1304 }
1308 } 1305 }
1309 1306
1310 if (buflen && (!cont || dict)) { 1307 if (buflen && (prefix || dict || cont != current)) {
1311 /* no continuation; flush existing buffer */ 1308 /* flush existing buffer */
1312 log_store(facility, buflevel, NULL, 0, buf, buflen); 1309 log_store(facility, buflevel, NULL, 0, buf, buflen);
1313 printed_len += buflen; 1310 printed_len += buflen;
1314 buflen = 0; 1311 buflen = 0;
@@ -1342,6 +1339,10 @@ asmlinkage int vprintk_emit(int facility, int level,
1342 dict, dictlen, text, textlen); 1339 dict, dictlen, text, textlen);
1343 printed_len += textlen; 1340 printed_len += textlen;
1344 } 1341 }
1342 cont = NULL;
1343 } else {
1344 /* remember thread which filled the buffer */
1345 cont = current;
1345 } 1346 }
1346 1347
1347 /* 1348 /*