| @@ -466,21 +466,6 @@ static struct latched_seq clear_seq = { · 465 unmodified lines |
| 466 | 466 | .val[1] = 0, |
| 467 | 467 | }; |
| 468 | 468 | |
| 469 | | −#ifdef CONFIG_PRINTK_CALLER |
| 470 | | −#define PREFIX_MAX 48 |
| 471 | | −#else |
| 472 | | −#define PREFIX_MAX 32 |
| 473 | | −#endif |
| 474 | | − |
| 475 | | −/* the maximum size of a formatted record (i.e. with prefix added per line) */ |
| 476 | | −#define CONSOLE_LOG_MAX 1024 |
| 477 | | − |
| 478 | | −/* the maximum size for a dropped text message */ |
| 479 | | −#define DROPPED_TEXT_MAX 64 |
| 480 | | − |
| 481 | | −/* the maximum size allowed to be reserved for a record */ |
| 482 | | −#define LOG_LINE_MAX (CONSOLE_LOG_MAX - PREFIX_MAX) |
| 483 | | − |
| 484 | 469 | #define LOG_LEVEL(v) ((v) & 0x07) |
| 485 | 470 | #define LOG_FACILITY(v) ((v) >> 3 & 0xff) |
| 486 | 471 | |
| @@ -711,16 +696,15 @@ out: · 224 unmodified lines |
| 711 | 696 | return len; |
| 712 | 697 | } |
| 713 | 698 | |
| 699 | +static bool printk_get_next_message(struct printk_message *pmsg, u64 seq, |
| 700 | + bool is_extended, bool may_supress); |
| 701 | + |
| 714 | 702 | /* /dev/kmsg - userspace message inject/listen interface */ |
| 715 | 703 | struct devkmsg_user { |
| 716 | 704 | atomic64_t seq; |
| 717 | 705 | struct ratelimit_state rs; |
| 718 | 706 | struct mutex lock; |
| 719 | | − char buf[CONSOLE_EXT_LOG_MAX]; |
| 720 | | − |
| 721 | | − struct printk_info info; |
| 722 | | − char text_buf[CONSOLE_EXT_LOG_MAX]; |
| 723 | | − struct printk_record record; |
| 707 | + struct printk_buffers pbufs; |
| 724 | 708 | }; |
| 725 | 709 | |
| 726 | 710 | static __printf(3, 4) __cold |
| @@ -746,7 +730,7 @@ static ssize_t devkmsg_write(struct kiocb *iocb, struct iov_iter *from) · 19 unmodified lines |
| 746 | 730 | size_t len = iov_iter_count(from); |
| 747 | 731 | ssize_t ret = len; |
| 748 | 732 | |
| 749 | | − if (!user || len > LOG_LINE_MAX) |
| 733 | + if (!user || len > PRINTKRB_RECORD_MAX) |
| 750 | 734 | return -EINVAL; |
| 751 | 735 | |
| 752 | 736 | /* Ignore when user logging is disabled. */ |
| @@ -802,8 +786,10 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, · 49 unmodified lines |
| 802 | 786 | size_t count, loff_t *ppos) |
| 803 | 787 | { |
| 804 | 788 | struct devkmsg_user *user = file->private_data; |
| 805 | | − struct printk_record *r = &user->record; |
| 806 | | − size_t len; |
| 789 | + char *outbuf = &user->pbufs.outbuf[0]; |
| 790 | + struct printk_message pmsg = { |
| 791 | + .pbufs = &user->pbufs, |
| 792 | + }; |
| 807 | 793 | ssize_t ret; |
| 808 | 794 | |
| 809 | 795 | if (!user) |
| @@ -813,7 +799,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, · 3 unmodified lines |
| 813 | 799 | if (ret) |
| 814 | 800 | return ret; |
| 815 | 801 | |
| 816 | | − if (!prb_read_valid(prb, atomic64_read(&user->seq), r)) { |
| 802 | + if (!printk_get_next_message(&pmsg, atomic64_read(&user->seq), true, false)) { |
| 817 | 803 | if (file->f_flags & O_NONBLOCK) { |
| 818 | 804 | ret = -EAGAIN; |
| 819 | 805 | goto out; |
| @@ -830,36 +816,31 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, · 10 unmodified lines |
| 830 | 816 | * This pairs with __wake_up_klogd:A. |
| 831 | 817 | */ |
| 832 | 818 | ret = wait_event_interruptible(log_wait, |
| 833 | | − prb_read_valid(prb, |
| 834 | | − atomic64_read(&user->seq), r)); /* LMM(devkmsg_read:A) */ |
| 819 | + printk_get_next_message(&pmsg, atomic64_read(&user->seq), true, |
| 820 | + false)); /* LMM(devkmsg_read:A) */ |
| 835 | 821 | if (ret) |
| 836 | 822 | goto out; |
| 837 | 823 | } |
| 838 | 824 | |
| 839 | | − if (r->info->seq != atomic64_read(&user->seq)) { |
| 825 | + if (pmsg.dropped) { |
| 840 | 826 | /* our last seen message is gone, return error and reset */ |
| 841 | | − atomic64_set(&user->seq, r->info->seq); |
| 827 | + atomic64_set(&user->seq, pmsg.seq); |
| 842 | 828 | ret = -EPIPE; |
| 843 | 829 | goto out; |
| 844 | 830 | } |
| 845 | 831 | |
| 846 | | − len = info_print_ext_header(user->buf, sizeof(user->buf), r->info); |
| 847 | | − len += msg_print_ext_body(user->buf + len, sizeof(user->buf) - len, |
| 848 | | − &r->text_buf[0], r->info->text_len, |
| 849 | | − &r->info->dev_info); |
| 850 | | − |
| 851 | | − atomic64_set(&user->seq, r->info->seq + 1); |
| 832 | + atomic64_set(&user->seq, pmsg.seq + 1); |
| 852 | 833 | |
| 853 | | − if (len > count) { |
| 834 | + if (pmsg.outbuf_len > count) { |
| 854 | 835 | ret = -EINVAL; |
| 855 | 836 | goto out; |
| 856 | 837 | } |
| 857 | 838 | |
| 858 | | − if (copy_to_user(buf, user->buf, len)) { |
| 839 | + if (copy_to_user(buf, outbuf, pmsg.outbuf_len)) { |
| 859 | 840 | ret = -EFAULT; |
| 860 | 841 | goto out; |
| 861 | 842 | } |
| 862 | | − ret = len; |
| 843 | + ret = pmsg.outbuf_len; |
| 863 | 844 | out: |
| 864 | 845 | mutex_unlock(&user->lock); |
| 865 | 846 | return ret; |
| @@ -953,9 +934,6 @@ static int devkmsg_open(struct inode *inode, struct file *file) · 87 unmodified lines |
| 953 | 934 | |
| 954 | 935 | mutex_init(&user->lock); |
| 955 | 936 | |
| 956 | | − prb_rec_init_rd(&user->record, &user->info, |
| 957 | | − &user->text_buf[0], sizeof(user->text_buf)); |
| 958 | | − |
| 959 | 937 | atomic64_set(&user->seq, prb_first_valid_seq(prb)); |
| 960 | 938 | |
| 961 | 939 | file->private_data = user; |
| @@ -1150,7 +1128,7 @@ static unsigned int __init add_to_rb(struct printk_ringbuffer *rb, · 188 unmodified lines |
| 1150 | 1128 | return prb_record_text_space(&e); |
| 1151 | 1129 | } |
| 1152 | 1130 | |
| 1153 | | −static char setup_text_buf[LOG_LINE_MAX] __initdata; |
| 1131 | +static char setup_text_buf[PRINTKRB_RECORD_MAX] __initdata; |
| 1154 | 1132 | |
| 1155 | 1133 | void __init setup_log_buf(int early) |
| 1156 | 1134 | { |
| @@ -1416,7 +1394,7 @@ static size_t record_print_text(struct printk_record *r, bool syslog, · 259 unmodified lines |
| 1416 | 1394 | size_t text_len = r->info->text_len; |
| 1417 | 1395 | size_t buf_size = r->text_buf_size; |
| 1418 | 1396 | char *text = r->text_buf; |
| 1419 | | − char prefix[PREFIX_MAX]; |
| 1397 | + char prefix[PRINTK_PREFIX_MAX]; |
| 1420 | 1398 | bool truncated = false; |
| 1421 | 1399 | size_t prefix_len; |
| 1422 | 1400 | size_t line_len; |
| @@ -1515,7 +1493,7 @@ static size_t get_record_print_text_size(struct printk_info *info, · 92 unmodified lines |
| 1515 | 1493 | unsigned int line_count, |
| 1516 | 1494 | bool syslog, bool time) |
| 1517 | 1495 | { |
| 1518 | | − char prefix[PREFIX_MAX]; |
| 1496 | + char prefix[PRINTK_PREFIX_MAX]; |
| 1519 | 1497 | size_t prefix_len; |
| 1520 | 1498 | |
| 1521 | 1499 | prefix_len = info_print_prefix(info, syslog, time, prefix); |
| @@ -1581,11 +1559,11 @@ static int syslog_print(char __user *buf, int size) · 59 unmodified lines |
| 1581 | 1559 | int len = 0; |
| 1582 | 1560 | u64 seq; |
| 1583 | 1561 | |
| 1584 | | − text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL); |
| 1562 | + text = kmalloc(PRINTK_MESSAGE_MAX, GFP_KERNEL); |
| 1585 | 1563 | if (!text) |
| 1586 | 1564 | return -ENOMEM; |
| 1587 | 1565 | |
| 1588 | | − prb_rec_init_rd(&r, &info, text, CONSOLE_LOG_MAX); |
| 1566 | + prb_rec_init_rd(&r, &info, text, PRINTK_MESSAGE_MAX); |
| 1589 | 1567 | |
| 1590 | 1568 | mutex_lock(&syslog_lock); |
| 1591 | 1569 | |
| @@ -1686,7 +1664,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear) · 94 unmodified lines |
| 1686 | 1664 | u64 seq; |
| 1687 | 1665 | bool time; |
| 1688 | 1666 | |
| 1689 | | − text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL); |
| 1667 | + text = kmalloc(PRINTK_MESSAGE_MAX, GFP_KERNEL); |
| 1690 | 1668 | if (!text) |
| 1691 | 1669 | return -ENOMEM; |
| 1692 | 1670 | |
| @@ -1698,7 +1676,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear) · 5 unmodified lines |
| 1698 | 1676 | seq = find_first_fitting_seq(latched_seq_read_nolock(&clear_seq), -1, |
| 1699 | 1677 | size, true, time); |
| 1700 | 1678 | |
| 1701 | | − prb_rec_init_rd(&r, &info, text, CONSOLE_LOG_MAX); |
| 1679 | + prb_rec_init_rd(&r, &info, text, PRINTK_MESSAGE_MAX); |
| 1702 | 1680 | |
| 1703 | 1681 | len = 0; |
| 1704 | 1682 | prb_for_each_record(seq, prb, seq, &r) { |
| @@ -2012,27 +1990,6 @@ static int console_trylock_spinning(void) · 307 unmodified lines |
| 2012 | 1990 | return 1; |
| 2013 | 1991 | } |
| 2014 | 1992 | |
| 2015 | | −/* |
| 2016 | | − * Call the specified console driver, asking it to write out the specified |
| 2017 | | − * text and length. If @dropped_text is non-NULL and any records have been |
| 2018 | | − * dropped, a dropped message will be written out first. |
| 2019 | | − */ |
| 2020 | | −static void call_console_driver(struct console *con, const char *text, size_t len, |
| 2021 | | − char *dropped_text) |
| 2022 | | −{ |
| 2023 | | − size_t dropped_len; |
| 2024 | | − |
| 2025 | | − if (con->dropped && dropped_text) { |
| 2026 | | − dropped_len = snprintf(dropped_text, DROPPED_TEXT_MAX, |
| 2027 | | − "** %lu printk messages dropped **\n", |
| 2028 | | − con->dropped); |
| 2029 | | − con->dropped = 0; |
| 2030 | | − con->write(con, dropped_text, dropped_len); |
| 2031 | | − } |
| 2032 | | − |
| 2033 | | − con->write(con, text, len); |
| 2034 | | −} |
| 2035 | | − |
| 2036 | 1993 | /* |
| 2037 | 1994 | * Recursion is tracked separately on each CPU. If NMIs are supported, an |
| 2038 | 1995 | * additional NMI context per CPU is also separately tracked. Until per-CPU |
| @@ -2243,8 +2200,8 @@ int vprintk_store(int facility, int level, · 204 unmodified lines |
| 2243 | 2200 | reserve_size = vsnprintf(&prefix_buf[0], sizeof(prefix_buf), fmt, args2) + 1; |
| 2244 | 2201 | va_end(args2); |
| 2245 | 2202 | |
| 2246 | | − if (reserve_size > LOG_LINE_MAX) |
| 2247 | | − reserve_size = LOG_LINE_MAX; |
| 2203 | + if (reserve_size > PRINTKRB_RECORD_MAX) |
| 2204 | + reserve_size = PRINTKRB_RECORD_MAX; |
| 2248 | 2205 | |
| 2249 | 2206 | /* Extract log level or control flags. */ |
| 2250 | 2207 | if (facility == 0) |
| @@ -2258,7 +2215,7 @@ int vprintk_store(int facility, int level, · 7 unmodified lines |
| 2258 | 2215 | |
| 2259 | 2216 | if (flags & LOG_CONT) { |
| 2260 | 2217 | prb_rec_init_wr(&r, reserve_size); |
| 2261 | | − if (prb_reserve_in_last(&e, prb, &r, caller_id, LOG_LINE_MAX)) { |
| 2218 | + if (prb_reserve_in_last(&e, prb, &r, caller_id, PRINTKRB_RECORD_MAX)) { |
| 2262 | 2219 | text_len = printk_sprint(&r.text_buf[r.info->text_len], reserve_size, |
| 2263 | 2220 | facility, &flags, fmt, args); |
| 2264 | 2221 | r.info->text_len += text_len; |
| @@ -2389,8 +2346,6 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre · 124 unmodified lines |
| 2389 | 2346 | |
| 2390 | 2347 | #else /* CONFIG_PRINTK */ |
| 2391 | 2348 | |
| 2392 | | −#define CONSOLE_LOG_MAX 0 |
| 2393 | | −#define DROPPED_TEXT_MAX 0 |
| 2394 | 2349 | #define printk_time false |
| 2395 | 2350 | |
| 2396 | 2351 | #define prb_read_valid(rb, seq, r) false |
| @@ -2414,10 +2369,6 @@ static ssize_t msg_print_ext_body(char *buf, size_t size, · 17 unmodified lines |
| 2414 | 2369 | struct dev_printk_info *dev_info) { return 0; } |
| 2415 | 2370 | static void console_lock_spinning_enable(void) { } |
| 2416 | 2371 | static int console_lock_spinning_disable_and_check(int cookie) { return 0; } |
| 2417 | | −static void call_console_driver(struct console *con, const char *text, size_t len, |
| 2418 | | − char *dropped_text) |
| 2419 | | −{ |
| 2420 | | −} |
| 2421 | 2372 | static bool suppress_message_printing(int level) { return false; } |
| 2422 | 2373 | static bool pr_flush(int timeout_ms, bool reset_on_progress) { return true; } |
| 2423 | 2374 | static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) { return true; } |
| @@ -2744,16 +2695,136 @@ static void __console_unlock(void) · 320 unmodified lines |
| 2744 | 2695 | } |
| 2745 | 2696 | |
| 2746 | 2697 | /* |
| 2747 | | − * Print one record for the given console. The record printed is whatever |
| 2748 | | − * record is the next available record for the given console. |
| 2698 | + * Prepend the message in @pmsg->pbufs->outbuf with a "dropped message". This |
| 2699 | + * is achieved by shifting the existing message over and inserting the dropped |
| 2700 | + * message. |
| 2701 | + * |
| 2702 | + * @pmsg is the printk message to prepend. |
| 2749 | 2703 | * |
| 2750 | | − * @text is a buffer of size CONSOLE_LOG_MAX. |
| 2704 | + * @dropped is the dropped count to report in the dropped message. |
| 2751 | 2705 | * |
| 2752 | | − * If extended messages should be printed, @ext_text is a buffer of size |
| 2753 | | − * CONSOLE_EXT_LOG_MAX. Otherwise @ext_text must be NULL. |
| 2706 | + * If the message text in @pmsg->pbufs->outbuf does not have enough space for |
| 2707 | + * the dropped message, the message text will be sufficiently truncated. |
| 2754 | 2708 | * |
| 2755 | | − * If dropped messages should be printed, @dropped_text is a buffer of size |
| 2756 | | − * DROPPED_TEXT_MAX. Otherwise @dropped_text must be NULL. |
| 2709 | + * If @pmsg->pbufs->outbuf is modified, @pmsg->outbuf_len is updated. |
| 2710 | + */ |
| 2711 | +#ifdef CONFIG_PRINTK |
| 2712 | +static void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped) |
| 2713 | +{ |
| 2714 | + struct printk_buffers *pbufs = pmsg->pbufs; |
| 2715 | + const size_t scratchbuf_sz = sizeof(pbufs->scratchbuf); |
| 2716 | + const size_t outbuf_sz = sizeof(pbufs->outbuf); |
| 2717 | + char *scratchbuf = &pbufs->scratchbuf[0]; |
| 2718 | + char *outbuf = &pbufs->outbuf[0]; |
| 2719 | + size_t len; |
| 2720 | + |
| 2721 | + len = scnprintf(scratchbuf, scratchbuf_sz, |
| 2722 | + "** %lu printk messages dropped **\n", dropped); |
| 2723 | + |
| 2724 | + /* |
| 2725 | + * Make sure outbuf is sufficiently large before prepending. |
| 2726 | + * Keep at least the prefix when the message must be truncated. |
| 2727 | + * It is a rather theoretical problem when someone tries to |
| 2728 | + * use a minimalist buffer. |
| 2729 | + */ |
| 2730 | + if (WARN_ON_ONCE(len + PRINTK_PREFIX_MAX >= outbuf_sz)) |
| 2731 | + return; |
| 2732 | + |
| 2733 | + if (pmsg->outbuf_len + len >= outbuf_sz) { |
| 2734 | + /* Truncate the message, but keep it terminated. */ |
| 2735 | + pmsg->outbuf_len = outbuf_sz - (len + 1); |
| 2736 | + outbuf[pmsg->outbuf_len] = 0; |
| 2737 | + } |
| 2738 | + |
| 2739 | + memmove(outbuf + len, outbuf, pmsg->outbuf_len + 1); |
| 2740 | + memcpy(outbuf, scratchbuf, len); |
| 2741 | + pmsg->outbuf_len += len; |
| 2742 | +} |
| 2743 | +#else |
| 2744 | +#define console_prepend_dropped(pmsg, dropped) |
| 2745 | +#endif /* CONFIG_PRINTK */ |
| 2746 | + |
| 2747 | +/* |
| 2748 | + * Read and format the specified record (or a later record if the specified |
| 2749 | + * record is not available). |
| 2750 | + * |
| 2751 | + * @pmsg will contain the formatted result. @pmsg->pbufs must point to a |
| 2752 | + * struct printk_buffers. |
| 2753 | + * |
| 2754 | + * @seq is the record to read and format. If it is not available, the next |
| 2755 | + * valid record is read. |
| 2756 | + * |
| 2757 | + * @is_extended specifies if the message should be formatted for extended |
| 2758 | + * console output. |
| 2759 | + * |
| 2760 | + * @may_supress specifies if records may be skipped based on loglevel. |
| 2761 | + * |
| 2762 | + * Returns false if no record is available. Otherwise true and all fields |
| 2763 | + * of @pmsg are valid. (See the documentation of struct printk_message |
| 2764 | + * for information about the @pmsg fields.) |
| 2765 | + */ |
| 2766 | +static bool printk_get_next_message(struct printk_message *pmsg, u64 seq, |
| 2767 | + bool is_extended, bool may_suppress) |
| 2768 | +{ |
| 2769 | + static int panic_console_dropped; |
| 2770 | + |
| 2771 | + struct printk_buffers *pbufs = pmsg->pbufs; |
| 2772 | + const size_t scratchbuf_sz = sizeof(pbufs->scratchbuf); |
| 2773 | + const size_t outbuf_sz = sizeof(pbufs->outbuf); |
| 2774 | + char *scratchbuf = &pbufs->scratchbuf[0]; |
| 2775 | + char *outbuf = &pbufs->outbuf[0]; |
| 2776 | + struct printk_info info; |
| 2777 | + struct printk_record r; |
| 2778 | + size_t len = 0; |
| 2779 | + |
| 2780 | + /* |
| 2781 | + * Formatting extended messages requires a separate buffer, so use the |
| 2782 | + * scratch buffer to read in the ringbuffer text. |
| 2783 | + * |
| 2784 | + * Formatting normal messages is done in-place, so read the ringbuffer |
| 2785 | + * text directly into the output buffer. |
| 2786 | + */ |
| 2787 | + if (is_extended) |
| 2788 | + prb_rec_init_rd(&r, &info, scratchbuf, scratchbuf_sz); |
| 2789 | + else |
| 2790 | + prb_rec_init_rd(&r, &info, outbuf, outbuf_sz); |
| 2791 | + |
| 2792 | + if (!prb_read_valid(prb, seq, &r)) |
| 2793 | + return false; |
| 2794 | + |
| 2795 | + pmsg->seq = r.info->seq; |
| 2796 | + pmsg->dropped = r.info->seq - seq; |
| 2797 | + |
| 2798 | + /* |
| 2799 | + * Check for dropped messages in panic here so that printk |
| 2800 | + * suppression can occur as early as possible if necessary. |
| 2801 | + */ |
| 2802 | + if (pmsg->dropped && |
| 2803 | + panic_in_progress() && |
| 2804 | + panic_console_dropped++ > 10) { |
| 2805 | + suppress_panic_printk = 1; |
| 2806 | + pr_warn_once("Too many dropped messages. Suppress messages on non-panic CPUs to prevent livelock.\n"); |
| 2807 | + } |
| 2808 | + |
| 2809 | + /* Skip record that has level above the console loglevel. */ |
| 2810 | + if (may_suppress && suppress_message_printing(r.info->level)) |
| 2811 | + goto out; |
| 2812 | + |
| 2813 | + if (is_extended) { |
| 2814 | + len = info_print_ext_header(outbuf, outbuf_sz, r.info); |
| 2815 | + len += msg_print_ext_body(outbuf + len, outbuf_sz - len, |
| 2816 | + &r.text_buf[0], r.info->text_len, &r.info->dev_info); |
| 2817 | + } else { |
| 2818 | + len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time); |
| 2819 | + } |
| 2820 | +out: |
| 2821 | + pmsg->outbuf_len = len; |
| 2822 | + return true; |
| 2823 | +} |
| 2824 | + |
| 2825 | +/* |
| 2826 | + * Print one record for the given console. The record printed is whatever |
| 2827 | + * record is the next available record for the given console. |
| 2757 | 2828 | * |
| 2758 | 2829 | * @handover will be set to true if a printk waiter has taken over the |
| 2759 | 2830 | * console_lock, in which case the caller is no longer holding both the |
| @@ -2766,46 +2837,33 @@ static void __console_unlock(void) · 6 unmodified lines |
| 2766 | 2837 | * |
| 2767 | 2838 | * Requires the console_lock and the SRCU read lock. |
| 2768 | 2839 | */ |
| 2769 | | −static bool console_emit_next_record(struct console *con, char *text, char *ext_text, |
| 2770 | | − char *dropped_text, bool *handover, int cookie) |
| 2840 | +static bool console_emit_next_record(struct console *con, bool *handover, int cookie) |
| 2771 | 2841 | { |
| 2772 | | − static int panic_console_dropped; |
| 2773 | | − struct printk_info info; |
| 2774 | | − struct printk_record r; |
| 2775 | | − unsigned long flags; |
| 2776 | | − char *write_text; |
| 2777 | | − size_t len; |
| 2842 | + static struct printk_buffers pbufs; |
| 2778 | 2843 | |
| 2779 | | − prb_rec_init_rd(&r, &info, text, CONSOLE_LOG_MAX); |
| 2844 | + bool is_extended = console_srcu_read_flags(con) & CON_EXTENDED; |
| 2845 | + char *outbuf = &pbufs.outbuf[0]; |
| 2846 | + struct printk_message pmsg = { |
| 2847 | + .pbufs = &pbufs, |
| 2848 | + }; |
| 2849 | + unsigned long flags; |
| 2780 | 2850 | |
| 2781 | 2851 | *handover = false; |
| 2782 | 2852 | |
| 2783 | | − if (!prb_read_valid(prb, con->seq, &r)) |
| 2853 | + if (!printk_get_next_message(&pmsg, con->seq, is_extended, true)) |
| 2784 | 2854 | return false; |
| 2785 | 2855 | |
| 2786 | | − if (con->seq != r.info->seq) { |
| 2787 | | − con->dropped += r.info->seq - con->seq; |
| 2788 | | − con->seq = r.info->seq; |
| 2789 | | − if (panic_in_progress() && panic_console_dropped++ > 10) { |
| 2790 | | − suppress_panic_printk = 1; |
| 2791 | | − pr_warn_once("Too many dropped messages. Suppress messages on non-panic CPUs to prevent livelock.\n"); |
| 2792 | | − } |
| 2793 | | − } |
| 2856 | + con->dropped += pmsg.dropped; |
| 2794 | 2857 | |
| 2795 | | − /* Skip record that has level above the console loglevel. */ |
| 2796 | | − if (suppress_message_printing(r.info->level)) { |
| 2797 | | − con->seq++; |
| 2858 | + /* Skip messages of formatted length 0. */ |
| 2859 | + if (pmsg.outbuf_len == 0) { |
| 2860 | + con->seq = pmsg.seq + 1; |
| 2798 | 2861 | goto skip; |
| 2799 | 2862 | } |
| 2800 | 2863 | |
| 2801 | | − if (ext_text) { |
| 2802 | | − write_text = ext_text; |
| 2803 | | − len = info_print_ext_header(ext_text, CONSOLE_EXT_LOG_MAX, r.info); |
| 2804 | | − len += msg_print_ext_body(ext_text + len, CONSOLE_EXT_LOG_MAX - len, |
| 2805 | | − &r.text_buf[0], r.info->text_len, &r.info->dev_info); |
| 2806 | | − } else { |
| 2807 | | − write_text = text; |
| 2808 | | − len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time); |
| 2864 | + if (con->dropped && !is_extended) { |
| 2865 | + console_prepend_dropped(&pmsg, con->dropped); |
| 2866 | + con->dropped = 0; |
| 2809 | 2867 | } |
| 2810 | 2868 | |
| 2811 | 2869 | /* |
| @@ -2821,11 +2879,15 @@ static bool console_emit_next_record(struct console *con, char *text, char *ext_ · 9 unmodified lines |
| 2821 | 2879 | printk_safe_enter_irqsave(flags); |
| 2822 | 2880 | console_lock_spinning_enable(); |
| 2823 | 2881 | |
| 2824 | | − stop_critical_timings(); /* don't trace print latency */ |
| 2825 | | − call_console_driver(con, write_text, len, dropped_text); |
| 2882 | + /* Do not trace print latency. */ |
| 2883 | + stop_critical_timings(); |
| 2884 | + |
| 2885 | + /* Write everything out to the hardware. */ |
| 2886 | + con->write(con, outbuf, pmsg.outbuf_len); |
| 2887 | + |
| 2826 | 2888 | start_critical_timings(); |
| 2827 | 2889 | |
| 2828 | | − con->seq++; |
| 2890 | + con->seq = pmsg.seq + 1; |
| 2829 | 2891 | |
| 2830 | 2892 | *handover = console_lock_spinning_disable_and_check(cookie); |
| 2831 | 2893 | printk_safe_exit_irqrestore(flags); |
| @@ -2858,9 +2920,6 @@ skip: · 26 unmodified lines |
| 2858 | 2920 | */ |
| 2859 | 2921 | static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handover) |
| 2860 | 2922 | { |
| 2861 | | − static char dropped_text[DROPPED_TEXT_MAX]; |
| 2862 | | − static char ext_text[CONSOLE_EXT_LOG_MAX]; |
| 2863 | | − static char text[CONSOLE_LOG_MAX]; |
| 2864 | 2923 | bool any_usable = false; |
| 2865 | 2924 | struct console *con; |
| 2866 | 2925 | bool any_progress; |
| @@ -2880,16 +2939,7 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove · 13 unmodified lines |
| 2880 | 2939 | continue; |
| 2881 | 2940 | any_usable = true; |
| 2882 | 2941 | |
| 2883 | | − if (console_srcu_read_flags(con) & CON_EXTENDED) { |
| 2884 | | − /* Extended consoles do not print "dropped messages". */ |
| 2885 | | − progress = console_emit_next_record(con, &text[0], |
| 2886 | | − &ext_text[0], NULL, |
| 2887 | | − handover, cookie); |
| 2888 | | − } else { |
| 2889 | | − progress = console_emit_next_record(con, &text[0], |
| 2890 | | − NULL, &dropped_text[0], |
| 2891 | | − handover, cookie); |
| 2892 | | − } |
| 2942 | + progress = console_emit_next_record(con, handover, cookie); |
| 2893 | 2943 | |
| 2894 | 2944 | /* |
| 2895 | 2945 | * If a handover has occurred, the SRCU read lock |