16
16
* 01Mar01 Andrew Morton
17
17
*/
18
18
19
+ #define pr_fmt (fmt ) KBUILD_MODNAME ": " fmt
20
+
19
21
#include <linux/kernel.h>
20
22
#include <linux/mm.h>
21
23
#include <linux/tty.h>
@@ -192,16 +194,7 @@ int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write,
192
194
return 0 ;
193
195
}
194
196
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. */
205
198
static int nr_ext_console_drivers ;
206
199
207
200
/*
@@ -423,6 +416,7 @@ static u32 log_next_idx;
423
416
/* the next printk record to write to the console */
424
417
static u64 console_seq ;
425
418
static u32 console_idx ;
419
+ static u64 exclusive_console_stop_seq ;
426
420
427
421
/* the next printk record to read after the last 'clear' command */
428
422
static u64 clear_seq ;
@@ -437,6 +431,7 @@ static u32 clear_idx;
437
431
/* record buffer */
438
432
#define LOG_ALIGN __alignof__(struct printk_log)
439
433
#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
434
+ #define LOG_BUF_LEN_MAX (u32)(1 << 31)
440
435
static char __log_buf [__LOG_BUF_LEN ] __aligned (LOG_ALIGN );
441
436
static char * log_buf = __log_buf ;
442
437
static u32 log_buf_len = __LOG_BUF_LEN ;
@@ -1037,18 +1032,28 @@ void log_buf_vmcoreinfo_setup(void)
1037
1032
static unsigned long __initdata new_log_buf_len ;
1038
1033
1039
1034
/* 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 )
1041
1036
{
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
+
1042
1042
if (size )
1043
1043
size = roundup_pow_of_two (size );
1044
1044
if (size > log_buf_len )
1045
- new_log_buf_len = size ;
1045
+ new_log_buf_len = ( unsigned long ) size ;
1046
1046
}
1047
1047
1048
1048
/* save requested log_buf_len since it's too early to process it */
1049
1049
static int __init log_buf_len_setup (char * str )
1050
1050
{
1051
- unsigned size = memparse (str , & str );
1051
+ u64 size ;
1052
+
1053
+ if (!str )
1054
+ return - EINVAL ;
1055
+
1056
+ size = memparse (str , & str );
1052
1057
1053
1058
log_buf_len_update (size );
1054
1059
@@ -1093,7 +1098,7 @@ void __init setup_log_buf(int early)
1093
1098
{
1094
1099
unsigned long flags ;
1095
1100
char * new_log_buf ;
1096
- int free ;
1101
+ unsigned int free ;
1097
1102
1098
1103
if (log_buf != __log_buf )
1099
1104
return ;
@@ -1113,7 +1118,7 @@ void __init setup_log_buf(int early)
1113
1118
}
1114
1119
1115
1120
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" ,
1117
1122
new_log_buf_len );
1118
1123
return ;
1119
1124
}
@@ -1126,8 +1131,8 @@ void __init setup_log_buf(int early)
1126
1131
memcpy (log_buf , __log_buf , __LOG_BUF_LEN );
1127
1132
logbuf_unlock_irqrestore (flags );
1128
1133
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" ,
1131
1136
free , (free * 100 ) / __LOG_BUF_LEN );
1132
1137
}
1133
1138
@@ -1767,12 +1772,8 @@ static void cont_flush(void)
1767
1772
1768
1773
static bool cont_add (int facility , int level , enum log_flags flags , const char * text , size_t len )
1769
1774
{
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 )) {
1776
1777
cont_flush ();
1777
1778
return false;
1778
1779
}
@@ -1795,9 +1796,6 @@ static bool cont_add(int facility, int level, enum log_flags flags, const char *
1795
1796
cont_flush ();
1796
1797
}
1797
1798
1798
- if (cont .len > (sizeof (cont .buf ) * 80 ) / 100 )
1799
- cont_flush ();
1800
-
1801
1799
return true;
1802
1800
}
1803
1801
@@ -1889,8 +1887,9 @@ asmlinkage int vprintk_emit(int facility, int level,
1889
1887
const char * fmt , va_list args )
1890
1888
{
1891
1889
int printed_len ;
1892
- bool in_sched = false;
1890
+ bool in_sched = false, pending_output ;
1893
1891
unsigned long flags ;
1892
+ u64 curr_log_seq ;
1894
1893
1895
1894
if (level == LOGLEVEL_SCHED ) {
1896
1895
level = LOGLEVEL_DEFAULT ;
@@ -1902,11 +1901,13 @@ asmlinkage int vprintk_emit(int facility, int level,
1902
1901
1903
1902
/* This stops the holder of console_sem just where we want him */
1904
1903
logbuf_lock_irqsave (flags );
1904
+ curr_log_seq = log_next_seq ;
1905
1905
printed_len = vprintk_store (facility , level , dict , dictlen , fmt , args );
1906
+ pending_output = (curr_log_seq != log_next_seq );
1906
1907
logbuf_unlock_irqrestore (flags );
1907
1908
1908
1909
/* If called from the scheduler, we can not call up(). */
1909
- if (!in_sched ) {
1910
+ if (!in_sched && pending_output ) {
1910
1911
/*
1911
1912
* Disable preemption to avoid being preempted while holding
1912
1913
* console_sem which would prevent anyone from printing to
@@ -1923,7 +1924,8 @@ asmlinkage int vprintk_emit(int facility, int level,
1923
1924
preempt_enable ();
1924
1925
}
1925
1926
1926
- wake_up_klogd ();
1927
+ if (pending_output )
1928
+ wake_up_klogd ();
1927
1929
return printed_len ;
1928
1930
}
1929
1931
EXPORT_SYMBOL (vprintk_emit );
@@ -2009,6 +2011,7 @@ static u64 syslog_seq;
2009
2011
static u32 syslog_idx ;
2010
2012
static u64 console_seq ;
2011
2013
static u32 console_idx ;
2014
+ static u64 exclusive_console_stop_seq ;
2012
2015
static u64 log_first_seq ;
2013
2016
static u32 log_first_idx ;
2014
2017
static u64 log_next_seq ;
@@ -2351,8 +2354,9 @@ void console_unlock(void)
2351
2354
printk_safe_enter_irqsave (flags );
2352
2355
raw_spin_lock (& logbuf_lock );
2353
2356
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 );
2356
2360
2357
2361
/* messages are gone, move to first one */
2358
2362
console_seq = log_first_seq ;
@@ -2376,6 +2380,12 @@ void console_unlock(void)
2376
2380
goto skip ;
2377
2381
}
2378
2382
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
+
2379
2389
len += msg_print_text (msg ,
2380
2390
console_msg_format & MSG_FORMAT_SYSLOG ,
2381
2391
text + len ,
@@ -2418,10 +2428,6 @@ void console_unlock(void)
2418
2428
2419
2429
console_locked = 0 ;
2420
2430
2421
- /* Release the exclusive_console once it is used */
2422
- if (unlikely (exclusive_console ))
2423
- exclusive_console = NULL ;
2424
-
2425
2431
raw_spin_unlock (& logbuf_lock );
2426
2432
2427
2433
up_console_sem ();
@@ -2688,8 +2694,7 @@ void register_console(struct console *newcon)
2688
2694
}
2689
2695
2690
2696
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 ++ ;
2693
2698
2694
2699
if (newcon -> flags & CON_PRINTBUFFER ) {
2695
2700
/*
@@ -2699,13 +2704,18 @@ void register_console(struct console *newcon)
2699
2704
logbuf_lock_irqsave (flags );
2700
2705
console_seq = syslog_seq ;
2701
2706
console_idx = syslog_idx ;
2702
- logbuf_unlock_irqrestore (flags );
2703
2707
/*
2704
2708
* We're about to replay the log buffer. Only do this to the
2705
2709
* just-registered console to avoid excessive message spam to
2706
2710
* 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.
2707
2715
*/
2708
2716
exclusive_console = newcon ;
2717
+ exclusive_console_stop_seq = console_seq ;
2718
+ logbuf_unlock_irqrestore (flags );
2709
2719
}
2710
2720
console_unlock ();
2711
2721
console_sysfs_notify ();
0 commit comments