aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/printk.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/printk.c')
-rw-r--r--kernel/printk.c241
1 files changed, 208 insertions, 33 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index 32462d2b364a..a2276b916769 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -227,10 +227,10 @@ static u32 clear_idx;
227#define LOG_LINE_MAX 1024 227#define LOG_LINE_MAX 1024
228 228
229/* record buffer */ 229/* record buffer */
230#if !defined(CONFIG_64BIT) || defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) 230#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
231#define LOG_ALIGN 4 231#define LOG_ALIGN 4
232#else 232#else
233#define LOG_ALIGN 8 233#define LOG_ALIGN __alignof__(struct log)
234#endif 234#endif
235#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT) 235#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
236static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN); 236static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN);
@@ -414,7 +414,9 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
414 if (!user) 414 if (!user)
415 return -EBADF; 415 return -EBADF;
416 416
417 mutex_lock(&user->lock); 417 ret = mutex_lock_interruptible(&user->lock);
418 if (ret)
419 return ret;
418 raw_spin_lock(&logbuf_lock); 420 raw_spin_lock(&logbuf_lock);
419 while (user->seq == log_next_seq) { 421 while (user->seq == log_next_seq) {
420 if (file->f_flags & O_NONBLOCK) { 422 if (file->f_flags & O_NONBLOCK) {
@@ -878,7 +880,9 @@ static int syslog_print(char __user *buf, int size)
878 syslog_seq++; 880 syslog_seq++;
879 raw_spin_unlock_irq(&logbuf_lock); 881 raw_spin_unlock_irq(&logbuf_lock);
880 882
881 if (len > 0 && copy_to_user(buf, text, len)) 883 if (len > size)
884 len = -EINVAL;
885 else if (len > 0 && copy_to_user(buf, text, len))
882 len = -EFAULT; 886 len = -EFAULT;
883 887
884 kfree(text); 888 kfree(text);
@@ -909,7 +913,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
909 /* 913 /*
910 * Find first record that fits, including all following records, 914 * Find first record that fits, including all following records,
911 * into the user-provided buffer for this dump. 915 * into the user-provided buffer for this dump.
912 */ 916 */
913 seq = clear_seq; 917 seq = clear_seq;
914 idx = clear_idx; 918 idx = clear_idx;
915 while (seq < log_next_seq) { 919 while (seq < log_next_seq) {
@@ -919,6 +923,8 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
919 idx = log_next(idx); 923 idx = log_next(idx);
920 seq++; 924 seq++;
921 } 925 }
926
927 /* move first record forward until length fits into the buffer */
922 seq = clear_seq; 928 seq = clear_seq;
923 idx = clear_idx; 929 idx = clear_idx;
924 while (len > size && seq < log_next_seq) { 930 while (len > size && seq < log_next_seq) {
@@ -929,7 +935,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
929 seq++; 935 seq++;
930 } 936 }
931 937
932 /* last message in this dump */ 938 /* last message fitting into this dump */
933 next_seq = log_next_seq; 939 next_seq = log_next_seq;
934 940
935 len = 0; 941 len = 0;
@@ -974,6 +980,7 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
974{ 980{
975 bool clear = false; 981 bool clear = false;
976 static int saved_console_loglevel = -1; 982 static int saved_console_loglevel = -1;
983 static DEFINE_MUTEX(syslog_mutex);
977 int error; 984 int error;
978 985
979 error = check_syslog_permissions(type, from_file); 986 error = check_syslog_permissions(type, from_file);
@@ -1000,11 +1007,17 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
1000 error = -EFAULT; 1007 error = -EFAULT;
1001 goto out; 1008 goto out;
1002 } 1009 }
1010 error = mutex_lock_interruptible(&syslog_mutex);
1011 if (error)
1012 goto out;
1003 error = wait_event_interruptible(log_wait, 1013 error = wait_event_interruptible(log_wait,
1004 syslog_seq != log_next_seq); 1014 syslog_seq != log_next_seq);
1005 if (error) 1015 if (error) {
1016 mutex_unlock(&syslog_mutex);
1006 goto out; 1017 goto out;
1018 }
1007 error = syslog_print(buf, len); 1019 error = syslog_print(buf, len);
1020 mutex_unlock(&syslog_mutex);
1008 break; 1021 break;
1009 /* Read/clear last kernel messages */ 1022 /* Read/clear last kernel messages */
1010 case SYSLOG_ACTION_READ_CLEAR: 1023 case SYSLOG_ACTION_READ_CLEAR:
@@ -2300,48 +2313,210 @@ module_param_named(always_kmsg_dump, always_kmsg_dump, bool, S_IRUGO | S_IWUSR);
2300 * kmsg_dump - dump kernel log to kernel message dumpers. 2313 * kmsg_dump - dump kernel log to kernel message dumpers.
2301 * @reason: the reason (oops, panic etc) for dumping 2314 * @reason: the reason (oops, panic etc) for dumping
2302 * 2315 *
2303 * Iterate through each of the dump devices and call the oops/panic 2316 * Call each of the registered dumper's dump() callback, which can
2304 * callbacks with the log buffer. 2317 * retrieve the kmsg records with kmsg_dump_get_line() or
2318 * kmsg_dump_get_buffer().
2305 */ 2319 */
2306void kmsg_dump(enum kmsg_dump_reason reason) 2320void kmsg_dump(enum kmsg_dump_reason reason)
2307{ 2321{
2308 u64 idx;
2309 struct kmsg_dumper *dumper; 2322 struct kmsg_dumper *dumper;
2310 const char *s1, *s2;
2311 unsigned long l1, l2;
2312 unsigned long flags; 2323 unsigned long flags;
2313 2324
2314 if ((reason > KMSG_DUMP_OOPS) && !always_kmsg_dump) 2325 if ((reason > KMSG_DUMP_OOPS) && !always_kmsg_dump)
2315 return; 2326 return;
2316 2327
2317 /* Theoretically, the log could move on after we do this, but 2328 rcu_read_lock();
2318 there's not a lot we can do about that. The new messages 2329 list_for_each_entry_rcu(dumper, &dump_list, list) {
2319 will overwrite the start of what we dump. */ 2330 if (dumper->max_reason && reason > dumper->max_reason)
2331 continue;
2332
2333 /* initialize iterator with data about the stored records */
2334 dumper->active = true;
2335
2336 raw_spin_lock_irqsave(&logbuf_lock, flags);
2337 dumper->cur_seq = clear_seq;
2338 dumper->cur_idx = clear_idx;
2339 dumper->next_seq = log_next_seq;
2340 dumper->next_idx = log_next_idx;
2341 raw_spin_unlock_irqrestore(&logbuf_lock, flags);
2342
2343 /* invoke dumper which will iterate over records */
2344 dumper->dump(dumper, reason);
2345
2346 /* reset iterator */
2347 dumper->active = false;
2348 }
2349 rcu_read_unlock();
2350}
2351
2352/**
2353 * kmsg_dump_get_line - retrieve one kmsg log line
2354 * @dumper: registered kmsg dumper
2355 * @syslog: include the "<4>" prefixes
2356 * @line: buffer to copy the line to
2357 * @size: maximum size of the buffer
2358 * @len: length of line placed into buffer
2359 *
2360 * Start at the beginning of the kmsg buffer, with the oldest kmsg
2361 * record, and copy one record into the provided buffer.
2362 *
2363 * Consecutive calls will return the next available record moving
2364 * towards the end of the buffer with the youngest messages.
2365 *
2366 * A return value of FALSE indicates that there are no more records to
2367 * read.
2368 */
2369bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
2370 char *line, size_t size, size_t *len)
2371{
2372 unsigned long flags;
2373 struct log *msg;
2374 size_t l = 0;
2375 bool ret = false;
2376
2377 if (!dumper->active)
2378 goto out;
2320 2379
2321 raw_spin_lock_irqsave(&logbuf_lock, flags); 2380 raw_spin_lock_irqsave(&logbuf_lock, flags);
2322 if (syslog_seq < log_first_seq) 2381 if (dumper->cur_seq < log_first_seq) {
2323 idx = syslog_idx; 2382 /* messages are gone, move to first available one */
2324 else 2383 dumper->cur_seq = log_first_seq;
2325 idx = log_first_idx; 2384 dumper->cur_idx = log_first_idx;
2385 }
2386
2387 /* last entry */
2388 if (dumper->cur_seq >= log_next_seq) {
2389 raw_spin_unlock_irqrestore(&logbuf_lock, flags);
2390 goto out;
2391 }
2326 2392
2327 if (idx > log_next_idx) { 2393 msg = log_from_idx(dumper->cur_idx);
2328 s1 = log_buf; 2394 l = msg_print_text(msg, syslog,
2329 l1 = log_next_idx; 2395 line, size);
2330 2396
2331 s2 = log_buf + idx; 2397 dumper->cur_idx = log_next(dumper->cur_idx);
2332 l2 = log_buf_len - idx; 2398 dumper->cur_seq++;
2333 } else { 2399 ret = true;
2334 s1 = ""; 2400 raw_spin_unlock_irqrestore(&logbuf_lock, flags);
2335 l1 = 0; 2401out:
2402 if (len)
2403 *len = l;
2404 return ret;
2405}
2406EXPORT_SYMBOL_GPL(kmsg_dump_get_line);
2407
2408/**
2409 * kmsg_dump_get_buffer - copy kmsg log lines
2410 * @dumper: registered kmsg dumper
2411 * @syslog: include the "<4>" prefixes
2412 * @line: buffer to copy the line to
2413 * @size: maximum size of the buffer
2414 * @len: length of line placed into buffer
2415 *
2416 * Start at the end of the kmsg buffer and fill the provided buffer
2417 * with as many of the the *youngest* kmsg records that fit into it.
2418 * If the buffer is large enough, all available kmsg records will be
2419 * copied with a single call.
2420 *
2421 * Consecutive calls will fill the buffer with the next block of
2422 * available older records, not including the earlier retrieved ones.
2423 *
2424 * A return value of FALSE indicates that there are no more records to
2425 * read.
2426 */
2427bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
2428 char *buf, size_t size, size_t *len)
2429{
2430 unsigned long flags;
2431 u64 seq;
2432 u32 idx;
2433 u64 next_seq;
2434 u32 next_idx;
2435 size_t l = 0;
2436 bool ret = false;
2437
2438 if (!dumper->active)
2439 goto out;
2440
2441 raw_spin_lock_irqsave(&logbuf_lock, flags);
2442 if (dumper->cur_seq < log_first_seq) {
2443 /* messages are gone, move to first available one */
2444 dumper->cur_seq = log_first_seq;
2445 dumper->cur_idx = log_first_idx;
2446 }
2447
2448 /* last entry */
2449 if (dumper->cur_seq >= dumper->next_seq) {
2450 raw_spin_unlock_irqrestore(&logbuf_lock, flags);
2451 goto out;
2452 }
2453
2454 /* calculate length of entire buffer */
2455 seq = dumper->cur_seq;
2456 idx = dumper->cur_idx;
2457 while (seq < dumper->next_seq) {
2458 struct log *msg = log_from_idx(idx);
2459
2460 l += msg_print_text(msg, true, NULL, 0);
2461 idx = log_next(idx);
2462 seq++;
2463 }
2336 2464
2337 s2 = log_buf + idx; 2465 /* move first record forward until length fits into the buffer */
2338 l2 = log_next_idx - idx; 2466 seq = dumper->cur_seq;
2467 idx = dumper->cur_idx;
2468 while (l > size && seq < dumper->next_seq) {
2469 struct log *msg = log_from_idx(idx);
2470
2471 l -= msg_print_text(msg, true, NULL, 0);
2472 idx = log_next(idx);
2473 seq++;
2474 }
2475
2476 /* last message in next interation */
2477 next_seq = seq;
2478 next_idx = idx;
2479
2480 l = 0;
2481 while (seq < dumper->next_seq) {
2482 struct log *msg = log_from_idx(idx);
2483
2484 l += msg_print_text(msg, syslog,
2485 buf + l, size - l);
2486
2487 idx = log_next(idx);
2488 seq++;
2339 } 2489 }
2490
2491 dumper->next_seq = next_seq;
2492 dumper->next_idx = next_idx;
2493 ret = true;
2340 raw_spin_unlock_irqrestore(&logbuf_lock, flags); 2494 raw_spin_unlock_irqrestore(&logbuf_lock, flags);
2495out:
2496 if (len)
2497 *len = l;
2498 return ret;
2499}
2500EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
2341 2501
2342 rcu_read_lock(); 2502/**
2343 list_for_each_entry_rcu(dumper, &dump_list, list) 2503 * kmsg_dump_rewind - reset the interator
2344 dumper->dump(dumper, reason, s1, l1, s2, l2); 2504 * @dumper: registered kmsg dumper
2345 rcu_read_unlock(); 2505 *
2506 * Reset the dumper's iterator so that kmsg_dump_get_line() and
2507 * kmsg_dump_get_buffer() can be called again and used multiple
2508 * times within the same dumper.dump() callback.
2509 */
2510void kmsg_dump_rewind(struct kmsg_dumper *dumper)
2511{
2512 unsigned long flags;
2513
2514 raw_spin_lock_irqsave(&logbuf_lock, flags);
2515 dumper->cur_seq = clear_seq;
2516 dumper->cur_idx = clear_idx;
2517 dumper->next_seq = log_next_seq;
2518 dumper->next_idx = log_next_idx;
2519 raw_spin_unlock_irqrestore(&logbuf_lock, flags);
2346} 2520}
2521EXPORT_SYMBOL_GPL(kmsg_dump_rewind);
2347#endif 2522#endif