Skip to content

Commit a67eefa

Browse files
committed
Merge tag 'printk-for-4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk
Pull printk updates from Petr Mladek: - Fix two more locations where printf formatting leaked pointers - Better log_buf_len parameter handling - Add prefix to messages from printk code - Do not miss messages on other consoles when the log is replayed on a new one - Reduce race between console registration and panic() when the log might get replayed on all consoles - Some cont buffer code clean up - Call console only when there is something to do (log vs cont buffer) * tag 'printk-for-4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk: lib/vsprintf: Hash printed address for netdev bits fallback lib/vsprintf: Hash legacy clock addresses lib/vsprintf: Prepare for more general use of ptr_to_id() lib/vsprintf: Make ptr argument conts in ptr_to_id() printk: fix integer overflow in setup_log_buf() printk: do not preliminary split up cont buffer printk: lock/unlock console only for new logbuf entries printk: keep kernel cont support always enabled printk: Give error on attempt to set log buffer length to over 2G printk: Add KBUILD_MODNAME and remove a redundant print prefix printk: Correct wrong casting printk: Fix panic caused by passing log_buf_len to command line printk: CON_PRINTBUFFER console registration is a bit racy printk: Do not miss new messages when replaying the log
2 parents 62606c2 + 54edeb0 commit a67eefa

File tree

3 files changed

+158
-149
lines changed

3 files changed

+158
-149
lines changed

Documentation/core-api/printk-formats.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -420,9 +420,8 @@ struct clk
420420
%pC pll1
421421
%pCn pll1
422422

423-
For printing struct clk structures. %pC and %pCn print the name
424-
(Common Clock Framework) or address (legacy clock framework) of the
425-
structure.
423+
For printing struct clk structures. %pC and %pCn print the name of the clock
424+
(Common Clock Framework) or a unique 32-bit ID (legacy clock framework).
426425

427426
Passed by reference.
428427

kernel/printk/printk.c

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
* 01Mar01 Andrew Morton
1717
*/
1818

19+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20+
1921
#include <linux/kernel.h>
2022
#include <linux/mm.h>
2123
#include <linux/tty.h>
@@ -192,16 +194,7 @@ int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write,
192194
return 0;
193195
}
194196

195-
/*
196-
* Number of registered extended console drivers.
197-
*
198-
* If extended consoles are present, in-kernel cont reassembly is disabled
199-
* and each fragment is stored as a separate log entry with proper
200-
* continuation flag so that every emitted message has full metadata. This
201-
* doesn't change the result for regular consoles or /proc/kmsg. For
202-
* /dev/kmsg, as long as the reader concatenates messages according to
203-
* consecutive continuation flags, the end result should be the same too.
204-
*/
197+
/* Number of registered extended console drivers. */
205198
static int nr_ext_console_drivers;
206199

207200
/*
@@ -423,6 +416,7 @@ static u32 log_next_idx;
423416
/* the next printk record to write to the console */
424417
static u64 console_seq;
425418
static u32 console_idx;
419+
static u64 exclusive_console_stop_seq;
426420

427421
/* the next printk record to read after the last 'clear' command */
428422
static u64 clear_seq;
@@ -437,6 +431,7 @@ static u32 clear_idx;
437431
/* record buffer */
438432
#define LOG_ALIGN __alignof__(struct printk_log)
439433
#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
434+
#define LOG_BUF_LEN_MAX (u32)(1 << 31)
440435
static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN);
441436
static char *log_buf = __log_buf;
442437
static u32 log_buf_len = __LOG_BUF_LEN;
@@ -1037,18 +1032,28 @@ void log_buf_vmcoreinfo_setup(void)
10371032
static unsigned long __initdata new_log_buf_len;
10381033

10391034
/* we practice scaling the ring buffer by powers of 2 */
1040-
static void __init log_buf_len_update(unsigned size)
1035+
static void __init log_buf_len_update(u64 size)
10411036
{
1037+
if (size > (u64)LOG_BUF_LEN_MAX) {
1038+
size = (u64)LOG_BUF_LEN_MAX;
1039+
pr_err("log_buf over 2G is not supported.\n");
1040+
}
1041+
10421042
if (size)
10431043
size = roundup_pow_of_two(size);
10441044
if (size > log_buf_len)
1045-
new_log_buf_len = size;
1045+
new_log_buf_len = (unsigned long)size;
10461046
}
10471047

10481048
/* save requested log_buf_len since it's too early to process it */
10491049
static int __init log_buf_len_setup(char *str)
10501050
{
1051-
unsigned size = memparse(str, &str);
1051+
u64 size;
1052+
1053+
if (!str)
1054+
return -EINVAL;
1055+
1056+
size = memparse(str, &str);
10521057

10531058
log_buf_len_update(size);
10541059

@@ -1093,7 +1098,7 @@ void __init setup_log_buf(int early)
10931098
{
10941099
unsigned long flags;
10951100
char *new_log_buf;
1096-
int free;
1101+
unsigned int free;
10971102

10981103
if (log_buf != __log_buf)
10991104
return;
@@ -1113,7 +1118,7 @@ void __init setup_log_buf(int early)
11131118
}
11141119

11151120
if (unlikely(!new_log_buf)) {
1116-
pr_err("log_buf_len: %ld bytes not available\n",
1121+
pr_err("log_buf_len: %lu bytes not available\n",
11171122
new_log_buf_len);
11181123
return;
11191124
}
@@ -1126,8 +1131,8 @@ void __init setup_log_buf(int early)
11261131
memcpy(log_buf, __log_buf, __LOG_BUF_LEN);
11271132
logbuf_unlock_irqrestore(flags);
11281133

1129-
pr_info("log_buf_len: %d bytes\n", log_buf_len);
1130-
pr_info("early log buf free: %d(%d%%)\n",
1134+
pr_info("log_buf_len: %u bytes\n", log_buf_len);
1135+
pr_info("early log buf free: %u(%u%%)\n",
11311136
free, (free * 100) / __LOG_BUF_LEN);
11321137
}
11331138

@@ -1767,12 +1772,8 @@ static void cont_flush(void)
17671772

17681773
static bool cont_add(int facility, int level, enum log_flags flags, const char *text, size_t len)
17691774
{
1770-
/*
1771-
* If ext consoles are present, flush and skip in-kernel
1772-
* continuation. See nr_ext_console_drivers definition. Also, if
1773-
* the line gets too long, split it up in separate records.
1774-
*/
1775-
if (nr_ext_console_drivers || cont.len + len > sizeof(cont.buf)) {
1775+
/* If the line gets too long, split it up in separate records. */
1776+
if (cont.len + len > sizeof(cont.buf)) {
17761777
cont_flush();
17771778
return false;
17781779
}
@@ -1795,9 +1796,6 @@ static bool cont_add(int facility, int level, enum log_flags flags, const char *
17951796
cont_flush();
17961797
}
17971798

1798-
if (cont.len > (sizeof(cont.buf) * 80) / 100)
1799-
cont_flush();
1800-
18011799
return true;
18021800
}
18031801

@@ -1889,8 +1887,9 @@ asmlinkage int vprintk_emit(int facility, int level,
18891887
const char *fmt, va_list args)
18901888
{
18911889
int printed_len;
1892-
bool in_sched = false;
1890+
bool in_sched = false, pending_output;
18931891
unsigned long flags;
1892+
u64 curr_log_seq;
18941893

18951894
if (level == LOGLEVEL_SCHED) {
18961895
level = LOGLEVEL_DEFAULT;
@@ -1902,11 +1901,13 @@ asmlinkage int vprintk_emit(int facility, int level,
19021901

19031902
/* This stops the holder of console_sem just where we want him */
19041903
logbuf_lock_irqsave(flags);
1904+
curr_log_seq = log_next_seq;
19051905
printed_len = vprintk_store(facility, level, dict, dictlen, fmt, args);
1906+
pending_output = (curr_log_seq != log_next_seq);
19061907
logbuf_unlock_irqrestore(flags);
19071908

19081909
/* If called from the scheduler, we can not call up(). */
1909-
if (!in_sched) {
1910+
if (!in_sched && pending_output) {
19101911
/*
19111912
* Disable preemption to avoid being preempted while holding
19121913
* console_sem which would prevent anyone from printing to
@@ -1923,7 +1924,8 @@ asmlinkage int vprintk_emit(int facility, int level,
19231924
preempt_enable();
19241925
}
19251926

1926-
wake_up_klogd();
1927+
if (pending_output)
1928+
wake_up_klogd();
19271929
return printed_len;
19281930
}
19291931
EXPORT_SYMBOL(vprintk_emit);
@@ -2009,6 +2011,7 @@ static u64 syslog_seq;
20092011
static u32 syslog_idx;
20102012
static u64 console_seq;
20112013
static u32 console_idx;
2014+
static u64 exclusive_console_stop_seq;
20122015
static u64 log_first_seq;
20132016
static u32 log_first_idx;
20142017
static u64 log_next_seq;
@@ -2351,8 +2354,9 @@ void console_unlock(void)
23512354
printk_safe_enter_irqsave(flags);
23522355
raw_spin_lock(&logbuf_lock);
23532356
if (console_seq < log_first_seq) {
2354-
len = sprintf(text, "** %u printk messages dropped **\n",
2355-
(unsigned)(log_first_seq - console_seq));
2357+
len = sprintf(text,
2358+
"** %llu printk messages dropped **\n",
2359+
log_first_seq - console_seq);
23562360

23572361
/* messages are gone, move to first one */
23582362
console_seq = log_first_seq;
@@ -2376,6 +2380,12 @@ void console_unlock(void)
23762380
goto skip;
23772381
}
23782382

2383+
/* Output to all consoles once old messages replayed. */
2384+
if (unlikely(exclusive_console &&
2385+
console_seq >= exclusive_console_stop_seq)) {
2386+
exclusive_console = NULL;
2387+
}
2388+
23792389
len += msg_print_text(msg,
23802390
console_msg_format & MSG_FORMAT_SYSLOG,
23812391
text + len,
@@ -2418,10 +2428,6 @@ void console_unlock(void)
24182428

24192429
console_locked = 0;
24202430

2421-
/* Release the exclusive_console once it is used */
2422-
if (unlikely(exclusive_console))
2423-
exclusive_console = NULL;
2424-
24252431
raw_spin_unlock(&logbuf_lock);
24262432

24272433
up_console_sem();
@@ -2688,8 +2694,7 @@ void register_console(struct console *newcon)
26882694
}
26892695

26902696
if (newcon->flags & CON_EXTENDED)
2691-
if (!nr_ext_console_drivers++)
2692-
pr_info("printk: continuation disabled due to ext consoles, expect more fragments in /dev/kmsg\n");
2697+
nr_ext_console_drivers++;
26932698

26942699
if (newcon->flags & CON_PRINTBUFFER) {
26952700
/*
@@ -2699,13 +2704,18 @@ void register_console(struct console *newcon)
26992704
logbuf_lock_irqsave(flags);
27002705
console_seq = syslog_seq;
27012706
console_idx = syslog_idx;
2702-
logbuf_unlock_irqrestore(flags);
27032707
/*
27042708
* We're about to replay the log buffer. Only do this to the
27052709
* just-registered console to avoid excessive message spam to
27062710
* the already-registered consoles.
2711+
*
2712+
* Set exclusive_console with disabled interrupts to reduce
2713+
* race window with eventual console_flush_on_panic() that
2714+
* ignores console_lock.
27072715
*/
27082716
exclusive_console = newcon;
2717+
exclusive_console_stop_seq = console_seq;
2718+
logbuf_unlock_irqrestore(flags);
27092719
}
27102720
console_unlock();
27112721
console_sysfs_notify();

0 commit comments

Comments
 (0)