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.
Unified · Split
| @@ -1230,12 +1230,13 @@ asmlinkage int vprintk_emit(int facility, int level, · 1229 unmodified lines | |||
| 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, · 53 unmodified lines | |||
| 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, · 27 unmodified lines | |||
| 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 | /* |