diff options
Diffstat (limited to 'kernel/printk/printk.c')
| -rw-r--r-- | kernel/printk/printk.c | 348 |
1 files changed, 227 insertions, 121 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index a45b50962295..ea2d5f6962ed 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c | |||
| @@ -54,20 +54,16 @@ | |||
| 54 | #include "console_cmdline.h" | 54 | #include "console_cmdline.h" |
| 55 | #include "braille.h" | 55 | #include "braille.h" |
| 56 | 56 | ||
| 57 | /* printk's without a loglevel use this.. */ | ||
| 58 | #define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL | ||
| 59 | |||
| 60 | /* We show everything that is MORE important than this.. */ | ||
| 61 | #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */ | ||
| 62 | #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */ | ||
| 63 | |||
| 64 | int console_printk[4] = { | 57 | int console_printk[4] = { |
| 65 | DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */ | 58 | CONSOLE_LOGLEVEL_DEFAULT, /* console_loglevel */ |
| 66 | DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */ | 59 | DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */ |
| 67 | MINIMUM_CONSOLE_LOGLEVEL, /* minimum_console_loglevel */ | 60 | CONSOLE_LOGLEVEL_MIN, /* minimum_console_loglevel */ |
| 68 | DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */ | 61 | CONSOLE_LOGLEVEL_DEFAULT, /* default_console_loglevel */ |
| 69 | }; | 62 | }; |
| 70 | 63 | ||
| 64 | /* Deferred messaged from sched code are marked by this special level */ | ||
| 65 | #define SCHED_MESSAGE_LOGLEVEL -2 | ||
| 66 | |||
| 71 | /* | 67 | /* |
| 72 | * Low level drivers may need that to know if they can schedule in | 68 | * Low level drivers may need that to know if they can schedule in |
| 73 | * their unblank() callback or not. So let's export it. | 69 | * their unblank() callback or not. So let's export it. |
| @@ -91,6 +87,29 @@ static struct lockdep_map console_lock_dep_map = { | |||
| 91 | #endif | 87 | #endif |
| 92 | 88 | ||
| 93 | /* | 89 | /* |
| 90 | * Helper macros to handle lockdep when locking/unlocking console_sem. We use | ||
| 91 | * macros instead of functions so that _RET_IP_ contains useful information. | ||
| 92 | */ | ||
| 93 | #define down_console_sem() do { \ | ||
| 94 | down(&console_sem);\ | ||
| 95 | mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_);\ | ||
| 96 | } while (0) | ||
| 97 | |||
| 98 | static int __down_trylock_console_sem(unsigned long ip) | ||
| 99 | { | ||
| 100 | if (down_trylock(&console_sem)) | ||
| 101 | return 1; | ||
| 102 | mutex_acquire(&console_lock_dep_map, 0, 1, ip); | ||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | #define down_trylock_console_sem() __down_trylock_console_sem(_RET_IP_) | ||
| 106 | |||
| 107 | #define up_console_sem() do { \ | ||
| 108 | mutex_release(&console_lock_dep_map, 1, _RET_IP_);\ | ||
| 109 | up(&console_sem);\ | ||
| 110 | } while (0) | ||
| 111 | |||
| 112 | /* | ||
| 94 | * This is used for debugging the mess that is the VT code by | 113 | * This is used for debugging the mess that is the VT code by |
| 95 | * keeping track if we have the console semaphore held. It's | 114 | * keeping track if we have the console semaphore held. It's |
| 96 | * definitely not the perfect debug tool (we don't know if _WE_ | 115 | * definitely not the perfect debug tool (we don't know if _WE_ |
| @@ -206,8 +225,9 @@ struct printk_log { | |||
| 206 | }; | 225 | }; |
| 207 | 226 | ||
| 208 | /* | 227 | /* |
| 209 | * The logbuf_lock protects kmsg buffer, indices, counters. It is also | 228 | * The logbuf_lock protects kmsg buffer, indices, counters. This can be taken |
| 210 | * used in interesting ways to provide interlocking in console_unlock(); | 229 | * within the scheduler's rq lock. It must be released before calling |
| 230 | * console_unlock() or anything else that might wake up a process. | ||
| 211 | */ | 231 | */ |
| 212 | static DEFINE_RAW_SPINLOCK(logbuf_lock); | 232 | static DEFINE_RAW_SPINLOCK(logbuf_lock); |
| 213 | 233 | ||
| @@ -250,9 +270,6 @@ static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN); | |||
| 250 | static char *log_buf = __log_buf; | 270 | static char *log_buf = __log_buf; |
| 251 | static u32 log_buf_len = __LOG_BUF_LEN; | 271 | static u32 log_buf_len = __LOG_BUF_LEN; |
| 252 | 272 | ||
| 253 | /* cpu currently holding logbuf_lock */ | ||
| 254 | static volatile unsigned int logbuf_cpu = UINT_MAX; | ||
| 255 | |||
| 256 | /* human readable text of the record */ | 273 | /* human readable text of the record */ |
| 257 | static char *log_text(const struct printk_log *msg) | 274 | static char *log_text(const struct printk_log *msg) |
| 258 | { | 275 | { |
| @@ -297,34 +314,106 @@ static u32 log_next(u32 idx) | |||
| 297 | return idx + msg->len; | 314 | return idx + msg->len; |
| 298 | } | 315 | } |
| 299 | 316 | ||
| 300 | /* insert record into the buffer, discard old ones, update heads */ | 317 | /* |
| 301 | static void log_store(int facility, int level, | 318 | * Check whether there is enough free space for the given message. |
| 302 | enum log_flags flags, u64 ts_nsec, | 319 | * |
| 303 | const char *dict, u16 dict_len, | 320 | * The same values of first_idx and next_idx mean that the buffer |
| 304 | const char *text, u16 text_len) | 321 | * is either empty or full. |
| 322 | * | ||
| 323 | * If the buffer is empty, we must respect the position of the indexes. | ||
| 324 | * They cannot be reset to the beginning of the buffer. | ||
| 325 | */ | ||
| 326 | static int logbuf_has_space(u32 msg_size, bool empty) | ||
| 305 | { | 327 | { |
| 306 | struct printk_log *msg; | 328 | u32 free; |
| 307 | u32 size, pad_len; | ||
| 308 | 329 | ||
| 309 | /* number of '\0' padding bytes to next message */ | 330 | if (log_next_idx > log_first_idx || empty) |
| 310 | size = sizeof(struct printk_log) + text_len + dict_len; | 331 | free = max(log_buf_len - log_next_idx, log_first_idx); |
| 311 | pad_len = (-size) & (LOG_ALIGN - 1); | 332 | else |
| 312 | size += pad_len; | 333 | free = log_first_idx - log_next_idx; |
| 334 | |||
| 335 | /* | ||
| 336 | * We need space also for an empty header that signalizes wrapping | ||
| 337 | * of the buffer. | ||
| 338 | */ | ||
| 339 | return free >= msg_size + sizeof(struct printk_log); | ||
| 340 | } | ||
| 313 | 341 | ||
| 342 | static int log_make_free_space(u32 msg_size) | ||
| 343 | { | ||
| 314 | while (log_first_seq < log_next_seq) { | 344 | while (log_first_seq < log_next_seq) { |
| 315 | u32 free; | 345 | if (logbuf_has_space(msg_size, false)) |
| 346 | return 0; | ||
| 347 | /* drop old messages until we have enough continuous space */ | ||
| 348 | log_first_idx = log_next(log_first_idx); | ||
| 349 | log_first_seq++; | ||
| 350 | } | ||
| 316 | 351 | ||
| 317 | if (log_next_idx > log_first_idx) | 352 | /* sequence numbers are equal, so the log buffer is empty */ |
| 318 | free = max(log_buf_len - log_next_idx, log_first_idx); | 353 | if (logbuf_has_space(msg_size, true)) |
| 319 | else | 354 | return 0; |
| 320 | free = log_first_idx - log_next_idx; | ||
| 321 | 355 | ||
| 322 | if (free >= size + sizeof(struct printk_log)) | 356 | return -ENOMEM; |
| 323 | break; | 357 | } |
| 324 | 358 | ||
| 325 | /* drop old messages until we have enough contiuous space */ | 359 | /* compute the message size including the padding bytes */ |
| 326 | log_first_idx = log_next(log_first_idx); | 360 | static u32 msg_used_size(u16 text_len, u16 dict_len, u32 *pad_len) |
| 327 | log_first_seq++; | 361 | { |
| 362 | u32 size; | ||
| 363 | |||
| 364 | size = sizeof(struct printk_log) + text_len + dict_len; | ||
| 365 | *pad_len = (-size) & (LOG_ALIGN - 1); | ||
| 366 | size += *pad_len; | ||
| 367 | |||
| 368 | return size; | ||
| 369 | } | ||
| 370 | |||
| 371 | /* | ||
| 372 | * Define how much of the log buffer we could take at maximum. The value | ||
| 373 | * must be greater than two. Note that only half of the buffer is available | ||
| 374 | * when the index points to the middle. | ||
| 375 | */ | ||
| 376 | #define MAX_LOG_TAKE_PART 4 | ||
| 377 | static const char trunc_msg[] = "<truncated>"; | ||
| 378 | |||
| 379 | static u32 truncate_msg(u16 *text_len, u16 *trunc_msg_len, | ||
| 380 | u16 *dict_len, u32 *pad_len) | ||
| 381 | { | ||
| 382 | /* | ||
| 383 | * The message should not take the whole buffer. Otherwise, it might | ||
| 384 | * get removed too soon. | ||
| 385 | */ | ||
| 386 | u32 max_text_len = log_buf_len / MAX_LOG_TAKE_PART; | ||
| 387 | if (*text_len > max_text_len) | ||
| 388 | *text_len = max_text_len; | ||
| 389 | /* enable the warning message */ | ||
| 390 | *trunc_msg_len = strlen(trunc_msg); | ||
| 391 | /* disable the "dict" completely */ | ||
| 392 | *dict_len = 0; | ||
| 393 | /* compute the size again, count also the warning message */ | ||
| 394 | return msg_used_size(*text_len + *trunc_msg_len, 0, pad_len); | ||
| 395 | } | ||
| 396 | |||
| 397 | /* insert record into the buffer, discard old ones, update heads */ | ||
| 398 | static int log_store(int facility, int level, | ||
| 399 | enum log_flags flags, u64 ts_nsec, | ||
| 400 | const char *dict, u16 dict_len, | ||
| 401 | const char *text, u16 text_len) | ||
| 402 | { | ||
| 403 | struct printk_log *msg; | ||
| 404 | u32 size, pad_len; | ||
| 405 | u16 trunc_msg_len = 0; | ||
| 406 | |||
| 407 | /* number of '\0' padding bytes to next message */ | ||
| 408 | size = msg_used_size(text_len, dict_len, &pad_len); | ||
| 409 | |||
| 410 | if (log_make_free_space(size)) { | ||
| 411 | /* truncate the message if it is too long for empty buffer */ | ||
| 412 | size = truncate_msg(&text_len, &trunc_msg_len, | ||
| 413 | &dict_len, &pad_len); | ||
| 414 | /* survive when the log buffer is too small for trunc_msg */ | ||
| 415 | if (log_make_free_space(size)) | ||
| 416 | return 0; | ||
| 328 | } | 417 | } |
| 329 | 418 | ||
| 330 | if (log_next_idx + size + sizeof(struct printk_log) > log_buf_len) { | 419 | if (log_next_idx + size + sizeof(struct printk_log) > log_buf_len) { |
| @@ -341,6 +430,10 @@ static void log_store(int facility, int level, | |||
| 341 | msg = (struct printk_log *)(log_buf + log_next_idx); | 430 | msg = (struct printk_log *)(log_buf + log_next_idx); |
| 342 | memcpy(log_text(msg), text, text_len); | 431 | memcpy(log_text(msg), text, text_len); |
| 343 | msg->text_len = text_len; | 432 | msg->text_len = text_len; |
| 433 | if (trunc_msg_len) { | ||
| 434 | memcpy(log_text(msg) + text_len, trunc_msg, trunc_msg_len); | ||
| 435 | msg->text_len += trunc_msg_len; | ||
| 436 | } | ||
| 344 | memcpy(log_dict(msg), dict, dict_len); | 437 | memcpy(log_dict(msg), dict, dict_len); |
| 345 | msg->dict_len = dict_len; | 438 | msg->dict_len = dict_len; |
| 346 | msg->facility = facility; | 439 | msg->facility = facility; |
| @@ -356,6 +449,8 @@ static void log_store(int facility, int level, | |||
| 356 | /* insert message */ | 449 | /* insert message */ |
| 357 | log_next_idx += msg->len; | 450 | log_next_idx += msg->len; |
| 358 | log_next_seq++; | 451 | log_next_seq++; |
| 452 | |||
| 453 | return msg->text_len; | ||
| 359 | } | 454 | } |
| 360 | 455 | ||
| 361 | #ifdef CONFIG_SECURITY_DMESG_RESTRICT | 456 | #ifdef CONFIG_SECURITY_DMESG_RESTRICT |
| @@ -1303,7 +1398,10 @@ static void zap_locks(void) | |||
| 1303 | sema_init(&console_sem, 1); | 1398 | sema_init(&console_sem, 1); |
| 1304 | } | 1399 | } |
| 1305 | 1400 | ||
| 1306 | /* Check if we have any console registered that can be called early in boot. */ | 1401 | /* |
| 1402 | * Check if we have any console that is capable of printing while cpu is | ||
| 1403 | * booting or shutting down. Requires console_sem. | ||
| 1404 | */ | ||
| 1307 | static int have_callable_console(void) | 1405 | static int have_callable_console(void) |
| 1308 | { | 1406 | { |
| 1309 | struct console *con; | 1407 | struct console *con; |
| @@ -1318,10 +1416,9 @@ static int have_callable_console(void) | |||
| 1318 | /* | 1416 | /* |
| 1319 | * Can we actually use the console at this time on this cpu? | 1417 | * Can we actually use the console at this time on this cpu? |
| 1320 | * | 1418 | * |
| 1321 | * Console drivers may assume that per-cpu resources have | 1419 | * Console drivers may assume that per-cpu resources have been allocated. So |
| 1322 | * been allocated. So unless they're explicitly marked as | 1420 | * unless they're explicitly marked as being able to cope (CON_ANYTIME) don't |
| 1323 | * being able to cope (CON_ANYTIME) don't call them until | 1421 | * call them until this CPU is officially up. |
| 1324 | * this CPU is officially up. | ||
| 1325 | */ | 1422 | */ |
| 1326 | static inline int can_use_console(unsigned int cpu) | 1423 | static inline int can_use_console(unsigned int cpu) |
| 1327 | { | 1424 | { |
| @@ -1333,36 +1430,24 @@ static inline int can_use_console(unsigned int cpu) | |||
| 1333 | * messages from a 'printk'. Return true (and with the | 1430 | * messages from a 'printk'. Return true (and with the |
| 1334 | * console_lock held, and 'console_locked' set) if it | 1431 | * console_lock held, and 'console_locked' set) if it |
| 1335 | * is successful, false otherwise. | 1432 | * is successful, false otherwise. |
| 1336 | * | ||
| 1337 | * This gets called with the 'logbuf_lock' spinlock held and | ||
| 1338 | * interrupts disabled. It should return with 'lockbuf_lock' | ||
| 1339 | * released but interrupts still disabled. | ||
| 1340 | */ | 1433 | */ |
| 1341 | static int console_trylock_for_printk(unsigned int cpu) | 1434 | static int console_trylock_for_printk(void) |
| 1342 | __releases(&logbuf_lock) | ||
| 1343 | { | 1435 | { |
| 1344 | int retval = 0, wake = 0; | 1436 | unsigned int cpu = smp_processor_id(); |
| 1345 | 1437 | ||
| 1346 | if (console_trylock()) { | 1438 | if (!console_trylock()) |
| 1347 | retval = 1; | 1439 | return 0; |
| 1348 | 1440 | /* | |
| 1349 | /* | 1441 | * If we can't use the console, we need to release the console |
| 1350 | * If we can't use the console, we need to release | 1442 | * semaphore by hand to avoid flushing the buffer. We need to hold the |
| 1351 | * the console semaphore by hand to avoid flushing | 1443 | * console semaphore in order to do this test safely. |
| 1352 | * the buffer. We need to hold the console semaphore | 1444 | */ |
| 1353 | * in order to do this test safely. | 1445 | if (!can_use_console(cpu)) { |
| 1354 | */ | 1446 | console_locked = 0; |
| 1355 | if (!can_use_console(cpu)) { | 1447 | up_console_sem(); |
| 1356 | console_locked = 0; | 1448 | return 0; |
| 1357 | wake = 1; | ||
| 1358 | retval = 0; | ||
| 1359 | } | ||
| 1360 | } | 1449 | } |
| 1361 | logbuf_cpu = UINT_MAX; | 1450 | return 1; |
| 1362 | raw_spin_unlock(&logbuf_lock); | ||
| 1363 | if (wake) | ||
| 1364 | up(&console_sem); | ||
| 1365 | return retval; | ||
| 1366 | } | 1451 | } |
| 1367 | 1452 | ||
| 1368 | int printk_delay_msec __read_mostly; | 1453 | int printk_delay_msec __read_mostly; |
| @@ -1490,11 +1575,19 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
| 1490 | static int recursion_bug; | 1575 | static int recursion_bug; |
| 1491 | static char textbuf[LOG_LINE_MAX]; | 1576 | static char textbuf[LOG_LINE_MAX]; |
| 1492 | char *text = textbuf; | 1577 | char *text = textbuf; |
| 1493 | size_t text_len; | 1578 | size_t text_len = 0; |
| 1494 | enum log_flags lflags = 0; | 1579 | enum log_flags lflags = 0; |
| 1495 | unsigned long flags; | 1580 | unsigned long flags; |
| 1496 | int this_cpu; | 1581 | int this_cpu; |
| 1497 | int printed_len = 0; | 1582 | int printed_len = 0; |
| 1583 | bool in_sched = false; | ||
| 1584 | /* cpu currently holding logbuf_lock in this function */ | ||
| 1585 | static volatile unsigned int logbuf_cpu = UINT_MAX; | ||
| 1586 | |||
| 1587 | if (level == SCHED_MESSAGE_LOGLEVEL) { | ||
| 1588 | level = -1; | ||
| 1589 | in_sched = true; | ||
| 1590 | } | ||
| 1498 | 1591 | ||
| 1499 | boot_delay_msec(level); | 1592 | boot_delay_msec(level); |
| 1500 | printk_delay(); | 1593 | printk_delay(); |
| @@ -1516,7 +1609,8 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
| 1516 | */ | 1609 | */ |
| 1517 | if (!oops_in_progress && !lockdep_recursing(current)) { | 1610 | if (!oops_in_progress && !lockdep_recursing(current)) { |
| 1518 | recursion_bug = 1; | 1611 | recursion_bug = 1; |
| 1519 | goto out_restore_irqs; | 1612 | local_irq_restore(flags); |
| 1613 | return 0; | ||
| 1520 | } | 1614 | } |
| 1521 | zap_locks(); | 1615 | zap_locks(); |
| 1522 | } | 1616 | } |
| @@ -1530,17 +1624,22 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
| 1530 | "BUG: recent printk recursion!"; | 1624 | "BUG: recent printk recursion!"; |
| 1531 | 1625 | ||
| 1532 | recursion_bug = 0; | 1626 | recursion_bug = 0; |
| 1533 | printed_len += strlen(recursion_msg); | 1627 | text_len = strlen(recursion_msg); |
| 1534 | /* emit KERN_CRIT message */ | 1628 | /* emit KERN_CRIT message */ |
| 1535 | log_store(0, 2, LOG_PREFIX|LOG_NEWLINE, 0, | 1629 | printed_len += log_store(0, 2, LOG_PREFIX|LOG_NEWLINE, 0, |
| 1536 | NULL, 0, recursion_msg, printed_len); | 1630 | NULL, 0, recursion_msg, text_len); |
| 1537 | } | 1631 | } |
| 1538 | 1632 | ||
| 1539 | /* | 1633 | /* |
| 1540 | * The printf needs to come first; we need the syslog | 1634 | * The printf needs to come first; we need the syslog |
| 1541 | * prefix which might be passed-in as a parameter. | 1635 | * prefix which might be passed-in as a parameter. |
| 1542 | */ | 1636 | */ |
| 1543 | text_len = vscnprintf(text, sizeof(textbuf), fmt, args); | 1637 | if (in_sched) |
| 1638 | text_len = scnprintf(text, sizeof(textbuf), | ||
| 1639 | KERN_WARNING "[sched_delayed] "); | ||
| 1640 | |||
| 1641 | text_len += vscnprintf(text + text_len, | ||
| 1642 | sizeof(textbuf) - text_len, fmt, args); | ||
| 1544 | 1643 | ||
| 1545 | /* mark and strip a trailing newline */ | 1644 | /* mark and strip a trailing newline */ |
| 1546 | if (text_len && text[text_len-1] == '\n') { | 1645 | if (text_len && text[text_len-1] == '\n') { |
| @@ -1586,9 +1685,12 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
| 1586 | cont_flush(LOG_NEWLINE); | 1685 | cont_flush(LOG_NEWLINE); |
| 1587 | 1686 | ||
| 1588 | /* buffer line if possible, otherwise store it right away */ | 1687 | /* buffer line if possible, otherwise store it right away */ |
| 1589 | if (!cont_add(facility, level, text, text_len)) | 1688 | if (cont_add(facility, level, text, text_len)) |
| 1590 | log_store(facility, level, lflags | LOG_CONT, 0, | 1689 | printed_len += text_len; |
| 1591 | dict, dictlen, text, text_len); | 1690 | else |
| 1691 | printed_len += log_store(facility, level, | ||
| 1692 | lflags | LOG_CONT, 0, | ||
| 1693 | dict, dictlen, text, text_len); | ||
| 1592 | } else { | 1694 | } else { |
| 1593 | bool stored = false; | 1695 | bool stored = false; |
| 1594 | 1696 | ||
| @@ -1607,26 +1709,35 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
| 1607 | cont_flush(LOG_NEWLINE); | 1709 | cont_flush(LOG_NEWLINE); |
| 1608 | } | 1710 | } |
| 1609 | 1711 | ||
| 1610 | if (!stored) | 1712 | if (stored) |
| 1611 | log_store(facility, level, lflags, 0, | 1713 | printed_len += text_len; |
| 1612 | dict, dictlen, text, text_len); | 1714 | else |
| 1715 | printed_len += log_store(facility, level, lflags, 0, | ||
| 1716 | dict, dictlen, text, text_len); | ||
| 1613 | } | 1717 | } |
| 1614 | printed_len += text_len; | 1718 | |
| 1719 | logbuf_cpu = UINT_MAX; | ||
| 1720 | raw_spin_unlock(&logbuf_lock); | ||
| 1721 | lockdep_on(); | ||
| 1722 | local_irq_restore(flags); | ||
| 1723 | |||
| 1724 | /* If called from the scheduler, we can not call up(). */ | ||
| 1725 | if (in_sched) | ||
| 1726 | return printed_len; | ||
| 1615 | 1727 | ||
| 1616 | /* | 1728 | /* |
| 1729 | * Disable preemption to avoid being preempted while holding | ||
| 1730 | * console_sem which would prevent anyone from printing to console | ||
| 1731 | */ | ||
| 1732 | preempt_disable(); | ||
| 1733 | /* | ||
| 1617 | * Try to acquire and then immediately release the console semaphore. | 1734 | * Try to acquire and then immediately release the console semaphore. |
| 1618 | * The release will print out buffers and wake up /dev/kmsg and syslog() | 1735 | * The release will print out buffers and wake up /dev/kmsg and syslog() |
| 1619 | * users. | 1736 | * users. |
| 1620 | * | ||
| 1621 | * The console_trylock_for_printk() function will release 'logbuf_lock' | ||
| 1622 | * regardless of whether it actually gets the console semaphore or not. | ||
| 1623 | */ | 1737 | */ |
| 1624 | if (console_trylock_for_printk(this_cpu)) | 1738 | if (console_trylock_for_printk()) |
| 1625 | console_unlock(); | 1739 | console_unlock(); |
| 1626 | 1740 | preempt_enable(); | |
| 1627 | lockdep_on(); | ||
| 1628 | out_restore_irqs: | ||
| 1629 | local_irq_restore(flags); | ||
| 1630 | 1741 | ||
| 1631 | return printed_len; | 1742 | return printed_len; |
| 1632 | } | 1743 | } |
| @@ -1674,7 +1785,7 @@ EXPORT_SYMBOL(printk_emit); | |||
| 1674 | * | 1785 | * |
| 1675 | * See the vsnprintf() documentation for format string extensions over C99. | 1786 | * See the vsnprintf() documentation for format string extensions over C99. |
| 1676 | */ | 1787 | */ |
| 1677 | asmlinkage int printk(const char *fmt, ...) | 1788 | asmlinkage __visible int printk(const char *fmt, ...) |
| 1678 | { | 1789 | { |
| 1679 | va_list args; | 1790 | va_list args; |
| 1680 | int r; | 1791 | int r; |
| @@ -1737,7 +1848,7 @@ void early_vprintk(const char *fmt, va_list ap) | |||
| 1737 | } | 1848 | } |
| 1738 | } | 1849 | } |
| 1739 | 1850 | ||
| 1740 | asmlinkage void early_printk(const char *fmt, ...) | 1851 | asmlinkage __visible void early_printk(const char *fmt, ...) |
| 1741 | { | 1852 | { |
| 1742 | va_list ap; | 1853 | va_list ap; |
| 1743 | 1854 | ||
| @@ -1882,16 +1993,14 @@ void suspend_console(void) | |||
| 1882 | printk("Suspending console(s) (use no_console_suspend to debug)\n"); | 1993 | printk("Suspending console(s) (use no_console_suspend to debug)\n"); |
| 1883 | console_lock(); | 1994 | console_lock(); |
| 1884 | console_suspended = 1; | 1995 | console_suspended = 1; |
| 1885 | up(&console_sem); | 1996 | up_console_sem(); |
| 1886 | mutex_release(&console_lock_dep_map, 1, _RET_IP_); | ||
| 1887 | } | 1997 | } |
| 1888 | 1998 | ||
| 1889 | void resume_console(void) | 1999 | void resume_console(void) |
| 1890 | { | 2000 | { |
| 1891 | if (!console_suspend_enabled) | 2001 | if (!console_suspend_enabled) |
| 1892 | return; | 2002 | return; |
| 1893 | down(&console_sem); | 2003 | down_console_sem(); |
| 1894 | mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_); | ||
| 1895 | console_suspended = 0; | 2004 | console_suspended = 0; |
| 1896 | console_unlock(); | 2005 | console_unlock(); |
| 1897 | } | 2006 | } |
| @@ -1933,12 +2042,11 @@ void console_lock(void) | |||
| 1933 | { | 2042 | { |
| 1934 | might_sleep(); | 2043 | might_sleep(); |
| 1935 | 2044 | ||
| 1936 | down(&console_sem); | 2045 | down_console_sem(); |
| 1937 | if (console_suspended) | 2046 | if (console_suspended) |
| 1938 | return; | 2047 | return; |
| 1939 | console_locked = 1; | 2048 | console_locked = 1; |
| 1940 | console_may_schedule = 1; | 2049 | console_may_schedule = 1; |
| 1941 | mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_); | ||
| 1942 | } | 2050 | } |
| 1943 | EXPORT_SYMBOL(console_lock); | 2051 | EXPORT_SYMBOL(console_lock); |
| 1944 | 2052 | ||
| @@ -1952,15 +2060,14 @@ EXPORT_SYMBOL(console_lock); | |||
| 1952 | */ | 2060 | */ |
| 1953 | int console_trylock(void) | 2061 | int console_trylock(void) |
| 1954 | { | 2062 | { |
| 1955 | if (down_trylock(&console_sem)) | 2063 | if (down_trylock_console_sem()) |
| 1956 | return 0; | 2064 | return 0; |
| 1957 | if (console_suspended) { | 2065 | if (console_suspended) { |
| 1958 | up(&console_sem); | 2066 | up_console_sem(); |
| 1959 | return 0; | 2067 | return 0; |
| 1960 | } | 2068 | } |
| 1961 | console_locked = 1; | 2069 | console_locked = 1; |
| 1962 | console_may_schedule = 0; | 2070 | console_may_schedule = 0; |
| 1963 | mutex_acquire(&console_lock_dep_map, 0, 1, _RET_IP_); | ||
| 1964 | return 1; | 2071 | return 1; |
| 1965 | } | 2072 | } |
| 1966 | EXPORT_SYMBOL(console_trylock); | 2073 | EXPORT_SYMBOL(console_trylock); |
| @@ -2022,7 +2129,7 @@ void console_unlock(void) | |||
| 2022 | bool retry; | 2129 | bool retry; |
| 2023 | 2130 | ||
| 2024 | if (console_suspended) { | 2131 | if (console_suspended) { |
| 2025 | up(&console_sem); | 2132 | up_console_sem(); |
| 2026 | return; | 2133 | return; |
| 2027 | } | 2134 | } |
| 2028 | 2135 | ||
| @@ -2043,10 +2150,15 @@ again: | |||
| 2043 | } | 2150 | } |
| 2044 | 2151 | ||
| 2045 | if (console_seq < log_first_seq) { | 2152 | if (console_seq < log_first_seq) { |
| 2153 | len = sprintf(text, "** %u printk messages dropped ** ", | ||
| 2154 | (unsigned)(log_first_seq - console_seq)); | ||
| 2155 | |||
| 2046 | /* messages are gone, move to first one */ | 2156 | /* messages are gone, move to first one */ |
| 2047 | console_seq = log_first_seq; | 2157 | console_seq = log_first_seq; |
| 2048 | console_idx = log_first_idx; | 2158 | console_idx = log_first_idx; |
| 2049 | console_prev = 0; | 2159 | console_prev = 0; |
| 2160 | } else { | ||
| 2161 | len = 0; | ||
| 2050 | } | 2162 | } |
| 2051 | skip: | 2163 | skip: |
| 2052 | if (console_seq == log_next_seq) | 2164 | if (console_seq == log_next_seq) |
| @@ -2071,8 +2183,8 @@ skip: | |||
| 2071 | } | 2183 | } |
| 2072 | 2184 | ||
| 2073 | level = msg->level; | 2185 | level = msg->level; |
| 2074 | len = msg_print_text(msg, console_prev, false, | 2186 | len += msg_print_text(msg, console_prev, false, |
| 2075 | text, sizeof(text)); | 2187 | text + len, sizeof(text) - len); |
| 2076 | console_idx = log_next(console_idx); | 2188 | console_idx = log_next(console_idx); |
| 2077 | console_seq++; | 2189 | console_seq++; |
| 2078 | console_prev = msg->flags; | 2190 | console_prev = msg->flags; |
| @@ -2084,7 +2196,6 @@ skip: | |||
| 2084 | local_irq_restore(flags); | 2196 | local_irq_restore(flags); |
| 2085 | } | 2197 | } |
| 2086 | console_locked = 0; | 2198 | console_locked = 0; |
| 2087 | mutex_release(&console_lock_dep_map, 1, _RET_IP_); | ||
| 2088 | 2199 | ||
| 2089 | /* Release the exclusive_console once it is used */ | 2200 | /* Release the exclusive_console once it is used */ |
| 2090 | if (unlikely(exclusive_console)) | 2201 | if (unlikely(exclusive_console)) |
| @@ -2092,7 +2203,7 @@ skip: | |||
| 2092 | 2203 | ||
| 2093 | raw_spin_unlock(&logbuf_lock); | 2204 | raw_spin_unlock(&logbuf_lock); |
| 2094 | 2205 | ||
| 2095 | up(&console_sem); | 2206 | up_console_sem(); |
| 2096 | 2207 | ||
| 2097 | /* | 2208 | /* |
| 2098 | * Someone could have filled up the buffer again, so re-check if there's | 2209 | * Someone could have filled up the buffer again, so re-check if there's |
| @@ -2137,7 +2248,7 @@ void console_unblank(void) | |||
| 2137 | * oops_in_progress is set to 1.. | 2248 | * oops_in_progress is set to 1.. |
| 2138 | */ | 2249 | */ |
| 2139 | if (oops_in_progress) { | 2250 | if (oops_in_progress) { |
| 2140 | if (down_trylock(&console_sem) != 0) | 2251 | if (down_trylock_console_sem() != 0) |
| 2141 | return; | 2252 | return; |
| 2142 | } else | 2253 | } else |
| 2143 | console_lock(); | 2254 | console_lock(); |
| @@ -2413,6 +2524,7 @@ int unregister_console(struct console *console) | |||
| 2413 | if (console_drivers != NULL && console->flags & CON_CONSDEV) | 2524 | if (console_drivers != NULL && console->flags & CON_CONSDEV) |
| 2414 | console_drivers->flags |= CON_CONSDEV; | 2525 | console_drivers->flags |= CON_CONSDEV; |
| 2415 | 2526 | ||
| 2527 | console->flags &= ~CON_ENABLED; | ||
| 2416 | console_unlock(); | 2528 | console_unlock(); |
| 2417 | console_sysfs_notify(); | 2529 | console_sysfs_notify(); |
| 2418 | return res; | 2530 | return res; |
| @@ -2437,21 +2549,19 @@ late_initcall(printk_late_init); | |||
| 2437 | /* | 2549 | /* |
| 2438 | * Delayed printk version, for scheduler-internal messages: | 2550 | * Delayed printk version, for scheduler-internal messages: |
| 2439 | */ | 2551 | */ |
| 2440 | #define PRINTK_BUF_SIZE 512 | ||
| 2441 | |||
| 2442 | #define PRINTK_PENDING_WAKEUP 0x01 | 2552 | #define PRINTK_PENDING_WAKEUP 0x01 |
| 2443 | #define PRINTK_PENDING_SCHED 0x02 | 2553 | #define PRINTK_PENDING_OUTPUT 0x02 |
| 2444 | 2554 | ||
| 2445 | static DEFINE_PER_CPU(int, printk_pending); | 2555 | static DEFINE_PER_CPU(int, printk_pending); |
| 2446 | static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); | ||
| 2447 | 2556 | ||
| 2448 | static void wake_up_klogd_work_func(struct irq_work *irq_work) | 2557 | static void wake_up_klogd_work_func(struct irq_work *irq_work) |
| 2449 | { | 2558 | { |
| 2450 | int pending = __this_cpu_xchg(printk_pending, 0); | 2559 | int pending = __this_cpu_xchg(printk_pending, 0); |
| 2451 | 2560 | ||
| 2452 | if (pending & PRINTK_PENDING_SCHED) { | 2561 | if (pending & PRINTK_PENDING_OUTPUT) { |
| 2453 | char *buf = __get_cpu_var(printk_sched_buf); | 2562 | /* If trylock fails, someone else is doing the printing */ |
| 2454 | pr_warn("[sched_delayed] %s", buf); | 2563 | if (console_trylock()) |
| 2564 | console_unlock(); | ||
| 2455 | } | 2565 | } |
| 2456 | 2566 | ||
| 2457 | if (pending & PRINTK_PENDING_WAKEUP) | 2567 | if (pending & PRINTK_PENDING_WAKEUP) |
| @@ -2473,23 +2583,19 @@ void wake_up_klogd(void) | |||
| 2473 | preempt_enable(); | 2583 | preempt_enable(); |
| 2474 | } | 2584 | } |
| 2475 | 2585 | ||
| 2476 | int printk_sched(const char *fmt, ...) | 2586 | int printk_deferred(const char *fmt, ...) |
| 2477 | { | 2587 | { |
| 2478 | unsigned long flags; | ||
| 2479 | va_list args; | 2588 | va_list args; |
| 2480 | char *buf; | ||
| 2481 | int r; | 2589 | int r; |
| 2482 | 2590 | ||
| 2483 | local_irq_save(flags); | 2591 | preempt_disable(); |
| 2484 | buf = __get_cpu_var(printk_sched_buf); | ||
| 2485 | |||
| 2486 | va_start(args, fmt); | 2592 | va_start(args, fmt); |
| 2487 | r = vsnprintf(buf, PRINTK_BUF_SIZE, fmt, args); | 2593 | r = vprintk_emit(0, SCHED_MESSAGE_LOGLEVEL, NULL, 0, fmt, args); |
| 2488 | va_end(args); | 2594 | va_end(args); |
| 2489 | 2595 | ||
| 2490 | __this_cpu_or(printk_pending, PRINTK_PENDING_SCHED); | 2596 | __this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT); |
| 2491 | irq_work_queue(&__get_cpu_var(wake_up_klogd_work)); | 2597 | irq_work_queue(&__get_cpu_var(wake_up_klogd_work)); |
| 2492 | local_irq_restore(flags); | 2598 | preempt_enable(); |
| 2493 | 2599 | ||
| 2494 | return r; | 2600 | return r; |
| 2495 | } | 2601 | } |
