diff options
Diffstat (limited to 'kernel/printk.c')
-rw-r--r-- | kernel/printk.c | 186 |
1 files changed, 98 insertions, 88 deletions
diff --git a/kernel/printk.c b/kernel/printk.c index ab3ffc5b3b64..36231525e22f 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -39,16 +39,11 @@ | |||
39 | #include <linux/syslog.h> | 39 | #include <linux/syslog.h> |
40 | #include <linux/cpu.h> | 40 | #include <linux/cpu.h> |
41 | #include <linux/notifier.h> | 41 | #include <linux/notifier.h> |
42 | #include <linux/rculist.h> | ||
42 | 43 | ||
43 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
44 | 45 | ||
45 | /* | 46 | /* |
46 | * for_each_console() allows you to iterate on each console | ||
47 | */ | ||
48 | #define for_each_console(con) \ | ||
49 | for (con = console_drivers; con != NULL; con = con->next) | ||
50 | |||
51 | /* | ||
52 | * Architectures can override it: | 47 | * Architectures can override it: |
53 | */ | 48 | */ |
54 | void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...) | 49 | void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...) |
@@ -102,7 +97,7 @@ static int console_locked, console_suspended; | |||
102 | /* | 97 | /* |
103 | * 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 |
104 | * It is also used in interesting ways to provide interlocking in | 99 | * It is also used in interesting ways to provide interlocking in |
105 | * release_console_sem(). | 100 | * console_unlock();. |
106 | */ | 101 | */ |
107 | static DEFINE_SPINLOCK(logbuf_lock); | 102 | static DEFINE_SPINLOCK(logbuf_lock); |
108 | 103 | ||
@@ -267,25 +262,47 @@ int dmesg_restrict = 1; | |||
267 | int dmesg_restrict; | 262 | int dmesg_restrict; |
268 | #endif | 263 | #endif |
269 | 264 | ||
265 | static int syslog_action_restricted(int type) | ||
266 | { | ||
267 | if (dmesg_restrict) | ||
268 | return 1; | ||
269 | /* Unless restricted, we allow "read all" and "get buffer size" for everybody */ | ||
270 | return type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER; | ||
271 | } | ||
272 | |||
273 | static int check_syslog_permissions(int type, bool from_file) | ||
274 | { | ||
275 | /* | ||
276 | * If this is from /proc/kmsg and we've already opened it, then we've | ||
277 | * already done the capabilities checks at open time. | ||
278 | */ | ||
279 | if (from_file && type != SYSLOG_ACTION_OPEN) | ||
280 | return 0; | ||
281 | |||
282 | if (syslog_action_restricted(type)) { | ||
283 | if (capable(CAP_SYSLOG)) | ||
284 | return 0; | ||
285 | /* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */ | ||
286 | if (capable(CAP_SYS_ADMIN)) { | ||
287 | WARN_ONCE(1, "Attempt to access syslog with CAP_SYS_ADMIN " | ||
288 | "but no CAP_SYSLOG (deprecated).\n"); | ||
289 | return 0; | ||
290 | } | ||
291 | return -EPERM; | ||
292 | } | ||
293 | return 0; | ||
294 | } | ||
295 | |||
270 | int do_syslog(int type, char __user *buf, int len, bool from_file) | 296 | int do_syslog(int type, char __user *buf, int len, bool from_file) |
271 | { | 297 | { |
272 | unsigned i, j, limit, count; | 298 | unsigned i, j, limit, count; |
273 | int do_clear = 0; | 299 | int do_clear = 0; |
274 | char c; | 300 | char c; |
275 | int error = 0; | 301 | int error; |
276 | 302 | ||
277 | /* | 303 | error = check_syslog_permissions(type, from_file); |
278 | * If this is from /proc/kmsg we only do the capabilities checks | 304 | if (error) |
279 | * at open time. | 305 | goto out; |
280 | */ | ||
281 | if (type == SYSLOG_ACTION_OPEN || !from_file) { | ||
282 | if (dmesg_restrict && !capable(CAP_SYS_ADMIN)) | ||
283 | return -EPERM; | ||
284 | if ((type != SYSLOG_ACTION_READ_ALL && | ||
285 | type != SYSLOG_ACTION_SIZE_BUFFER) && | ||
286 | !capable(CAP_SYS_ADMIN)) | ||
287 | return -EPERM; | ||
288 | } | ||
289 | 306 | ||
290 | error = security_syslog(type); | 307 | error = security_syslog(type); |
291 | if (error) | 308 | if (error) |
@@ -500,7 +517,7 @@ static void _call_console_drivers(unsigned start, | |||
500 | /* | 517 | /* |
501 | * Call the console drivers, asking them to write out | 518 | * Call the console drivers, asking them to write out |
502 | * log_buf[start] to log_buf[end - 1]. | 519 | * log_buf[start] to log_buf[end - 1]. |
503 | * The console_sem must be held. | 520 | * The console_lock must be held. |
504 | */ | 521 | */ |
505 | static void call_console_drivers(unsigned start, unsigned end) | 522 | static void call_console_drivers(unsigned start, unsigned end) |
506 | { | 523 | { |
@@ -603,11 +620,11 @@ static int have_callable_console(void) | |||
603 | * | 620 | * |
604 | * This is printk(). It can be called from any context. We want it to work. | 621 | * This is printk(). It can be called from any context. We want it to work. |
605 | * | 622 | * |
606 | * We try to grab the console_sem. If we succeed, it's easy - we log the output and | 623 | * We try to grab the console_lock. If we succeed, it's easy - we log the output and |
607 | * call the console drivers. If we fail to get the semaphore we place the output | 624 | * call the console drivers. If we fail to get the semaphore we place the output |
608 | * into the log buffer and return. The current holder of the console_sem will | 625 | * into the log buffer and return. The current holder of the console_sem will |
609 | * notice the new output in release_console_sem() and will send it to the | 626 | * notice the new output in console_unlock(); and will send it to the |
610 | * consoles before releasing the semaphore. | 627 | * consoles before releasing the lock. |
611 | * | 628 | * |
612 | * One effect of this deferred printing is that code which calls printk() and | 629 | * One effect of this deferred printing is that code which calls printk() and |
613 | * then changes console_loglevel may break. This is because console_loglevel | 630 | * then changes console_loglevel may break. This is because console_loglevel |
@@ -658,19 +675,19 @@ static inline int can_use_console(unsigned int cpu) | |||
658 | /* | 675 | /* |
659 | * Try to get console ownership to actually show the kernel | 676 | * Try to get console ownership to actually show the kernel |
660 | * messages from a 'printk'. Return true (and with the | 677 | * messages from a 'printk'. Return true (and with the |
661 | * console_semaphore held, and 'console_locked' set) if it | 678 | * console_lock held, and 'console_locked' set) if it |
662 | * is successful, false otherwise. | 679 | * is successful, false otherwise. |
663 | * | 680 | * |
664 | * This gets called with the 'logbuf_lock' spinlock held and | 681 | * This gets called with the 'logbuf_lock' spinlock held and |
665 | * interrupts disabled. It should return with 'lockbuf_lock' | 682 | * interrupts disabled. It should return with 'lockbuf_lock' |
666 | * released but interrupts still disabled. | 683 | * released but interrupts still disabled. |
667 | */ | 684 | */ |
668 | static int acquire_console_semaphore_for_printk(unsigned int cpu) | 685 | static int console_trylock_for_printk(unsigned int cpu) |
669 | __releases(&logbuf_lock) | 686 | __releases(&logbuf_lock) |
670 | { | 687 | { |
671 | int retval = 0; | 688 | int retval = 0; |
672 | 689 | ||
673 | if (!try_acquire_console_sem()) { | 690 | if (console_trylock()) { |
674 | retval = 1; | 691 | retval = 1; |
675 | 692 | ||
676 | /* | 693 | /* |
@@ -826,12 +843,12 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
826 | * actual magic (print out buffers, wake up klogd, | 843 | * actual magic (print out buffers, wake up klogd, |
827 | * etc). | 844 | * etc). |
828 | * | 845 | * |
829 | * The acquire_console_semaphore_for_printk() function | 846 | * The console_trylock_for_printk() function |
830 | * will release 'logbuf_lock' regardless of whether it | 847 | * will release 'logbuf_lock' regardless of whether it |
831 | * actually gets the semaphore or not. | 848 | * actually gets the semaphore or not. |
832 | */ | 849 | */ |
833 | if (acquire_console_semaphore_for_printk(this_cpu)) | 850 | if (console_trylock_for_printk(this_cpu)) |
834 | release_console_sem(); | 851 | console_unlock(); |
835 | 852 | ||
836 | lockdep_on(); | 853 | lockdep_on(); |
837 | out_restore_irqs: | 854 | out_restore_irqs: |
@@ -992,7 +1009,7 @@ void suspend_console(void) | |||
992 | if (!console_suspend_enabled) | 1009 | if (!console_suspend_enabled) |
993 | return; | 1010 | return; |
994 | printk("Suspending console(s) (use no_console_suspend to debug)\n"); | 1011 | printk("Suspending console(s) (use no_console_suspend to debug)\n"); |
995 | acquire_console_sem(); | 1012 | console_lock(); |
996 | console_suspended = 1; | 1013 | console_suspended = 1; |
997 | up(&console_sem); | 1014 | up(&console_sem); |
998 | } | 1015 | } |
@@ -1003,7 +1020,7 @@ void resume_console(void) | |||
1003 | return; | 1020 | return; |
1004 | down(&console_sem); | 1021 | down(&console_sem); |
1005 | console_suspended = 0; | 1022 | console_suspended = 0; |
1006 | release_console_sem(); | 1023 | console_unlock(); |
1007 | } | 1024 | } |
1008 | 1025 | ||
1009 | /** | 1026 | /** |
@@ -1026,21 +1043,21 @@ static int __cpuinit console_cpu_notify(struct notifier_block *self, | |||
1026 | case CPU_DYING: | 1043 | case CPU_DYING: |
1027 | case CPU_DOWN_FAILED: | 1044 | case CPU_DOWN_FAILED: |
1028 | case CPU_UP_CANCELED: | 1045 | case CPU_UP_CANCELED: |
1029 | acquire_console_sem(); | 1046 | console_lock(); |
1030 | release_console_sem(); | 1047 | console_unlock(); |
1031 | } | 1048 | } |
1032 | return NOTIFY_OK; | 1049 | return NOTIFY_OK; |
1033 | } | 1050 | } |
1034 | 1051 | ||
1035 | /** | 1052 | /** |
1036 | * acquire_console_sem - lock the console system for exclusive use. | 1053 | * console_lock - lock the console system for exclusive use. |
1037 | * | 1054 | * |
1038 | * Acquires a semaphore which guarantees that the caller has | 1055 | * Acquires a lock which guarantees that the caller has |
1039 | * exclusive access to the console system and the console_drivers list. | 1056 | * exclusive access to the console system and the console_drivers list. |
1040 | * | 1057 | * |
1041 | * Can sleep, returns nothing. | 1058 | * Can sleep, returns nothing. |
1042 | */ | 1059 | */ |
1043 | void acquire_console_sem(void) | 1060 | void console_lock(void) |
1044 | { | 1061 | { |
1045 | BUG_ON(in_interrupt()); | 1062 | BUG_ON(in_interrupt()); |
1046 | down(&console_sem); | 1063 | down(&console_sem); |
@@ -1049,21 +1066,29 @@ void acquire_console_sem(void) | |||
1049 | console_locked = 1; | 1066 | console_locked = 1; |
1050 | console_may_schedule = 1; | 1067 | console_may_schedule = 1; |
1051 | } | 1068 | } |
1052 | EXPORT_SYMBOL(acquire_console_sem); | 1069 | EXPORT_SYMBOL(console_lock); |
1053 | 1070 | ||
1054 | int try_acquire_console_sem(void) | 1071 | /** |
1072 | * console_trylock - try to lock the console system for exclusive use. | ||
1073 | * | ||
1074 | * Tried to acquire a lock which guarantees that the caller has | ||
1075 | * exclusive access to the console system and the console_drivers list. | ||
1076 | * | ||
1077 | * returns 1 on success, and 0 on failure to acquire the lock. | ||
1078 | */ | ||
1079 | int console_trylock(void) | ||
1055 | { | 1080 | { |
1056 | if (down_trylock(&console_sem)) | 1081 | if (down_trylock(&console_sem)) |
1057 | return -1; | 1082 | return 0; |
1058 | if (console_suspended) { | 1083 | if (console_suspended) { |
1059 | up(&console_sem); | 1084 | up(&console_sem); |
1060 | return -1; | 1085 | return 0; |
1061 | } | 1086 | } |
1062 | console_locked = 1; | 1087 | console_locked = 1; |
1063 | console_may_schedule = 0; | 1088 | console_may_schedule = 0; |
1064 | return 0; | 1089 | return 1; |
1065 | } | 1090 | } |
1066 | EXPORT_SYMBOL(try_acquire_console_sem); | 1091 | EXPORT_SYMBOL(console_trylock); |
1067 | 1092 | ||
1068 | int is_console_locked(void) | 1093 | int is_console_locked(void) |
1069 | { | 1094 | { |
@@ -1094,20 +1119,20 @@ void wake_up_klogd(void) | |||
1094 | } | 1119 | } |
1095 | 1120 | ||
1096 | /** | 1121 | /** |
1097 | * release_console_sem - unlock the console system | 1122 | * console_unlock - unlock the console system |
1098 | * | 1123 | * |
1099 | * Releases the semaphore which the caller holds on the console system | 1124 | * Releases the console_lock which the caller holds on the console system |
1100 | * and the console driver list. | 1125 | * and the console driver list. |
1101 | * | 1126 | * |
1102 | * While the semaphore was held, console output may have been buffered | 1127 | * While the console_lock was held, console output may have been buffered |
1103 | * by printk(). If this is the case, release_console_sem() emits | 1128 | * by printk(). If this is the case, console_unlock(); emits |
1104 | * the output prior to releasing the semaphore. | 1129 | * the output prior to releasing the lock. |
1105 | * | 1130 | * |
1106 | * If there is output waiting for klogd, we wake it up. | 1131 | * If there is output waiting for klogd, we wake it up. |
1107 | * | 1132 | * |
1108 | * release_console_sem() may be called from any context. | 1133 | * console_unlock(); may be called from any context. |
1109 | */ | 1134 | */ |
1110 | void release_console_sem(void) | 1135 | void console_unlock(void) |
1111 | { | 1136 | { |
1112 | unsigned long flags; | 1137 | unsigned long flags; |
1113 | unsigned _con_start, _log_end; | 1138 | unsigned _con_start, _log_end; |
@@ -1140,7 +1165,7 @@ void release_console_sem(void) | |||
1140 | if (wake_klogd) | 1165 | if (wake_klogd) |
1141 | wake_up_klogd(); | 1166 | wake_up_klogd(); |
1142 | } | 1167 | } |
1143 | EXPORT_SYMBOL(release_console_sem); | 1168 | EXPORT_SYMBOL(console_unlock); |
1144 | 1169 | ||
1145 | /** | 1170 | /** |
1146 | * console_conditional_schedule - yield the CPU if required | 1171 | * console_conditional_schedule - yield the CPU if required |
@@ -1149,7 +1174,7 @@ EXPORT_SYMBOL(release_console_sem); | |||
1149 | * if this CPU should yield the CPU to another task, do | 1174 | * if this CPU should yield the CPU to another task, do |
1150 | * so here. | 1175 | * so here. |
1151 | * | 1176 | * |
1152 | * Must be called within acquire_console_sem(). | 1177 | * Must be called within console_lock();. |
1153 | */ | 1178 | */ |
1154 | void __sched console_conditional_schedule(void) | 1179 | void __sched console_conditional_schedule(void) |
1155 | { | 1180 | { |
@@ -1170,14 +1195,14 @@ void console_unblank(void) | |||
1170 | if (down_trylock(&console_sem) != 0) | 1195 | if (down_trylock(&console_sem) != 0) |
1171 | return; | 1196 | return; |
1172 | } else | 1197 | } else |
1173 | acquire_console_sem(); | 1198 | console_lock(); |
1174 | 1199 | ||
1175 | console_locked = 1; | 1200 | console_locked = 1; |
1176 | console_may_schedule = 0; | 1201 | console_may_schedule = 0; |
1177 | for_each_console(c) | 1202 | for_each_console(c) |
1178 | if ((c->flags & CON_ENABLED) && c->unblank) | 1203 | if ((c->flags & CON_ENABLED) && c->unblank) |
1179 | c->unblank(); | 1204 | c->unblank(); |
1180 | release_console_sem(); | 1205 | console_unlock(); |
1181 | } | 1206 | } |
1182 | 1207 | ||
1183 | /* | 1208 | /* |
@@ -1188,7 +1213,7 @@ struct tty_driver *console_device(int *index) | |||
1188 | struct console *c; | 1213 | struct console *c; |
1189 | struct tty_driver *driver = NULL; | 1214 | struct tty_driver *driver = NULL; |
1190 | 1215 | ||
1191 | acquire_console_sem(); | 1216 | console_lock(); |
1192 | for_each_console(c) { | 1217 | for_each_console(c) { |
1193 | if (!c->device) | 1218 | if (!c->device) |
1194 | continue; | 1219 | continue; |
@@ -1196,7 +1221,7 @@ struct tty_driver *console_device(int *index) | |||
1196 | if (driver) | 1221 | if (driver) |
1197 | break; | 1222 | break; |
1198 | } | 1223 | } |
1199 | release_console_sem(); | 1224 | console_unlock(); |
1200 | return driver; | 1225 | return driver; |
1201 | } | 1226 | } |
1202 | 1227 | ||
@@ -1207,17 +1232,17 @@ struct tty_driver *console_device(int *index) | |||
1207 | */ | 1232 | */ |
1208 | void console_stop(struct console *console) | 1233 | void console_stop(struct console *console) |
1209 | { | 1234 | { |
1210 | acquire_console_sem(); | 1235 | console_lock(); |
1211 | console->flags &= ~CON_ENABLED; | 1236 | console->flags &= ~CON_ENABLED; |
1212 | release_console_sem(); | 1237 | console_unlock(); |
1213 | } | 1238 | } |
1214 | EXPORT_SYMBOL(console_stop); | 1239 | EXPORT_SYMBOL(console_stop); |
1215 | 1240 | ||
1216 | void console_start(struct console *console) | 1241 | void console_start(struct console *console) |
1217 | { | 1242 | { |
1218 | acquire_console_sem(); | 1243 | console_lock(); |
1219 | console->flags |= CON_ENABLED; | 1244 | console->flags |= CON_ENABLED; |
1220 | release_console_sem(); | 1245 | console_unlock(); |
1221 | } | 1246 | } |
1222 | EXPORT_SYMBOL(console_start); | 1247 | EXPORT_SYMBOL(console_start); |
1223 | 1248 | ||
@@ -1339,7 +1364,7 @@ void register_console(struct console *newcon) | |||
1339 | * Put this console in the list - keep the | 1364 | * Put this console in the list - keep the |
1340 | * preferred driver at the head of the list. | 1365 | * preferred driver at the head of the list. |
1341 | */ | 1366 | */ |
1342 | acquire_console_sem(); | 1367 | console_lock(); |
1343 | if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) { | 1368 | if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) { |
1344 | newcon->next = console_drivers; | 1369 | newcon->next = console_drivers; |
1345 | console_drivers = newcon; | 1370 | console_drivers = newcon; |
@@ -1351,14 +1376,15 @@ void register_console(struct console *newcon) | |||
1351 | } | 1376 | } |
1352 | if (newcon->flags & CON_PRINTBUFFER) { | 1377 | if (newcon->flags & CON_PRINTBUFFER) { |
1353 | /* | 1378 | /* |
1354 | * release_console_sem() will print out the buffered messages | 1379 | * console_unlock(); will print out the buffered messages |
1355 | * for us. | 1380 | * for us. |
1356 | */ | 1381 | */ |
1357 | spin_lock_irqsave(&logbuf_lock, flags); | 1382 | spin_lock_irqsave(&logbuf_lock, flags); |
1358 | con_start = log_start; | 1383 | con_start = log_start; |
1359 | spin_unlock_irqrestore(&logbuf_lock, flags); | 1384 | spin_unlock_irqrestore(&logbuf_lock, flags); |
1360 | } | 1385 | } |
1361 | release_console_sem(); | 1386 | console_unlock(); |
1387 | console_sysfs_notify(); | ||
1362 | 1388 | ||
1363 | /* | 1389 | /* |
1364 | * By unregistering the bootconsoles after we enable the real console | 1390 | * By unregistering the bootconsoles after we enable the real console |
@@ -1394,7 +1420,7 @@ int unregister_console(struct console *console) | |||
1394 | return braille_unregister_console(console); | 1420 | return braille_unregister_console(console); |
1395 | #endif | 1421 | #endif |
1396 | 1422 | ||
1397 | acquire_console_sem(); | 1423 | console_lock(); |
1398 | if (console_drivers == console) { | 1424 | if (console_drivers == console) { |
1399 | console_drivers=console->next; | 1425 | console_drivers=console->next; |
1400 | res = 0; | 1426 | res = 0; |
@@ -1416,7 +1442,8 @@ int unregister_console(struct console *console) | |||
1416 | if (console_drivers != NULL && console->flags & CON_CONSDEV) | 1442 | if (console_drivers != NULL && console->flags & CON_CONSDEV) |
1417 | console_drivers->flags |= CON_CONSDEV; | 1443 | console_drivers->flags |= CON_CONSDEV; |
1418 | 1444 | ||
1419 | release_console_sem(); | 1445 | console_unlock(); |
1446 | console_sysfs_notify(); | ||
1420 | return res; | 1447 | return res; |
1421 | } | 1448 | } |
1422 | EXPORT_SYMBOL(unregister_console); | 1449 | EXPORT_SYMBOL(unregister_console); |
@@ -1500,7 +1527,7 @@ int kmsg_dump_register(struct kmsg_dumper *dumper) | |||
1500 | /* Don't allow registering multiple times */ | 1527 | /* Don't allow registering multiple times */ |
1501 | if (!dumper->registered) { | 1528 | if (!dumper->registered) { |
1502 | dumper->registered = 1; | 1529 | dumper->registered = 1; |
1503 | list_add_tail(&dumper->list, &dump_list); | 1530 | list_add_tail_rcu(&dumper->list, &dump_list); |
1504 | err = 0; | 1531 | err = 0; |
1505 | } | 1532 | } |
1506 | spin_unlock_irqrestore(&dump_list_lock, flags); | 1533 | spin_unlock_irqrestore(&dump_list_lock, flags); |
@@ -1524,29 +1551,16 @@ int kmsg_dump_unregister(struct kmsg_dumper *dumper) | |||
1524 | spin_lock_irqsave(&dump_list_lock, flags); | 1551 | spin_lock_irqsave(&dump_list_lock, flags); |
1525 | if (dumper->registered) { | 1552 | if (dumper->registered) { |
1526 | dumper->registered = 0; | 1553 | dumper->registered = 0; |
1527 | list_del(&dumper->list); | 1554 | list_del_rcu(&dumper->list); |
1528 | err = 0; | 1555 | err = 0; |
1529 | } | 1556 | } |
1530 | spin_unlock_irqrestore(&dump_list_lock, flags); | 1557 | spin_unlock_irqrestore(&dump_list_lock, flags); |
1558 | synchronize_rcu(); | ||
1531 | 1559 | ||
1532 | return err; | 1560 | return err; |
1533 | } | 1561 | } |
1534 | EXPORT_SYMBOL_GPL(kmsg_dump_unregister); | 1562 | EXPORT_SYMBOL_GPL(kmsg_dump_unregister); |
1535 | 1563 | ||
1536 | static const char * const kmsg_reasons[] = { | ||
1537 | [KMSG_DUMP_OOPS] = "oops", | ||
1538 | [KMSG_DUMP_PANIC] = "panic", | ||
1539 | [KMSG_DUMP_KEXEC] = "kexec", | ||
1540 | }; | ||
1541 | |||
1542 | static const char *kmsg_to_str(enum kmsg_dump_reason reason) | ||
1543 | { | ||
1544 | if (reason >= ARRAY_SIZE(kmsg_reasons) || reason < 0) | ||
1545 | return "unknown"; | ||
1546 | |||
1547 | return kmsg_reasons[reason]; | ||
1548 | } | ||
1549 | |||
1550 | /** | 1564 | /** |
1551 | * kmsg_dump - dump kernel log to kernel message dumpers. | 1565 | * kmsg_dump - dump kernel log to kernel message dumpers. |
1552 | * @reason: the reason (oops, panic etc) for dumping | 1566 | * @reason: the reason (oops, panic etc) for dumping |
@@ -1585,13 +1599,9 @@ void kmsg_dump(enum kmsg_dump_reason reason) | |||
1585 | l2 = chars; | 1599 | l2 = chars; |
1586 | } | 1600 | } |
1587 | 1601 | ||
1588 | if (!spin_trylock_irqsave(&dump_list_lock, flags)) { | 1602 | rcu_read_lock(); |
1589 | printk(KERN_ERR "dump_kmsg: dump list lock is held during %s, skipping dump\n", | 1603 | list_for_each_entry_rcu(dumper, &dump_list, list) |
1590 | kmsg_to_str(reason)); | ||
1591 | return; | ||
1592 | } | ||
1593 | list_for_each_entry(dumper, &dump_list, list) | ||
1594 | dumper->dump(dumper, reason, s1, l1, s2, l2); | 1604 | dumper->dump(dumper, reason, s1, l1, s2, l2); |
1595 | spin_unlock_irqrestore(&dump_list_lock, flags); | 1605 | rcu_read_unlock(); |
1596 | } | 1606 | } |
1597 | #endif | 1607 | #endif |