.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * linux/kernel/printk.c |
---|
3 | 4 | * |
---|
.. | .. |
---|
16 | 17 | * 01Mar01 Andrew Morton |
---|
17 | 18 | */ |
---|
18 | 19 | |
---|
| 20 | +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
| 21 | + |
---|
19 | 22 | #include <linux/kernel.h> |
---|
20 | 23 | #include <linux/mm.h> |
---|
21 | 24 | #include <linux/tty.h> |
---|
.. | .. |
---|
29 | 32 | #include <linux/delay.h> |
---|
30 | 33 | #include <linux/smp.h> |
---|
31 | 34 | #include <linux/security.h> |
---|
32 | | -#include <linux/bootmem.h> |
---|
33 | 35 | #include <linux/memblock.h> |
---|
34 | 36 | #include <linux/syscalls.h> |
---|
35 | 37 | #include <linux/crash_core.h> |
---|
36 | | -#include <linux/kdb.h> |
---|
37 | 38 | #include <linux/ratelimit.h> |
---|
38 | 39 | #include <linux/kmsg_dump.h> |
---|
39 | 40 | #include <linux/syslog.h> |
---|
.. | .. |
---|
53 | 54 | #include <trace/events/initcall.h> |
---|
54 | 55 | #define CREATE_TRACE_POINTS |
---|
55 | 56 | #include <trace/events/printk.h> |
---|
| 57 | +#undef CREATE_TRACE_POINTS |
---|
| 58 | +#include <trace/hooks/printk.h> |
---|
| 59 | +#include <trace/hooks/logbuf.h> |
---|
56 | 60 | |
---|
| 61 | +#include "printk_ringbuffer.h" |
---|
57 | 62 | #include "console_cmdline.h" |
---|
58 | 63 | #include "braille.h" |
---|
59 | 64 | #include "internal.h" |
---|
.. | .. |
---|
82 | 87 | CONSOLE_LOGLEVEL_MIN, /* minimum_console_loglevel */ |
---|
83 | 88 | CONSOLE_LOGLEVEL_DEFAULT, /* default_console_loglevel */ |
---|
84 | 89 | }; |
---|
| 90 | +EXPORT_SYMBOL_GPL(console_printk); |
---|
85 | 91 | |
---|
86 | 92 | atomic_t ignore_console_lock_warning __read_mostly = ATOMIC_INIT(0); |
---|
87 | 93 | EXPORT_SYMBOL(ignore_console_lock_warning); |
---|
.. | .. |
---|
101 | 107 | static DEFINE_SEMAPHORE(console_sem); |
---|
102 | 108 | struct console *console_drivers; |
---|
103 | 109 | EXPORT_SYMBOL_GPL(console_drivers); |
---|
| 110 | + |
---|
| 111 | +/* |
---|
| 112 | + * System may need to suppress printk message under certain |
---|
| 113 | + * circumstances, like after kernel panic happens. |
---|
| 114 | + */ |
---|
| 115 | +int __read_mostly suppress_printk; |
---|
104 | 116 | |
---|
105 | 117 | #ifdef CONFIG_LOCKDEP |
---|
106 | 118 | static struct lockdep_map console_lock_dep_map = { |
---|
.. | .. |
---|
127 | 139 | |
---|
128 | 140 | static int __control_devkmsg(char *str) |
---|
129 | 141 | { |
---|
| 142 | + size_t len; |
---|
| 143 | + |
---|
130 | 144 | if (!str) |
---|
131 | 145 | return -EINVAL; |
---|
132 | 146 | |
---|
133 | | - if (!strncmp(str, "on", 2)) { |
---|
| 147 | + len = str_has_prefix(str, "on"); |
---|
| 148 | + if (len) { |
---|
134 | 149 | devkmsg_log = DEVKMSG_LOG_MASK_ON; |
---|
135 | | - return 2; |
---|
136 | | - } else if (!strncmp(str, "off", 3)) { |
---|
137 | | - devkmsg_log = DEVKMSG_LOG_MASK_OFF; |
---|
138 | | - return 3; |
---|
139 | | - } else if (!strncmp(str, "ratelimit", 9)) { |
---|
140 | | - devkmsg_log = DEVKMSG_LOG_MASK_DEFAULT; |
---|
141 | | - return 9; |
---|
| 150 | + return len; |
---|
142 | 151 | } |
---|
| 152 | + |
---|
| 153 | + len = str_has_prefix(str, "off"); |
---|
| 154 | + if (len) { |
---|
| 155 | + devkmsg_log = DEVKMSG_LOG_MASK_OFF; |
---|
| 156 | + return len; |
---|
| 157 | + } |
---|
| 158 | + |
---|
| 159 | + len = str_has_prefix(str, "ratelimit"); |
---|
| 160 | + if (len) { |
---|
| 161 | + devkmsg_log = DEVKMSG_LOG_MASK_DEFAULT; |
---|
| 162 | + return len; |
---|
| 163 | + } |
---|
| 164 | + |
---|
143 | 165 | return -EINVAL; |
---|
144 | 166 | } |
---|
145 | 167 | |
---|
146 | 168 | static int __init control_devkmsg(char *str) |
---|
147 | 169 | { |
---|
148 | | - if (__control_devkmsg(str) < 0) |
---|
| 170 | + if (__control_devkmsg(str) < 0) { |
---|
| 171 | + pr_warn("printk.devkmsg: bad option string '%s'\n", str); |
---|
149 | 172 | return 1; |
---|
| 173 | + } |
---|
150 | 174 | |
---|
151 | 175 | /* |
---|
152 | 176 | * Set sysctl string accordingly: |
---|
.. | .. |
---|
165 | 189 | */ |
---|
166 | 190 | devkmsg_log |= DEVKMSG_LOG_MASK_LOCK; |
---|
167 | 191 | |
---|
168 | | - return 0; |
---|
| 192 | + return 1; |
---|
169 | 193 | } |
---|
170 | 194 | __setup("printk.devkmsg=", control_devkmsg); |
---|
171 | 195 | |
---|
172 | 196 | char devkmsg_log_str[DEVKMSG_STR_MAX_SIZE] = "ratelimit"; |
---|
173 | 197 | |
---|
174 | 198 | int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write, |
---|
175 | | - void __user *buffer, size_t *lenp, loff_t *ppos) |
---|
| 199 | + void *buffer, size_t *lenp, loff_t *ppos) |
---|
176 | 200 | { |
---|
177 | 201 | char old_str[DEVKMSG_STR_MAX_SIZE]; |
---|
178 | 202 | unsigned int old; |
---|
.. | .. |
---|
210 | 234 | return 0; |
---|
211 | 235 | } |
---|
212 | 236 | |
---|
213 | | -/* |
---|
214 | | - * Number of registered extended console drivers. |
---|
215 | | - * |
---|
216 | | - * If extended consoles are present, in-kernel cont reassembly is disabled |
---|
217 | | - * and each fragment is stored as a separate log entry with proper |
---|
218 | | - * continuation flag so that every emitted message has full metadata. This |
---|
219 | | - * doesn't change the result for regular consoles or /proc/kmsg. For |
---|
220 | | - * /dev/kmsg, as long as the reader concatenates messages according to |
---|
221 | | - * consecutive continuation flags, the end result should be the same too. |
---|
222 | | - */ |
---|
| 237 | +/* Number of registered extended console drivers. */ |
---|
223 | 238 | static int nr_ext_console_drivers; |
---|
224 | 239 | |
---|
225 | 240 | /* |
---|
.. | .. |
---|
256 | 271 | { |
---|
257 | 272 | unsigned long flags; |
---|
258 | 273 | |
---|
259 | | - mutex_release(&console_lock_dep_map, 1, ip); |
---|
| 274 | + mutex_release(&console_lock_dep_map, ip); |
---|
260 | 275 | |
---|
261 | 276 | printk_safe_enter_irqsave(flags); |
---|
262 | 277 | up(&console_sem); |
---|
.. | .. |
---|
288 | 303 | static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES]; |
---|
289 | 304 | |
---|
290 | 305 | static int preferred_console = -1; |
---|
| 306 | +static bool has_preferred_console; |
---|
291 | 307 | int console_set_on_cmdline; |
---|
292 | 308 | EXPORT_SYMBOL(console_set_on_cmdline); |
---|
293 | 309 | |
---|
.. | .. |
---|
302 | 318 | static int console_msg_format = MSG_FORMAT_DEFAULT; |
---|
303 | 319 | |
---|
304 | 320 | /* |
---|
305 | | - * The printk log buffer consists of a chain of concatenated variable |
---|
306 | | - * length records. Every record starts with a record header, containing |
---|
307 | | - * the overall length of the record. |
---|
| 321 | + * The printk log buffer consists of a sequenced collection of records, each |
---|
| 322 | + * containing variable length message text. Every record also contains its |
---|
| 323 | + * own meta-data (@info). |
---|
308 | 324 | * |
---|
309 | | - * The heads to the first and last entry in the buffer, as well as the |
---|
310 | | - * sequence numbers of these entries are maintained when messages are |
---|
311 | | - * stored. |
---|
| 325 | + * Every record meta-data carries the timestamp in microseconds, as well as |
---|
| 326 | + * the standard userspace syslog level and syslog facility. The usual kernel |
---|
| 327 | + * messages use LOG_KERN; userspace-injected messages always carry a matching |
---|
| 328 | + * syslog facility, by default LOG_USER. The origin of every message can be |
---|
| 329 | + * reliably determined that way. |
---|
312 | 330 | * |
---|
313 | | - * If the heads indicate available messages, the length in the header |
---|
314 | | - * tells the start next message. A length == 0 for the next message |
---|
315 | | - * indicates a wrap-around to the beginning of the buffer. |
---|
| 331 | + * The human readable log message of a record is available in @text, the |
---|
| 332 | + * length of the message text in @text_len. The stored message is not |
---|
| 333 | + * terminated. |
---|
316 | 334 | * |
---|
317 | | - * Every record carries the monotonic timestamp in microseconds, as well as |
---|
318 | | - * the standard userspace syslog level and syslog facility. The usual |
---|
319 | | - * kernel messages use LOG_KERN; userspace-injected messages always carry |
---|
320 | | - * a matching syslog facility, by default LOG_USER. The origin of every |
---|
321 | | - * message can be reliably determined that way. |
---|
322 | | - * |
---|
323 | | - * The human readable log message directly follows the message header. The |
---|
324 | | - * length of the message text is stored in the header, the stored message |
---|
325 | | - * is not terminated. |
---|
326 | | - * |
---|
327 | | - * Optionally, a message can carry a dictionary of properties (key/value pairs), |
---|
328 | | - * to provide userspace with a machine-readable message context. |
---|
| 335 | + * Optionally, a record can carry a dictionary of properties (key/value |
---|
| 336 | + * pairs), to provide userspace with a machine-readable message context. |
---|
329 | 337 | * |
---|
330 | 338 | * Examples for well-defined, commonly used property names are: |
---|
331 | 339 | * DEVICE=b12:8 device identifier |
---|
.. | .. |
---|
335 | 343 | * +sound:card0 subsystem:devname |
---|
336 | 344 | * SUBSYSTEM=pci driver-core subsystem name |
---|
337 | 345 | * |
---|
338 | | - * Valid characters in property names are [a-zA-Z0-9.-_]. The plain text value |
---|
339 | | - * follows directly after a '=' character. Every property is terminated by |
---|
340 | | - * a '\0' character. The last property is not terminated. |
---|
| 346 | + * Valid characters in property names are [a-zA-Z0-9.-_]. Property names |
---|
| 347 | + * and values are terminated by a '\0' character. |
---|
341 | 348 | * |
---|
342 | | - * Example of a message structure: |
---|
343 | | - * 0000 ff 8f 00 00 00 00 00 00 monotonic time in nsec |
---|
344 | | - * 0008 34 00 record is 52 bytes long |
---|
345 | | - * 000a 0b 00 text is 11 bytes long |
---|
346 | | - * 000c 1f 00 dictionary is 23 bytes long |
---|
347 | | - * 000e 03 00 LOG_KERN (facility) LOG_ERR (level) |
---|
348 | | - * 0010 69 74 27 73 20 61 20 6c "it's a l" |
---|
349 | | - * 69 6e 65 "ine" |
---|
350 | | - * 001b 44 45 56 49 43 "DEVIC" |
---|
351 | | - * 45 3d 62 38 3a 32 00 44 "E=b8:2\0D" |
---|
352 | | - * 52 49 56 45 52 3d 62 75 "RIVER=bu" |
---|
353 | | - * 67 "g" |
---|
354 | | - * 0032 00 00 00 padding to next message header |
---|
| 349 | + * Example of record values: |
---|
| 350 | + * record.text_buf = "it's a line" (unterminated) |
---|
| 351 | + * record.info.seq = 56 |
---|
| 352 | + * record.info.ts_nsec = 36863 |
---|
| 353 | + * record.info.text_len = 11 |
---|
| 354 | + * record.info.facility = 0 (LOG_KERN) |
---|
| 355 | + * record.info.flags = 0 |
---|
| 356 | + * record.info.level = 3 (LOG_ERR) |
---|
| 357 | + * record.info.caller_id = 299 (task 299) |
---|
| 358 | + * record.info.dev_info.subsystem = "pci" (terminated) |
---|
| 359 | + * record.info.dev_info.device = "+pci:0000:00:01.0" (terminated) |
---|
355 | 360 | * |
---|
356 | | - * The 'struct printk_log' buffer header must never be directly exported to |
---|
| 361 | + * The 'struct printk_info' buffer must never be directly exported to |
---|
357 | 362 | * userspace, it is a kernel-private implementation detail that might |
---|
358 | 363 | * need to be changed in the future, when the requirements change. |
---|
359 | 364 | * |
---|
.. | .. |
---|
370 | 375 | |
---|
371 | 376 | enum log_flags { |
---|
372 | 377 | LOG_NEWLINE = 2, /* text ended with a newline */ |
---|
373 | | - LOG_PREFIX = 4, /* text started with a prefix */ |
---|
374 | 378 | LOG_CONT = 8, /* text is a fragment of a continuation line */ |
---|
375 | 379 | }; |
---|
376 | | - |
---|
377 | | -struct printk_log { |
---|
378 | | - u64 ts_nsec; /* timestamp in nanoseconds */ |
---|
379 | | - u16 len; /* length of entire record */ |
---|
380 | | - u16 text_len; /* length of text buffer */ |
---|
381 | | - u16 dict_len; /* length of dictionary buffer */ |
---|
382 | | - u8 facility; /* syslog facility */ |
---|
383 | | - u8 flags:5; /* internal record flags */ |
---|
384 | | - u8 level:3; /* syslog level */ |
---|
385 | | -#ifdef CONFIG_PRINTK_PROCESS |
---|
386 | | - char process[16]; /* process name */ |
---|
387 | | - pid_t pid; /* process id */ |
---|
388 | | - u8 cpu; /* cpu id */ |
---|
389 | | - u8 in_interrupt; /* interrupt context */ |
---|
390 | | -#endif |
---|
391 | | -} |
---|
392 | | -#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS |
---|
393 | | -__packed __aligned(4) |
---|
394 | | -#endif |
---|
395 | | -; |
---|
396 | 380 | |
---|
397 | 381 | /* |
---|
398 | 382 | * The logbuf_lock protects kmsg buffer, indices, counters. This can be taken |
---|
.. | .. |
---|
433 | 417 | DECLARE_WAIT_QUEUE_HEAD(log_wait); |
---|
434 | 418 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ |
---|
435 | 419 | static u64 syslog_seq; |
---|
436 | | -static u32 syslog_idx; |
---|
437 | 420 | static size_t syslog_partial; |
---|
438 | | - |
---|
439 | | -/* index and sequence number of the first record stored in the buffer */ |
---|
440 | | -static u64 log_first_seq; |
---|
441 | | -static u32 log_first_idx; |
---|
442 | | - |
---|
443 | | -/* index and sequence number of the next record to store in the buffer */ |
---|
444 | | -static u64 log_next_seq; |
---|
445 | | -static u32 log_next_idx; |
---|
| 421 | +static bool syslog_time; |
---|
446 | 422 | |
---|
447 | 423 | /* the next printk record to write to the console */ |
---|
448 | 424 | static u64 console_seq; |
---|
449 | | -static u32 console_idx; |
---|
450 | 425 | static u64 exclusive_console_stop_seq; |
---|
| 426 | +static unsigned long console_dropped; |
---|
451 | 427 | |
---|
452 | 428 | /* the next printk record to read after the last 'clear' command */ |
---|
453 | 429 | static u64 clear_seq; |
---|
454 | | -static u32 clear_idx; |
---|
455 | 430 | |
---|
456 | | -#ifdef CONFIG_PRINTK_PROCESS |
---|
| 431 | +#ifdef CONFIG_PRINTK_CALLER |
---|
457 | 432 | #define PREFIX_MAX 48 |
---|
458 | 433 | #else |
---|
459 | 434 | #define PREFIX_MAX 32 |
---|
.. | .. |
---|
464 | 439 | #define LOG_FACILITY(v) ((v) >> 3 & 0xff) |
---|
465 | 440 | |
---|
466 | 441 | /* record buffer */ |
---|
467 | | -#define LOG_ALIGN __alignof__(struct printk_log) |
---|
| 442 | +#define LOG_ALIGN __alignof__(unsigned long) |
---|
468 | 443 | #define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT) |
---|
469 | 444 | #define LOG_BUF_LEN_MAX (u32)(1 << 31) |
---|
470 | 445 | static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN); |
---|
471 | 446 | static char *log_buf = __log_buf; |
---|
472 | 447 | static u32 log_buf_len = __LOG_BUF_LEN; |
---|
| 448 | + |
---|
| 449 | +/* |
---|
| 450 | + * Define the average message size. This only affects the number of |
---|
| 451 | + * descriptors that will be available. Underestimating is better than |
---|
| 452 | + * overestimating (too many available descriptors is better than not enough). |
---|
| 453 | + */ |
---|
| 454 | +#define PRB_AVGBITS 5 /* 32 character average length */ |
---|
| 455 | + |
---|
| 456 | +#if CONFIG_LOG_BUF_SHIFT <= PRB_AVGBITS |
---|
| 457 | +#error CONFIG_LOG_BUF_SHIFT value too small. |
---|
| 458 | +#endif |
---|
| 459 | +_DEFINE_PRINTKRB(printk_rb_static, CONFIG_LOG_BUF_SHIFT - PRB_AVGBITS, |
---|
| 460 | + PRB_AVGBITS, &__log_buf[0]); |
---|
| 461 | + |
---|
| 462 | +static struct printk_ringbuffer printk_rb_dynamic; |
---|
| 463 | + |
---|
| 464 | +static struct printk_ringbuffer *prb = &printk_rb_static; |
---|
473 | 465 | |
---|
474 | 466 | /* |
---|
475 | 467 | * We cannot access per-CPU data (e.g. per-CPU flush irq_work) before |
---|
.. | .. |
---|
497 | 489 | } |
---|
498 | 490 | EXPORT_SYMBOL_GPL(log_buf_len_get); |
---|
499 | 491 | |
---|
500 | | -/* human readable text of the record */ |
---|
501 | | -static char *log_text(const struct printk_log *msg) |
---|
502 | | -{ |
---|
503 | | - return (char *)msg + sizeof(struct printk_log); |
---|
504 | | -} |
---|
505 | | - |
---|
506 | | -/* optional key/value pair dictionary attached to the record */ |
---|
507 | | -static char *log_dict(const struct printk_log *msg) |
---|
508 | | -{ |
---|
509 | | - return (char *)msg + sizeof(struct printk_log) + msg->text_len; |
---|
510 | | -} |
---|
511 | | - |
---|
512 | | -/* get record by index; idx must point to valid msg */ |
---|
513 | | -static struct printk_log *log_from_idx(u32 idx) |
---|
514 | | -{ |
---|
515 | | - struct printk_log *msg = (struct printk_log *)(log_buf + idx); |
---|
516 | | - |
---|
517 | | - /* |
---|
518 | | - * A length == 0 record is the end of buffer marker. Wrap around and |
---|
519 | | - * read the message at the start of the buffer. |
---|
520 | | - */ |
---|
521 | | - if (!msg->len) |
---|
522 | | - return (struct printk_log *)log_buf; |
---|
523 | | - return msg; |
---|
524 | | -} |
---|
525 | | - |
---|
526 | | -/* get next record; idx must point to valid msg */ |
---|
527 | | -static u32 log_next(u32 idx) |
---|
528 | | -{ |
---|
529 | | - struct printk_log *msg = (struct printk_log *)(log_buf + idx); |
---|
530 | | - |
---|
531 | | - /* length == 0 indicates the end of the buffer; wrap */ |
---|
532 | | - /* |
---|
533 | | - * A length == 0 record is the end of buffer marker. Wrap around and |
---|
534 | | - * read the message at the start of the buffer as *this* one, and |
---|
535 | | - * return the one after that. |
---|
536 | | - */ |
---|
537 | | - if (!msg->len) { |
---|
538 | | - msg = (struct printk_log *)log_buf; |
---|
539 | | - return msg->len; |
---|
540 | | - } |
---|
541 | | - return idx + msg->len; |
---|
542 | | -} |
---|
543 | | - |
---|
544 | | -#ifdef CONFIG_PRINTK_PROCESS |
---|
545 | | -static bool printk_process = true; |
---|
546 | | -static size_t print_process(const struct printk_log *msg, char *buf) |
---|
547 | | -{ |
---|
548 | | - if (!printk_process) |
---|
549 | | - return 0; |
---|
550 | | - |
---|
551 | | - if (!buf) |
---|
552 | | - return snprintf(NULL, 0, "%c[%1d:%15s:%5d] ", ' ', 0, " ", 0); |
---|
553 | | - |
---|
554 | | - return sprintf(buf, "%c[%1d:%15s:%5d] ", |
---|
555 | | - msg->in_interrupt ? 'I' : ' ', |
---|
556 | | - msg->cpu, |
---|
557 | | - msg->process, |
---|
558 | | - msg->pid); |
---|
559 | | -} |
---|
560 | | -module_param_named(process, printk_process, bool, 0644); |
---|
561 | | -#endif |
---|
562 | | - |
---|
563 | | -/* |
---|
564 | | - * Check whether there is enough free space for the given message. |
---|
565 | | - * |
---|
566 | | - * The same values of first_idx and next_idx mean that the buffer |
---|
567 | | - * is either empty or full. |
---|
568 | | - * |
---|
569 | | - * If the buffer is empty, we must respect the position of the indexes. |
---|
570 | | - * They cannot be reset to the beginning of the buffer. |
---|
571 | | - */ |
---|
572 | | -static int logbuf_has_space(u32 msg_size, bool empty) |
---|
573 | | -{ |
---|
574 | | - u32 free; |
---|
575 | | - |
---|
576 | | - if (log_next_idx > log_first_idx || empty) |
---|
577 | | - free = max(log_buf_len - log_next_idx, log_first_idx); |
---|
578 | | - else |
---|
579 | | - free = log_first_idx - log_next_idx; |
---|
580 | | - |
---|
581 | | - /* |
---|
582 | | - * We need space also for an empty header that signalizes wrapping |
---|
583 | | - * of the buffer. |
---|
584 | | - */ |
---|
585 | | - return free >= msg_size + sizeof(struct printk_log); |
---|
586 | | -} |
---|
587 | | - |
---|
588 | | -static int log_make_free_space(u32 msg_size) |
---|
589 | | -{ |
---|
590 | | - while (log_first_seq < log_next_seq && |
---|
591 | | - !logbuf_has_space(msg_size, false)) { |
---|
592 | | - /* drop old messages until we have enough contiguous space */ |
---|
593 | | - log_first_idx = log_next(log_first_idx); |
---|
594 | | - log_first_seq++; |
---|
595 | | - } |
---|
596 | | - |
---|
597 | | - if (clear_seq < log_first_seq) { |
---|
598 | | - clear_seq = log_first_seq; |
---|
599 | | - clear_idx = log_first_idx; |
---|
600 | | - } |
---|
601 | | - |
---|
602 | | - /* sequence numbers are equal, so the log buffer is empty */ |
---|
603 | | - if (logbuf_has_space(msg_size, log_first_seq == log_next_seq)) |
---|
604 | | - return 0; |
---|
605 | | - |
---|
606 | | - return -ENOMEM; |
---|
607 | | -} |
---|
608 | | - |
---|
609 | | -/* compute the message size including the padding bytes */ |
---|
610 | | -static u32 msg_used_size(u16 text_len, u16 dict_len, u32 *pad_len) |
---|
611 | | -{ |
---|
612 | | - u32 size; |
---|
613 | | - |
---|
614 | | - size = sizeof(struct printk_log) + text_len + dict_len; |
---|
615 | | - *pad_len = (-size) & (LOG_ALIGN - 1); |
---|
616 | | - size += *pad_len; |
---|
617 | | - |
---|
618 | | - return size; |
---|
619 | | -} |
---|
620 | | - |
---|
621 | 492 | /* |
---|
622 | 493 | * Define how much of the log buffer we could take at maximum. The value |
---|
623 | 494 | * must be greater than two. Note that only half of the buffer is available |
---|
.. | .. |
---|
626 | 497 | #define MAX_LOG_TAKE_PART 4 |
---|
627 | 498 | static const char trunc_msg[] = "<truncated>"; |
---|
628 | 499 | |
---|
629 | | -static u32 truncate_msg(u16 *text_len, u16 *trunc_msg_len, |
---|
630 | | - u16 *dict_len, u32 *pad_len) |
---|
| 500 | +static void truncate_msg(u16 *text_len, u16 *trunc_msg_len) |
---|
631 | 501 | { |
---|
632 | 502 | /* |
---|
633 | 503 | * The message should not take the whole buffer. Otherwise, it might |
---|
634 | 504 | * get removed too soon. |
---|
635 | 505 | */ |
---|
636 | 506 | u32 max_text_len = log_buf_len / MAX_LOG_TAKE_PART; |
---|
| 507 | + |
---|
637 | 508 | if (*text_len > max_text_len) |
---|
638 | 509 | *text_len = max_text_len; |
---|
639 | | - /* enable the warning message */ |
---|
| 510 | + |
---|
| 511 | + /* enable the warning message (if there is room) */ |
---|
640 | 512 | *trunc_msg_len = strlen(trunc_msg); |
---|
641 | | - /* disable the "dict" completely */ |
---|
642 | | - *dict_len = 0; |
---|
643 | | - /* compute the size again, count also the warning message */ |
---|
644 | | - return msg_used_size(*text_len + *trunc_msg_len, 0, pad_len); |
---|
| 513 | + if (*text_len >= *trunc_msg_len) |
---|
| 514 | + *text_len -= *trunc_msg_len; |
---|
| 515 | + else |
---|
| 516 | + *trunc_msg_len = 0; |
---|
645 | 517 | } |
---|
646 | 518 | |
---|
647 | 519 | /* insert record into the buffer, discard old ones, update heads */ |
---|
648 | | -static int log_store(int facility, int level, |
---|
| 520 | +static int log_store(u32 caller_id, int facility, int level, |
---|
649 | 521 | enum log_flags flags, u64 ts_nsec, |
---|
650 | | - const char *dict, u16 dict_len, |
---|
| 522 | + const struct dev_printk_info *dev_info, |
---|
651 | 523 | const char *text, u16 text_len) |
---|
652 | 524 | { |
---|
653 | | - struct printk_log *msg; |
---|
654 | | - u32 size, pad_len; |
---|
| 525 | + struct prb_reserved_entry e; |
---|
| 526 | + struct printk_record r; |
---|
655 | 527 | u16 trunc_msg_len = 0; |
---|
656 | 528 | |
---|
657 | | - /* number of '\0' padding bytes to next message */ |
---|
658 | | - size = msg_used_size(text_len, dict_len, &pad_len); |
---|
| 529 | + prb_rec_init_wr(&r, text_len); |
---|
659 | 530 | |
---|
660 | | - if (log_make_free_space(size)) { |
---|
| 531 | + if (!prb_reserve(&e, prb, &r)) { |
---|
661 | 532 | /* truncate the message if it is too long for empty buffer */ |
---|
662 | | - size = truncate_msg(&text_len, &trunc_msg_len, |
---|
663 | | - &dict_len, &pad_len); |
---|
| 533 | + truncate_msg(&text_len, &trunc_msg_len); |
---|
| 534 | + prb_rec_init_wr(&r, text_len + trunc_msg_len); |
---|
664 | 535 | /* survive when the log buffer is too small for trunc_msg */ |
---|
665 | | - if (log_make_free_space(size)) |
---|
| 536 | + if (!prb_reserve(&e, prb, &r)) |
---|
666 | 537 | return 0; |
---|
667 | 538 | } |
---|
668 | 539 | |
---|
669 | | - if (log_next_idx + size + sizeof(struct printk_log) > log_buf_len) { |
---|
670 | | - /* |
---|
671 | | - * This message + an additional empty header does not fit |
---|
672 | | - * at the end of the buffer. Add an empty header with len == 0 |
---|
673 | | - * to signify a wrap around. |
---|
674 | | - */ |
---|
675 | | - memset(log_buf + log_next_idx, 0, sizeof(struct printk_log)); |
---|
676 | | - log_next_idx = 0; |
---|
677 | | - } |
---|
678 | | - |
---|
679 | 540 | /* fill message */ |
---|
680 | | - msg = (struct printk_log *)(log_buf + log_next_idx); |
---|
681 | | - memcpy(log_text(msg), text, text_len); |
---|
682 | | - msg->text_len = text_len; |
---|
683 | | - if (trunc_msg_len) { |
---|
684 | | - memcpy(log_text(msg) + text_len, trunc_msg, trunc_msg_len); |
---|
685 | | - msg->text_len += trunc_msg_len; |
---|
686 | | - } |
---|
687 | | - memcpy(log_dict(msg), dict, dict_len); |
---|
688 | | - msg->dict_len = dict_len; |
---|
689 | | - msg->facility = facility; |
---|
690 | | - msg->level = level & 7; |
---|
691 | | - msg->flags = flags & 0x1f; |
---|
| 541 | + memcpy(&r.text_buf[0], text, text_len); |
---|
| 542 | + if (trunc_msg_len) |
---|
| 543 | + memcpy(&r.text_buf[text_len], trunc_msg, trunc_msg_len); |
---|
| 544 | + r.info->text_len = text_len + trunc_msg_len; |
---|
| 545 | + r.info->facility = facility; |
---|
| 546 | + r.info->level = level & 7; |
---|
| 547 | + r.info->flags = flags & 0x1f; |
---|
692 | 548 | if (ts_nsec > 0) |
---|
693 | | - msg->ts_nsec = ts_nsec; |
---|
| 549 | + r.info->ts_nsec = ts_nsec; |
---|
694 | 550 | else |
---|
695 | | - msg->ts_nsec = get_local_clock(); |
---|
696 | | - memset(log_dict(msg) + dict_len, 0, pad_len); |
---|
697 | | - msg->len = size; |
---|
| 551 | + r.info->ts_nsec = get_local_clock(); |
---|
| 552 | + r.info->caller_id = caller_id; |
---|
| 553 | + if (dev_info) |
---|
| 554 | + memcpy(&r.info->dev_info, dev_info, sizeof(r.info->dev_info)); |
---|
698 | 555 | |
---|
699 | | -#ifdef CONFIG_PRINTK_PROCESS |
---|
700 | | - if (printk_process) { |
---|
701 | | - strncpy(msg->process, current->comm, sizeof(msg->process) - 1); |
---|
702 | | - msg->process[sizeof(msg->process) - 1] = '\0'; |
---|
703 | | - msg->pid = task_pid_nr(current); |
---|
704 | | - msg->cpu = raw_smp_processor_id(); |
---|
705 | | - msg->in_interrupt = in_interrupt() ? 1 : 0; |
---|
706 | | - } |
---|
707 | | -#endif |
---|
| 556 | + /* A message without a trailing newline can be continued. */ |
---|
| 557 | + if (!(flags & LOG_NEWLINE)) |
---|
| 558 | + prb_commit(&e); |
---|
| 559 | + else |
---|
| 560 | + prb_final_commit(&e); |
---|
708 | 561 | |
---|
709 | | - /* insert message */ |
---|
710 | | - log_next_idx += msg->len; |
---|
711 | | - log_next_seq++; |
---|
| 562 | + trace_android_vh_logbuf(prb, &r); |
---|
712 | 563 | |
---|
713 | | - return msg->text_len; |
---|
| 564 | + return (text_len + trunc_msg_len); |
---|
714 | 565 | } |
---|
715 | 566 | |
---|
716 | 567 | int dmesg_restrict = IS_ENABLED(CONFIG_SECURITY_DMESG_RESTRICT); |
---|
.. | .. |
---|
762 | 613 | *(*pp)++ = c; |
---|
763 | 614 | } |
---|
764 | 615 | |
---|
765 | | -static ssize_t msg_print_ext_header(char *buf, size_t size, |
---|
766 | | - struct printk_log *msg, u64 seq) |
---|
| 616 | +static ssize_t info_print_ext_header(char *buf, size_t size, |
---|
| 617 | + struct printk_info *info) |
---|
767 | 618 | { |
---|
768 | | - u64 ts_usec = msg->ts_nsec; |
---|
| 619 | + u64 ts_usec = info->ts_nsec; |
---|
| 620 | + char caller[20]; |
---|
| 621 | +#ifdef CONFIG_PRINTK_CALLER |
---|
| 622 | + u32 id = info->caller_id; |
---|
| 623 | + |
---|
| 624 | + snprintf(caller, sizeof(caller), ",caller=%c%u", |
---|
| 625 | + id & 0x80000000 ? 'C' : 'T', id & ~0x80000000); |
---|
| 626 | +#else |
---|
| 627 | + caller[0] = '\0'; |
---|
| 628 | +#endif |
---|
769 | 629 | |
---|
770 | 630 | do_div(ts_usec, 1000); |
---|
771 | 631 | |
---|
772 | | - return scnprintf(buf, size, "%u,%llu,%llu,%c;", |
---|
773 | | - (msg->facility << 3) | msg->level, seq, ts_usec, |
---|
774 | | - msg->flags & LOG_CONT ? 'c' : '-'); |
---|
| 632 | + return scnprintf(buf, size, "%u,%llu,%llu,%c%s;", |
---|
| 633 | + (info->facility << 3) | info->level, info->seq, |
---|
| 634 | + ts_usec, info->flags & LOG_CONT ? 'c' : '-', caller); |
---|
775 | 635 | } |
---|
776 | 636 | |
---|
777 | | -static ssize_t msg_print_ext_body(char *buf, size_t size, |
---|
778 | | - char *dict, size_t dict_len, |
---|
779 | | - char *text, size_t text_len) |
---|
| 637 | +static ssize_t msg_add_ext_text(char *buf, size_t size, |
---|
| 638 | + const char *text, size_t text_len, |
---|
| 639 | + unsigned char endc) |
---|
780 | 640 | { |
---|
781 | 641 | char *p = buf, *e = buf + size; |
---|
782 | 642 | size_t i; |
---|
.. | .. |
---|
790 | 650 | else |
---|
791 | 651 | append_char(&p, e, c); |
---|
792 | 652 | } |
---|
793 | | - append_char(&p, e, '\n'); |
---|
794 | | - |
---|
795 | | - if (dict_len) { |
---|
796 | | - bool line = true; |
---|
797 | | - |
---|
798 | | - for (i = 0; i < dict_len; i++) { |
---|
799 | | - unsigned char c = dict[i]; |
---|
800 | | - |
---|
801 | | - if (line) { |
---|
802 | | - append_char(&p, e, ' '); |
---|
803 | | - line = false; |
---|
804 | | - } |
---|
805 | | - |
---|
806 | | - if (c == '\0') { |
---|
807 | | - append_char(&p, e, '\n'); |
---|
808 | | - line = true; |
---|
809 | | - continue; |
---|
810 | | - } |
---|
811 | | - |
---|
812 | | - if (c < ' ' || c >= 127 || c == '\\') { |
---|
813 | | - p += scnprintf(p, e - p, "\\x%02x", c); |
---|
814 | | - continue; |
---|
815 | | - } |
---|
816 | | - |
---|
817 | | - append_char(&p, e, c); |
---|
818 | | - } |
---|
819 | | - append_char(&p, e, '\n'); |
---|
820 | | - } |
---|
| 653 | + append_char(&p, e, endc); |
---|
821 | 654 | |
---|
822 | 655 | return p - buf; |
---|
| 656 | +} |
---|
| 657 | + |
---|
| 658 | +static ssize_t msg_add_dict_text(char *buf, size_t size, |
---|
| 659 | + const char *key, const char *val) |
---|
| 660 | +{ |
---|
| 661 | + size_t val_len = strlen(val); |
---|
| 662 | + ssize_t len; |
---|
| 663 | + |
---|
| 664 | + if (!val_len) |
---|
| 665 | + return 0; |
---|
| 666 | + |
---|
| 667 | + len = msg_add_ext_text(buf, size, "", 0, ' '); /* dict prefix */ |
---|
| 668 | + len += msg_add_ext_text(buf + len, size - len, key, strlen(key), '='); |
---|
| 669 | + len += msg_add_ext_text(buf + len, size - len, val, val_len, '\n'); |
---|
| 670 | + |
---|
| 671 | + return len; |
---|
| 672 | +} |
---|
| 673 | + |
---|
| 674 | +static ssize_t msg_print_ext_body(char *buf, size_t size, |
---|
| 675 | + char *text, size_t text_len, |
---|
| 676 | + struct dev_printk_info *dev_info) |
---|
| 677 | +{ |
---|
| 678 | + ssize_t len; |
---|
| 679 | + |
---|
| 680 | + len = msg_add_ext_text(buf, size, text, text_len, '\n'); |
---|
| 681 | + |
---|
| 682 | + if (!dev_info) |
---|
| 683 | + goto out; |
---|
| 684 | + |
---|
| 685 | + len += msg_add_dict_text(buf + len, size - len, "SUBSYSTEM", |
---|
| 686 | + dev_info->subsystem); |
---|
| 687 | + len += msg_add_dict_text(buf + len, size - len, "DEVICE", |
---|
| 688 | + dev_info->device); |
---|
| 689 | +out: |
---|
| 690 | + return len; |
---|
823 | 691 | } |
---|
824 | 692 | |
---|
825 | 693 | /* /dev/kmsg - userspace message inject/listen interface */ |
---|
826 | 694 | struct devkmsg_user { |
---|
827 | 695 | u64 seq; |
---|
828 | | - u32 idx; |
---|
829 | 696 | struct ratelimit_state rs; |
---|
830 | 697 | struct mutex lock; |
---|
831 | 698 | char buf[CONSOLE_EXT_LOG_MAX]; |
---|
| 699 | + |
---|
| 700 | + struct printk_info info; |
---|
| 701 | + char text_buf[CONSOLE_EXT_LOG_MAX]; |
---|
| 702 | + struct printk_record record; |
---|
832 | 703 | }; |
---|
| 704 | + |
---|
| 705 | +static __printf(3, 4) __cold |
---|
| 706 | +int devkmsg_emit(int facility, int level, const char *fmt, ...) |
---|
| 707 | +{ |
---|
| 708 | + va_list args; |
---|
| 709 | + int r; |
---|
| 710 | + |
---|
| 711 | + va_start(args, fmt); |
---|
| 712 | + r = vprintk_emit(facility, level, NULL, fmt, args); |
---|
| 713 | + va_end(args); |
---|
| 714 | + |
---|
| 715 | + return r; |
---|
| 716 | +} |
---|
833 | 717 | |
---|
834 | 718 | static ssize_t devkmsg_write(struct kiocb *iocb, struct iov_iter *from) |
---|
835 | 719 | { |
---|
.. | .. |
---|
889 | 773 | } |
---|
890 | 774 | } |
---|
891 | 775 | |
---|
892 | | - printk_emit(facility, level, NULL, 0, "%s", line); |
---|
| 776 | + devkmsg_emit(facility, level, "%s", line); |
---|
893 | 777 | kfree(buf); |
---|
894 | 778 | return ret; |
---|
895 | 779 | } |
---|
.. | .. |
---|
898 | 782 | size_t count, loff_t *ppos) |
---|
899 | 783 | { |
---|
900 | 784 | struct devkmsg_user *user = file->private_data; |
---|
901 | | - struct printk_log *msg; |
---|
| 785 | + struct printk_record *r = &user->record; |
---|
902 | 786 | size_t len; |
---|
903 | 787 | ssize_t ret; |
---|
904 | 788 | |
---|
.. | .. |
---|
910 | 794 | return ret; |
---|
911 | 795 | |
---|
912 | 796 | logbuf_lock_irq(); |
---|
913 | | - while (user->seq == log_next_seq) { |
---|
| 797 | + if (!prb_read_valid(prb, user->seq, r)) { |
---|
914 | 798 | if (file->f_flags & O_NONBLOCK) { |
---|
915 | 799 | ret = -EAGAIN; |
---|
916 | 800 | logbuf_unlock_irq(); |
---|
.. | .. |
---|
919 | 803 | |
---|
920 | 804 | logbuf_unlock_irq(); |
---|
921 | 805 | ret = wait_event_interruptible(log_wait, |
---|
922 | | - user->seq != log_next_seq); |
---|
| 806 | + prb_read_valid(prb, user->seq, r)); |
---|
923 | 807 | if (ret) |
---|
924 | 808 | goto out; |
---|
925 | 809 | logbuf_lock_irq(); |
---|
926 | 810 | } |
---|
927 | 811 | |
---|
928 | | - if (user->seq < log_first_seq) { |
---|
| 812 | + if (r->info->seq != user->seq) { |
---|
929 | 813 | /* our last seen message is gone, return error and reset */ |
---|
930 | | - user->idx = log_first_idx; |
---|
931 | | - user->seq = log_first_seq; |
---|
| 814 | + user->seq = r->info->seq; |
---|
932 | 815 | ret = -EPIPE; |
---|
933 | 816 | logbuf_unlock_irq(); |
---|
934 | 817 | goto out; |
---|
935 | 818 | } |
---|
936 | 819 | |
---|
937 | | - msg = log_from_idx(user->idx); |
---|
938 | | - len = msg_print_ext_header(user->buf, sizeof(user->buf), |
---|
939 | | - msg, user->seq); |
---|
| 820 | + len = info_print_ext_header(user->buf, sizeof(user->buf), r->info); |
---|
940 | 821 | len += msg_print_ext_body(user->buf + len, sizeof(user->buf) - len, |
---|
941 | | - log_dict(msg), msg->dict_len, |
---|
942 | | - log_text(msg), msg->text_len); |
---|
| 822 | + &r->text_buf[0], r->info->text_len, |
---|
| 823 | + &r->info->dev_info); |
---|
943 | 824 | |
---|
944 | | - user->idx = log_next(user->idx); |
---|
945 | | - user->seq++; |
---|
| 825 | + user->seq = r->info->seq + 1; |
---|
946 | 826 | logbuf_unlock_irq(); |
---|
947 | 827 | |
---|
948 | 828 | if (len > count) { |
---|
.. | .. |
---|
960 | 840 | return ret; |
---|
961 | 841 | } |
---|
962 | 842 | |
---|
| 843 | +/* |
---|
| 844 | + * Be careful when modifying this function!!! |
---|
| 845 | + * |
---|
| 846 | + * Only few operations are supported because the device works only with the |
---|
| 847 | + * entire variable length messages (records). Non-standard values are |
---|
| 848 | + * returned in the other cases and has been this way for quite some time. |
---|
| 849 | + * User space applications might depend on this behavior. |
---|
| 850 | + */ |
---|
963 | 851 | static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence) |
---|
964 | 852 | { |
---|
965 | 853 | struct devkmsg_user *user = file->private_data; |
---|
.. | .. |
---|
974 | 862 | switch (whence) { |
---|
975 | 863 | case SEEK_SET: |
---|
976 | 864 | /* the first record */ |
---|
977 | | - user->idx = log_first_idx; |
---|
978 | | - user->seq = log_first_seq; |
---|
| 865 | + user->seq = prb_first_valid_seq(prb); |
---|
979 | 866 | break; |
---|
980 | 867 | case SEEK_DATA: |
---|
981 | 868 | /* |
---|
.. | .. |
---|
983 | 870 | * like issued by 'dmesg -c'. Reading /dev/kmsg itself |
---|
984 | 871 | * changes no global state, and does not clear anything. |
---|
985 | 872 | */ |
---|
986 | | - user->idx = clear_idx; |
---|
987 | 873 | user->seq = clear_seq; |
---|
988 | 874 | break; |
---|
989 | 875 | case SEEK_END: |
---|
990 | 876 | /* after the last record */ |
---|
991 | | - user->idx = log_next_idx; |
---|
992 | | - user->seq = log_next_seq; |
---|
| 877 | + user->seq = prb_next_seq(prb); |
---|
993 | 878 | break; |
---|
994 | 879 | default: |
---|
995 | 880 | ret = -EINVAL; |
---|
.. | .. |
---|
1001 | 886 | static __poll_t devkmsg_poll(struct file *file, poll_table *wait) |
---|
1002 | 887 | { |
---|
1003 | 888 | struct devkmsg_user *user = file->private_data; |
---|
| 889 | + struct printk_info info; |
---|
1004 | 890 | __poll_t ret = 0; |
---|
1005 | 891 | |
---|
1006 | 892 | if (!user) |
---|
.. | .. |
---|
1009 | 895 | poll_wait(file, &log_wait, wait); |
---|
1010 | 896 | |
---|
1011 | 897 | logbuf_lock_irq(); |
---|
1012 | | - if (user->seq < log_next_seq) { |
---|
| 898 | + if (prb_read_valid_info(prb, user->seq, &info, NULL)) { |
---|
1013 | 899 | /* return error when data has vanished underneath us */ |
---|
1014 | | - if (user->seq < log_first_seq) |
---|
| 900 | + if (info.seq != user->seq) |
---|
1015 | 901 | ret = EPOLLIN|EPOLLRDNORM|EPOLLERR|EPOLLPRI; |
---|
1016 | 902 | else |
---|
1017 | 903 | ret = EPOLLIN|EPOLLRDNORM; |
---|
.. | .. |
---|
1046 | 932 | |
---|
1047 | 933 | mutex_init(&user->lock); |
---|
1048 | 934 | |
---|
| 935 | + prb_rec_init_rd(&user->record, &user->info, |
---|
| 936 | + &user->text_buf[0], sizeof(user->text_buf)); |
---|
| 937 | + |
---|
1049 | 938 | logbuf_lock_irq(); |
---|
1050 | | - user->idx = log_first_idx; |
---|
1051 | | - user->seq = log_first_seq; |
---|
| 939 | + user->seq = prb_first_valid_seq(prb); |
---|
1052 | 940 | logbuf_unlock_irq(); |
---|
1053 | 941 | |
---|
1054 | 942 | file->private_data = user; |
---|
.. | .. |
---|
1089 | 977 | */ |
---|
1090 | 978 | void log_buf_vmcoreinfo_setup(void) |
---|
1091 | 979 | { |
---|
1092 | | - VMCOREINFO_SYMBOL(log_buf); |
---|
1093 | | - VMCOREINFO_SYMBOL(log_buf_len); |
---|
1094 | | - VMCOREINFO_SYMBOL(log_first_idx); |
---|
1095 | | - VMCOREINFO_SYMBOL(clear_idx); |
---|
1096 | | - VMCOREINFO_SYMBOL(log_next_idx); |
---|
| 980 | + struct dev_printk_info *dev_info = NULL; |
---|
| 981 | + |
---|
| 982 | + VMCOREINFO_SYMBOL(prb); |
---|
| 983 | + VMCOREINFO_SYMBOL(printk_rb_static); |
---|
| 984 | + VMCOREINFO_SYMBOL(clear_seq); |
---|
| 985 | + |
---|
1097 | 986 | /* |
---|
1098 | | - * Export struct printk_log size and field offsets. User space tools can |
---|
| 987 | + * Export struct size and field offsets. User space tools can |
---|
1099 | 988 | * parse it and detect any changes to structure down the line. |
---|
1100 | 989 | */ |
---|
1101 | | - VMCOREINFO_STRUCT_SIZE(printk_log); |
---|
1102 | | - VMCOREINFO_OFFSET(printk_log, ts_nsec); |
---|
1103 | | - VMCOREINFO_OFFSET(printk_log, len); |
---|
1104 | | - VMCOREINFO_OFFSET(printk_log, text_len); |
---|
1105 | | - VMCOREINFO_OFFSET(printk_log, dict_len); |
---|
| 990 | + |
---|
| 991 | + VMCOREINFO_STRUCT_SIZE(printk_ringbuffer); |
---|
| 992 | + VMCOREINFO_OFFSET(printk_ringbuffer, desc_ring); |
---|
| 993 | + VMCOREINFO_OFFSET(printk_ringbuffer, text_data_ring); |
---|
| 994 | + VMCOREINFO_OFFSET(printk_ringbuffer, fail); |
---|
| 995 | + |
---|
| 996 | + VMCOREINFO_STRUCT_SIZE(prb_desc_ring); |
---|
| 997 | + VMCOREINFO_OFFSET(prb_desc_ring, count_bits); |
---|
| 998 | + VMCOREINFO_OFFSET(prb_desc_ring, descs); |
---|
| 999 | + VMCOREINFO_OFFSET(prb_desc_ring, infos); |
---|
| 1000 | + VMCOREINFO_OFFSET(prb_desc_ring, head_id); |
---|
| 1001 | + VMCOREINFO_OFFSET(prb_desc_ring, tail_id); |
---|
| 1002 | + |
---|
| 1003 | + VMCOREINFO_STRUCT_SIZE(prb_desc); |
---|
| 1004 | + VMCOREINFO_OFFSET(prb_desc, state_var); |
---|
| 1005 | + VMCOREINFO_OFFSET(prb_desc, text_blk_lpos); |
---|
| 1006 | + |
---|
| 1007 | + VMCOREINFO_STRUCT_SIZE(prb_data_blk_lpos); |
---|
| 1008 | + VMCOREINFO_OFFSET(prb_data_blk_lpos, begin); |
---|
| 1009 | + VMCOREINFO_OFFSET(prb_data_blk_lpos, next); |
---|
| 1010 | + |
---|
| 1011 | + VMCOREINFO_STRUCT_SIZE(printk_info); |
---|
| 1012 | + VMCOREINFO_OFFSET(printk_info, seq); |
---|
| 1013 | + VMCOREINFO_OFFSET(printk_info, ts_nsec); |
---|
| 1014 | + VMCOREINFO_OFFSET(printk_info, text_len); |
---|
| 1015 | + VMCOREINFO_OFFSET(printk_info, caller_id); |
---|
| 1016 | + VMCOREINFO_OFFSET(printk_info, dev_info); |
---|
| 1017 | + |
---|
| 1018 | + VMCOREINFO_STRUCT_SIZE(dev_printk_info); |
---|
| 1019 | + VMCOREINFO_OFFSET(dev_printk_info, subsystem); |
---|
| 1020 | + VMCOREINFO_LENGTH(printk_info_subsystem, sizeof(dev_info->subsystem)); |
---|
| 1021 | + VMCOREINFO_OFFSET(dev_printk_info, device); |
---|
| 1022 | + VMCOREINFO_LENGTH(printk_info_device, sizeof(dev_info->device)); |
---|
| 1023 | + |
---|
| 1024 | + VMCOREINFO_STRUCT_SIZE(prb_data_ring); |
---|
| 1025 | + VMCOREINFO_OFFSET(prb_data_ring, size_bits); |
---|
| 1026 | + VMCOREINFO_OFFSET(prb_data_ring, data); |
---|
| 1027 | + VMCOREINFO_OFFSET(prb_data_ring, head_lpos); |
---|
| 1028 | + VMCOREINFO_OFFSET(prb_data_ring, tail_lpos); |
---|
| 1029 | + |
---|
| 1030 | + VMCOREINFO_SIZE(atomic_long_t); |
---|
| 1031 | + VMCOREINFO_TYPE_OFFSET(atomic_long_t, counter); |
---|
1106 | 1032 | } |
---|
1107 | 1033 | #endif |
---|
1108 | 1034 | |
---|
.. | .. |
---|
1180 | 1106 | __printk_percpu_data_ready = true; |
---|
1181 | 1107 | } |
---|
1182 | 1108 | |
---|
| 1109 | +static unsigned int __init add_to_rb(struct printk_ringbuffer *rb, |
---|
| 1110 | + struct printk_record *r) |
---|
| 1111 | +{ |
---|
| 1112 | + struct prb_reserved_entry e; |
---|
| 1113 | + struct printk_record dest_r; |
---|
| 1114 | + |
---|
| 1115 | + prb_rec_init_wr(&dest_r, r->info->text_len); |
---|
| 1116 | + |
---|
| 1117 | + if (!prb_reserve(&e, rb, &dest_r)) |
---|
| 1118 | + return 0; |
---|
| 1119 | + |
---|
| 1120 | + memcpy(&dest_r.text_buf[0], &r->text_buf[0], r->info->text_len); |
---|
| 1121 | + dest_r.info->text_len = r->info->text_len; |
---|
| 1122 | + dest_r.info->facility = r->info->facility; |
---|
| 1123 | + dest_r.info->level = r->info->level; |
---|
| 1124 | + dest_r.info->flags = r->info->flags; |
---|
| 1125 | + dest_r.info->ts_nsec = r->info->ts_nsec; |
---|
| 1126 | + dest_r.info->caller_id = r->info->caller_id; |
---|
| 1127 | + memcpy(&dest_r.info->dev_info, &r->info->dev_info, sizeof(dest_r.info->dev_info)); |
---|
| 1128 | + |
---|
| 1129 | + prb_final_commit(&e); |
---|
| 1130 | + |
---|
| 1131 | + return prb_record_text_space(&e); |
---|
| 1132 | +} |
---|
| 1133 | + |
---|
| 1134 | +static char setup_text_buf[LOG_LINE_MAX] __initdata; |
---|
| 1135 | + |
---|
1183 | 1136 | void __init setup_log_buf(int early) |
---|
1184 | 1137 | { |
---|
| 1138 | + struct printk_info *new_infos; |
---|
| 1139 | + unsigned int new_descs_count; |
---|
| 1140 | + struct prb_desc *new_descs; |
---|
| 1141 | + struct printk_info info; |
---|
| 1142 | + struct printk_record r; |
---|
| 1143 | + size_t new_descs_size; |
---|
| 1144 | + size_t new_infos_size; |
---|
1185 | 1145 | unsigned long flags; |
---|
1186 | 1146 | char *new_log_buf; |
---|
1187 | 1147 | unsigned int free; |
---|
| 1148 | + u64 seq; |
---|
1188 | 1149 | |
---|
1189 | 1150 | /* |
---|
1190 | 1151 | * Some archs call setup_log_buf() multiple times - first is very |
---|
.. | .. |
---|
1203 | 1164 | if (!new_log_buf_len) |
---|
1204 | 1165 | return; |
---|
1205 | 1166 | |
---|
1206 | | - if (early) { |
---|
1207 | | - new_log_buf = |
---|
1208 | | - memblock_virt_alloc(new_log_buf_len, LOG_ALIGN); |
---|
1209 | | - } else { |
---|
1210 | | - new_log_buf = memblock_virt_alloc_nopanic(new_log_buf_len, |
---|
1211 | | - LOG_ALIGN); |
---|
1212 | | - } |
---|
1213 | | - |
---|
1214 | | - if (unlikely(!new_log_buf)) { |
---|
1215 | | - pr_err("log_buf_len: %lu bytes not available\n", |
---|
1216 | | - new_log_buf_len); |
---|
| 1167 | + new_descs_count = new_log_buf_len >> PRB_AVGBITS; |
---|
| 1168 | + if (new_descs_count == 0) { |
---|
| 1169 | + pr_err("new_log_buf_len: %lu too small\n", new_log_buf_len); |
---|
1217 | 1170 | return; |
---|
1218 | 1171 | } |
---|
1219 | 1172 | |
---|
| 1173 | + new_log_buf = memblock_alloc(new_log_buf_len, LOG_ALIGN); |
---|
| 1174 | + if (unlikely(!new_log_buf)) { |
---|
| 1175 | + pr_err("log_buf_len: %lu text bytes not available\n", |
---|
| 1176 | + new_log_buf_len); |
---|
| 1177 | + return; |
---|
| 1178 | + } |
---|
| 1179 | + |
---|
| 1180 | + new_descs_size = new_descs_count * sizeof(struct prb_desc); |
---|
| 1181 | + new_descs = memblock_alloc(new_descs_size, LOG_ALIGN); |
---|
| 1182 | + if (unlikely(!new_descs)) { |
---|
| 1183 | + pr_err("log_buf_len: %zu desc bytes not available\n", |
---|
| 1184 | + new_descs_size); |
---|
| 1185 | + goto err_free_log_buf; |
---|
| 1186 | + } |
---|
| 1187 | + |
---|
| 1188 | + new_infos_size = new_descs_count * sizeof(struct printk_info); |
---|
| 1189 | + new_infos = memblock_alloc(new_infos_size, LOG_ALIGN); |
---|
| 1190 | + if (unlikely(!new_infos)) { |
---|
| 1191 | + pr_err("log_buf_len: %zu info bytes not available\n", |
---|
| 1192 | + new_infos_size); |
---|
| 1193 | + goto err_free_descs; |
---|
| 1194 | + } |
---|
| 1195 | + |
---|
| 1196 | + prb_rec_init_rd(&r, &info, &setup_text_buf[0], sizeof(setup_text_buf)); |
---|
| 1197 | + |
---|
| 1198 | + prb_init(&printk_rb_dynamic, |
---|
| 1199 | + new_log_buf, ilog2(new_log_buf_len), |
---|
| 1200 | + new_descs, ilog2(new_descs_count), |
---|
| 1201 | + new_infos); |
---|
| 1202 | + |
---|
1220 | 1203 | logbuf_lock_irqsave(flags); |
---|
| 1204 | + |
---|
1221 | 1205 | log_buf_len = new_log_buf_len; |
---|
1222 | 1206 | log_buf = new_log_buf; |
---|
1223 | 1207 | new_log_buf_len = 0; |
---|
1224 | | - free = __LOG_BUF_LEN - log_next_idx; |
---|
1225 | | - memcpy(log_buf, __log_buf, __LOG_BUF_LEN); |
---|
| 1208 | + |
---|
| 1209 | + free = __LOG_BUF_LEN; |
---|
| 1210 | + prb_for_each_record(0, &printk_rb_static, seq, &r) |
---|
| 1211 | + free -= add_to_rb(&printk_rb_dynamic, &r); |
---|
| 1212 | + |
---|
| 1213 | + /* |
---|
| 1214 | + * This is early enough that everything is still running on the |
---|
| 1215 | + * boot CPU and interrupts are disabled. So no new messages will |
---|
| 1216 | + * appear during the transition to the dynamic buffer. |
---|
| 1217 | + */ |
---|
| 1218 | + prb = &printk_rb_dynamic; |
---|
| 1219 | + |
---|
1226 | 1220 | logbuf_unlock_irqrestore(flags); |
---|
| 1221 | + |
---|
| 1222 | + if (seq != prb_next_seq(&printk_rb_static)) { |
---|
| 1223 | + pr_err("dropped %llu messages\n", |
---|
| 1224 | + prb_next_seq(&printk_rb_static) - seq); |
---|
| 1225 | + } |
---|
1227 | 1226 | |
---|
1228 | 1227 | pr_info("log_buf_len: %u bytes\n", log_buf_len); |
---|
1229 | 1228 | pr_info("early log buf free: %u(%u%%)\n", |
---|
1230 | 1229 | free, (free * 100) / __LOG_BUF_LEN); |
---|
| 1230 | + return; |
---|
| 1231 | + |
---|
| 1232 | +err_free_descs: |
---|
| 1233 | + memblock_free(__pa(new_descs), new_descs_size); |
---|
| 1234 | +err_free_log_buf: |
---|
| 1235 | + memblock_free(__pa(new_log_buf), new_log_buf_len); |
---|
1231 | 1236 | } |
---|
1232 | 1237 | |
---|
1233 | | -#ifdef CONFIG_PSTORE_CONSOLE_FORCE_ON |
---|
1234 | | -static bool __read_mostly ignore_loglevel = true; |
---|
1235 | | -#else |
---|
1236 | 1238 | static bool __read_mostly ignore_loglevel; |
---|
1237 | | -#endif |
---|
1238 | 1239 | |
---|
1239 | 1240 | static int __init ignore_loglevel_setup(char *str) |
---|
1240 | 1241 | { |
---|
.. | .. |
---|
1248 | 1249 | module_param(ignore_loglevel, bool, S_IRUGO | S_IWUSR); |
---|
1249 | 1250 | MODULE_PARM_DESC(ignore_loglevel, |
---|
1250 | 1251 | "ignore loglevel setting (prints all kernel messages to the console)"); |
---|
1251 | | - |
---|
1252 | | -#ifdef CONFIG_PSTORE_CONSOLE_FORCE |
---|
1253 | | -static bool __read_mostly pstore_con_force = IS_ENABLED(CONFIG_PSTORE_CONSOLE_FORCE_ON); |
---|
1254 | | - |
---|
1255 | | -static int __init pstore_con_force_setup(char *str) |
---|
1256 | | -{ |
---|
1257 | | - bool force; |
---|
1258 | | - int ret = strtobool(str, &force); |
---|
1259 | | - |
---|
1260 | | - if (ret) |
---|
1261 | | - return ret; |
---|
1262 | | - |
---|
1263 | | - ignore_loglevel = force; |
---|
1264 | | - pstore_con_force = force; |
---|
1265 | | - if (force) |
---|
1266 | | - pr_info("debug: pstore console ignoring loglevel setting.\n"); |
---|
1267 | | - |
---|
1268 | | - return 0; |
---|
1269 | | -} |
---|
1270 | | - |
---|
1271 | | -early_param("pstore_con_force", pstore_con_force_setup); |
---|
1272 | | -module_param(pstore_con_force, bool, S_IRUGO | S_IWUSR); |
---|
1273 | | -MODULE_PARM_DESC(pstore_con_force, |
---|
1274 | | - "ignore loglevel setting (prints all kernel messages to the pstore console)"); |
---|
1275 | | - |
---|
1276 | | -static void call_console_drivers_level(int level, const char *ext_text, size_t ext_len, |
---|
1277 | | - const char *text, size_t len) |
---|
1278 | | -{ |
---|
1279 | | - struct console *con; |
---|
1280 | | - |
---|
1281 | | - trace_console_rcuidle(text, len); |
---|
1282 | | - |
---|
1283 | | - if (!console_drivers) |
---|
1284 | | - return; |
---|
1285 | | - |
---|
1286 | | - for_each_console(con) { |
---|
1287 | | - if (pstore_con_force && |
---|
1288 | | - !(con->flags & CON_PSTORE) && level >= console_loglevel) |
---|
1289 | | - continue; |
---|
1290 | | - if (exclusive_console && con != exclusive_console) |
---|
1291 | | - continue; |
---|
1292 | | - if (!(con->flags & CON_ENABLED)) |
---|
1293 | | - continue; |
---|
1294 | | - if (!con->write) |
---|
1295 | | - continue; |
---|
1296 | | - if (!cpu_online(smp_processor_id()) && |
---|
1297 | | - !(con->flags & CON_ANYTIME)) |
---|
1298 | | - continue; |
---|
1299 | | - if (con->flags & CON_EXTENDED) |
---|
1300 | | - con->write(con, ext_text, ext_len); |
---|
1301 | | - else |
---|
1302 | | - con->write(con, text, len); |
---|
1303 | | - } |
---|
1304 | | -} |
---|
1305 | | -#endif |
---|
1306 | 1252 | |
---|
1307 | 1253 | static bool suppress_message_printing(int level) |
---|
1308 | 1254 | { |
---|
.. | .. |
---|
1367 | 1313 | static bool printk_time = IS_ENABLED(CONFIG_PRINTK_TIME); |
---|
1368 | 1314 | module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR); |
---|
1369 | 1315 | |
---|
| 1316 | +static size_t print_syslog(unsigned int level, char *buf) |
---|
| 1317 | +{ |
---|
| 1318 | + return sprintf(buf, "<%u>", level); |
---|
| 1319 | +} |
---|
| 1320 | + |
---|
1370 | 1321 | static size_t print_time(u64 ts, char *buf) |
---|
1371 | 1322 | { |
---|
1372 | | - unsigned long rem_nsec; |
---|
| 1323 | + unsigned long rem_nsec = do_div(ts, 1000000000); |
---|
1373 | 1324 | |
---|
1374 | | - if (!printk_time) |
---|
1375 | | - return 0; |
---|
1376 | | - |
---|
1377 | | - rem_nsec = do_div(ts, 1000000000); |
---|
1378 | | - |
---|
1379 | | - if (!buf) |
---|
1380 | | - return snprintf(NULL, 0, "[%5lu.000000] ", (unsigned long)ts); |
---|
1381 | | - |
---|
1382 | | - return sprintf(buf, "[%5lu.%06lu] ", |
---|
| 1325 | + return sprintf(buf, "[%5lu.%06lu]", |
---|
1383 | 1326 | (unsigned long)ts, rem_nsec / 1000); |
---|
1384 | 1327 | } |
---|
1385 | 1328 | |
---|
1386 | | -static size_t print_prefix(const struct printk_log *msg, bool syslog, char *buf) |
---|
| 1329 | +#ifdef CONFIG_PRINTK_CALLER |
---|
| 1330 | +static size_t print_caller(u32 id, char *buf) |
---|
| 1331 | +{ |
---|
| 1332 | + char caller[12]; |
---|
| 1333 | + |
---|
| 1334 | + snprintf(caller, sizeof(caller), "%c%u", |
---|
| 1335 | + id & 0x80000000 ? 'C' : 'T', id & ~0x80000000); |
---|
| 1336 | + return sprintf(buf, "[%6s]", caller); |
---|
| 1337 | +} |
---|
| 1338 | +#else |
---|
| 1339 | +#define print_caller(id, buf) 0 |
---|
| 1340 | +#endif |
---|
| 1341 | + |
---|
| 1342 | +static size_t info_print_prefix(const struct printk_info *info, bool syslog, |
---|
| 1343 | + bool time, char *buf) |
---|
1387 | 1344 | { |
---|
1388 | 1345 | size_t len = 0; |
---|
1389 | | - unsigned int prefix = (msg->facility << 3) | msg->level; |
---|
1390 | 1346 | |
---|
1391 | | - if (syslog) { |
---|
1392 | | - if (buf) { |
---|
1393 | | - len += sprintf(buf, "<%u>", prefix); |
---|
1394 | | - } else { |
---|
1395 | | - len += 3; |
---|
1396 | | - if (prefix > 999) |
---|
1397 | | - len += 3; |
---|
1398 | | - else if (prefix > 99) |
---|
1399 | | - len += 2; |
---|
1400 | | - else if (prefix > 9) |
---|
1401 | | - len++; |
---|
1402 | | - } |
---|
| 1347 | + if (syslog) |
---|
| 1348 | + len = print_syslog((info->facility << 3) | info->level, buf); |
---|
| 1349 | + |
---|
| 1350 | + if (time) |
---|
| 1351 | + len += print_time(info->ts_nsec, buf + len); |
---|
| 1352 | + |
---|
| 1353 | + len += print_caller(info->caller_id, buf + len); |
---|
| 1354 | + |
---|
| 1355 | + if (IS_ENABLED(CONFIG_PRINTK_CALLER) || time) { |
---|
| 1356 | + buf[len++] = ' '; |
---|
| 1357 | + buf[len] = '\0'; |
---|
1403 | 1358 | } |
---|
1404 | 1359 | |
---|
1405 | | - len += print_time(msg->ts_nsec, buf ? buf + len : NULL); |
---|
1406 | | -#ifdef CONFIG_PRINTK_PROCESS |
---|
1407 | | - len += print_process(msg, buf ? buf + len : NULL); |
---|
1408 | | -#endif |
---|
1409 | 1360 | return len; |
---|
1410 | 1361 | } |
---|
1411 | 1362 | |
---|
1412 | | -static size_t msg_print_text(const struct printk_log *msg, bool syslog, char *buf, size_t size) |
---|
| 1363 | +/* |
---|
| 1364 | + * Prepare the record for printing. The text is shifted within the given |
---|
| 1365 | + * buffer to avoid a need for another one. The following operations are |
---|
| 1366 | + * done: |
---|
| 1367 | + * |
---|
| 1368 | + * - Add prefix for each line. |
---|
| 1369 | + * - Drop truncated lines that no longer fit into the buffer. |
---|
| 1370 | + * - Add the trailing newline that has been removed in vprintk_store(). |
---|
| 1371 | + * - Add a string terminator. |
---|
| 1372 | + * |
---|
| 1373 | + * Since the produced string is always terminated, the maximum possible |
---|
| 1374 | + * return value is @r->text_buf_size - 1; |
---|
| 1375 | + * |
---|
| 1376 | + * Return: The length of the updated/prepared text, including the added |
---|
| 1377 | + * prefixes and the newline. The terminator is not counted. The dropped |
---|
| 1378 | + * line(s) are not counted. |
---|
| 1379 | + */ |
---|
| 1380 | +static size_t record_print_text(struct printk_record *r, bool syslog, |
---|
| 1381 | + bool time) |
---|
1413 | 1382 | { |
---|
1414 | | - const char *text = log_text(msg); |
---|
1415 | | - size_t text_size = msg->text_len; |
---|
| 1383 | + size_t text_len = r->info->text_len; |
---|
| 1384 | + size_t buf_size = r->text_buf_size; |
---|
| 1385 | + char *text = r->text_buf; |
---|
| 1386 | + char prefix[PREFIX_MAX]; |
---|
| 1387 | + bool truncated = false; |
---|
| 1388 | + size_t prefix_len; |
---|
| 1389 | + size_t line_len; |
---|
1416 | 1390 | size_t len = 0; |
---|
| 1391 | + char *next; |
---|
1417 | 1392 | |
---|
1418 | | - do { |
---|
1419 | | - const char *next = memchr(text, '\n', text_size); |
---|
1420 | | - size_t text_len; |
---|
| 1393 | + /* |
---|
| 1394 | + * If the message was truncated because the buffer was not large |
---|
| 1395 | + * enough, treat the available text as if it were the full text. |
---|
| 1396 | + */ |
---|
| 1397 | + if (text_len > buf_size) |
---|
| 1398 | + text_len = buf_size; |
---|
1421 | 1399 | |
---|
| 1400 | + prefix_len = info_print_prefix(r->info, syslog, time, prefix); |
---|
| 1401 | + |
---|
| 1402 | + /* |
---|
| 1403 | + * @text_len: bytes of unprocessed text |
---|
| 1404 | + * @line_len: bytes of current line _without_ newline |
---|
| 1405 | + * @text: pointer to beginning of current line |
---|
| 1406 | + * @len: number of bytes prepared in r->text_buf |
---|
| 1407 | + */ |
---|
| 1408 | + for (;;) { |
---|
| 1409 | + next = memchr(text, '\n', text_len); |
---|
1422 | 1410 | if (next) { |
---|
1423 | | - text_len = next - text; |
---|
1424 | | - next++; |
---|
1425 | | - text_size -= next - text; |
---|
| 1411 | + line_len = next - text; |
---|
1426 | 1412 | } else { |
---|
1427 | | - text_len = text_size; |
---|
| 1413 | + /* Drop truncated line(s). */ |
---|
| 1414 | + if (truncated) |
---|
| 1415 | + break; |
---|
| 1416 | + line_len = text_len; |
---|
1428 | 1417 | } |
---|
1429 | 1418 | |
---|
1430 | | - if (buf) { |
---|
1431 | | - if (print_prefix(msg, syslog, NULL) + |
---|
1432 | | - text_len + 1 >= size - len) |
---|
| 1419 | + /* |
---|
| 1420 | + * Truncate the text if there is not enough space to add the |
---|
| 1421 | + * prefix and a trailing newline and a terminator. |
---|
| 1422 | + */ |
---|
| 1423 | + if (len + prefix_len + text_len + 1 + 1 > buf_size) { |
---|
| 1424 | + /* Drop even the current line if no space. */ |
---|
| 1425 | + if (len + prefix_len + line_len + 1 + 1 > buf_size) |
---|
1433 | 1426 | break; |
---|
1434 | 1427 | |
---|
1435 | | - len += print_prefix(msg, syslog, buf + len); |
---|
1436 | | - memcpy(buf + len, text, text_len); |
---|
1437 | | - len += text_len; |
---|
1438 | | - buf[len++] = '\n'; |
---|
1439 | | - } else { |
---|
1440 | | - /* SYSLOG_ACTION_* buffer size only calculation */ |
---|
1441 | | - len += print_prefix(msg, syslog, NULL); |
---|
1442 | | - len += text_len; |
---|
1443 | | - len++; |
---|
| 1428 | + text_len = buf_size - len - prefix_len - 1 - 1; |
---|
| 1429 | + truncated = true; |
---|
1444 | 1430 | } |
---|
1445 | 1431 | |
---|
1446 | | - text = next; |
---|
1447 | | - } while (text); |
---|
| 1432 | + memmove(text + prefix_len, text, text_len); |
---|
| 1433 | + memcpy(text, prefix, prefix_len); |
---|
| 1434 | + |
---|
| 1435 | + /* |
---|
| 1436 | + * Increment the prepared length to include the text and |
---|
| 1437 | + * prefix that were just moved+copied. Also increment for the |
---|
| 1438 | + * newline at the end of this line. If this is the last line, |
---|
| 1439 | + * there is no newline, but it will be added immediately below. |
---|
| 1440 | + */ |
---|
| 1441 | + len += prefix_len + line_len + 1; |
---|
| 1442 | + if (text_len == line_len) { |
---|
| 1443 | + /* |
---|
| 1444 | + * This is the last line. Add the trailing newline |
---|
| 1445 | + * removed in vprintk_store(). |
---|
| 1446 | + */ |
---|
| 1447 | + text[prefix_len + line_len] = '\n'; |
---|
| 1448 | + break; |
---|
| 1449 | + } |
---|
| 1450 | + |
---|
| 1451 | + /* |
---|
| 1452 | + * Advance beyond the added prefix and the related line with |
---|
| 1453 | + * its newline. |
---|
| 1454 | + */ |
---|
| 1455 | + text += prefix_len + line_len + 1; |
---|
| 1456 | + |
---|
| 1457 | + /* |
---|
| 1458 | + * The remaining text has only decreased by the line with its |
---|
| 1459 | + * newline. |
---|
| 1460 | + * |
---|
| 1461 | + * Note that @text_len can become zero. It happens when @text |
---|
| 1462 | + * ended with a newline (either due to truncation or the |
---|
| 1463 | + * original string ending with "\n\n"). The loop is correctly |
---|
| 1464 | + * repeated and (if not truncated) an empty line with a prefix |
---|
| 1465 | + * will be prepared. |
---|
| 1466 | + */ |
---|
| 1467 | + text_len -= line_len + 1; |
---|
| 1468 | + } |
---|
| 1469 | + |
---|
| 1470 | + /* |
---|
| 1471 | + * If a buffer was provided, it will be terminated. Space for the |
---|
| 1472 | + * string terminator is guaranteed to be available. The terminator is |
---|
| 1473 | + * not counted in the return value. |
---|
| 1474 | + */ |
---|
| 1475 | + if (buf_size > 0) |
---|
| 1476 | + r->text_buf[len] = 0; |
---|
1448 | 1477 | |
---|
1449 | 1478 | return len; |
---|
| 1479 | +} |
---|
| 1480 | + |
---|
| 1481 | +static size_t get_record_print_text_size(struct printk_info *info, |
---|
| 1482 | + unsigned int line_count, |
---|
| 1483 | + bool syslog, bool time) |
---|
| 1484 | +{ |
---|
| 1485 | + char prefix[PREFIX_MAX]; |
---|
| 1486 | + size_t prefix_len; |
---|
| 1487 | + |
---|
| 1488 | + prefix_len = info_print_prefix(info, syslog, time, prefix); |
---|
| 1489 | + |
---|
| 1490 | + /* |
---|
| 1491 | + * Each line will be preceded with a prefix. The intermediate |
---|
| 1492 | + * newlines are already within the text, but a final trailing |
---|
| 1493 | + * newline will be added. |
---|
| 1494 | + */ |
---|
| 1495 | + return ((prefix_len * line_count) + info->text_len + 1); |
---|
1450 | 1496 | } |
---|
1451 | 1497 | |
---|
1452 | 1498 | static int syslog_print(char __user *buf, int size) |
---|
1453 | 1499 | { |
---|
| 1500 | + struct printk_info info; |
---|
| 1501 | + struct printk_record r; |
---|
1454 | 1502 | char *text; |
---|
1455 | | - struct printk_log *msg; |
---|
1456 | 1503 | int len = 0; |
---|
1457 | 1504 | |
---|
1458 | 1505 | text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); |
---|
1459 | 1506 | if (!text) |
---|
1460 | 1507 | return -ENOMEM; |
---|
1461 | 1508 | |
---|
| 1509 | + prb_rec_init_rd(&r, &info, text, LOG_LINE_MAX + PREFIX_MAX); |
---|
| 1510 | + |
---|
1462 | 1511 | while (size > 0) { |
---|
1463 | 1512 | size_t n; |
---|
1464 | 1513 | size_t skip; |
---|
1465 | 1514 | |
---|
1466 | 1515 | logbuf_lock_irq(); |
---|
1467 | | - if (syslog_seq < log_first_seq) { |
---|
1468 | | - /* messages are gone, move to first one */ |
---|
1469 | | - syslog_seq = log_first_seq; |
---|
1470 | | - syslog_idx = log_first_idx; |
---|
1471 | | - syslog_partial = 0; |
---|
1472 | | - } |
---|
1473 | | - if (syslog_seq == log_next_seq) { |
---|
| 1516 | + if (!prb_read_valid(prb, syslog_seq, &r)) { |
---|
1474 | 1517 | logbuf_unlock_irq(); |
---|
1475 | 1518 | break; |
---|
1476 | 1519 | } |
---|
| 1520 | + if (r.info->seq != syslog_seq) { |
---|
| 1521 | + /* message is gone, move to next valid one */ |
---|
| 1522 | + syslog_seq = r.info->seq; |
---|
| 1523 | + syslog_partial = 0; |
---|
| 1524 | + } |
---|
| 1525 | + |
---|
| 1526 | + /* |
---|
| 1527 | + * To keep reading/counting partial line consistent, |
---|
| 1528 | + * use printk_time value as of the beginning of a line. |
---|
| 1529 | + */ |
---|
| 1530 | + if (!syslog_partial) |
---|
| 1531 | + syslog_time = printk_time; |
---|
1477 | 1532 | |
---|
1478 | 1533 | skip = syslog_partial; |
---|
1479 | | - msg = log_from_idx(syslog_idx); |
---|
1480 | | - n = msg_print_text(msg, true, text, LOG_LINE_MAX + PREFIX_MAX); |
---|
| 1534 | + n = record_print_text(&r, true, syslog_time); |
---|
1481 | 1535 | if (n - syslog_partial <= size) { |
---|
1482 | 1536 | /* message fits into buffer, move forward */ |
---|
1483 | | - syslog_idx = log_next(syslog_idx); |
---|
1484 | | - syslog_seq++; |
---|
| 1537 | + syslog_seq = r.info->seq + 1; |
---|
1485 | 1538 | n -= syslog_partial; |
---|
1486 | 1539 | syslog_partial = 0; |
---|
1487 | 1540 | } else if (!len){ |
---|
.. | .. |
---|
1512 | 1565 | |
---|
1513 | 1566 | static int syslog_print_all(char __user *buf, int size, bool clear) |
---|
1514 | 1567 | { |
---|
| 1568 | + struct printk_info info; |
---|
| 1569 | + unsigned int line_count; |
---|
| 1570 | + struct printk_record r; |
---|
1515 | 1571 | char *text; |
---|
1516 | 1572 | int len = 0; |
---|
1517 | | - u64 next_seq; |
---|
1518 | 1573 | u64 seq; |
---|
1519 | | - u32 idx; |
---|
| 1574 | + bool time; |
---|
1520 | 1575 | |
---|
1521 | 1576 | text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); |
---|
1522 | 1577 | if (!text) |
---|
1523 | 1578 | return -ENOMEM; |
---|
1524 | 1579 | |
---|
| 1580 | + time = printk_time; |
---|
1525 | 1581 | logbuf_lock_irq(); |
---|
1526 | 1582 | /* |
---|
1527 | 1583 | * Find first record that fits, including all following records, |
---|
1528 | 1584 | * into the user-provided buffer for this dump. |
---|
1529 | 1585 | */ |
---|
1530 | | - seq = clear_seq; |
---|
1531 | | - idx = clear_idx; |
---|
1532 | | - while (seq < log_next_seq) { |
---|
1533 | | - struct printk_log *msg = log_from_idx(idx); |
---|
1534 | | - |
---|
1535 | | - len += msg_print_text(msg, true, NULL, 0); |
---|
1536 | | - idx = log_next(idx); |
---|
1537 | | - seq++; |
---|
1538 | | - } |
---|
| 1586 | + prb_for_each_info(clear_seq, prb, seq, &info, &line_count) |
---|
| 1587 | + len += get_record_print_text_size(&info, line_count, true, time); |
---|
1539 | 1588 | |
---|
1540 | 1589 | /* move first record forward until length fits into the buffer */ |
---|
1541 | | - seq = clear_seq; |
---|
1542 | | - idx = clear_idx; |
---|
1543 | | - while (len > size && seq < log_next_seq) { |
---|
1544 | | - struct printk_log *msg = log_from_idx(idx); |
---|
1545 | | - |
---|
1546 | | - len -= msg_print_text(msg, true, NULL, 0); |
---|
1547 | | - idx = log_next(idx); |
---|
1548 | | - seq++; |
---|
| 1590 | + prb_for_each_info(clear_seq, prb, seq, &info, &line_count) { |
---|
| 1591 | + if (len <= size) |
---|
| 1592 | + break; |
---|
| 1593 | + len -= get_record_print_text_size(&info, line_count, true, time); |
---|
1549 | 1594 | } |
---|
1550 | 1595 | |
---|
1551 | | - /* last message fitting into this dump */ |
---|
1552 | | - next_seq = log_next_seq; |
---|
| 1596 | + prb_rec_init_rd(&r, &info, text, LOG_LINE_MAX + PREFIX_MAX); |
---|
1553 | 1597 | |
---|
1554 | 1598 | len = 0; |
---|
1555 | | - while (len >= 0 && seq < next_seq) { |
---|
1556 | | - struct printk_log *msg = log_from_idx(idx); |
---|
| 1599 | + prb_for_each_record(seq, prb, seq, &r) { |
---|
1557 | 1600 | int textlen; |
---|
1558 | 1601 | |
---|
1559 | | - textlen = msg_print_text(msg, true, text, |
---|
1560 | | - LOG_LINE_MAX + PREFIX_MAX); |
---|
1561 | | - if (textlen < 0) { |
---|
1562 | | - len = textlen; |
---|
| 1602 | + textlen = record_print_text(&r, true, time); |
---|
| 1603 | + |
---|
| 1604 | + if (len + textlen > size) { |
---|
| 1605 | + seq--; |
---|
1563 | 1606 | break; |
---|
1564 | 1607 | } |
---|
1565 | | - idx = log_next(idx); |
---|
1566 | | - seq++; |
---|
1567 | 1608 | |
---|
1568 | 1609 | logbuf_unlock_irq(); |
---|
1569 | 1610 | if (copy_to_user(buf + len, text, textlen)) |
---|
.. | .. |
---|
1572 | 1613 | len += textlen; |
---|
1573 | 1614 | logbuf_lock_irq(); |
---|
1574 | 1615 | |
---|
1575 | | - if (seq < log_first_seq) { |
---|
1576 | | - /* messages are gone, move to next one */ |
---|
1577 | | - seq = log_first_seq; |
---|
1578 | | - idx = log_first_idx; |
---|
1579 | | - } |
---|
| 1616 | + if (len < 0) |
---|
| 1617 | + break; |
---|
1580 | 1618 | } |
---|
1581 | 1619 | |
---|
1582 | | - if (clear) { |
---|
1583 | | - clear_seq = log_next_seq; |
---|
1584 | | - clear_idx = log_next_idx; |
---|
1585 | | - } |
---|
| 1620 | + if (clear) |
---|
| 1621 | + clear_seq = seq; |
---|
1586 | 1622 | logbuf_unlock_irq(); |
---|
1587 | 1623 | |
---|
1588 | 1624 | kfree(text); |
---|
.. | .. |
---|
1592 | 1628 | static void syslog_clear(void) |
---|
1593 | 1629 | { |
---|
1594 | 1630 | logbuf_lock_irq(); |
---|
1595 | | - clear_seq = log_next_seq; |
---|
1596 | | - clear_idx = log_next_idx; |
---|
| 1631 | + clear_seq = prb_next_seq(prb); |
---|
1597 | 1632 | logbuf_unlock_irq(); |
---|
1598 | 1633 | } |
---|
1599 | 1634 | |
---|
1600 | 1635 | int do_syslog(int type, char __user *buf, int len, int source) |
---|
1601 | 1636 | { |
---|
| 1637 | + struct printk_info info; |
---|
1602 | 1638 | bool clear = false; |
---|
1603 | 1639 | static int saved_console_loglevel = LOGLEVEL_DEFAULT; |
---|
1604 | 1640 | int error; |
---|
.. | .. |
---|
1617 | 1653 | return -EINVAL; |
---|
1618 | 1654 | if (!len) |
---|
1619 | 1655 | return 0; |
---|
1620 | | - if (!access_ok(VERIFY_WRITE, buf, len)) |
---|
| 1656 | + if (!access_ok(buf, len)) |
---|
1621 | 1657 | return -EFAULT; |
---|
1622 | 1658 | error = wait_event_interruptible(log_wait, |
---|
1623 | | - syslog_seq != log_next_seq); |
---|
| 1659 | + prb_read_valid(prb, syslog_seq, NULL)); |
---|
1624 | 1660 | if (error) |
---|
1625 | 1661 | return error; |
---|
1626 | 1662 | error = syslog_print(buf, len); |
---|
.. | .. |
---|
1628 | 1664 | /* Read/clear last kernel messages */ |
---|
1629 | 1665 | case SYSLOG_ACTION_READ_CLEAR: |
---|
1630 | 1666 | clear = true; |
---|
1631 | | - /* FALL THRU */ |
---|
| 1667 | + fallthrough; |
---|
1632 | 1668 | /* Read last kernel messages */ |
---|
1633 | 1669 | case SYSLOG_ACTION_READ_ALL: |
---|
1634 | 1670 | if (!buf || len < 0) |
---|
1635 | 1671 | return -EINVAL; |
---|
1636 | 1672 | if (!len) |
---|
1637 | 1673 | return 0; |
---|
1638 | | - if (!access_ok(VERIFY_WRITE, buf, len)) |
---|
| 1674 | + if (!access_ok(buf, len)) |
---|
1639 | 1675 | return -EFAULT; |
---|
1640 | 1676 | error = syslog_print_all(buf, len, clear); |
---|
1641 | 1677 | break; |
---|
.. | .. |
---|
1669 | 1705 | /* Number of chars in the log buffer */ |
---|
1670 | 1706 | case SYSLOG_ACTION_SIZE_UNREAD: |
---|
1671 | 1707 | logbuf_lock_irq(); |
---|
1672 | | - if (syslog_seq < log_first_seq) { |
---|
| 1708 | + if (!prb_read_valid_info(prb, syslog_seq, &info, NULL)) { |
---|
| 1709 | + /* No unread messages. */ |
---|
| 1710 | + logbuf_unlock_irq(); |
---|
| 1711 | + return 0; |
---|
| 1712 | + } |
---|
| 1713 | + if (info.seq != syslog_seq) { |
---|
1673 | 1714 | /* messages are gone, move to first one */ |
---|
1674 | | - syslog_seq = log_first_seq; |
---|
1675 | | - syslog_idx = log_first_idx; |
---|
| 1715 | + syslog_seq = info.seq; |
---|
1676 | 1716 | syslog_partial = 0; |
---|
1677 | 1717 | } |
---|
1678 | 1718 | if (source == SYSLOG_FROM_PROC) { |
---|
.. | .. |
---|
1681 | 1721 | * for pending data, not the size; return the count of |
---|
1682 | 1722 | * records, not the length. |
---|
1683 | 1723 | */ |
---|
1684 | | - error = log_next_seq - syslog_seq; |
---|
| 1724 | + error = prb_next_seq(prb) - syslog_seq; |
---|
1685 | 1725 | } else { |
---|
1686 | | - u64 seq = syslog_seq; |
---|
1687 | | - u32 idx = syslog_idx; |
---|
| 1726 | + bool time = syslog_partial ? syslog_time : printk_time; |
---|
| 1727 | + unsigned int line_count; |
---|
| 1728 | + u64 seq; |
---|
1688 | 1729 | |
---|
1689 | | - while (seq < log_next_seq) { |
---|
1690 | | - struct printk_log *msg = log_from_idx(idx); |
---|
1691 | | - |
---|
1692 | | - error += msg_print_text(msg, true, NULL, 0); |
---|
1693 | | - idx = log_next(idx); |
---|
1694 | | - seq++; |
---|
| 1730 | + prb_for_each_info(syslog_seq, prb, seq, &info, |
---|
| 1731 | + &line_count) { |
---|
| 1732 | + error += get_record_print_text_size(&info, line_count, |
---|
| 1733 | + true, time); |
---|
| 1734 | + time = printk_time; |
---|
1695 | 1735 | } |
---|
1696 | 1736 | error -= syslog_partial; |
---|
1697 | 1737 | } |
---|
.. | .. |
---|
1773 | 1813 | raw_spin_unlock(&console_owner_lock); |
---|
1774 | 1814 | |
---|
1775 | 1815 | if (!waiter) { |
---|
1776 | | - spin_release(&console_owner_dep_map, 1, _THIS_IP_); |
---|
| 1816 | + spin_release(&console_owner_dep_map, _THIS_IP_); |
---|
1777 | 1817 | return 0; |
---|
1778 | 1818 | } |
---|
1779 | 1819 | |
---|
1780 | 1820 | /* The waiter is now free to continue */ |
---|
1781 | 1821 | WRITE_ONCE(console_waiter, false); |
---|
1782 | 1822 | |
---|
1783 | | - spin_release(&console_owner_dep_map, 1, _THIS_IP_); |
---|
| 1823 | + spin_release(&console_owner_dep_map, _THIS_IP_); |
---|
1784 | 1824 | |
---|
1785 | 1825 | /* |
---|
1786 | 1826 | * Hand off console_lock to waiter. The waiter will perform |
---|
1787 | 1827 | * the up(). After this, the waiter is the console_lock owner. |
---|
1788 | 1828 | */ |
---|
1789 | | - mutex_release(&console_lock_dep_map, 1, _THIS_IP_); |
---|
| 1829 | + mutex_release(&console_lock_dep_map, _THIS_IP_); |
---|
1790 | 1830 | return 1; |
---|
1791 | 1831 | } |
---|
1792 | 1832 | |
---|
.. | .. |
---|
1840 | 1880 | /* Owner will clear console_waiter on hand off */ |
---|
1841 | 1881 | while (READ_ONCE(console_waiter)) |
---|
1842 | 1882 | cpu_relax(); |
---|
1843 | | - spin_release(&console_owner_dep_map, 1, _THIS_IP_); |
---|
| 1883 | + spin_release(&console_owner_dep_map, _THIS_IP_); |
---|
1844 | 1884 | |
---|
1845 | 1885 | printk_safe_exit_irqrestore(flags); |
---|
1846 | 1886 | /* |
---|
.. | .. |
---|
1859 | 1899 | * log_buf[start] to log_buf[end - 1]. |
---|
1860 | 1900 | * The console_lock must be held. |
---|
1861 | 1901 | */ |
---|
1862 | | -#ifdef CONFIG_PSTORE_CONSOLE_FORCE |
---|
1863 | | -__maybe_unused |
---|
1864 | | -#endif |
---|
1865 | 1902 | static void call_console_drivers(const char *ext_text, size_t ext_len, |
---|
1866 | 1903 | const char *text, size_t len) |
---|
1867 | 1904 | { |
---|
| 1905 | + static char dropped_text[64]; |
---|
| 1906 | + size_t dropped_len = 0; |
---|
1868 | 1907 | struct console *con; |
---|
1869 | 1908 | |
---|
1870 | 1909 | trace_console_rcuidle(text, len); |
---|
1871 | 1910 | |
---|
1872 | 1911 | if (!console_drivers) |
---|
1873 | 1912 | return; |
---|
| 1913 | + |
---|
| 1914 | + if (console_dropped) { |
---|
| 1915 | + dropped_len = snprintf(dropped_text, sizeof(dropped_text), |
---|
| 1916 | + "** %lu printk messages dropped **\n", |
---|
| 1917 | + console_dropped); |
---|
| 1918 | + console_dropped = 0; |
---|
| 1919 | + } |
---|
1874 | 1920 | |
---|
1875 | 1921 | for_each_console(con) { |
---|
1876 | 1922 | if (exclusive_console && con != exclusive_console) |
---|
.. | .. |
---|
1884 | 1930 | continue; |
---|
1885 | 1931 | if (con->flags & CON_EXTENDED) |
---|
1886 | 1932 | con->write(con, ext_text, ext_len); |
---|
1887 | | - else |
---|
| 1933 | + else { |
---|
| 1934 | + if (dropped_len) |
---|
| 1935 | + con->write(con, dropped_text, dropped_len); |
---|
1888 | 1936 | con->write(con, text, len); |
---|
| 1937 | + } |
---|
1889 | 1938 | } |
---|
1890 | 1939 | } |
---|
1891 | 1940 | |
---|
.. | .. |
---|
1903 | 1952 | } |
---|
1904 | 1953 | } |
---|
1905 | 1954 | |
---|
1906 | | -/* |
---|
1907 | | - * Continuation lines are buffered, and not committed to the record buffer |
---|
1908 | | - * until the line is complete, or a race forces it. The line fragments |
---|
1909 | | - * though, are printed immediately to the consoles to ensure everything has |
---|
1910 | | - * reached the console in case of a kernel crash. |
---|
1911 | | - */ |
---|
1912 | | -static struct cont { |
---|
1913 | | - char buf[LOG_LINE_MAX]; |
---|
1914 | | - size_t len; /* length == 0 means unused buffer */ |
---|
1915 | | - struct task_struct *owner; /* task of first print*/ |
---|
1916 | | - u64 ts_nsec; /* time of first print */ |
---|
1917 | | - u8 level; /* log level of first message */ |
---|
1918 | | - u8 facility; /* log facility of first message */ |
---|
1919 | | - enum log_flags flags; /* prefix, newline flags */ |
---|
1920 | | -} cont; |
---|
1921 | | - |
---|
1922 | | -static void cont_flush(void) |
---|
| 1955 | +static inline u32 printk_caller_id(void) |
---|
1923 | 1956 | { |
---|
1924 | | - if (cont.len == 0) |
---|
1925 | | - return; |
---|
1926 | | - |
---|
1927 | | - log_store(cont.facility, cont.level, cont.flags, cont.ts_nsec, |
---|
1928 | | - NULL, 0, cont.buf, cont.len); |
---|
1929 | | - cont.len = 0; |
---|
| 1957 | + return in_task() ? task_pid_nr(current) : |
---|
| 1958 | + 0x80000000 + raw_smp_processor_id(); |
---|
1930 | 1959 | } |
---|
1931 | 1960 | |
---|
1932 | | -static bool cont_add(int facility, int level, enum log_flags flags, const char *text, size_t len) |
---|
| 1961 | +static size_t log_output(int facility, int level, enum log_flags lflags, |
---|
| 1962 | + const struct dev_printk_info *dev_info, |
---|
| 1963 | + char *text, size_t text_len) |
---|
1933 | 1964 | { |
---|
1934 | | - /* |
---|
1935 | | - * If ext consoles are present, flush and skip in-kernel |
---|
1936 | | - * continuation. See nr_ext_console_drivers definition. Also, if |
---|
1937 | | - * the line gets too long, split it up in separate records. |
---|
1938 | | - */ |
---|
1939 | | - if (nr_ext_console_drivers || cont.len + len > sizeof(cont.buf)) { |
---|
1940 | | - cont_flush(); |
---|
1941 | | - return false; |
---|
1942 | | - } |
---|
| 1965 | + const u32 caller_id = printk_caller_id(); |
---|
1943 | 1966 | |
---|
1944 | | - if (!cont.len) { |
---|
1945 | | - cont.facility = facility; |
---|
1946 | | - cont.level = level; |
---|
1947 | | - cont.owner = current; |
---|
1948 | | - cont.ts_nsec = get_local_clock(); |
---|
1949 | | - cont.flags = flags; |
---|
1950 | | - } |
---|
| 1967 | + if (lflags & LOG_CONT) { |
---|
| 1968 | + struct prb_reserved_entry e; |
---|
| 1969 | + struct printk_record r; |
---|
1951 | 1970 | |
---|
1952 | | - memcpy(cont.buf + cont.len, text, len); |
---|
1953 | | - cont.len += len; |
---|
| 1971 | + prb_rec_init_wr(&r, text_len); |
---|
| 1972 | + if (prb_reserve_in_last(&e, prb, &r, caller_id, LOG_LINE_MAX)) { |
---|
| 1973 | + memcpy(&r.text_buf[r.info->text_len], text, text_len); |
---|
| 1974 | + r.info->text_len += text_len; |
---|
| 1975 | + if (lflags & LOG_NEWLINE) { |
---|
| 1976 | + r.info->flags |= LOG_NEWLINE; |
---|
| 1977 | + prb_final_commit(&e); |
---|
| 1978 | + } else { |
---|
| 1979 | + prb_commit(&e); |
---|
| 1980 | + } |
---|
1954 | 1981 | |
---|
1955 | | - // The original flags come from the first line, |
---|
1956 | | - // but later continuations can add a newline. |
---|
1957 | | - if (flags & LOG_NEWLINE) { |
---|
1958 | | - cont.flags |= LOG_NEWLINE; |
---|
1959 | | - cont_flush(); |
---|
1960 | | - } |
---|
1961 | | - |
---|
1962 | | - if (cont.len > (sizeof(cont.buf) * 80) / 100) |
---|
1963 | | - cont_flush(); |
---|
1964 | | - |
---|
1965 | | - return true; |
---|
1966 | | -} |
---|
1967 | | - |
---|
1968 | | -static size_t log_output(int facility, int level, enum log_flags lflags, const char *dict, size_t dictlen, char *text, size_t text_len) |
---|
1969 | | -{ |
---|
1970 | | - /* |
---|
1971 | | - * If an earlier line was buffered, and we're a continuation |
---|
1972 | | - * write from the same process, try to add it to the buffer. |
---|
1973 | | - */ |
---|
1974 | | - if (cont.len) { |
---|
1975 | | - if (cont.owner == current && (lflags & LOG_CONT)) { |
---|
1976 | | - if (cont_add(facility, level, lflags, text, text_len)) |
---|
1977 | | - return text_len; |
---|
1978 | | - } |
---|
1979 | | - /* Otherwise, make sure it's flushed */ |
---|
1980 | | - cont_flush(); |
---|
1981 | | - } |
---|
1982 | | - |
---|
1983 | | - /* Skip empty continuation lines that couldn't be added - they just flush */ |
---|
1984 | | - if (!text_len && (lflags & LOG_CONT)) |
---|
1985 | | - return 0; |
---|
1986 | | - |
---|
1987 | | - /* If it doesn't end in a newline, try to buffer the current line */ |
---|
1988 | | - if (!(lflags & LOG_NEWLINE)) { |
---|
1989 | | - if (cont_add(facility, level, lflags, text, text_len)) |
---|
| 1982 | + trace_android_vh_logbuf_pr_cont(&r, text_len); |
---|
1990 | 1983 | return text_len; |
---|
| 1984 | + } |
---|
1991 | 1985 | } |
---|
1992 | 1986 | |
---|
1993 | 1987 | /* Store it in the record log */ |
---|
1994 | | - return log_store(facility, level, lflags, 0, dict, dictlen, text, text_len); |
---|
| 1988 | + return log_store(caller_id, facility, level, lflags, 0, |
---|
| 1989 | + dev_info, text, text_len); |
---|
1995 | 1990 | } |
---|
1996 | 1991 | |
---|
1997 | 1992 | /* Must be called under logbuf_lock. */ |
---|
1998 | 1993 | int vprintk_store(int facility, int level, |
---|
1999 | | - const char *dict, size_t dictlen, |
---|
| 1994 | + const struct dev_printk_info *dev_info, |
---|
2000 | 1995 | const char *fmt, va_list args) |
---|
2001 | 1996 | { |
---|
2002 | 1997 | static char textbuf[LOG_LINE_MAX]; |
---|
.. | .. |
---|
2025 | 2020 | case '0' ... '7': |
---|
2026 | 2021 | if (level == LOGLEVEL_DEFAULT) |
---|
2027 | 2022 | level = kern_level - '0'; |
---|
2028 | | - /* fallthrough */ |
---|
2029 | | - case 'd': /* KERN_DEFAULT */ |
---|
2030 | | - lflags |= LOG_PREFIX; |
---|
2031 | 2023 | break; |
---|
2032 | 2024 | case 'c': /* KERN_CONT */ |
---|
2033 | 2025 | lflags |= LOG_CONT; |
---|
.. | .. |
---|
2041 | 2033 | if (level == LOGLEVEL_DEFAULT) |
---|
2042 | 2034 | level = default_message_loglevel; |
---|
2043 | 2035 | |
---|
2044 | | - if (dict) |
---|
2045 | | - lflags |= LOG_PREFIX|LOG_NEWLINE; |
---|
| 2036 | + if (dev_info) |
---|
| 2037 | + lflags |= LOG_NEWLINE; |
---|
2046 | 2038 | |
---|
2047 | | - return log_output(facility, level, lflags, |
---|
2048 | | - dict, dictlen, text, text_len); |
---|
| 2039 | + return log_output(facility, level, lflags, dev_info, text, text_len); |
---|
2049 | 2040 | } |
---|
2050 | 2041 | |
---|
2051 | 2042 | asmlinkage int vprintk_emit(int facility, int level, |
---|
2052 | | - const char *dict, size_t dictlen, |
---|
| 2043 | + const struct dev_printk_info *dev_info, |
---|
2053 | 2044 | const char *fmt, va_list args) |
---|
2054 | 2045 | { |
---|
2055 | 2046 | int printed_len; |
---|
2056 | | - bool in_sched = false, pending_output; |
---|
| 2047 | + bool in_sched = false; |
---|
2057 | 2048 | unsigned long flags; |
---|
2058 | | - u64 curr_log_seq; |
---|
| 2049 | + |
---|
| 2050 | + /* Suppress unimportant messages after panic happens */ |
---|
| 2051 | + if (unlikely(suppress_printk)) |
---|
| 2052 | + return 0; |
---|
2059 | 2053 | |
---|
2060 | 2054 | if (level == LOGLEVEL_SCHED) { |
---|
2061 | 2055 | level = LOGLEVEL_DEFAULT; |
---|
.. | .. |
---|
2067 | 2061 | |
---|
2068 | 2062 | /* This stops the holder of console_sem just where we want him */ |
---|
2069 | 2063 | logbuf_lock_irqsave(flags); |
---|
2070 | | - curr_log_seq = log_next_seq; |
---|
2071 | | - printed_len = vprintk_store(facility, level, dict, dictlen, fmt, args); |
---|
2072 | | - pending_output = (curr_log_seq != log_next_seq); |
---|
| 2064 | + printed_len = vprintk_store(facility, level, dev_info, fmt, args); |
---|
2073 | 2065 | logbuf_unlock_irqrestore(flags); |
---|
2074 | 2066 | |
---|
2075 | 2067 | /* If called from the scheduler, we can not call up(). */ |
---|
2076 | | - if (!in_sched && pending_output) { |
---|
| 2068 | + if (!in_sched) { |
---|
2077 | 2069 | /* |
---|
2078 | 2070 | * Disable preemption to avoid being preempted while holding |
---|
2079 | 2071 | * console_sem which would prevent anyone from printing to |
---|
.. | .. |
---|
2090 | 2082 | preempt_enable(); |
---|
2091 | 2083 | } |
---|
2092 | 2084 | |
---|
2093 | | - if (pending_output) |
---|
2094 | | - wake_up_klogd(); |
---|
| 2085 | + wake_up_klogd(); |
---|
2095 | 2086 | return printed_len; |
---|
2096 | 2087 | } |
---|
2097 | 2088 | EXPORT_SYMBOL(vprintk_emit); |
---|
.. | .. |
---|
2102 | 2093 | } |
---|
2103 | 2094 | EXPORT_SYMBOL(vprintk); |
---|
2104 | 2095 | |
---|
2105 | | -asmlinkage int printk_emit(int facility, int level, |
---|
2106 | | - const char *dict, size_t dictlen, |
---|
2107 | | - const char *fmt, ...) |
---|
2108 | | -{ |
---|
2109 | | - va_list args; |
---|
2110 | | - int r; |
---|
2111 | | - |
---|
2112 | | - va_start(args, fmt); |
---|
2113 | | - r = vprintk_emit(facility, level, dict, dictlen, fmt, args); |
---|
2114 | | - va_end(args); |
---|
2115 | | - |
---|
2116 | | - return r; |
---|
2117 | | -} |
---|
2118 | | -EXPORT_SYMBOL(printk_emit); |
---|
2119 | | - |
---|
2120 | 2096 | int vprintk_default(const char *fmt, va_list args) |
---|
2121 | 2097 | { |
---|
2122 | | - int r; |
---|
2123 | | - |
---|
2124 | | -#ifdef CONFIG_KGDB_KDB |
---|
2125 | | - /* Allow to pass printk() to kdb but avoid a recursion. */ |
---|
2126 | | - if (unlikely(kdb_trap_printk && kdb_printf_cpu < 0)) { |
---|
2127 | | - r = vkdb_printf(KDB_MSGSRC_PRINTK, fmt, args); |
---|
2128 | | - return r; |
---|
2129 | | - } |
---|
2130 | | -#endif |
---|
2131 | | - r = vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, 0, fmt, args); |
---|
2132 | | - |
---|
2133 | | - return r; |
---|
| 2098 | + return vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, fmt, args); |
---|
2134 | 2099 | } |
---|
2135 | 2100 | EXPORT_SYMBOL_GPL(vprintk_default); |
---|
2136 | 2101 | |
---|
.. | .. |
---|
2172 | 2137 | |
---|
2173 | 2138 | #define LOG_LINE_MAX 0 |
---|
2174 | 2139 | #define PREFIX_MAX 0 |
---|
| 2140 | +#define printk_time false |
---|
| 2141 | + |
---|
| 2142 | +#define prb_read_valid(rb, seq, r) false |
---|
| 2143 | +#define prb_first_valid_seq(rb) 0 |
---|
2175 | 2144 | |
---|
2176 | 2145 | static u64 syslog_seq; |
---|
2177 | | -static u32 syslog_idx; |
---|
2178 | 2146 | static u64 console_seq; |
---|
2179 | | -static u32 console_idx; |
---|
2180 | 2147 | static u64 exclusive_console_stop_seq; |
---|
2181 | | -static u64 log_first_seq; |
---|
2182 | | -static u32 log_first_idx; |
---|
2183 | | -static u64 log_next_seq; |
---|
2184 | | -static char *log_text(const struct printk_log *msg) { return NULL; } |
---|
2185 | | -static char *log_dict(const struct printk_log *msg) { return NULL; } |
---|
2186 | | -static struct printk_log *log_from_idx(u32 idx) { return NULL; } |
---|
2187 | | -static u32 log_next(u32 idx) { return 0; } |
---|
2188 | | -static ssize_t msg_print_ext_header(char *buf, size_t size, |
---|
2189 | | - struct printk_log *msg, |
---|
2190 | | - u64 seq) { return 0; } |
---|
| 2148 | +static unsigned long console_dropped; |
---|
| 2149 | + |
---|
| 2150 | +static size_t record_print_text(const struct printk_record *r, |
---|
| 2151 | + bool syslog, bool time) |
---|
| 2152 | +{ |
---|
| 2153 | + return 0; |
---|
| 2154 | +} |
---|
| 2155 | +static ssize_t info_print_ext_header(char *buf, size_t size, |
---|
| 2156 | + struct printk_info *info) |
---|
| 2157 | +{ |
---|
| 2158 | + return 0; |
---|
| 2159 | +} |
---|
2191 | 2160 | static ssize_t msg_print_ext_body(char *buf, size_t size, |
---|
2192 | | - char *dict, size_t dict_len, |
---|
2193 | | - char *text, size_t text_len) { return 0; } |
---|
| 2161 | + char *text, size_t text_len, |
---|
| 2162 | + struct dev_printk_info *dev_info) { return 0; } |
---|
2194 | 2163 | static void console_lock_spinning_enable(void) { } |
---|
2195 | 2164 | static int console_lock_spinning_disable_and_check(void) { return 0; } |
---|
2196 | 2165 | static void call_console_drivers(const char *ext_text, size_t ext_len, |
---|
2197 | 2166 | const char *text, size_t len) {} |
---|
2198 | | -static size_t msg_print_text(const struct printk_log *msg, |
---|
2199 | | - bool syslog, char *buf, size_t size) { return 0; } |
---|
2200 | 2167 | static bool suppress_message_printing(int level) { return false; } |
---|
2201 | 2168 | |
---|
2202 | 2169 | #endif /* CONFIG_PRINTK */ |
---|
.. | .. |
---|
2222 | 2189 | #endif |
---|
2223 | 2190 | |
---|
2224 | 2191 | static int __add_preferred_console(char *name, int idx, char *options, |
---|
2225 | | - char *brl_options) |
---|
| 2192 | + char *brl_options, bool user_specified) |
---|
2226 | 2193 | { |
---|
2227 | 2194 | struct console_cmdline *c; |
---|
2228 | 2195 | int i; |
---|
.. | .. |
---|
2237 | 2204 | if (strcmp(c->name, name) == 0 && c->index == idx) { |
---|
2238 | 2205 | if (!brl_options) |
---|
2239 | 2206 | preferred_console = i; |
---|
| 2207 | + if (user_specified) |
---|
| 2208 | + c->user_specified = true; |
---|
2240 | 2209 | return 0; |
---|
2241 | 2210 | } |
---|
2242 | 2211 | } |
---|
.. | .. |
---|
2246 | 2215 | preferred_console = i; |
---|
2247 | 2216 | strlcpy(c->name, name, sizeof(c->name)); |
---|
2248 | 2217 | c->options = options; |
---|
| 2218 | + c->user_specified = user_specified; |
---|
2249 | 2219 | braille_set_options(c, brl_options); |
---|
2250 | 2220 | |
---|
2251 | 2221 | c->index = idx; |
---|
.. | .. |
---|
2278 | 2248 | * for exacly this purpose. |
---|
2279 | 2249 | */ |
---|
2280 | 2250 | if (str[0] == 0 || strcmp(str, "null") == 0) { |
---|
2281 | | - __add_preferred_console("ttynull", 0, NULL, NULL); |
---|
| 2251 | + __add_preferred_console("ttynull", 0, NULL, NULL, true); |
---|
2282 | 2252 | return 1; |
---|
2283 | 2253 | } |
---|
2284 | 2254 | |
---|
.. | .. |
---|
2310 | 2280 | idx = simple_strtoul(s, NULL, 10); |
---|
2311 | 2281 | *s = 0; |
---|
2312 | 2282 | |
---|
2313 | | - __add_preferred_console(buf, idx, options, brl_options); |
---|
| 2283 | + __add_preferred_console(buf, idx, options, brl_options, true); |
---|
2314 | 2284 | console_set_on_cmdline = 1; |
---|
2315 | 2285 | return 1; |
---|
2316 | 2286 | } |
---|
.. | .. |
---|
2331 | 2301 | */ |
---|
2332 | 2302 | int add_preferred_console(char *name, int idx, char *options) |
---|
2333 | 2303 | { |
---|
2334 | | - return __add_preferred_console(name, idx, options, NULL); |
---|
| 2304 | + return __add_preferred_console(name, idx, options, NULL, false); |
---|
2335 | 2305 | } |
---|
2336 | 2306 | |
---|
2337 | 2307 | bool console_suspend_enabled = true; |
---|
.. | .. |
---|
2383 | 2353 | */ |
---|
2384 | 2354 | static int console_cpu_notify(unsigned int cpu) |
---|
2385 | 2355 | { |
---|
| 2356 | + int flag = 0; |
---|
| 2357 | + |
---|
| 2358 | + trace_android_vh_printk_hotplug(&flag); |
---|
| 2359 | + if (flag) |
---|
| 2360 | + return 0; |
---|
| 2361 | + |
---|
2386 | 2362 | if (!cpuhp_tasks_frozen) { |
---|
2387 | 2363 | /* If trylock fails, someone else is doing the printing */ |
---|
2388 | 2364 | if (console_trylock()) |
---|
.. | .. |
---|
2487 | 2463 | static char text[LOG_LINE_MAX + PREFIX_MAX]; |
---|
2488 | 2464 | unsigned long flags; |
---|
2489 | 2465 | bool do_cond_resched, retry; |
---|
| 2466 | + struct printk_info info; |
---|
| 2467 | + struct printk_record r; |
---|
2490 | 2468 | |
---|
2491 | 2469 | if (console_suspended) { |
---|
2492 | 2470 | up_console_sem(); |
---|
2493 | 2471 | return; |
---|
2494 | 2472 | } |
---|
| 2473 | + |
---|
| 2474 | + prb_rec_init_rd(&r, &info, text, sizeof(text)); |
---|
2495 | 2475 | |
---|
2496 | 2476 | /* |
---|
2497 | 2477 | * Console drivers are called with interrupts disabled, so |
---|
.. | .. |
---|
2505 | 2485 | * |
---|
2506 | 2486 | * console_trylock() is not able to detect the preemptive |
---|
2507 | 2487 | * context reliably. Therefore the value must be stored before |
---|
2508 | | - * and cleared after the the "again" goto label. |
---|
| 2488 | + * and cleared after the "again" goto label. |
---|
2509 | 2489 | */ |
---|
2510 | 2490 | do_cond_resched = console_may_schedule; |
---|
2511 | 2491 | again: |
---|
.. | .. |
---|
2523 | 2503 | } |
---|
2524 | 2504 | |
---|
2525 | 2505 | for (;;) { |
---|
2526 | | - struct printk_log *msg; |
---|
2527 | 2506 | size_t ext_len = 0; |
---|
2528 | 2507 | size_t len; |
---|
2529 | 2508 | |
---|
2530 | 2509 | printk_safe_enter_irqsave(flags); |
---|
2531 | 2510 | raw_spin_lock(&logbuf_lock); |
---|
2532 | | - if (console_seq < log_first_seq) { |
---|
2533 | | - len = sprintf(text, |
---|
2534 | | - "** %llu printk messages dropped **\n", |
---|
2535 | | - log_first_seq - console_seq); |
---|
2536 | | - |
---|
2537 | | - /* messages are gone, move to first one */ |
---|
2538 | | - console_seq = log_first_seq; |
---|
2539 | | - console_idx = log_first_idx; |
---|
2540 | | - } else { |
---|
2541 | | - len = 0; |
---|
2542 | | - } |
---|
2543 | 2511 | skip: |
---|
2544 | | - if (console_seq == log_next_seq) |
---|
| 2512 | + if (!prb_read_valid(prb, console_seq, &r)) |
---|
2545 | 2513 | break; |
---|
2546 | 2514 | |
---|
2547 | | - msg = log_from_idx(console_idx); |
---|
2548 | | - if (suppress_message_printing(msg->level)) { |
---|
| 2515 | + if (console_seq != r.info->seq) { |
---|
| 2516 | + console_dropped += r.info->seq - console_seq; |
---|
| 2517 | + console_seq = r.info->seq; |
---|
| 2518 | + } |
---|
| 2519 | + |
---|
| 2520 | + if (suppress_message_printing(r.info->level)) { |
---|
2549 | 2521 | /* |
---|
2550 | 2522 | * Skip record we have buffered and already printed |
---|
2551 | 2523 | * directly to the console when we received it, and |
---|
2552 | 2524 | * record that has level above the console loglevel. |
---|
2553 | 2525 | */ |
---|
2554 | | - console_idx = log_next(console_idx); |
---|
2555 | 2526 | console_seq++; |
---|
2556 | 2527 | goto skip; |
---|
2557 | 2528 | } |
---|
.. | .. |
---|
2562 | 2533 | exclusive_console = NULL; |
---|
2563 | 2534 | } |
---|
2564 | 2535 | |
---|
2565 | | - len += msg_print_text(msg, |
---|
2566 | | - console_msg_format & MSG_FORMAT_SYSLOG, |
---|
2567 | | - text + len, |
---|
2568 | | - sizeof(text) - len); |
---|
| 2536 | + /* |
---|
| 2537 | + * Handle extended console text first because later |
---|
| 2538 | + * record_print_text() will modify the record buffer in-place. |
---|
| 2539 | + */ |
---|
2569 | 2540 | if (nr_ext_console_drivers) { |
---|
2570 | | - ext_len = msg_print_ext_header(ext_text, |
---|
| 2541 | + ext_len = info_print_ext_header(ext_text, |
---|
2571 | 2542 | sizeof(ext_text), |
---|
2572 | | - msg, console_seq); |
---|
| 2543 | + r.info); |
---|
2573 | 2544 | ext_len += msg_print_ext_body(ext_text + ext_len, |
---|
2574 | 2545 | sizeof(ext_text) - ext_len, |
---|
2575 | | - log_dict(msg), msg->dict_len, |
---|
2576 | | - log_text(msg), msg->text_len); |
---|
| 2546 | + &r.text_buf[0], |
---|
| 2547 | + r.info->text_len, |
---|
| 2548 | + &r.info->dev_info); |
---|
2577 | 2549 | } |
---|
2578 | | - console_idx = log_next(console_idx); |
---|
| 2550 | + len = record_print_text(&r, |
---|
| 2551 | + console_msg_format & MSG_FORMAT_SYSLOG, |
---|
| 2552 | + printk_time); |
---|
2579 | 2553 | console_seq++; |
---|
2580 | 2554 | raw_spin_unlock(&logbuf_lock); |
---|
2581 | 2555 | |
---|
.. | .. |
---|
2588 | 2562 | console_lock_spinning_enable(); |
---|
2589 | 2563 | |
---|
2590 | 2564 | stop_critical_timings(); /* don't trace print latency */ |
---|
2591 | | -#ifdef CONFIG_PSTORE_CONSOLE_FORCE |
---|
2592 | | - call_console_drivers_level(msg->level, ext_text, ext_len, text, len); |
---|
2593 | | -#else |
---|
2594 | 2565 | call_console_drivers(ext_text, ext_len, text, len); |
---|
2595 | | -#endif |
---|
2596 | 2566 | start_critical_timings(); |
---|
2597 | 2567 | |
---|
2598 | 2568 | if (console_lock_spinning_disable_and_check()) { |
---|
.. | .. |
---|
2619 | 2589 | * flush, no worries. |
---|
2620 | 2590 | */ |
---|
2621 | 2591 | raw_spin_lock(&logbuf_lock); |
---|
2622 | | - retry = console_seq != log_next_seq; |
---|
| 2592 | + retry = prb_read_valid(prb, console_seq, NULL); |
---|
2623 | 2593 | raw_spin_unlock(&logbuf_lock); |
---|
2624 | 2594 | printk_safe_exit_irqrestore(flags); |
---|
2625 | 2595 | |
---|
.. | .. |
---|
2668 | 2638 | |
---|
2669 | 2639 | /** |
---|
2670 | 2640 | * console_flush_on_panic - flush console content on panic |
---|
| 2641 | + * @mode: flush all messages in buffer or just the pending ones |
---|
2671 | 2642 | * |
---|
2672 | 2643 | * Immediately output all pending messages no matter what. |
---|
2673 | 2644 | */ |
---|
2674 | | -void console_flush_on_panic(void) |
---|
| 2645 | +void console_flush_on_panic(enum con_flush_mode mode) |
---|
2675 | 2646 | { |
---|
2676 | 2647 | /* |
---|
2677 | 2648 | * If someone else is holding the console lock, trylock will fail |
---|
.. | .. |
---|
2682 | 2653 | */ |
---|
2683 | 2654 | console_trylock(); |
---|
2684 | 2655 | console_may_schedule = 0; |
---|
| 2656 | + |
---|
| 2657 | + if (mode == CONSOLE_REPLAY_ALL) { |
---|
| 2658 | + unsigned long flags; |
---|
| 2659 | + |
---|
| 2660 | + logbuf_lock_irqsave(flags); |
---|
| 2661 | + console_seq = prb_first_valid_seq(prb); |
---|
| 2662 | + logbuf_unlock_irqrestore(flags); |
---|
| 2663 | + } |
---|
2685 | 2664 | console_unlock(); |
---|
2686 | 2665 | } |
---|
2687 | 2666 | |
---|
.. | .. |
---|
2739 | 2718 | early_param("keep_bootcon", keep_bootcon_setup); |
---|
2740 | 2719 | |
---|
2741 | 2720 | /* |
---|
| 2721 | + * This is called by register_console() to try to match |
---|
| 2722 | + * the newly registered console with any of the ones selected |
---|
| 2723 | + * by either the command line or add_preferred_console() and |
---|
| 2724 | + * setup/enable it. |
---|
| 2725 | + * |
---|
| 2726 | + * Care need to be taken with consoles that are statically |
---|
| 2727 | + * enabled such as netconsole |
---|
| 2728 | + */ |
---|
| 2729 | +static int try_enable_new_console(struct console *newcon, bool user_specified) |
---|
| 2730 | +{ |
---|
| 2731 | + struct console_cmdline *c; |
---|
| 2732 | + int i, err; |
---|
| 2733 | + |
---|
| 2734 | + for (i = 0, c = console_cmdline; |
---|
| 2735 | + i < MAX_CMDLINECONSOLES && c->name[0]; |
---|
| 2736 | + i++, c++) { |
---|
| 2737 | + if (c->user_specified != user_specified) |
---|
| 2738 | + continue; |
---|
| 2739 | + if (!newcon->match || |
---|
| 2740 | + newcon->match(newcon, c->name, c->index, c->options) != 0) { |
---|
| 2741 | + /* default matching */ |
---|
| 2742 | + BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name)); |
---|
| 2743 | + if (strcmp(c->name, newcon->name) != 0) |
---|
| 2744 | + continue; |
---|
| 2745 | + if (newcon->index >= 0 && |
---|
| 2746 | + newcon->index != c->index) |
---|
| 2747 | + continue; |
---|
| 2748 | + if (newcon->index < 0) |
---|
| 2749 | + newcon->index = c->index; |
---|
| 2750 | + |
---|
| 2751 | + if (_braille_register_console(newcon, c)) |
---|
| 2752 | + return 0; |
---|
| 2753 | + |
---|
| 2754 | + if (newcon->setup && |
---|
| 2755 | + (err = newcon->setup(newcon, c->options)) != 0) |
---|
| 2756 | + return err; |
---|
| 2757 | + } |
---|
| 2758 | + newcon->flags |= CON_ENABLED; |
---|
| 2759 | + if (i == preferred_console) { |
---|
| 2760 | + newcon->flags |= CON_CONSDEV; |
---|
| 2761 | + has_preferred_console = true; |
---|
| 2762 | + } |
---|
| 2763 | + return 0; |
---|
| 2764 | + } |
---|
| 2765 | + |
---|
| 2766 | + /* |
---|
| 2767 | + * Some consoles, such as pstore and netconsole, can be enabled even |
---|
| 2768 | + * without matching. Accept the pre-enabled consoles only when match() |
---|
| 2769 | + * and setup() had a chance to be called. |
---|
| 2770 | + */ |
---|
| 2771 | + if (newcon->flags & CON_ENABLED && c->user_specified == user_specified) |
---|
| 2772 | + return 0; |
---|
| 2773 | + |
---|
| 2774 | + return -ENOENT; |
---|
| 2775 | +} |
---|
| 2776 | + |
---|
| 2777 | +/* |
---|
2742 | 2778 | * The console driver calls this routine during kernel initialization |
---|
2743 | 2779 | * to register the console printing procedure with printk() and to |
---|
2744 | 2780 | * print any messages that were printed by the kernel before the |
---|
.. | .. |
---|
2759 | 2795 | */ |
---|
2760 | 2796 | void register_console(struct console *newcon) |
---|
2761 | 2797 | { |
---|
2762 | | - int i; |
---|
2763 | 2798 | unsigned long flags; |
---|
2764 | 2799 | struct console *bcon = NULL; |
---|
2765 | | - struct console_cmdline *c; |
---|
2766 | | - static bool has_preferred; |
---|
| 2800 | + int err; |
---|
2767 | 2801 | |
---|
2768 | | - if (console_drivers) |
---|
2769 | | - for_each_console(bcon) |
---|
2770 | | - if (WARN(bcon == newcon, |
---|
2771 | | - "console '%s%d' already registered\n", |
---|
2772 | | - bcon->name, bcon->index)) |
---|
2773 | | - return; |
---|
| 2802 | + for_each_console(bcon) { |
---|
| 2803 | + if (WARN(bcon == newcon, "console '%s%d' already registered\n", |
---|
| 2804 | + bcon->name, bcon->index)) |
---|
| 2805 | + return; |
---|
| 2806 | + } |
---|
2774 | 2807 | |
---|
2775 | 2808 | /* |
---|
2776 | 2809 | * before we register a new CON_BOOT console, make sure we don't |
---|
2777 | 2810 | * already have a valid console |
---|
2778 | 2811 | */ |
---|
2779 | | - if (console_drivers && newcon->flags & CON_BOOT) { |
---|
2780 | | - /* find the last or real console */ |
---|
| 2812 | + if (newcon->flags & CON_BOOT) { |
---|
2781 | 2813 | for_each_console(bcon) { |
---|
2782 | 2814 | if (!(bcon->flags & CON_BOOT)) { |
---|
2783 | 2815 | pr_info("Too late to register bootconsole %s%d\n", |
---|
.. | .. |
---|
2790 | 2822 | if (console_drivers && console_drivers->flags & CON_BOOT) |
---|
2791 | 2823 | bcon = console_drivers; |
---|
2792 | 2824 | |
---|
2793 | | - if (!has_preferred || bcon || !console_drivers) |
---|
2794 | | - has_preferred = preferred_console >= 0; |
---|
| 2825 | + if (!has_preferred_console || bcon || !console_drivers) |
---|
| 2826 | + has_preferred_console = preferred_console >= 0; |
---|
2795 | 2827 | |
---|
2796 | 2828 | /* |
---|
2797 | 2829 | * See if we want to use this console driver. If we |
---|
2798 | 2830 | * didn't select a console we take the first one |
---|
2799 | 2831 | * that registers here. |
---|
2800 | 2832 | */ |
---|
2801 | | - if (!has_preferred) { |
---|
| 2833 | + if (!has_preferred_console) { |
---|
2802 | 2834 | if (newcon->index < 0) |
---|
2803 | 2835 | newcon->index = 0; |
---|
2804 | 2836 | if (newcon->setup == NULL || |
---|
.. | .. |
---|
2806 | 2838 | newcon->flags |= CON_ENABLED; |
---|
2807 | 2839 | if (newcon->device) { |
---|
2808 | 2840 | newcon->flags |= CON_CONSDEV; |
---|
2809 | | - has_preferred = true; |
---|
| 2841 | + has_preferred_console = true; |
---|
2810 | 2842 | } |
---|
2811 | 2843 | } |
---|
2812 | 2844 | } |
---|
2813 | 2845 | |
---|
2814 | | - /* |
---|
2815 | | - * See if this console matches one we selected on |
---|
2816 | | - * the command line. |
---|
2817 | | - */ |
---|
2818 | | - for (i = 0, c = console_cmdline; |
---|
2819 | | - i < MAX_CMDLINECONSOLES && c->name[0]; |
---|
2820 | | - i++, c++) { |
---|
2821 | | - if (!newcon->match || |
---|
2822 | | - newcon->match(newcon, c->name, c->index, c->options) != 0) { |
---|
2823 | | - /* default matching */ |
---|
2824 | | - BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name)); |
---|
2825 | | - if (strcmp(c->name, newcon->name) != 0) |
---|
2826 | | - continue; |
---|
2827 | | - if (newcon->index >= 0 && |
---|
2828 | | - newcon->index != c->index) |
---|
2829 | | - continue; |
---|
2830 | | - if (newcon->index < 0) |
---|
2831 | | - newcon->index = c->index; |
---|
| 2846 | + /* See if this console matches one we selected on the command line */ |
---|
| 2847 | + err = try_enable_new_console(newcon, true); |
---|
2832 | 2848 | |
---|
2833 | | - if (_braille_register_console(newcon, c)) |
---|
2834 | | - return; |
---|
| 2849 | + /* If not, try to match against the platform default(s) */ |
---|
| 2850 | + if (err == -ENOENT) |
---|
| 2851 | + err = try_enable_new_console(newcon, false); |
---|
2835 | 2852 | |
---|
2836 | | - if (newcon->setup && |
---|
2837 | | - newcon->setup(newcon, c->options) != 0) |
---|
2838 | | - break; |
---|
2839 | | - } |
---|
2840 | | - |
---|
2841 | | - newcon->flags |= CON_ENABLED; |
---|
2842 | | - if (i == preferred_console) { |
---|
2843 | | - newcon->flags |= CON_CONSDEV; |
---|
2844 | | - has_preferred = true; |
---|
2845 | | - } |
---|
2846 | | - break; |
---|
2847 | | - } |
---|
2848 | | - |
---|
2849 | | - if (!(newcon->flags & CON_ENABLED)) |
---|
| 2853 | + /* printk() messages are not printed to the Braille console. */ |
---|
| 2854 | + if (err || newcon->flags & CON_BRL) |
---|
2850 | 2855 | return; |
---|
2851 | 2856 | |
---|
2852 | 2857 | /* |
---|
.. | .. |
---|
2868 | 2873 | console_drivers = newcon; |
---|
2869 | 2874 | if (newcon->next) |
---|
2870 | 2875 | newcon->next->flags &= ~CON_CONSDEV; |
---|
| 2876 | + /* Ensure this flag is always set for the head of the list */ |
---|
| 2877 | + newcon->flags |= CON_CONSDEV; |
---|
2871 | 2878 | } else { |
---|
2872 | 2879 | newcon->next = console_drivers->next; |
---|
2873 | 2880 | console_drivers->next = newcon; |
---|
2874 | 2881 | } |
---|
2875 | 2882 | |
---|
2876 | 2883 | if (newcon->flags & CON_EXTENDED) |
---|
2877 | | - if (!nr_ext_console_drivers++) |
---|
2878 | | - pr_info("printk: continuation disabled due to ext consoles, expect more fragments in /dev/kmsg\n"); |
---|
| 2884 | + nr_ext_console_drivers++; |
---|
2879 | 2885 | |
---|
2880 | 2886 | if (newcon->flags & CON_PRINTBUFFER) { |
---|
2881 | 2887 | /* |
---|
.. | .. |
---|
2895 | 2901 | exclusive_console = newcon; |
---|
2896 | 2902 | exclusive_console_stop_seq = console_seq; |
---|
2897 | 2903 | console_seq = syslog_seq; |
---|
2898 | | - console_idx = syslog_idx; |
---|
2899 | 2904 | logbuf_unlock_irqrestore(flags); |
---|
2900 | 2905 | } |
---|
2901 | 2906 | console_unlock(); |
---|
.. | .. |
---|
2926 | 2931 | |
---|
2927 | 2932 | int unregister_console(struct console *console) |
---|
2928 | 2933 | { |
---|
2929 | | - struct console *a, *b; |
---|
| 2934 | + struct console *con; |
---|
2930 | 2935 | int res; |
---|
2931 | 2936 | |
---|
2932 | 2937 | pr_info("%sconsole [%s%d] disabled\n", |
---|
.. | .. |
---|
2934 | 2939 | console->name, console->index); |
---|
2935 | 2940 | |
---|
2936 | 2941 | res = _braille_unregister_console(console); |
---|
2937 | | - if (res) |
---|
| 2942 | + if (res < 0) |
---|
2938 | 2943 | return res; |
---|
| 2944 | + if (res > 0) |
---|
| 2945 | + return 0; |
---|
2939 | 2946 | |
---|
2940 | | - res = 1; |
---|
| 2947 | + res = -ENODEV; |
---|
2941 | 2948 | console_lock(); |
---|
2942 | 2949 | if (console_drivers == console) { |
---|
2943 | 2950 | console_drivers=console->next; |
---|
2944 | 2951 | res = 0; |
---|
2945 | | - } else if (console_drivers) { |
---|
2946 | | - for (a=console_drivers->next, b=console_drivers ; |
---|
2947 | | - a; b=a, a=b->next) { |
---|
2948 | | - if (a == console) { |
---|
2949 | | - b->next = a->next; |
---|
| 2952 | + } else { |
---|
| 2953 | + for_each_console(con) { |
---|
| 2954 | + if (con->next == console) { |
---|
| 2955 | + con->next = console->next; |
---|
2950 | 2956 | res = 0; |
---|
2951 | 2957 | break; |
---|
2952 | 2958 | } |
---|
2953 | 2959 | } |
---|
2954 | 2960 | } |
---|
2955 | 2961 | |
---|
2956 | | - if (!res && (console->flags & CON_EXTENDED)) |
---|
| 2962 | + if (res) |
---|
| 2963 | + goto out_disable_unlock; |
---|
| 2964 | + |
---|
| 2965 | + if (console->flags & CON_EXTENDED) |
---|
2957 | 2966 | nr_ext_console_drivers--; |
---|
2958 | 2967 | |
---|
2959 | 2968 | /* |
---|
.. | .. |
---|
2966 | 2975 | console->flags &= ~CON_ENABLED; |
---|
2967 | 2976 | console_unlock(); |
---|
2968 | 2977 | console_sysfs_notify(); |
---|
| 2978 | + |
---|
| 2979 | + if (console->exit) |
---|
| 2980 | + res = console->exit(console); |
---|
| 2981 | + |
---|
| 2982 | + return res; |
---|
| 2983 | + |
---|
| 2984 | +out_disable_unlock: |
---|
| 2985 | + console->flags &= ~CON_ENABLED; |
---|
| 2986 | + console_unlock(); |
---|
| 2987 | + |
---|
2969 | 2988 | return res; |
---|
2970 | 2989 | } |
---|
2971 | 2990 | EXPORT_SYMBOL(unregister_console); |
---|
.. | .. |
---|
3074 | 3093 | |
---|
3075 | 3094 | static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = { |
---|
3076 | 3095 | .func = wake_up_klogd_work_func, |
---|
3077 | | - .flags = IRQ_WORK_LAZY, |
---|
| 3096 | + .flags = ATOMIC_INIT(IRQ_WORK_LAZY), |
---|
3078 | 3097 | }; |
---|
3079 | 3098 | |
---|
3080 | 3099 | void wake_up_klogd(void) |
---|
.. | .. |
---|
3105 | 3124 | { |
---|
3106 | 3125 | int r; |
---|
3107 | 3126 | |
---|
3108 | | - r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, 0, fmt, args); |
---|
| 3127 | + r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, fmt, args); |
---|
3109 | 3128 | defer_console_output(); |
---|
3110 | 3129 | |
---|
3111 | 3130 | return r; |
---|
.. | .. |
---|
3122 | 3141 | |
---|
3123 | 3142 | return r; |
---|
3124 | 3143 | } |
---|
| 3144 | +EXPORT_SYMBOL_GPL(printk_deferred); |
---|
3125 | 3145 | |
---|
3126 | 3146 | /* |
---|
3127 | 3147 | * printk rate limiting, lifted from the networking subsystem. |
---|
.. | .. |
---|
3220 | 3240 | static bool always_kmsg_dump; |
---|
3221 | 3241 | module_param_named(always_kmsg_dump, always_kmsg_dump, bool, S_IRUGO | S_IWUSR); |
---|
3222 | 3242 | |
---|
| 3243 | +const char *kmsg_dump_reason_str(enum kmsg_dump_reason reason) |
---|
| 3244 | +{ |
---|
| 3245 | + switch (reason) { |
---|
| 3246 | + case KMSG_DUMP_PANIC: |
---|
| 3247 | + return "Panic"; |
---|
| 3248 | + case KMSG_DUMP_OOPS: |
---|
| 3249 | + return "Oops"; |
---|
| 3250 | + case KMSG_DUMP_EMERG: |
---|
| 3251 | + return "Emergency"; |
---|
| 3252 | + case KMSG_DUMP_SHUTDOWN: |
---|
| 3253 | + return "Shutdown"; |
---|
| 3254 | + default: |
---|
| 3255 | + return "Unknown"; |
---|
| 3256 | + } |
---|
| 3257 | +} |
---|
| 3258 | +EXPORT_SYMBOL_GPL(kmsg_dump_reason_str); |
---|
| 3259 | + |
---|
3223 | 3260 | /** |
---|
3224 | 3261 | * kmsg_dump - dump kernel log to kernel message dumpers. |
---|
3225 | 3262 | * @reason: the reason (oops, panic etc) for dumping |
---|
.. | .. |
---|
3233 | 3270 | struct kmsg_dumper *dumper; |
---|
3234 | 3271 | unsigned long flags; |
---|
3235 | 3272 | |
---|
3236 | | - if ((reason > KMSG_DUMP_OOPS) && !always_kmsg_dump) |
---|
3237 | | - return; |
---|
3238 | | - |
---|
3239 | 3273 | rcu_read_lock(); |
---|
3240 | 3274 | list_for_each_entry_rcu(dumper, &dump_list, list) { |
---|
3241 | | - if (dumper->max_reason && reason > dumper->max_reason) |
---|
| 3275 | + enum kmsg_dump_reason max_reason = dumper->max_reason; |
---|
| 3276 | + |
---|
| 3277 | + /* |
---|
| 3278 | + * If client has not provided a specific max_reason, default |
---|
| 3279 | + * to KMSG_DUMP_OOPS, unless always_kmsg_dump was set. |
---|
| 3280 | + */ |
---|
| 3281 | + if (max_reason == KMSG_DUMP_UNDEF) { |
---|
| 3282 | + max_reason = always_kmsg_dump ? KMSG_DUMP_MAX : |
---|
| 3283 | + KMSG_DUMP_OOPS; |
---|
| 3284 | + } |
---|
| 3285 | + if (reason > max_reason) |
---|
3242 | 3286 | continue; |
---|
3243 | 3287 | |
---|
3244 | 3288 | /* initialize iterator with data about the stored records */ |
---|
.. | .. |
---|
3246 | 3290 | |
---|
3247 | 3291 | logbuf_lock_irqsave(flags); |
---|
3248 | 3292 | dumper->cur_seq = clear_seq; |
---|
3249 | | - dumper->cur_idx = clear_idx; |
---|
3250 | | - dumper->next_seq = log_next_seq; |
---|
3251 | | - dumper->next_idx = log_next_idx; |
---|
| 3293 | + dumper->next_seq = prb_next_seq(prb); |
---|
3252 | 3294 | logbuf_unlock_irqrestore(flags); |
---|
3253 | 3295 | |
---|
3254 | 3296 | /* invoke dumper which will iterate over records */ |
---|
.. | .. |
---|
3282 | 3324 | bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog, |
---|
3283 | 3325 | char *line, size_t size, size_t *len) |
---|
3284 | 3326 | { |
---|
3285 | | - struct printk_log *msg; |
---|
| 3327 | + struct printk_info info; |
---|
| 3328 | + unsigned int line_count; |
---|
| 3329 | + struct printk_record r; |
---|
3286 | 3330 | size_t l = 0; |
---|
3287 | 3331 | bool ret = false; |
---|
| 3332 | + |
---|
| 3333 | + prb_rec_init_rd(&r, &info, line, size); |
---|
3288 | 3334 | |
---|
3289 | 3335 | if (!dumper->active) |
---|
3290 | 3336 | goto out; |
---|
3291 | 3337 | |
---|
3292 | | - if (dumper->cur_seq < log_first_seq) { |
---|
3293 | | - /* messages are gone, move to first available one */ |
---|
3294 | | - dumper->cur_seq = log_first_seq; |
---|
3295 | | - dumper->cur_idx = log_first_idx; |
---|
| 3338 | + /* Read text or count text lines? */ |
---|
| 3339 | + if (line) { |
---|
| 3340 | + if (!prb_read_valid(prb, dumper->cur_seq, &r)) |
---|
| 3341 | + goto out; |
---|
| 3342 | + l = record_print_text(&r, syslog, printk_time); |
---|
| 3343 | + } else { |
---|
| 3344 | + if (!prb_read_valid_info(prb, dumper->cur_seq, |
---|
| 3345 | + &info, &line_count)) { |
---|
| 3346 | + goto out; |
---|
| 3347 | + } |
---|
| 3348 | + l = get_record_print_text_size(&info, line_count, syslog, |
---|
| 3349 | + printk_time); |
---|
| 3350 | + |
---|
3296 | 3351 | } |
---|
3297 | 3352 | |
---|
3298 | | - /* last entry */ |
---|
3299 | | - if (dumper->cur_seq >= log_next_seq) |
---|
3300 | | - goto out; |
---|
3301 | | - |
---|
3302 | | - msg = log_from_idx(dumper->cur_idx); |
---|
3303 | | - l = msg_print_text(msg, syslog, line, size); |
---|
3304 | | - |
---|
3305 | | - dumper->cur_idx = log_next(dumper->cur_idx); |
---|
3306 | | - dumper->cur_seq++; |
---|
| 3353 | + dumper->cur_seq = r.info->seq + 1; |
---|
3307 | 3354 | ret = true; |
---|
3308 | 3355 | out: |
---|
3309 | 3356 | if (len) |
---|
.. | .. |
---|
3351 | 3398 | * @len: length of line placed into buffer |
---|
3352 | 3399 | * |
---|
3353 | 3400 | * Start at the end of the kmsg buffer and fill the provided buffer |
---|
3354 | | - * with as many of the the *youngest* kmsg records that fit into it. |
---|
| 3401 | + * with as many of the *youngest* kmsg records that fit into it. |
---|
3355 | 3402 | * If the buffer is large enough, all available kmsg records will be |
---|
3356 | 3403 | * copied with a single call. |
---|
3357 | 3404 | * |
---|
.. | .. |
---|
3364 | 3411 | bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, |
---|
3365 | 3412 | char *buf, size_t size, size_t *len) |
---|
3366 | 3413 | { |
---|
| 3414 | + struct printk_info info; |
---|
| 3415 | + unsigned int line_count; |
---|
| 3416 | + struct printk_record r; |
---|
3367 | 3417 | unsigned long flags; |
---|
3368 | 3418 | u64 seq; |
---|
3369 | | - u32 idx; |
---|
3370 | 3419 | u64 next_seq; |
---|
3371 | | - u32 next_idx; |
---|
3372 | 3420 | size_t l = 0; |
---|
3373 | 3421 | bool ret = false; |
---|
| 3422 | + bool time = printk_time; |
---|
3374 | 3423 | |
---|
3375 | | - if (!dumper->active) |
---|
| 3424 | + prb_rec_init_rd(&r, &info, buf, size); |
---|
| 3425 | + |
---|
| 3426 | + if (!dumper->active || !buf || !size) |
---|
3376 | 3427 | goto out; |
---|
3377 | 3428 | |
---|
3378 | 3429 | logbuf_lock_irqsave(flags); |
---|
3379 | | - if (dumper->cur_seq < log_first_seq) { |
---|
3380 | | - /* messages are gone, move to first available one */ |
---|
3381 | | - dumper->cur_seq = log_first_seq; |
---|
3382 | | - dumper->cur_idx = log_first_idx; |
---|
| 3430 | + if (prb_read_valid_info(prb, dumper->cur_seq, &info, NULL)) { |
---|
| 3431 | + if (info.seq != dumper->cur_seq) { |
---|
| 3432 | + /* messages are gone, move to first available one */ |
---|
| 3433 | + dumper->cur_seq = info.seq; |
---|
| 3434 | + } |
---|
3383 | 3435 | } |
---|
3384 | 3436 | |
---|
3385 | 3437 | /* last entry */ |
---|
.. | .. |
---|
3390 | 3442 | |
---|
3391 | 3443 | /* calculate length of entire buffer */ |
---|
3392 | 3444 | seq = dumper->cur_seq; |
---|
3393 | | - idx = dumper->cur_idx; |
---|
3394 | | - while (seq < dumper->next_seq) { |
---|
3395 | | - struct printk_log *msg = log_from_idx(idx); |
---|
3396 | | - |
---|
3397 | | - l += msg_print_text(msg, true, NULL, 0); |
---|
3398 | | - idx = log_next(idx); |
---|
3399 | | - seq++; |
---|
| 3445 | + while (prb_read_valid_info(prb, seq, &info, &line_count)) { |
---|
| 3446 | + if (r.info->seq >= dumper->next_seq) |
---|
| 3447 | + break; |
---|
| 3448 | + l += get_record_print_text_size(&info, line_count, syslog, time); |
---|
| 3449 | + seq = r.info->seq + 1; |
---|
3400 | 3450 | } |
---|
3401 | 3451 | |
---|
3402 | 3452 | /* move first record forward until length fits into the buffer */ |
---|
3403 | 3453 | seq = dumper->cur_seq; |
---|
3404 | | - idx = dumper->cur_idx; |
---|
3405 | | - while (l >= size && seq < dumper->next_seq) { |
---|
3406 | | - struct printk_log *msg = log_from_idx(idx); |
---|
3407 | | - |
---|
3408 | | - l -= msg_print_text(msg, true, NULL, 0); |
---|
3409 | | - idx = log_next(idx); |
---|
3410 | | - seq++; |
---|
| 3454 | + while (l >= size && prb_read_valid_info(prb, seq, |
---|
| 3455 | + &info, &line_count)) { |
---|
| 3456 | + if (r.info->seq >= dumper->next_seq) |
---|
| 3457 | + break; |
---|
| 3458 | + l -= get_record_print_text_size(&info, line_count, syslog, time); |
---|
| 3459 | + seq = r.info->seq + 1; |
---|
3411 | 3460 | } |
---|
3412 | 3461 | |
---|
3413 | 3462 | /* last message in next interation */ |
---|
3414 | 3463 | next_seq = seq; |
---|
3415 | | - next_idx = idx; |
---|
3416 | 3464 | |
---|
| 3465 | + /* actually read text into the buffer now */ |
---|
3417 | 3466 | l = 0; |
---|
3418 | | - while (seq < dumper->next_seq) { |
---|
3419 | | - struct printk_log *msg = log_from_idx(idx); |
---|
| 3467 | + while (prb_read_valid(prb, seq, &r)) { |
---|
| 3468 | + if (r.info->seq >= dumper->next_seq) |
---|
| 3469 | + break; |
---|
3420 | 3470 | |
---|
3421 | | - l += msg_print_text(msg, syslog, buf + l, size - l); |
---|
3422 | | - idx = log_next(idx); |
---|
3423 | | - seq++; |
---|
| 3471 | + l += record_print_text(&r, syslog, time); |
---|
| 3472 | + |
---|
| 3473 | + /* adjust record to store to remaining buffer space */ |
---|
| 3474 | + prb_rec_init_rd(&r, &info, buf + l, size - l); |
---|
| 3475 | + |
---|
| 3476 | + seq = r.info->seq + 1; |
---|
3424 | 3477 | } |
---|
3425 | 3478 | |
---|
3426 | 3479 | dumper->next_seq = next_seq; |
---|
3427 | | - dumper->next_idx = next_idx; |
---|
3428 | 3480 | ret = true; |
---|
3429 | 3481 | logbuf_unlock_irqrestore(flags); |
---|
3430 | 3482 | out: |
---|
.. | .. |
---|
3435 | 3487 | EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); |
---|
3436 | 3488 | |
---|
3437 | 3489 | /** |
---|
3438 | | - * kmsg_dump_rewind_nolock - reset the interator (unlocked version) |
---|
| 3490 | + * kmsg_dump_rewind_nolock - reset the iterator (unlocked version) |
---|
3439 | 3491 | * @dumper: registered kmsg dumper |
---|
3440 | 3492 | * |
---|
3441 | 3493 | * Reset the dumper's iterator so that kmsg_dump_get_line() and |
---|
.. | .. |
---|
3447 | 3499 | void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper) |
---|
3448 | 3500 | { |
---|
3449 | 3501 | dumper->cur_seq = clear_seq; |
---|
3450 | | - dumper->cur_idx = clear_idx; |
---|
3451 | | - dumper->next_seq = log_next_seq; |
---|
3452 | | - dumper->next_idx = log_next_idx; |
---|
| 3502 | + dumper->next_seq = prb_next_seq(prb); |
---|
3453 | 3503 | } |
---|
3454 | 3504 | |
---|
3455 | 3505 | /** |
---|
3456 | | - * kmsg_dump_rewind - reset the interator |
---|
| 3506 | + * kmsg_dump_rewind - reset the iterator |
---|
3457 | 3507 | * @dumper: registered kmsg dumper |
---|
3458 | 3508 | * |
---|
3459 | 3509 | * Reset the dumper's iterator so that kmsg_dump_get_line() and |
---|