aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/printk.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/printk.c')
-rw-r--r--kernel/printk.c328
1 files changed, 227 insertions, 101 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index 53d9a9ec88e6..da8ca817eae3 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -53,7 +53,7 @@ void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
53#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT) 53#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
54 54
55/* printk's without a loglevel use this.. */ 55/* printk's without a loglevel use this.. */
56#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */ 56#define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL
57 57
58/* We show everything that is MORE important than this.. */ 58/* We show everything that is MORE important than this.. */
59#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */ 59#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
@@ -97,7 +97,7 @@ static int console_locked, console_suspended;
97/* 97/*
98 * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars 98 * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars
99 * It is also used in interesting ways to provide interlocking in 99 * It is also used in interesting ways to provide interlocking in
100 * release_console_sem(). 100 * console_unlock();.
101 */ 101 */
102static DEFINE_SPINLOCK(logbuf_lock); 102static DEFINE_SPINLOCK(logbuf_lock);
103 103
@@ -113,6 +113,11 @@ static unsigned con_start; /* Index into log_buf: next char to be sent to consol
113static unsigned log_end; /* Index into log_buf: most-recently-written-char + 1 */ 113static unsigned log_end; /* Index into log_buf: most-recently-written-char + 1 */
114 114
115/* 115/*
116 * If exclusive_console is non-NULL then only this console is to be printed to.
117 */
118static struct console *exclusive_console;
119
120/*
116 * Array of consoles built from command line options (console=) 121 * Array of consoles built from command line options (console=)
117 */ 122 */
118struct console_cmdline 123struct console_cmdline
@@ -262,25 +267,47 @@ int dmesg_restrict = 1;
262int dmesg_restrict; 267int dmesg_restrict;
263#endif 268#endif
264 269
270static int syslog_action_restricted(int type)
271{
272 if (dmesg_restrict)
273 return 1;
274 /* Unless restricted, we allow "read all" and "get buffer size" for everybody */
275 return type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER;
276}
277
278static int check_syslog_permissions(int type, bool from_file)
279{
280 /*
281 * If this is from /proc/kmsg and we've already opened it, then we've
282 * already done the capabilities checks at open time.
283 */
284 if (from_file && type != SYSLOG_ACTION_OPEN)
285 return 0;
286
287 if (syslog_action_restricted(type)) {
288 if (capable(CAP_SYSLOG))
289 return 0;
290 /* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */
291 if (capable(CAP_SYS_ADMIN)) {
292 WARN_ONCE(1, "Attempt to access syslog with CAP_SYS_ADMIN "
293 "but no CAP_SYSLOG (deprecated).\n");
294 return 0;
295 }
296 return -EPERM;
297 }
298 return 0;
299}
300
265int do_syslog(int type, char __user *buf, int len, bool from_file) 301int do_syslog(int type, char __user *buf, int len, bool from_file)
266{ 302{
267 unsigned i, j, limit, count; 303 unsigned i, j, limit, count;
268 int do_clear = 0; 304 int do_clear = 0;
269 char c; 305 char c;
270 int error = 0; 306 int error;
271 307
272 /* 308 error = check_syslog_permissions(type, from_file);
273 * If this is from /proc/kmsg we only do the capabilities checks 309 if (error)
274 * at open time. 310 goto out;
275 */
276 if (type == SYSLOG_ACTION_OPEN || !from_file) {
277 if (dmesg_restrict && !capable(CAP_SYSLOG))
278 goto warn; /* switch to return -EPERM after 2.6.39 */
279 if ((type != SYSLOG_ACTION_READ_ALL &&
280 type != SYSLOG_ACTION_SIZE_BUFFER) &&
281 !capable(CAP_SYSLOG))
282 goto warn; /* switch to return -EPERM after 2.6.39 */
283 }
284 311
285 error = security_syslog(type); 312 error = security_syslog(type);
286 if (error) 313 if (error)
@@ -423,12 +450,6 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
423 } 450 }
424out: 451out:
425 return error; 452 return error;
426warn:
427 /* remove after 2.6.39 */
428 if (capable(CAP_SYS_ADMIN))
429 WARN_ONCE(1, "Attempt to access syslog with CAP_SYS_ADMIN "
430 "but no CAP_SYSLOG (deprecated and denied).\n");
431 return -EPERM;
432} 453}
433 454
434SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len) 455SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
@@ -460,6 +481,8 @@ static void __call_console_drivers(unsigned start, unsigned end)
460 struct console *con; 481 struct console *con;
461 482
462 for_each_console(con) { 483 for_each_console(con) {
484 if (exclusive_console && con != exclusive_console)
485 continue;
463 if ((con->flags & CON_ENABLED) && con->write && 486 if ((con->flags & CON_ENABLED) && con->write &&
464 (cpu_online(smp_processor_id()) || 487 (cpu_online(smp_processor_id()) ||
465 (con->flags & CON_ANYTIME))) 488 (con->flags & CON_ANYTIME)))
@@ -499,9 +522,74 @@ static void _call_console_drivers(unsigned start,
499} 522}
500 523
501/* 524/*
525 * Parse the syslog header <[0-9]*>. The decimal value represents 32bit, the
526 * lower 3 bit are the log level, the rest are the log facility. In case
527 * userspace passes usual userspace syslog messages to /dev/kmsg or
528 * /dev/ttyprintk, the log prefix might contain the facility. Printk needs
529 * to extract the correct log level for in-kernel processing, and not mangle
530 * the original value.
531 *
532 * If a prefix is found, the length of the prefix is returned. If 'level' is
533 * passed, it will be filled in with the log level without a possible facility
534 * value. If 'special' is passed, the special printk prefix chars are accepted
535 * and returned. If no valid header is found, 0 is returned and the passed
536 * variables are not touched.
537 */
538static size_t log_prefix(const char *p, unsigned int *level, char *special)
539{
540 unsigned int lev = 0;
541 char sp = '\0';
542 size_t len;
543
544 if (p[0] != '<' || !p[1])
545 return 0;
546 if (p[2] == '>') {
547 /* usual single digit level number or special char */
548 switch (p[1]) {
549 case '0' ... '7':
550 lev = p[1] - '0';
551 break;
552 case 'c': /* KERN_CONT */
553 case 'd': /* KERN_DEFAULT */
554 sp = p[1];
555 break;
556 default:
557 return 0;
558 }
559 len = 3;
560 } else {
561 /* multi digit including the level and facility number */
562 char *endp = NULL;
563
564 if (p[1] < '0' && p[1] > '9')
565 return 0;
566
567 lev = (simple_strtoul(&p[1], &endp, 10) & 7);
568 if (endp == NULL || endp[0] != '>')
569 return 0;
570 len = (endp + 1) - p;
571 }
572
573 /* do not accept special char if not asked for */
574 if (sp && !special)
575 return 0;
576
577 if (special) {
578 *special = sp;
579 /* return special char, do not touch level */
580 if (sp)
581 return len;
582 }
583
584 if (level)
585 *level = lev;
586 return len;
587}
588
589/*
502 * Call the console drivers, asking them to write out 590 * Call the console drivers, asking them to write out
503 * log_buf[start] to log_buf[end - 1]. 591 * log_buf[start] to log_buf[end - 1].
504 * The console_sem must be held. 592 * The console_lock must be held.
505 */ 593 */
506static void call_console_drivers(unsigned start, unsigned end) 594static void call_console_drivers(unsigned start, unsigned end)
507{ 595{
@@ -513,13 +601,9 @@ static void call_console_drivers(unsigned start, unsigned end)
513 cur_index = start; 601 cur_index = start;
514 start_print = start; 602 start_print = start;
515 while (cur_index != end) { 603 while (cur_index != end) {
516 if (msg_level < 0 && ((end - cur_index) > 2) && 604 if (msg_level < 0 && ((end - cur_index) > 2)) {
517 LOG_BUF(cur_index + 0) == '<' && 605 /* strip log prefix */
518 LOG_BUF(cur_index + 1) >= '0' && 606 cur_index += log_prefix(&LOG_BUF(cur_index), &msg_level, NULL);
519 LOG_BUF(cur_index + 1) <= '7' &&
520 LOG_BUF(cur_index + 2) == '>') {
521 msg_level = LOG_BUF(cur_index + 1) - '0';
522 cur_index += 3;
523 start_print = cur_index; 607 start_print = cur_index;
524 } 608 }
525 while (cur_index != end) { 609 while (cur_index != end) {
@@ -604,11 +688,11 @@ static int have_callable_console(void)
604 * 688 *
605 * This is printk(). It can be called from any context. We want it to work. 689 * This is printk(). It can be called from any context. We want it to work.
606 * 690 *
607 * We try to grab the console_sem. If we succeed, it's easy - we log the output and 691 * We try to grab the console_lock. If we succeed, it's easy - we log the output and
608 * call the console drivers. If we fail to get the semaphore we place the output 692 * call the console drivers. If we fail to get the semaphore we place the output
609 * into the log buffer and return. The current holder of the console_sem will 693 * into the log buffer and return. The current holder of the console_sem will
610 * notice the new output in release_console_sem() and will send it to the 694 * notice the new output in console_unlock(); and will send it to the
611 * consoles before releasing the semaphore. 695 * consoles before releasing the lock.
612 * 696 *
613 * One effect of this deferred printing is that code which calls printk() and 697 * One effect of this deferred printing is that code which calls printk() and
614 * then changes console_loglevel may break. This is because console_loglevel 698 * then changes console_loglevel may break. This is because console_loglevel
@@ -659,19 +743,19 @@ static inline int can_use_console(unsigned int cpu)
659/* 743/*
660 * Try to get console ownership to actually show the kernel 744 * Try to get console ownership to actually show the kernel
661 * messages from a 'printk'. Return true (and with the 745 * messages from a 'printk'. Return true (and with the
662 * console_semaphore held, and 'console_locked' set) if it 746 * console_lock held, and 'console_locked' set) if it
663 * is successful, false otherwise. 747 * is successful, false otherwise.
664 * 748 *
665 * This gets called with the 'logbuf_lock' spinlock held and 749 * This gets called with the 'logbuf_lock' spinlock held and
666 * interrupts disabled. It should return with 'lockbuf_lock' 750 * interrupts disabled. It should return with 'lockbuf_lock'
667 * released but interrupts still disabled. 751 * released but interrupts still disabled.
668 */ 752 */
669static int acquire_console_semaphore_for_printk(unsigned int cpu) 753static int console_trylock_for_printk(unsigned int cpu)
670 __releases(&logbuf_lock) 754 __releases(&logbuf_lock)
671{ 755{
672 int retval = 0; 756 int retval = 0;
673 757
674 if (!try_acquire_console_sem()) { 758 if (console_trylock()) {
675 retval = 1; 759 retval = 1;
676 760
677 /* 761 /*
@@ -717,6 +801,8 @@ asmlinkage int vprintk(const char *fmt, va_list args)
717 unsigned long flags; 801 unsigned long flags;
718 int this_cpu; 802 int this_cpu;
719 char *p; 803 char *p;
804 size_t plen;
805 char special;
720 806
721 boot_delay_msec(); 807 boot_delay_msec();
722 printk_delay(); 808 printk_delay();
@@ -757,45 +843,52 @@ asmlinkage int vprintk(const char *fmt, va_list args)
757 printed_len += vscnprintf(printk_buf + printed_len, 843 printed_len += vscnprintf(printk_buf + printed_len,
758 sizeof(printk_buf) - printed_len, fmt, args); 844 sizeof(printk_buf) - printed_len, fmt, args);
759 845
760
761 p = printk_buf; 846 p = printk_buf;
762 847
763 /* Do we have a loglevel in the string? */ 848 /* Read log level and handle special printk prefix */
764 if (p[0] == '<') { 849 plen = log_prefix(p, &current_log_level, &special);
765 unsigned char c = p[1]; 850 if (plen) {
766 if (c && p[2] == '>') { 851 p += plen;
767 switch (c) { 852
768 case '0' ... '7': /* loglevel */ 853 switch (special) {
769 current_log_level = c - '0'; 854 case 'c': /* Strip <c> KERN_CONT, continue line */
770 /* Fallthrough - make sure we're on a new line */ 855 plen = 0;
771 case 'd': /* KERN_DEFAULT */ 856 break;
772 if (!new_text_line) { 857 case 'd': /* Strip <d> KERN_DEFAULT, start new line */
773 emit_log_char('\n'); 858 plen = 0;
774 new_text_line = 1; 859 default:
775 } 860 if (!new_text_line) {
776 /* Fallthrough - skip the loglevel */ 861 emit_log_char('\n');
777 case 'c': /* KERN_CONT */ 862 new_text_line = 1;
778 p += 3;
779 break;
780 } 863 }
781 } 864 }
782 } 865 }
783 866
784 /* 867 /*
785 * Copy the output into log_buf. If the caller didn't provide 868 * Copy the output into log_buf. If the caller didn't provide
786 * appropriate log level tags, we insert them here 869 * the appropriate log prefix, we insert them here
787 */ 870 */
788 for ( ; *p; p++) { 871 for (; *p; p++) {
789 if (new_text_line) { 872 if (new_text_line) {
790 /* Always output the token */
791 emit_log_char('<');
792 emit_log_char(current_log_level + '0');
793 emit_log_char('>');
794 printed_len += 3;
795 new_text_line = 0; 873 new_text_line = 0;
796 874
875 if (plen) {
876 /* Copy original log prefix */
877 int i;
878
879 for (i = 0; i < plen; i++)
880 emit_log_char(printk_buf[i]);
881 printed_len += plen;
882 } else {
883 /* Add log prefix */
884 emit_log_char('<');
885 emit_log_char(current_log_level + '0');
886 emit_log_char('>');
887 printed_len += 3;
888 }
889
797 if (printk_time) { 890 if (printk_time) {
798 /* Follow the token with the time */ 891 /* Add the current time stamp */
799 char tbuf[50], *tp; 892 char tbuf[50], *tp;
800 unsigned tlen; 893 unsigned tlen;
801 unsigned long long t; 894 unsigned long long t;
@@ -827,12 +920,12 @@ asmlinkage int vprintk(const char *fmt, va_list args)
827 * actual magic (print out buffers, wake up klogd, 920 * actual magic (print out buffers, wake up klogd,
828 * etc). 921 * etc).
829 * 922 *
830 * The acquire_console_semaphore_for_printk() function 923 * The console_trylock_for_printk() function
831 * will release 'logbuf_lock' regardless of whether it 924 * will release 'logbuf_lock' regardless of whether it
832 * actually gets the semaphore or not. 925 * actually gets the semaphore or not.
833 */ 926 */
834 if (acquire_console_semaphore_for_printk(this_cpu)) 927 if (console_trylock_for_printk(this_cpu))
835 release_console_sem(); 928 console_unlock();
836 929
837 lockdep_on(); 930 lockdep_on();
838out_restore_irqs: 931out_restore_irqs:
@@ -993,7 +1086,7 @@ void suspend_console(void)
993 if (!console_suspend_enabled) 1086 if (!console_suspend_enabled)
994 return; 1087 return;
995 printk("Suspending console(s) (use no_console_suspend to debug)\n"); 1088 printk("Suspending console(s) (use no_console_suspend to debug)\n");
996 acquire_console_sem(); 1089 console_lock();
997 console_suspended = 1; 1090 console_suspended = 1;
998 up(&console_sem); 1091 up(&console_sem);
999} 1092}
@@ -1004,7 +1097,7 @@ void resume_console(void)
1004 return; 1097 return;
1005 down(&console_sem); 1098 down(&console_sem);
1006 console_suspended = 0; 1099 console_suspended = 0;
1007 release_console_sem(); 1100 console_unlock();
1008} 1101}
1009 1102
1010/** 1103/**
@@ -1027,21 +1120,21 @@ static int __cpuinit console_cpu_notify(struct notifier_block *self,
1027 case CPU_DYING: 1120 case CPU_DYING:
1028 case CPU_DOWN_FAILED: 1121 case CPU_DOWN_FAILED:
1029 case CPU_UP_CANCELED: 1122 case CPU_UP_CANCELED:
1030 acquire_console_sem(); 1123 console_lock();
1031 release_console_sem(); 1124 console_unlock();
1032 } 1125 }
1033 return NOTIFY_OK; 1126 return NOTIFY_OK;
1034} 1127}
1035 1128
1036/** 1129/**
1037 * acquire_console_sem - lock the console system for exclusive use. 1130 * console_lock - lock the console system for exclusive use.
1038 * 1131 *
1039 * Acquires a semaphore which guarantees that the caller has 1132 * Acquires a lock which guarantees that the caller has
1040 * exclusive access to the console system and the console_drivers list. 1133 * exclusive access to the console system and the console_drivers list.
1041 * 1134 *
1042 * Can sleep, returns nothing. 1135 * Can sleep, returns nothing.
1043 */ 1136 */
1044void acquire_console_sem(void) 1137void console_lock(void)
1045{ 1138{
1046 BUG_ON(in_interrupt()); 1139 BUG_ON(in_interrupt());
1047 down(&console_sem); 1140 down(&console_sem);
@@ -1050,21 +1143,29 @@ void acquire_console_sem(void)
1050 console_locked = 1; 1143 console_locked = 1;
1051 console_may_schedule = 1; 1144 console_may_schedule = 1;
1052} 1145}
1053EXPORT_SYMBOL(acquire_console_sem); 1146EXPORT_SYMBOL(console_lock);
1054 1147
1055int try_acquire_console_sem(void) 1148/**
1149 * console_trylock - try to lock the console system for exclusive use.
1150 *
1151 * Tried to acquire a lock which guarantees that the caller has
1152 * exclusive access to the console system and the console_drivers list.
1153 *
1154 * returns 1 on success, and 0 on failure to acquire the lock.
1155 */
1156int console_trylock(void)
1056{ 1157{
1057 if (down_trylock(&console_sem)) 1158 if (down_trylock(&console_sem))
1058 return -1; 1159 return 0;
1059 if (console_suspended) { 1160 if (console_suspended) {
1060 up(&console_sem); 1161 up(&console_sem);
1061 return -1; 1162 return 0;
1062 } 1163 }
1063 console_locked = 1; 1164 console_locked = 1;
1064 console_may_schedule = 0; 1165 console_may_schedule = 0;
1065 return 0; 1166 return 1;
1066} 1167}
1067EXPORT_SYMBOL(try_acquire_console_sem); 1168EXPORT_SYMBOL(console_trylock);
1068 1169
1069int is_console_locked(void) 1170int is_console_locked(void)
1070{ 1171{
@@ -1095,20 +1196,20 @@ void wake_up_klogd(void)
1095} 1196}
1096 1197
1097/** 1198/**
1098 * release_console_sem - unlock the console system 1199 * console_unlock - unlock the console system
1099 * 1200 *
1100 * Releases the semaphore which the caller holds on the console system 1201 * Releases the console_lock which the caller holds on the console system
1101 * and the console driver list. 1202 * and the console driver list.
1102 * 1203 *
1103 * While the semaphore was held, console output may have been buffered 1204 * While the console_lock was held, console output may have been buffered
1104 * by printk(). If this is the case, release_console_sem() emits 1205 * by printk(). If this is the case, console_unlock(); emits
1105 * the output prior to releasing the semaphore. 1206 * the output prior to releasing the lock.
1106 * 1207 *
1107 * If there is output waiting for klogd, we wake it up. 1208 * If there is output waiting for klogd, we wake it up.
1108 * 1209 *
1109 * release_console_sem() may be called from any context. 1210 * console_unlock(); may be called from any context.
1110 */ 1211 */
1111void release_console_sem(void) 1212void console_unlock(void)
1112{ 1213{
1113 unsigned long flags; 1214 unsigned long flags;
1114 unsigned _con_start, _log_end; 1215 unsigned _con_start, _log_end;
@@ -1136,12 +1237,17 @@ void release_console_sem(void)
1136 local_irq_restore(flags); 1237 local_irq_restore(flags);
1137 } 1238 }
1138 console_locked = 0; 1239 console_locked = 0;
1240
1241 /* Release the exclusive_console once it is used */
1242 if (unlikely(exclusive_console))
1243 exclusive_console = NULL;
1244
1139 up(&console_sem); 1245 up(&console_sem);
1140 spin_unlock_irqrestore(&logbuf_lock, flags); 1246 spin_unlock_irqrestore(&logbuf_lock, flags);
1141 if (wake_klogd) 1247 if (wake_klogd)
1142 wake_up_klogd(); 1248 wake_up_klogd();
1143} 1249}
1144EXPORT_SYMBOL(release_console_sem); 1250EXPORT_SYMBOL(console_unlock);
1145 1251
1146/** 1252/**
1147 * console_conditional_schedule - yield the CPU if required 1253 * console_conditional_schedule - yield the CPU if required
@@ -1150,7 +1256,7 @@ EXPORT_SYMBOL(release_console_sem);
1150 * if this CPU should yield the CPU to another task, do 1256 * if this CPU should yield the CPU to another task, do
1151 * so here. 1257 * so here.
1152 * 1258 *
1153 * Must be called within acquire_console_sem(). 1259 * Must be called within console_lock();.
1154 */ 1260 */
1155void __sched console_conditional_schedule(void) 1261void __sched console_conditional_schedule(void)
1156{ 1262{
@@ -1171,14 +1277,14 @@ void console_unblank(void)
1171 if (down_trylock(&console_sem) != 0) 1277 if (down_trylock(&console_sem) != 0)
1172 return; 1278 return;
1173 } else 1279 } else
1174 acquire_console_sem(); 1280 console_lock();
1175 1281
1176 console_locked = 1; 1282 console_locked = 1;
1177 console_may_schedule = 0; 1283 console_may_schedule = 0;
1178 for_each_console(c) 1284 for_each_console(c)
1179 if ((c->flags & CON_ENABLED) && c->unblank) 1285 if ((c->flags & CON_ENABLED) && c->unblank)
1180 c->unblank(); 1286 c->unblank();
1181 release_console_sem(); 1287 console_unlock();
1182} 1288}
1183 1289
1184/* 1290/*
@@ -1189,7 +1295,7 @@ struct tty_driver *console_device(int *index)
1189 struct console *c; 1295 struct console *c;
1190 struct tty_driver *driver = NULL; 1296 struct tty_driver *driver = NULL;
1191 1297
1192 acquire_console_sem(); 1298 console_lock();
1193 for_each_console(c) { 1299 for_each_console(c) {
1194 if (!c->device) 1300 if (!c->device)
1195 continue; 1301 continue;
@@ -1197,7 +1303,7 @@ struct tty_driver *console_device(int *index)
1197 if (driver) 1303 if (driver)
1198 break; 1304 break;
1199 } 1305 }
1200 release_console_sem(); 1306 console_unlock();
1201 return driver; 1307 return driver;
1202} 1308}
1203 1309
@@ -1208,20 +1314,32 @@ struct tty_driver *console_device(int *index)
1208 */ 1314 */
1209void console_stop(struct console *console) 1315void console_stop(struct console *console)
1210{ 1316{
1211 acquire_console_sem(); 1317 console_lock();
1212 console->flags &= ~CON_ENABLED; 1318 console->flags &= ~CON_ENABLED;
1213 release_console_sem(); 1319 console_unlock();
1214} 1320}
1215EXPORT_SYMBOL(console_stop); 1321EXPORT_SYMBOL(console_stop);
1216 1322
1217void console_start(struct console *console) 1323void console_start(struct console *console)
1218{ 1324{
1219 acquire_console_sem(); 1325 console_lock();
1220 console->flags |= CON_ENABLED; 1326 console->flags |= CON_ENABLED;
1221 release_console_sem(); 1327 console_unlock();
1222} 1328}
1223EXPORT_SYMBOL(console_start); 1329EXPORT_SYMBOL(console_start);
1224 1330
1331static int __read_mostly keep_bootcon;
1332
1333static int __init keep_bootcon_setup(char *str)
1334{
1335 keep_bootcon = 1;
1336 printk(KERN_INFO "debug: skip boot console de-registration.\n");
1337
1338 return 0;
1339}
1340
1341early_param("keep_bootcon", keep_bootcon_setup);
1342
1225/* 1343/*
1226 * The console driver calls this routine during kernel initialization 1344 * The console driver calls this routine during kernel initialization
1227 * to register the console printing procedure with printk() and to 1345 * to register the console printing procedure with printk() and to
@@ -1340,7 +1458,7 @@ void register_console(struct console *newcon)
1340 * Put this console in the list - keep the 1458 * Put this console in the list - keep the
1341 * preferred driver at the head of the list. 1459 * preferred driver at the head of the list.
1342 */ 1460 */
1343 acquire_console_sem(); 1461 console_lock();
1344 if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) { 1462 if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) {
1345 newcon->next = console_drivers; 1463 newcon->next = console_drivers;
1346 console_drivers = newcon; 1464 console_drivers = newcon;
@@ -1352,14 +1470,20 @@ void register_console(struct console *newcon)
1352 } 1470 }
1353 if (newcon->flags & CON_PRINTBUFFER) { 1471 if (newcon->flags & CON_PRINTBUFFER) {
1354 /* 1472 /*
1355 * release_console_sem() will print out the buffered messages 1473 * console_unlock(); will print out the buffered messages
1356 * for us. 1474 * for us.
1357 */ 1475 */
1358 spin_lock_irqsave(&logbuf_lock, flags); 1476 spin_lock_irqsave(&logbuf_lock, flags);
1359 con_start = log_start; 1477 con_start = log_start;
1360 spin_unlock_irqrestore(&logbuf_lock, flags); 1478 spin_unlock_irqrestore(&logbuf_lock, flags);
1479 /*
1480 * We're about to replay the log buffer. Only do this to the
1481 * just-registered console to avoid excessive message spam to
1482 * the already-registered consoles.
1483 */
1484 exclusive_console = newcon;
1361 } 1485 }
1362 release_console_sem(); 1486 console_unlock();
1363 console_sysfs_notify(); 1487 console_sysfs_notify();
1364 1488
1365 /* 1489 /*
@@ -1369,7 +1493,9 @@ void register_console(struct console *newcon)
1369 * users know there might be something in the kernel's log buffer that 1493 * users know there might be something in the kernel's log buffer that
1370 * went to the bootconsole (that they do not see on the real console) 1494 * went to the bootconsole (that they do not see on the real console)
1371 */ 1495 */
1372 if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV)) { 1496 if (bcon &&
1497 ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) &&
1498 !keep_bootcon) {
1373 /* we need to iterate through twice, to make sure we print 1499 /* we need to iterate through twice, to make sure we print
1374 * everything out, before we unregister the console(s) 1500 * everything out, before we unregister the console(s)
1375 */ 1501 */
@@ -1396,7 +1522,7 @@ int unregister_console(struct console *console)
1396 return braille_unregister_console(console); 1522 return braille_unregister_console(console);
1397#endif 1523#endif
1398 1524
1399 acquire_console_sem(); 1525 console_lock();
1400 if (console_drivers == console) { 1526 if (console_drivers == console) {
1401 console_drivers=console->next; 1527 console_drivers=console->next;
1402 res = 0; 1528 res = 0;
@@ -1418,7 +1544,7 @@ int unregister_console(struct console *console)
1418 if (console_drivers != NULL && console->flags & CON_CONSDEV) 1544 if (console_drivers != NULL && console->flags & CON_CONSDEV)
1419 console_drivers->flags |= CON_CONSDEV; 1545 console_drivers->flags |= CON_CONSDEV;
1420 1546
1421 release_console_sem(); 1547 console_unlock();
1422 console_sysfs_notify(); 1548 console_sysfs_notify();
1423 return res; 1549 return res;
1424} 1550}