aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/printk.c93
1 files changed, 68 insertions, 25 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index a41106e19077..4da2377131b0 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -231,6 +231,11 @@ static u32 log_first_idx;
231static u64 log_next_seq; 231static u64 log_next_seq;
232static u32 log_next_idx; 232static u32 log_next_idx;
233 233
234/* the next printk record to write to the console */
235static u64 console_seq;
236static u32 console_idx;
237static enum log_flags console_prev;
238
234/* the next printk record to read after the last 'clear' command */ 239/* the next printk record to read after the last 'clear' command */
235static u64 clear_seq; 240static u64 clear_seq;
236static u32 clear_idx; 241static u32 clear_idx;
@@ -1386,6 +1391,7 @@ static struct cont {
1386 u64 ts_nsec; /* time of first print */ 1391 u64 ts_nsec; /* time of first print */
1387 u8 level; /* log level of first message */ 1392 u8 level; /* log level of first message */
1388 u8 facility; /* log level of first message */ 1393 u8 facility; /* log level of first message */
1394 enum log_flags flags; /* prefix, newline flags */
1389 bool flushed:1; /* buffer sealed and committed */ 1395 bool flushed:1; /* buffer sealed and committed */
1390} cont; 1396} cont;
1391 1397
@@ -1396,10 +1402,25 @@ static void cont_flush(enum log_flags flags)
1396 if (cont.len == 0) 1402 if (cont.len == 0)
1397 return; 1403 return;
1398 1404
1399 log_store(cont.facility, cont.level, LOG_NOCONS | flags, 1405 if (cont.cons) {
1400 cont.ts_nsec, NULL, 0, cont.buf, cont.len); 1406 /*
1401 1407 * If a fragment of this line was directly flushed to the
1402 cont.flushed = true; 1408 * console; wait for the console to pick up the rest of the
1409 * line. LOG_NOCONS suppresses a duplicated output.
1410 */
1411 log_store(cont.facility, cont.level, flags | LOG_NOCONS,
1412 cont.ts_nsec, NULL, 0, cont.buf, cont.len);
1413 cont.flags = flags;
1414 cont.flushed = true;
1415 } else {
1416 /*
1417 * If no fragment of this line ever reached the console,
1418 * just submit it to the store and free the buffer.
1419 */
1420 log_store(cont.facility, cont.level, flags, 0,
1421 NULL, 0, cont.buf, cont.len);
1422 cont.len = 0;
1423 }
1403} 1424}
1404 1425
1405static bool cont_add(int facility, int level, const char *text, size_t len) 1426static bool cont_add(int facility, int level, const char *text, size_t len)
@@ -1418,12 +1439,17 @@ static bool cont_add(int facility, int level, const char *text, size_t len)
1418 cont.level = level; 1439 cont.level = level;
1419 cont.owner = current; 1440 cont.owner = current;
1420 cont.ts_nsec = local_clock(); 1441 cont.ts_nsec = local_clock();
1442 cont.flags = 0;
1421 cont.cons = 0; 1443 cont.cons = 0;
1422 cont.flushed = false; 1444 cont.flushed = false;
1423 } 1445 }
1424 1446
1425 memcpy(cont.buf + cont.len, text, len); 1447 memcpy(cont.buf + cont.len, text, len);
1426 cont.len += len; 1448 cont.len += len;
1449
1450 if (cont.len > (sizeof(cont.buf) * 80) / 100)
1451 cont_flush(LOG_CONT);
1452
1427 return true; 1453 return true;
1428} 1454}
1429 1455
@@ -1432,7 +1458,7 @@ static size_t cont_print_text(char *text, size_t size)
1432 size_t textlen = 0; 1458 size_t textlen = 0;
1433 size_t len; 1459 size_t len;
1434 1460
1435 if (cont.cons == 0) { 1461 if (cont.cons == 0 && (console_prev & LOG_NEWLINE)) {
1436 textlen += print_time(cont.ts_nsec, text); 1462 textlen += print_time(cont.ts_nsec, text);
1437 size -= textlen; 1463 size -= textlen;
1438 } 1464 }
@@ -1447,7 +1473,8 @@ static size_t cont_print_text(char *text, size_t size)
1447 } 1473 }
1448 1474
1449 if (cont.flushed) { 1475 if (cont.flushed) {
1450 text[textlen++] = '\n'; 1476 if (cont.flags & LOG_NEWLINE)
1477 text[textlen++] = '\n';
1451 /* got everything, release buffer */ 1478 /* got everything, release buffer */
1452 cont.len = 0; 1479 cont.len = 0;
1453 } 1480 }
@@ -1545,7 +1572,7 @@ asmlinkage int vprintk_emit(int facility, int level,
1545 * or another task also prints continuation lines. 1572 * or another task also prints continuation lines.
1546 */ 1573 */
1547 if (cont.len && (lflags & LOG_PREFIX || cont.owner != current)) 1574 if (cont.len && (lflags & LOG_PREFIX || cont.owner != current))
1548 cont_flush(0); 1575 cont_flush(LOG_NEWLINE);
1549 1576
1550 /* buffer line if possible, otherwise store it right away */ 1577 /* buffer line if possible, otherwise store it right away */
1551 if (!cont_add(facility, level, text, text_len)) 1578 if (!cont_add(facility, level, text, text_len))
@@ -1563,7 +1590,7 @@ asmlinkage int vprintk_emit(int facility, int level,
1563 if (cont.len && cont.owner == current) { 1590 if (cont.len && cont.owner == current) {
1564 if (!(lflags & LOG_PREFIX)) 1591 if (!(lflags & LOG_PREFIX))
1565 stored = cont_add(facility, level, text, text_len); 1592 stored = cont_add(facility, level, text, text_len);
1566 cont_flush(0); 1593 cont_flush(LOG_NEWLINE);
1567 } 1594 }
1568 1595
1569 if (!stored) 1596 if (!stored)
@@ -1661,10 +1688,13 @@ EXPORT_SYMBOL(printk);
1661#define LOG_LINE_MAX 0 1688#define LOG_LINE_MAX 0
1662static u64 syslog_seq; 1689static u64 syslog_seq;
1663static u32 syslog_idx; 1690static u32 syslog_idx;
1691static u64 console_seq;
1692static u32 console_idx;
1664static enum log_flags syslog_prev; 1693static enum log_flags syslog_prev;
1665static u64 log_first_seq; 1694static u64 log_first_seq;
1666static u32 log_first_idx; 1695static u32 log_first_idx;
1667static u64 log_next_seq; 1696static u64 log_next_seq;
1697static enum log_flags console_prev;
1668static struct cont { 1698static struct cont {
1669 size_t len; 1699 size_t len;
1670 size_t cons; 1700 size_t cons;
@@ -1948,10 +1978,34 @@ void wake_up_klogd(void)
1948 this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); 1978 this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
1949} 1979}
1950 1980
1951/* the next printk record to write to the console */ 1981static void console_cont_flush(char *text, size_t size)
1952static u64 console_seq; 1982{
1953static u32 console_idx; 1983 unsigned long flags;
1954static enum log_flags console_prev; 1984 size_t len;
1985
1986 raw_spin_lock_irqsave(&logbuf_lock, flags);
1987
1988 if (!cont.len)
1989 goto out;
1990
1991 /*
1992 * We still queue earlier records, likely because the console was
1993 * busy. The earlier ones need to be printed before this one, we
1994 * did not flush any fragment so far, so just let it queue up.
1995 */
1996 if (console_seq < log_next_seq && !cont.cons)
1997 goto out;
1998
1999 len = cont_print_text(text, size);
2000 raw_spin_unlock(&logbuf_lock);
2001 stop_critical_timings();
2002 call_console_drivers(cont.level, text, len);
2003 start_critical_timings();
2004 local_irq_restore(flags);
2005 return;
2006out:
2007 raw_spin_unlock_irqrestore(&logbuf_lock, flags);
2008}
1955 2009
1956/** 2010/**
1957 * console_unlock - unlock the console system 2011 * console_unlock - unlock the console system
@@ -1983,19 +2037,7 @@ void console_unlock(void)
1983 console_may_schedule = 0; 2037 console_may_schedule = 0;
1984 2038
1985 /* flush buffered message fragment immediately to console */ 2039 /* flush buffered message fragment immediately to console */
1986 raw_spin_lock_irqsave(&logbuf_lock, flags); 2040 console_cont_flush(text, sizeof(text));
1987 if (cont.len && (cont.cons < cont.len || cont.flushed)) {
1988 size_t len;
1989
1990 len = cont_print_text(text, sizeof(text));
1991 raw_spin_unlock(&logbuf_lock);
1992 stop_critical_timings();
1993 call_console_drivers(cont.level, text, len);
1994 start_critical_timings();
1995 local_irq_restore(flags);
1996 } else
1997 raw_spin_unlock_irqrestore(&logbuf_lock, flags);
1998
1999again: 2041again:
2000 for (;;) { 2042 for (;;) {
2001 struct log *msg; 2043 struct log *msg;
@@ -2032,6 +2074,7 @@ skip:
2032 * will properly dump everything later. 2074 * will properly dump everything later.
2033 */ 2075 */
2034 msg->flags &= ~LOG_NOCONS; 2076 msg->flags &= ~LOG_NOCONS;
2077 console_prev = msg->flags;
2035 goto skip; 2078 goto skip;
2036 } 2079 }
2037 2080