| .. | .. |
|---|
| 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> |
|---|
| .. | .. |
|---|
| 43 | 44 | #include <linux/irq_work.h> |
|---|
| 44 | 45 | #include <linux/ctype.h> |
|---|
| 45 | 46 | #include <linux/uio.h> |
|---|
| 47 | +#include <linux/kthread.h> |
|---|
| 48 | +#include <linux/kdb.h> |
|---|
| 49 | +#include <linux/clocksource.h> |
|---|
| 46 | 50 | #include <linux/sched/clock.h> |
|---|
| 47 | 51 | #include <linux/sched/debug.h> |
|---|
| 48 | 52 | #include <linux/sched/task_stack.h> |
|---|
| .. | .. |
|---|
| 53 | 57 | #include <trace/events/initcall.h> |
|---|
| 54 | 58 | #define CREATE_TRACE_POINTS |
|---|
| 55 | 59 | #include <trace/events/printk.h> |
|---|
| 60 | +#undef CREATE_TRACE_POINTS |
|---|
| 61 | +#include <trace/hooks/printk.h> |
|---|
| 62 | +#include <trace/hooks/logbuf.h> |
|---|
| 56 | 63 | |
|---|
| 64 | +#include "printk_ringbuffer.h" |
|---|
| 57 | 65 | #include "console_cmdline.h" |
|---|
| 58 | 66 | #include "braille.h" |
|---|
| 59 | | -#include "internal.h" |
|---|
| 60 | | - |
|---|
| 61 | | -#ifdef CONFIG_PRINTK_TIME_FROM_ARM_ARCH_TIMER |
|---|
| 62 | | -#include <clocksource/arm_arch_timer.h> |
|---|
| 63 | | -static u64 get_local_clock(void) |
|---|
| 64 | | -{ |
|---|
| 65 | | - u64 ns; |
|---|
| 66 | | - |
|---|
| 67 | | - ns = arch_timer_read_counter() * 1000; |
|---|
| 68 | | - do_div(ns, 24); |
|---|
| 69 | | - |
|---|
| 70 | | - return ns; |
|---|
| 71 | | -} |
|---|
| 72 | | -#else |
|---|
| 73 | | -static inline u64 get_local_clock(void) |
|---|
| 74 | | -{ |
|---|
| 75 | | - return local_clock(); |
|---|
| 76 | | -} |
|---|
| 77 | | -#endif |
|---|
| 78 | 67 | |
|---|
| 79 | 68 | int console_printk[4] = { |
|---|
| 80 | 69 | CONSOLE_LOGLEVEL_DEFAULT, /* console_loglevel */ |
|---|
| .. | .. |
|---|
| 82 | 71 | CONSOLE_LOGLEVEL_MIN, /* minimum_console_loglevel */ |
|---|
| 83 | 72 | CONSOLE_LOGLEVEL_DEFAULT, /* default_console_loglevel */ |
|---|
| 84 | 73 | }; |
|---|
| 74 | +EXPORT_SYMBOL_GPL(console_printk); |
|---|
| 85 | 75 | |
|---|
| 86 | 76 | atomic_t ignore_console_lock_warning __read_mostly = ATOMIC_INIT(0); |
|---|
| 87 | 77 | EXPORT_SYMBOL(ignore_console_lock_warning); |
|---|
| .. | .. |
|---|
| 101 | 91 | static DEFINE_SEMAPHORE(console_sem); |
|---|
| 102 | 92 | struct console *console_drivers; |
|---|
| 103 | 93 | EXPORT_SYMBOL_GPL(console_drivers); |
|---|
| 94 | + |
|---|
| 95 | +/* |
|---|
| 96 | + * System may need to suppress printk message under certain |
|---|
| 97 | + * circumstances, like after kernel panic happens. |
|---|
| 98 | + */ |
|---|
| 99 | +int __read_mostly suppress_printk; |
|---|
| 104 | 100 | |
|---|
| 105 | 101 | #ifdef CONFIG_LOCKDEP |
|---|
| 106 | 102 | static struct lockdep_map console_lock_dep_map = { |
|---|
| .. | .. |
|---|
| 127 | 123 | |
|---|
| 128 | 124 | static int __control_devkmsg(char *str) |
|---|
| 129 | 125 | { |
|---|
| 126 | + size_t len; |
|---|
| 127 | + |
|---|
| 130 | 128 | if (!str) |
|---|
| 131 | 129 | return -EINVAL; |
|---|
| 132 | 130 | |
|---|
| 133 | | - if (!strncmp(str, "on", 2)) { |
|---|
| 131 | + len = str_has_prefix(str, "on"); |
|---|
| 132 | + if (len) { |
|---|
| 134 | 133 | 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; |
|---|
| 134 | + return len; |
|---|
| 142 | 135 | } |
|---|
| 136 | + |
|---|
| 137 | + len = str_has_prefix(str, "off"); |
|---|
| 138 | + if (len) { |
|---|
| 139 | + devkmsg_log = DEVKMSG_LOG_MASK_OFF; |
|---|
| 140 | + return len; |
|---|
| 141 | + } |
|---|
| 142 | + |
|---|
| 143 | + len = str_has_prefix(str, "ratelimit"); |
|---|
| 144 | + if (len) { |
|---|
| 145 | + devkmsg_log = DEVKMSG_LOG_MASK_DEFAULT; |
|---|
| 146 | + return len; |
|---|
| 147 | + } |
|---|
| 148 | + |
|---|
| 143 | 149 | return -EINVAL; |
|---|
| 144 | 150 | } |
|---|
| 145 | 151 | |
|---|
| 146 | 152 | static int __init control_devkmsg(char *str) |
|---|
| 147 | 153 | { |
|---|
| 148 | | - if (__control_devkmsg(str) < 0) |
|---|
| 154 | + if (__control_devkmsg(str) < 0) { |
|---|
| 155 | + pr_warn("printk.devkmsg: bad option string '%s'\n", str); |
|---|
| 149 | 156 | return 1; |
|---|
| 157 | + } |
|---|
| 150 | 158 | |
|---|
| 151 | 159 | /* |
|---|
| 152 | 160 | * Set sysctl string accordingly: |
|---|
| .. | .. |
|---|
| 165 | 173 | */ |
|---|
| 166 | 174 | devkmsg_log |= DEVKMSG_LOG_MASK_LOCK; |
|---|
| 167 | 175 | |
|---|
| 168 | | - return 0; |
|---|
| 176 | + return 1; |
|---|
| 169 | 177 | } |
|---|
| 170 | 178 | __setup("printk.devkmsg=", control_devkmsg); |
|---|
| 171 | 179 | |
|---|
| 172 | 180 | char devkmsg_log_str[DEVKMSG_STR_MAX_SIZE] = "ratelimit"; |
|---|
| 173 | 181 | |
|---|
| 174 | 182 | int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write, |
|---|
| 175 | | - void __user *buffer, size_t *lenp, loff_t *ppos) |
|---|
| 183 | + void *buffer, size_t *lenp, loff_t *ppos) |
|---|
| 176 | 184 | { |
|---|
| 177 | 185 | char old_str[DEVKMSG_STR_MAX_SIZE]; |
|---|
| 178 | 186 | unsigned int old; |
|---|
| .. | .. |
|---|
| 210 | 218 | return 0; |
|---|
| 211 | 219 | } |
|---|
| 212 | 220 | |
|---|
| 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 | | - */ |
|---|
| 221 | +/* Number of registered extended console drivers. */ |
|---|
| 223 | 222 | static int nr_ext_console_drivers; |
|---|
| 224 | 223 | |
|---|
| 225 | 224 | /* |
|---|
| .. | .. |
|---|
| 233 | 232 | |
|---|
| 234 | 233 | static int __down_trylock_console_sem(unsigned long ip) |
|---|
| 235 | 234 | { |
|---|
| 236 | | - int lock_failed; |
|---|
| 237 | | - unsigned long flags; |
|---|
| 238 | | - |
|---|
| 239 | | - /* |
|---|
| 240 | | - * Here and in __up_console_sem() we need to be in safe mode, |
|---|
| 241 | | - * because spindump/WARN/etc from under console ->lock will |
|---|
| 242 | | - * deadlock in printk()->down_trylock_console_sem() otherwise. |
|---|
| 243 | | - */ |
|---|
| 244 | | - printk_safe_enter_irqsave(flags); |
|---|
| 245 | | - lock_failed = down_trylock(&console_sem); |
|---|
| 246 | | - printk_safe_exit_irqrestore(flags); |
|---|
| 247 | | - |
|---|
| 248 | | - if (lock_failed) |
|---|
| 235 | + if (down_trylock(&console_sem)) |
|---|
| 249 | 236 | return 1; |
|---|
| 250 | 237 | mutex_acquire(&console_lock_dep_map, 0, 1, ip); |
|---|
| 251 | 238 | return 0; |
|---|
| .. | .. |
|---|
| 254 | 241 | |
|---|
| 255 | 242 | static void __up_console_sem(unsigned long ip) |
|---|
| 256 | 243 | { |
|---|
| 257 | | - unsigned long flags; |
|---|
| 244 | + mutex_release(&console_lock_dep_map, ip); |
|---|
| 258 | 245 | |
|---|
| 259 | | - mutex_release(&console_lock_dep_map, 1, ip); |
|---|
| 260 | | - |
|---|
| 261 | | - printk_safe_enter_irqsave(flags); |
|---|
| 262 | 246 | up(&console_sem); |
|---|
| 263 | | - printk_safe_exit_irqrestore(flags); |
|---|
| 264 | 247 | } |
|---|
| 265 | 248 | #define up_console_sem() __up_console_sem(_RET_IP_) |
|---|
| 266 | 249 | |
|---|
| .. | .. |
|---|
| 275 | 258 | static int console_locked, console_suspended; |
|---|
| 276 | 259 | |
|---|
| 277 | 260 | /* |
|---|
| 278 | | - * If exclusive_console is non-NULL then only this console is to be printed to. |
|---|
| 279 | | - */ |
|---|
| 280 | | -static struct console *exclusive_console; |
|---|
| 281 | | - |
|---|
| 282 | | -/* |
|---|
| 283 | 261 | * Array of consoles built from command line options (console=) |
|---|
| 284 | 262 | */ |
|---|
| 285 | 263 | |
|---|
| .. | .. |
|---|
| 288 | 266 | static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES]; |
|---|
| 289 | 267 | |
|---|
| 290 | 268 | static int preferred_console = -1; |
|---|
| 269 | +static bool has_preferred_console; |
|---|
| 291 | 270 | int console_set_on_cmdline; |
|---|
| 292 | 271 | EXPORT_SYMBOL(console_set_on_cmdline); |
|---|
| 293 | 272 | |
|---|
| .. | .. |
|---|
| 302 | 281 | static int console_msg_format = MSG_FORMAT_DEFAULT; |
|---|
| 303 | 282 | |
|---|
| 304 | 283 | /* |
|---|
| 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. |
|---|
| 284 | + * The printk log buffer consists of a sequenced collection of records, each |
|---|
| 285 | + * containing variable length message text. Every record also contains its |
|---|
| 286 | + * own meta-data (@info). |
|---|
| 308 | 287 | * |
|---|
| 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. |
|---|
| 288 | + * Every record meta-data carries the timestamp in microseconds, as well as |
|---|
| 289 | + * the standard userspace syslog level and syslog facility. The usual kernel |
|---|
| 290 | + * messages use LOG_KERN; userspace-injected messages always carry a matching |
|---|
| 291 | + * syslog facility, by default LOG_USER. The origin of every message can be |
|---|
| 292 | + * reliably determined that way. |
|---|
| 312 | 293 | * |
|---|
| 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. |
|---|
| 294 | + * The human readable log message of a record is available in @text, the |
|---|
| 295 | + * length of the message text in @text_len. The stored message is not |
|---|
| 296 | + * terminated. |
|---|
| 316 | 297 | * |
|---|
| 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. |
|---|
| 298 | + * Optionally, a record can carry a dictionary of properties (key/value |
|---|
| 299 | + * pairs), to provide userspace with a machine-readable message context. |
|---|
| 329 | 300 | * |
|---|
| 330 | 301 | * Examples for well-defined, commonly used property names are: |
|---|
| 331 | 302 | * DEVICE=b12:8 device identifier |
|---|
| .. | .. |
|---|
| 335 | 306 | * +sound:card0 subsystem:devname |
|---|
| 336 | 307 | * SUBSYSTEM=pci driver-core subsystem name |
|---|
| 337 | 308 | * |
|---|
| 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. |
|---|
| 309 | + * Valid characters in property names are [a-zA-Z0-9.-_]. Property names |
|---|
| 310 | + * and values are terminated by a '\0' character. |
|---|
| 341 | 311 | * |
|---|
| 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 |
|---|
| 312 | + * Example of record values: |
|---|
| 313 | + * record.text_buf = "it's a line" (unterminated) |
|---|
| 314 | + * record.info.seq = 56 |
|---|
| 315 | + * record.info.ts_nsec = 36863 |
|---|
| 316 | + * record.info.text_len = 11 |
|---|
| 317 | + * record.info.facility = 0 (LOG_KERN) |
|---|
| 318 | + * record.info.flags = 0 |
|---|
| 319 | + * record.info.level = 3 (LOG_ERR) |
|---|
| 320 | + * record.info.caller_id = 299 (task 299) |
|---|
| 321 | + * record.info.dev_info.subsystem = "pci" (terminated) |
|---|
| 322 | + * record.info.dev_info.device = "+pci:0000:00:01.0" (terminated) |
|---|
| 355 | 323 | * |
|---|
| 356 | | - * The 'struct printk_log' buffer header must never be directly exported to |
|---|
| 324 | + * The 'struct printk_info' buffer must never be directly exported to |
|---|
| 357 | 325 | * userspace, it is a kernel-private implementation detail that might |
|---|
| 358 | 326 | * need to be changed in the future, when the requirements change. |
|---|
| 359 | 327 | * |
|---|
| .. | .. |
|---|
| 370 | 338 | |
|---|
| 371 | 339 | enum log_flags { |
|---|
| 372 | 340 | LOG_NEWLINE = 2, /* text ended with a newline */ |
|---|
| 373 | | - LOG_PREFIX = 4, /* text started with a prefix */ |
|---|
| 374 | 341 | LOG_CONT = 8, /* text is a fragment of a continuation line */ |
|---|
| 375 | 342 | }; |
|---|
| 376 | 343 | |
|---|
| 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 | | - |
|---|
| 397 | | -/* |
|---|
| 398 | | - * The logbuf_lock protects kmsg buffer, indices, counters. This can be taken |
|---|
| 399 | | - * within the scheduler's rq lock. It must be released before calling |
|---|
| 400 | | - * console_unlock() or anything else that might wake up a process. |
|---|
| 401 | | - */ |
|---|
| 402 | | -DEFINE_RAW_SPINLOCK(logbuf_lock); |
|---|
| 403 | | - |
|---|
| 404 | | -/* |
|---|
| 405 | | - * Helper macros to lock/unlock logbuf_lock and switch between |
|---|
| 406 | | - * printk-safe/unsafe modes. |
|---|
| 407 | | - */ |
|---|
| 408 | | -#define logbuf_lock_irq() \ |
|---|
| 409 | | - do { \ |
|---|
| 410 | | - printk_safe_enter_irq(); \ |
|---|
| 411 | | - raw_spin_lock(&logbuf_lock); \ |
|---|
| 412 | | - } while (0) |
|---|
| 413 | | - |
|---|
| 414 | | -#define logbuf_unlock_irq() \ |
|---|
| 415 | | - do { \ |
|---|
| 416 | | - raw_spin_unlock(&logbuf_lock); \ |
|---|
| 417 | | - printk_safe_exit_irq(); \ |
|---|
| 418 | | - } while (0) |
|---|
| 419 | | - |
|---|
| 420 | | -#define logbuf_lock_irqsave(flags) \ |
|---|
| 421 | | - do { \ |
|---|
| 422 | | - printk_safe_enter_irqsave(flags); \ |
|---|
| 423 | | - raw_spin_lock(&logbuf_lock); \ |
|---|
| 424 | | - } while (0) |
|---|
| 425 | | - |
|---|
| 426 | | -#define logbuf_unlock_irqrestore(flags) \ |
|---|
| 427 | | - do { \ |
|---|
| 428 | | - raw_spin_unlock(&logbuf_lock); \ |
|---|
| 429 | | - printk_safe_exit_irqrestore(flags); \ |
|---|
| 430 | | - } while (0) |
|---|
| 431 | | - |
|---|
| 432 | | -#ifdef CONFIG_EARLY_PRINTK |
|---|
| 433 | | -struct console *early_console; |
|---|
| 434 | | - |
|---|
| 435 | | -static void early_vprintk(const char *fmt, va_list ap) |
|---|
| 436 | | -{ |
|---|
| 437 | | - if (early_console) { |
|---|
| 438 | | - char buf[512]; |
|---|
| 439 | | - int n = vscnprintf(buf, sizeof(buf), fmt, ap); |
|---|
| 440 | | - |
|---|
| 441 | | - early_console->write(early_console, buf, n); |
|---|
| 442 | | - } |
|---|
| 443 | | -} |
|---|
| 444 | | - |
|---|
| 445 | | -asmlinkage void early_printk(const char *fmt, ...) |
|---|
| 446 | | -{ |
|---|
| 447 | | - va_list ap; |
|---|
| 448 | | - |
|---|
| 449 | | - va_start(ap, fmt); |
|---|
| 450 | | - early_vprintk(fmt, ap); |
|---|
| 451 | | - va_end(ap); |
|---|
| 452 | | -} |
|---|
| 453 | | - |
|---|
| 454 | | -/* |
|---|
| 455 | | - * This is independent of any log levels - a global |
|---|
| 456 | | - * kill switch that turns off all of printk. |
|---|
| 457 | | - * |
|---|
| 458 | | - * Used by the NMI watchdog if early-printk is enabled. |
|---|
| 459 | | - */ |
|---|
| 460 | | -static bool __read_mostly printk_killswitch; |
|---|
| 461 | | - |
|---|
| 462 | | -static int __init force_early_printk_setup(char *str) |
|---|
| 463 | | -{ |
|---|
| 464 | | - printk_killswitch = true; |
|---|
| 465 | | - return 0; |
|---|
| 466 | | -} |
|---|
| 467 | | -early_param("force_early_printk", force_early_printk_setup); |
|---|
| 468 | | - |
|---|
| 469 | | -void printk_kill(void) |
|---|
| 470 | | -{ |
|---|
| 471 | | - printk_killswitch = true; |
|---|
| 472 | | -} |
|---|
| 473 | | - |
|---|
| 474 | 344 | #ifdef CONFIG_PRINTK |
|---|
| 475 | | -static int forced_early_printk(const char *fmt, va_list ap) |
|---|
| 476 | | -{ |
|---|
| 477 | | - if (!printk_killswitch) |
|---|
| 478 | | - return 0; |
|---|
| 479 | | - early_vprintk(fmt, ap); |
|---|
| 480 | | - return 1; |
|---|
| 481 | | -} |
|---|
| 482 | | -#endif |
|---|
| 345 | +/* syslog_lock protects syslog_* variables and write access to clear_seq. */ |
|---|
| 346 | +static DEFINE_SPINLOCK(syslog_lock); |
|---|
| 483 | 347 | |
|---|
| 484 | | -#else |
|---|
| 485 | | -static inline int forced_early_printk(const char *fmt, va_list ap) |
|---|
| 486 | | -{ |
|---|
| 487 | | - return 0; |
|---|
| 488 | | -} |
|---|
| 489 | | -#endif |
|---|
| 348 | +/* Set to enable sync mode. Once set, it is never cleared. */ |
|---|
| 349 | +static bool sync_mode; |
|---|
| 490 | 350 | |
|---|
| 491 | | -#ifdef CONFIG_PRINTK |
|---|
| 492 | 351 | DECLARE_WAIT_QUEUE_HEAD(log_wait); |
|---|
| 352 | +/* All 3 protected by @syslog_lock. */ |
|---|
| 493 | 353 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ |
|---|
| 494 | 354 | static u64 syslog_seq; |
|---|
| 495 | | -static u32 syslog_idx; |
|---|
| 496 | 355 | static size_t syslog_partial; |
|---|
| 356 | +static bool syslog_time; |
|---|
| 497 | 357 | |
|---|
| 498 | | -/* index and sequence number of the first record stored in the buffer */ |
|---|
| 499 | | -static u64 log_first_seq; |
|---|
| 500 | | -static u32 log_first_idx; |
|---|
| 358 | +struct latched_seq { |
|---|
| 359 | + seqcount_latch_t latch; |
|---|
| 360 | + u64 val[2]; |
|---|
| 361 | +}; |
|---|
| 501 | 362 | |
|---|
| 502 | | -/* index and sequence number of the next record to store in the buffer */ |
|---|
| 503 | | -static u64 log_next_seq; |
|---|
| 504 | | -static u32 log_next_idx; |
|---|
| 363 | +/* |
|---|
| 364 | + * The next printk record to read after the last 'clear' command. There are |
|---|
| 365 | + * two copies (updated with seqcount_latch) so that reads can locklessly |
|---|
| 366 | + * access a valid value. Writers are synchronized by @syslog_lock. |
|---|
| 367 | + */ |
|---|
| 368 | +static struct latched_seq clear_seq = { |
|---|
| 369 | + .latch = SEQCNT_LATCH_ZERO(clear_seq.latch), |
|---|
| 370 | + .val[0] = 0, |
|---|
| 371 | + .val[1] = 0, |
|---|
| 372 | +}; |
|---|
| 505 | 373 | |
|---|
| 506 | | -/* the next printk record to write to the console */ |
|---|
| 507 | | -static u64 console_seq; |
|---|
| 508 | | -static u32 console_idx; |
|---|
| 509 | | -static u64 exclusive_console_stop_seq; |
|---|
| 510 | | - |
|---|
| 511 | | -/* the next printk record to read after the last 'clear' command */ |
|---|
| 512 | | -static u64 clear_seq; |
|---|
| 513 | | -static u32 clear_idx; |
|---|
| 514 | | - |
|---|
| 515 | | -#ifdef CONFIG_PRINTK_PROCESS |
|---|
| 374 | +#ifdef CONFIG_PRINTK_CALLER |
|---|
| 516 | 375 | #define PREFIX_MAX 48 |
|---|
| 517 | 376 | #else |
|---|
| 518 | 377 | #define PREFIX_MAX 32 |
|---|
| 519 | 378 | #endif |
|---|
| 379 | + |
|---|
| 380 | +/* the maximum size allowed to be reserved for a record */ |
|---|
| 520 | 381 | #define LOG_LINE_MAX (1024 - PREFIX_MAX) |
|---|
| 521 | 382 | |
|---|
| 522 | 383 | #define LOG_LEVEL(v) ((v) & 0x07) |
|---|
| 523 | 384 | #define LOG_FACILITY(v) ((v) >> 3 & 0xff) |
|---|
| 524 | 385 | |
|---|
| 525 | 386 | /* record buffer */ |
|---|
| 526 | | -#define LOG_ALIGN __alignof__(struct printk_log) |
|---|
| 387 | +#define LOG_ALIGN __alignof__(unsigned long) |
|---|
| 527 | 388 | #define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT) |
|---|
| 528 | 389 | #define LOG_BUF_LEN_MAX (u32)(1 << 31) |
|---|
| 529 | 390 | static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN); |
|---|
| 530 | 391 | static char *log_buf = __log_buf; |
|---|
| 531 | 392 | static u32 log_buf_len = __LOG_BUF_LEN; |
|---|
| 393 | + |
|---|
| 394 | +/* |
|---|
| 395 | + * Define the average message size. This only affects the number of |
|---|
| 396 | + * descriptors that will be available. Underestimating is better than |
|---|
| 397 | + * overestimating (too many available descriptors is better than not enough). |
|---|
| 398 | + */ |
|---|
| 399 | +#define PRB_AVGBITS 5 /* 32 character average length */ |
|---|
| 400 | + |
|---|
| 401 | +#if CONFIG_LOG_BUF_SHIFT <= PRB_AVGBITS |
|---|
| 402 | +#error CONFIG_LOG_BUF_SHIFT value too small. |
|---|
| 403 | +#endif |
|---|
| 404 | +_DEFINE_PRINTKRB(printk_rb_static, CONFIG_LOG_BUF_SHIFT - PRB_AVGBITS, |
|---|
| 405 | + PRB_AVGBITS, &__log_buf[0]); |
|---|
| 406 | + |
|---|
| 407 | +static struct printk_ringbuffer printk_rb_dynamic; |
|---|
| 408 | + |
|---|
| 409 | +static struct printk_ringbuffer *prb = &printk_rb_static; |
|---|
| 532 | 410 | |
|---|
| 533 | 411 | /* |
|---|
| 534 | 412 | * We cannot access per-CPU data (e.g. per-CPU flush irq_work) before |
|---|
| .. | .. |
|---|
| 537 | 415 | */ |
|---|
| 538 | 416 | static bool __printk_percpu_data_ready __read_mostly; |
|---|
| 539 | 417 | |
|---|
| 540 | | -bool printk_percpu_data_ready(void) |
|---|
| 418 | +static bool printk_percpu_data_ready(void) |
|---|
| 541 | 419 | { |
|---|
| 542 | 420 | return __printk_percpu_data_ready; |
|---|
| 421 | +} |
|---|
| 422 | + |
|---|
| 423 | +/* Must be called under syslog_lock. */ |
|---|
| 424 | +static void latched_seq_write(struct latched_seq *ls, u64 val) |
|---|
| 425 | +{ |
|---|
| 426 | + raw_write_seqcount_latch(&ls->latch); |
|---|
| 427 | + ls->val[0] = val; |
|---|
| 428 | + raw_write_seqcount_latch(&ls->latch); |
|---|
| 429 | + ls->val[1] = val; |
|---|
| 430 | +} |
|---|
| 431 | + |
|---|
| 432 | +/* Can be called from any context. */ |
|---|
| 433 | +static u64 latched_seq_read_nolock(struct latched_seq *ls) |
|---|
| 434 | +{ |
|---|
| 435 | + unsigned int seq; |
|---|
| 436 | + unsigned int idx; |
|---|
| 437 | + u64 val; |
|---|
| 438 | + |
|---|
| 439 | + do { |
|---|
| 440 | + seq = raw_read_seqcount_latch(&ls->latch); |
|---|
| 441 | + idx = seq & 0x1; |
|---|
| 442 | + val = ls->val[idx]; |
|---|
| 443 | + } while (read_seqcount_latch_retry(&ls->latch, seq)); |
|---|
| 444 | + |
|---|
| 445 | + return val; |
|---|
| 543 | 446 | } |
|---|
| 544 | 447 | |
|---|
| 545 | 448 | /* Return log buffer address */ |
|---|
| .. | .. |
|---|
| 556 | 459 | } |
|---|
| 557 | 460 | EXPORT_SYMBOL_GPL(log_buf_len_get); |
|---|
| 558 | 461 | |
|---|
| 559 | | -/* human readable text of the record */ |
|---|
| 560 | | -static char *log_text(const struct printk_log *msg) |
|---|
| 561 | | -{ |
|---|
| 562 | | - return (char *)msg + sizeof(struct printk_log); |
|---|
| 563 | | -} |
|---|
| 564 | | - |
|---|
| 565 | | -/* optional key/value pair dictionary attached to the record */ |
|---|
| 566 | | -static char *log_dict(const struct printk_log *msg) |
|---|
| 567 | | -{ |
|---|
| 568 | | - return (char *)msg + sizeof(struct printk_log) + msg->text_len; |
|---|
| 569 | | -} |
|---|
| 570 | | - |
|---|
| 571 | | -/* get record by index; idx must point to valid msg */ |
|---|
| 572 | | -static struct printk_log *log_from_idx(u32 idx) |
|---|
| 573 | | -{ |
|---|
| 574 | | - struct printk_log *msg = (struct printk_log *)(log_buf + idx); |
|---|
| 575 | | - |
|---|
| 576 | | - /* |
|---|
| 577 | | - * A length == 0 record is the end of buffer marker. Wrap around and |
|---|
| 578 | | - * read the message at the start of the buffer. |
|---|
| 579 | | - */ |
|---|
| 580 | | - if (!msg->len) |
|---|
| 581 | | - return (struct printk_log *)log_buf; |
|---|
| 582 | | - return msg; |
|---|
| 583 | | -} |
|---|
| 584 | | - |
|---|
| 585 | | -/* get next record; idx must point to valid msg */ |
|---|
| 586 | | -static u32 log_next(u32 idx) |
|---|
| 587 | | -{ |
|---|
| 588 | | - struct printk_log *msg = (struct printk_log *)(log_buf + idx); |
|---|
| 589 | | - |
|---|
| 590 | | - /* length == 0 indicates the end of the buffer; wrap */ |
|---|
| 591 | | - /* |
|---|
| 592 | | - * A length == 0 record is the end of buffer marker. Wrap around and |
|---|
| 593 | | - * read the message at the start of the buffer as *this* one, and |
|---|
| 594 | | - * return the one after that. |
|---|
| 595 | | - */ |
|---|
| 596 | | - if (!msg->len) { |
|---|
| 597 | | - msg = (struct printk_log *)log_buf; |
|---|
| 598 | | - return msg->len; |
|---|
| 599 | | - } |
|---|
| 600 | | - return idx + msg->len; |
|---|
| 601 | | -} |
|---|
| 602 | | - |
|---|
| 603 | | -#ifdef CONFIG_PRINTK_PROCESS |
|---|
| 604 | | -static bool printk_process = true; |
|---|
| 605 | | -static size_t print_process(const struct printk_log *msg, char *buf) |
|---|
| 606 | | -{ |
|---|
| 607 | | - if (!printk_process) |
|---|
| 608 | | - return 0; |
|---|
| 609 | | - |
|---|
| 610 | | - if (!buf) |
|---|
| 611 | | - return snprintf(NULL, 0, "%c[%1d:%15s:%5d] ", ' ', 0, " ", 0); |
|---|
| 612 | | - |
|---|
| 613 | | - return sprintf(buf, "%c[%1d:%15s:%5d] ", |
|---|
| 614 | | - msg->in_interrupt ? 'I' : ' ', |
|---|
| 615 | | - msg->cpu, |
|---|
| 616 | | - msg->process, |
|---|
| 617 | | - msg->pid); |
|---|
| 618 | | -} |
|---|
| 619 | | -module_param_named(process, printk_process, bool, 0644); |
|---|
| 620 | | -#endif |
|---|
| 621 | | - |
|---|
| 622 | | -/* |
|---|
| 623 | | - * Check whether there is enough free space for the given message. |
|---|
| 624 | | - * |
|---|
| 625 | | - * The same values of first_idx and next_idx mean that the buffer |
|---|
| 626 | | - * is either empty or full. |
|---|
| 627 | | - * |
|---|
| 628 | | - * If the buffer is empty, we must respect the position of the indexes. |
|---|
| 629 | | - * They cannot be reset to the beginning of the buffer. |
|---|
| 630 | | - */ |
|---|
| 631 | | -static int logbuf_has_space(u32 msg_size, bool empty) |
|---|
| 632 | | -{ |
|---|
| 633 | | - u32 free; |
|---|
| 634 | | - |
|---|
| 635 | | - if (log_next_idx > log_first_idx || empty) |
|---|
| 636 | | - free = max(log_buf_len - log_next_idx, log_first_idx); |
|---|
| 637 | | - else |
|---|
| 638 | | - free = log_first_idx - log_next_idx; |
|---|
| 639 | | - |
|---|
| 640 | | - /* |
|---|
| 641 | | - * We need space also for an empty header that signalizes wrapping |
|---|
| 642 | | - * of the buffer. |
|---|
| 643 | | - */ |
|---|
| 644 | | - return free >= msg_size + sizeof(struct printk_log); |
|---|
| 645 | | -} |
|---|
| 646 | | - |
|---|
| 647 | | -static int log_make_free_space(u32 msg_size) |
|---|
| 648 | | -{ |
|---|
| 649 | | - while (log_first_seq < log_next_seq && |
|---|
| 650 | | - !logbuf_has_space(msg_size, false)) { |
|---|
| 651 | | - /* drop old messages until we have enough contiguous space */ |
|---|
| 652 | | - log_first_idx = log_next(log_first_idx); |
|---|
| 653 | | - log_first_seq++; |
|---|
| 654 | | - } |
|---|
| 655 | | - |
|---|
| 656 | | - if (clear_seq < log_first_seq) { |
|---|
| 657 | | - clear_seq = log_first_seq; |
|---|
| 658 | | - clear_idx = log_first_idx; |
|---|
| 659 | | - } |
|---|
| 660 | | - |
|---|
| 661 | | - /* sequence numbers are equal, so the log buffer is empty */ |
|---|
| 662 | | - if (logbuf_has_space(msg_size, log_first_seq == log_next_seq)) |
|---|
| 663 | | - return 0; |
|---|
| 664 | | - |
|---|
| 665 | | - return -ENOMEM; |
|---|
| 666 | | -} |
|---|
| 667 | | - |
|---|
| 668 | | -/* compute the message size including the padding bytes */ |
|---|
| 669 | | -static u32 msg_used_size(u16 text_len, u16 dict_len, u32 *pad_len) |
|---|
| 670 | | -{ |
|---|
| 671 | | - u32 size; |
|---|
| 672 | | - |
|---|
| 673 | | - size = sizeof(struct printk_log) + text_len + dict_len; |
|---|
| 674 | | - *pad_len = (-size) & (LOG_ALIGN - 1); |
|---|
| 675 | | - size += *pad_len; |
|---|
| 676 | | - |
|---|
| 677 | | - return size; |
|---|
| 678 | | -} |
|---|
| 679 | | - |
|---|
| 680 | 462 | /* |
|---|
| 681 | 463 | * Define how much of the log buffer we could take at maximum. The value |
|---|
| 682 | 464 | * must be greater than two. Note that only half of the buffer is available |
|---|
| .. | .. |
|---|
| 685 | 467 | #define MAX_LOG_TAKE_PART 4 |
|---|
| 686 | 468 | static const char trunc_msg[] = "<truncated>"; |
|---|
| 687 | 469 | |
|---|
| 688 | | -static u32 truncate_msg(u16 *text_len, u16 *trunc_msg_len, |
|---|
| 689 | | - u16 *dict_len, u32 *pad_len) |
|---|
| 470 | +static void truncate_msg(u16 *text_len, u16 *trunc_msg_len) |
|---|
| 690 | 471 | { |
|---|
| 691 | 472 | /* |
|---|
| 692 | 473 | * The message should not take the whole buffer. Otherwise, it might |
|---|
| 693 | 474 | * get removed too soon. |
|---|
| 694 | 475 | */ |
|---|
| 695 | 476 | u32 max_text_len = log_buf_len / MAX_LOG_TAKE_PART; |
|---|
| 477 | + |
|---|
| 696 | 478 | if (*text_len > max_text_len) |
|---|
| 697 | 479 | *text_len = max_text_len; |
|---|
| 698 | | - /* enable the warning message */ |
|---|
| 480 | + |
|---|
| 481 | + /* enable the warning message (if there is room) */ |
|---|
| 699 | 482 | *trunc_msg_len = strlen(trunc_msg); |
|---|
| 700 | | - /* disable the "dict" completely */ |
|---|
| 701 | | - *dict_len = 0; |
|---|
| 702 | | - /* compute the size again, count also the warning message */ |
|---|
| 703 | | - return msg_used_size(*text_len + *trunc_msg_len, 0, pad_len); |
|---|
| 704 | | -} |
|---|
| 705 | | - |
|---|
| 706 | | -/* insert record into the buffer, discard old ones, update heads */ |
|---|
| 707 | | -static int log_store(int facility, int level, |
|---|
| 708 | | - enum log_flags flags, u64 ts_nsec, |
|---|
| 709 | | - const char *dict, u16 dict_len, |
|---|
| 710 | | - const char *text, u16 text_len) |
|---|
| 711 | | -{ |
|---|
| 712 | | - struct printk_log *msg; |
|---|
| 713 | | - u32 size, pad_len; |
|---|
| 714 | | - u16 trunc_msg_len = 0; |
|---|
| 715 | | - |
|---|
| 716 | | - /* number of '\0' padding bytes to next message */ |
|---|
| 717 | | - size = msg_used_size(text_len, dict_len, &pad_len); |
|---|
| 718 | | - |
|---|
| 719 | | - if (log_make_free_space(size)) { |
|---|
| 720 | | - /* truncate the message if it is too long for empty buffer */ |
|---|
| 721 | | - size = truncate_msg(&text_len, &trunc_msg_len, |
|---|
| 722 | | - &dict_len, &pad_len); |
|---|
| 723 | | - /* survive when the log buffer is too small for trunc_msg */ |
|---|
| 724 | | - if (log_make_free_space(size)) |
|---|
| 725 | | - return 0; |
|---|
| 726 | | - } |
|---|
| 727 | | - |
|---|
| 728 | | - if (log_next_idx + size + sizeof(struct printk_log) > log_buf_len) { |
|---|
| 729 | | - /* |
|---|
| 730 | | - * This message + an additional empty header does not fit |
|---|
| 731 | | - * at the end of the buffer. Add an empty header with len == 0 |
|---|
| 732 | | - * to signify a wrap around. |
|---|
| 733 | | - */ |
|---|
| 734 | | - memset(log_buf + log_next_idx, 0, sizeof(struct printk_log)); |
|---|
| 735 | | - log_next_idx = 0; |
|---|
| 736 | | - } |
|---|
| 737 | | - |
|---|
| 738 | | - /* fill message */ |
|---|
| 739 | | - msg = (struct printk_log *)(log_buf + log_next_idx); |
|---|
| 740 | | - memcpy(log_text(msg), text, text_len); |
|---|
| 741 | | - msg->text_len = text_len; |
|---|
| 742 | | - if (trunc_msg_len) { |
|---|
| 743 | | - memcpy(log_text(msg) + text_len, trunc_msg, trunc_msg_len); |
|---|
| 744 | | - msg->text_len += trunc_msg_len; |
|---|
| 745 | | - } |
|---|
| 746 | | - memcpy(log_dict(msg), dict, dict_len); |
|---|
| 747 | | - msg->dict_len = dict_len; |
|---|
| 748 | | - msg->facility = facility; |
|---|
| 749 | | - msg->level = level & 7; |
|---|
| 750 | | - msg->flags = flags & 0x1f; |
|---|
| 751 | | - if (ts_nsec > 0) |
|---|
| 752 | | - msg->ts_nsec = ts_nsec; |
|---|
| 483 | + if (*text_len >= *trunc_msg_len) |
|---|
| 484 | + *text_len -= *trunc_msg_len; |
|---|
| 753 | 485 | else |
|---|
| 754 | | - msg->ts_nsec = get_local_clock(); |
|---|
| 755 | | - memset(log_dict(msg) + dict_len, 0, pad_len); |
|---|
| 756 | | - msg->len = size; |
|---|
| 757 | | - |
|---|
| 758 | | -#ifdef CONFIG_PRINTK_PROCESS |
|---|
| 759 | | - if (printk_process) { |
|---|
| 760 | | - strncpy(msg->process, current->comm, sizeof(msg->process) - 1); |
|---|
| 761 | | - msg->process[sizeof(msg->process) - 1] = '\0'; |
|---|
| 762 | | - msg->pid = task_pid_nr(current); |
|---|
| 763 | | - msg->cpu = raw_smp_processor_id(); |
|---|
| 764 | | - msg->in_interrupt = in_interrupt() ? 1 : 0; |
|---|
| 765 | | - } |
|---|
| 766 | | -#endif |
|---|
| 767 | | - |
|---|
| 768 | | - /* insert message */ |
|---|
| 769 | | - log_next_idx += msg->len; |
|---|
| 770 | | - log_next_seq++; |
|---|
| 771 | | - |
|---|
| 772 | | - return msg->text_len; |
|---|
| 486 | + *trunc_msg_len = 0; |
|---|
| 773 | 487 | } |
|---|
| 774 | 488 | |
|---|
| 775 | 489 | int dmesg_restrict = IS_ENABLED(CONFIG_SECURITY_DMESG_RESTRICT); |
|---|
| .. | .. |
|---|
| 821 | 535 | *(*pp)++ = c; |
|---|
| 822 | 536 | } |
|---|
| 823 | 537 | |
|---|
| 824 | | -static ssize_t msg_print_ext_header(char *buf, size_t size, |
|---|
| 825 | | - struct printk_log *msg, u64 seq) |
|---|
| 538 | +static ssize_t info_print_ext_header(char *buf, size_t size, |
|---|
| 539 | + struct printk_info *info) |
|---|
| 826 | 540 | { |
|---|
| 827 | | - u64 ts_usec = msg->ts_nsec; |
|---|
| 541 | + u64 ts_usec = info->ts_nsec; |
|---|
| 542 | + char caller[20]; |
|---|
| 543 | +#ifdef CONFIG_PRINTK_CALLER |
|---|
| 544 | + u32 id = info->caller_id; |
|---|
| 545 | + |
|---|
| 546 | + snprintf(caller, sizeof(caller), ",caller=%c%u", |
|---|
| 547 | + id & 0x80000000 ? 'C' : 'T', id & ~0x80000000); |
|---|
| 548 | +#else |
|---|
| 549 | + caller[0] = '\0'; |
|---|
| 550 | +#endif |
|---|
| 828 | 551 | |
|---|
| 829 | 552 | do_div(ts_usec, 1000); |
|---|
| 830 | 553 | |
|---|
| 831 | | - return scnprintf(buf, size, "%u,%llu,%llu,%c;", |
|---|
| 832 | | - (msg->facility << 3) | msg->level, seq, ts_usec, |
|---|
| 833 | | - msg->flags & LOG_CONT ? 'c' : '-'); |
|---|
| 554 | + return scnprintf(buf, size, "%u,%llu,%llu,%c%s;", |
|---|
| 555 | + (info->facility << 3) | info->level, info->seq, |
|---|
| 556 | + ts_usec, info->flags & LOG_CONT ? 'c' : '-', caller); |
|---|
| 834 | 557 | } |
|---|
| 835 | 558 | |
|---|
| 836 | | -static ssize_t msg_print_ext_body(char *buf, size_t size, |
|---|
| 837 | | - char *dict, size_t dict_len, |
|---|
| 838 | | - char *text, size_t text_len) |
|---|
| 559 | +static ssize_t msg_add_ext_text(char *buf, size_t size, |
|---|
| 560 | + const char *text, size_t text_len, |
|---|
| 561 | + unsigned char endc) |
|---|
| 839 | 562 | { |
|---|
| 840 | 563 | char *p = buf, *e = buf + size; |
|---|
| 841 | 564 | size_t i; |
|---|
| .. | .. |
|---|
| 849 | 572 | else |
|---|
| 850 | 573 | append_char(&p, e, c); |
|---|
| 851 | 574 | } |
|---|
| 852 | | - append_char(&p, e, '\n'); |
|---|
| 853 | | - |
|---|
| 854 | | - if (dict_len) { |
|---|
| 855 | | - bool line = true; |
|---|
| 856 | | - |
|---|
| 857 | | - for (i = 0; i < dict_len; i++) { |
|---|
| 858 | | - unsigned char c = dict[i]; |
|---|
| 859 | | - |
|---|
| 860 | | - if (line) { |
|---|
| 861 | | - append_char(&p, e, ' '); |
|---|
| 862 | | - line = false; |
|---|
| 863 | | - } |
|---|
| 864 | | - |
|---|
| 865 | | - if (c == '\0') { |
|---|
| 866 | | - append_char(&p, e, '\n'); |
|---|
| 867 | | - line = true; |
|---|
| 868 | | - continue; |
|---|
| 869 | | - } |
|---|
| 870 | | - |
|---|
| 871 | | - if (c < ' ' || c >= 127 || c == '\\') { |
|---|
| 872 | | - p += scnprintf(p, e - p, "\\x%02x", c); |
|---|
| 873 | | - continue; |
|---|
| 874 | | - } |
|---|
| 875 | | - |
|---|
| 876 | | - append_char(&p, e, c); |
|---|
| 877 | | - } |
|---|
| 878 | | - append_char(&p, e, '\n'); |
|---|
| 879 | | - } |
|---|
| 575 | + append_char(&p, e, endc); |
|---|
| 880 | 576 | |
|---|
| 881 | 577 | return p - buf; |
|---|
| 882 | 578 | } |
|---|
| 883 | 579 | |
|---|
| 580 | +static ssize_t msg_add_dict_text(char *buf, size_t size, |
|---|
| 581 | + const char *key, const char *val) |
|---|
| 582 | +{ |
|---|
| 583 | + size_t val_len = strlen(val); |
|---|
| 584 | + ssize_t len; |
|---|
| 585 | + |
|---|
| 586 | + if (!val_len) |
|---|
| 587 | + return 0; |
|---|
| 588 | + |
|---|
| 589 | + len = msg_add_ext_text(buf, size, "", 0, ' '); /* dict prefix */ |
|---|
| 590 | + len += msg_add_ext_text(buf + len, size - len, key, strlen(key), '='); |
|---|
| 591 | + len += msg_add_ext_text(buf + len, size - len, val, val_len, '\n'); |
|---|
| 592 | + |
|---|
| 593 | + return len; |
|---|
| 594 | +} |
|---|
| 595 | + |
|---|
| 596 | +static ssize_t msg_print_ext_body(char *buf, size_t size, |
|---|
| 597 | + char *text, size_t text_len, |
|---|
| 598 | + struct dev_printk_info *dev_info) |
|---|
| 599 | +{ |
|---|
| 600 | + ssize_t len; |
|---|
| 601 | + |
|---|
| 602 | + len = msg_add_ext_text(buf, size, text, text_len, '\n'); |
|---|
| 603 | + |
|---|
| 604 | + if (!dev_info) |
|---|
| 605 | + goto out; |
|---|
| 606 | + |
|---|
| 607 | + len += msg_add_dict_text(buf + len, size - len, "SUBSYSTEM", |
|---|
| 608 | + dev_info->subsystem); |
|---|
| 609 | + len += msg_add_dict_text(buf + len, size - len, "DEVICE", |
|---|
| 610 | + dev_info->device); |
|---|
| 611 | +out: |
|---|
| 612 | + return len; |
|---|
| 613 | +} |
|---|
| 614 | + |
|---|
| 884 | 615 | /* /dev/kmsg - userspace message inject/listen interface */ |
|---|
| 885 | 616 | struct devkmsg_user { |
|---|
| 886 | | - u64 seq; |
|---|
| 887 | | - u32 idx; |
|---|
| 617 | + atomic64_t seq; |
|---|
| 888 | 618 | struct ratelimit_state rs; |
|---|
| 889 | 619 | struct mutex lock; |
|---|
| 890 | 620 | char buf[CONSOLE_EXT_LOG_MAX]; |
|---|
| 621 | + |
|---|
| 622 | + struct printk_info info; |
|---|
| 623 | + char text_buf[CONSOLE_EXT_LOG_MAX]; |
|---|
| 624 | + struct printk_record record; |
|---|
| 891 | 625 | }; |
|---|
| 626 | + |
|---|
| 627 | +static __printf(3, 4) __cold |
|---|
| 628 | +int devkmsg_emit(int facility, int level, const char *fmt, ...) |
|---|
| 629 | +{ |
|---|
| 630 | + va_list args; |
|---|
| 631 | + int r; |
|---|
| 632 | + |
|---|
| 633 | + va_start(args, fmt); |
|---|
| 634 | + r = vprintk_emit(facility, level, NULL, fmt, args); |
|---|
| 635 | + va_end(args); |
|---|
| 636 | + |
|---|
| 637 | + return r; |
|---|
| 638 | +} |
|---|
| 892 | 639 | |
|---|
| 893 | 640 | static ssize_t devkmsg_write(struct kiocb *iocb, struct iov_iter *from) |
|---|
| 894 | 641 | { |
|---|
| .. | .. |
|---|
| 948 | 695 | } |
|---|
| 949 | 696 | } |
|---|
| 950 | 697 | |
|---|
| 951 | | - printk_emit(facility, level, NULL, 0, "%s", line); |
|---|
| 698 | + devkmsg_emit(facility, level, "%s", line); |
|---|
| 952 | 699 | kfree(buf); |
|---|
| 953 | 700 | return ret; |
|---|
| 954 | 701 | } |
|---|
| .. | .. |
|---|
| 957 | 704 | size_t count, loff_t *ppos) |
|---|
| 958 | 705 | { |
|---|
| 959 | 706 | struct devkmsg_user *user = file->private_data; |
|---|
| 960 | | - struct printk_log *msg; |
|---|
| 707 | + struct printk_record *r = &user->record; |
|---|
| 961 | 708 | size_t len; |
|---|
| 962 | 709 | ssize_t ret; |
|---|
| 963 | 710 | |
|---|
| .. | .. |
|---|
| 968 | 715 | if (ret) |
|---|
| 969 | 716 | return ret; |
|---|
| 970 | 717 | |
|---|
| 971 | | - logbuf_lock_irq(); |
|---|
| 972 | | - while (user->seq == log_next_seq) { |
|---|
| 718 | + if (!prb_read_valid(prb, atomic64_read(&user->seq), r)) { |
|---|
| 973 | 719 | if (file->f_flags & O_NONBLOCK) { |
|---|
| 974 | 720 | ret = -EAGAIN; |
|---|
| 975 | | - logbuf_unlock_irq(); |
|---|
| 976 | 721 | goto out; |
|---|
| 977 | 722 | } |
|---|
| 978 | 723 | |
|---|
| 979 | | - logbuf_unlock_irq(); |
|---|
| 980 | 724 | ret = wait_event_interruptible(log_wait, |
|---|
| 981 | | - user->seq != log_next_seq); |
|---|
| 725 | + prb_read_valid(prb, atomic64_read(&user->seq), r)); |
|---|
| 982 | 726 | if (ret) |
|---|
| 983 | 727 | goto out; |
|---|
| 984 | | - logbuf_lock_irq(); |
|---|
| 985 | 728 | } |
|---|
| 986 | 729 | |
|---|
| 987 | | - if (user->seq < log_first_seq) { |
|---|
| 730 | + if (r->info->seq != atomic64_read(&user->seq)) { |
|---|
| 988 | 731 | /* our last seen message is gone, return error and reset */ |
|---|
| 989 | | - user->idx = log_first_idx; |
|---|
| 990 | | - user->seq = log_first_seq; |
|---|
| 732 | + atomic64_set(&user->seq, r->info->seq); |
|---|
| 991 | 733 | ret = -EPIPE; |
|---|
| 992 | | - logbuf_unlock_irq(); |
|---|
| 993 | 734 | goto out; |
|---|
| 994 | 735 | } |
|---|
| 995 | 736 | |
|---|
| 996 | | - msg = log_from_idx(user->idx); |
|---|
| 997 | | - len = msg_print_ext_header(user->buf, sizeof(user->buf), |
|---|
| 998 | | - msg, user->seq); |
|---|
| 737 | + len = info_print_ext_header(user->buf, sizeof(user->buf), r->info); |
|---|
| 999 | 738 | len += msg_print_ext_body(user->buf + len, sizeof(user->buf) - len, |
|---|
| 1000 | | - log_dict(msg), msg->dict_len, |
|---|
| 1001 | | - log_text(msg), msg->text_len); |
|---|
| 739 | + &r->text_buf[0], r->info->text_len, |
|---|
| 740 | + &r->info->dev_info); |
|---|
| 1002 | 741 | |
|---|
| 1003 | | - user->idx = log_next(user->idx); |
|---|
| 1004 | | - user->seq++; |
|---|
| 1005 | | - logbuf_unlock_irq(); |
|---|
| 742 | + atomic64_set(&user->seq, r->info->seq + 1); |
|---|
| 1006 | 743 | |
|---|
| 1007 | 744 | if (len > count) { |
|---|
| 1008 | 745 | ret = -EINVAL; |
|---|
| .. | .. |
|---|
| 1019 | 756 | return ret; |
|---|
| 1020 | 757 | } |
|---|
| 1021 | 758 | |
|---|
| 759 | +/* |
|---|
| 760 | + * Be careful when modifying this function!!! |
|---|
| 761 | + * |
|---|
| 762 | + * Only few operations are supported because the device works only with the |
|---|
| 763 | + * entire variable length messages (records). Non-standard values are |
|---|
| 764 | + * returned in the other cases and has been this way for quite some time. |
|---|
| 765 | + * User space applications might depend on this behavior. |
|---|
| 766 | + */ |
|---|
| 1022 | 767 | static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence) |
|---|
| 1023 | 768 | { |
|---|
| 1024 | 769 | struct devkmsg_user *user = file->private_data; |
|---|
| .. | .. |
|---|
| 1029 | 774 | if (offset) |
|---|
| 1030 | 775 | return -ESPIPE; |
|---|
| 1031 | 776 | |
|---|
| 1032 | | - logbuf_lock_irq(); |
|---|
| 1033 | 777 | switch (whence) { |
|---|
| 1034 | 778 | case SEEK_SET: |
|---|
| 1035 | 779 | /* the first record */ |
|---|
| 1036 | | - user->idx = log_first_idx; |
|---|
| 1037 | | - user->seq = log_first_seq; |
|---|
| 780 | + atomic64_set(&user->seq, prb_first_valid_seq(prb)); |
|---|
| 1038 | 781 | break; |
|---|
| 1039 | 782 | case SEEK_DATA: |
|---|
| 1040 | 783 | /* |
|---|
| .. | .. |
|---|
| 1042 | 785 | * like issued by 'dmesg -c'. Reading /dev/kmsg itself |
|---|
| 1043 | 786 | * changes no global state, and does not clear anything. |
|---|
| 1044 | 787 | */ |
|---|
| 1045 | | - user->idx = clear_idx; |
|---|
| 1046 | | - user->seq = clear_seq; |
|---|
| 788 | + atomic64_set(&user->seq, latched_seq_read_nolock(&clear_seq)); |
|---|
| 1047 | 789 | break; |
|---|
| 1048 | 790 | case SEEK_END: |
|---|
| 1049 | 791 | /* after the last record */ |
|---|
| 1050 | | - user->idx = log_next_idx; |
|---|
| 1051 | | - user->seq = log_next_seq; |
|---|
| 792 | + atomic64_set(&user->seq, prb_next_seq(prb)); |
|---|
| 1052 | 793 | break; |
|---|
| 1053 | 794 | default: |
|---|
| 1054 | 795 | ret = -EINVAL; |
|---|
| 1055 | 796 | } |
|---|
| 1056 | | - logbuf_unlock_irq(); |
|---|
| 1057 | 797 | return ret; |
|---|
| 1058 | 798 | } |
|---|
| 1059 | 799 | |
|---|
| 1060 | 800 | static __poll_t devkmsg_poll(struct file *file, poll_table *wait) |
|---|
| 1061 | 801 | { |
|---|
| 1062 | 802 | struct devkmsg_user *user = file->private_data; |
|---|
| 803 | + struct printk_info info; |
|---|
| 1063 | 804 | __poll_t ret = 0; |
|---|
| 1064 | 805 | |
|---|
| 1065 | 806 | if (!user) |
|---|
| .. | .. |
|---|
| 1067 | 808 | |
|---|
| 1068 | 809 | poll_wait(file, &log_wait, wait); |
|---|
| 1069 | 810 | |
|---|
| 1070 | | - logbuf_lock_irq(); |
|---|
| 1071 | | - if (user->seq < log_next_seq) { |
|---|
| 811 | + if (prb_read_valid_info(prb, atomic64_read(&user->seq), &info, NULL)) { |
|---|
| 1072 | 812 | /* return error when data has vanished underneath us */ |
|---|
| 1073 | | - if (user->seq < log_first_seq) |
|---|
| 813 | + if (info.seq != atomic64_read(&user->seq)) |
|---|
| 1074 | 814 | ret = EPOLLIN|EPOLLRDNORM|EPOLLERR|EPOLLPRI; |
|---|
| 1075 | 815 | else |
|---|
| 1076 | 816 | ret = EPOLLIN|EPOLLRDNORM; |
|---|
| 1077 | 817 | } |
|---|
| 1078 | | - logbuf_unlock_irq(); |
|---|
| 1079 | 818 | |
|---|
| 1080 | 819 | return ret; |
|---|
| 1081 | 820 | } |
|---|
| .. | .. |
|---|
| 1105 | 844 | |
|---|
| 1106 | 845 | mutex_init(&user->lock); |
|---|
| 1107 | 846 | |
|---|
| 1108 | | - logbuf_lock_irq(); |
|---|
| 1109 | | - user->idx = log_first_idx; |
|---|
| 1110 | | - user->seq = log_first_seq; |
|---|
| 1111 | | - logbuf_unlock_irq(); |
|---|
| 847 | + prb_rec_init_rd(&user->record, &user->info, |
|---|
| 848 | + &user->text_buf[0], sizeof(user->text_buf)); |
|---|
| 849 | + |
|---|
| 850 | + atomic64_set(&user->seq, prb_first_valid_seq(prb)); |
|---|
| 1112 | 851 | |
|---|
| 1113 | 852 | file->private_data = user; |
|---|
| 1114 | 853 | return 0; |
|---|
| .. | .. |
|---|
| 1148 | 887 | */ |
|---|
| 1149 | 888 | void log_buf_vmcoreinfo_setup(void) |
|---|
| 1150 | 889 | { |
|---|
| 1151 | | - VMCOREINFO_SYMBOL(log_buf); |
|---|
| 1152 | | - VMCOREINFO_SYMBOL(log_buf_len); |
|---|
| 1153 | | - VMCOREINFO_SYMBOL(log_first_idx); |
|---|
| 1154 | | - VMCOREINFO_SYMBOL(clear_idx); |
|---|
| 1155 | | - VMCOREINFO_SYMBOL(log_next_idx); |
|---|
| 890 | + struct dev_printk_info *dev_info = NULL; |
|---|
| 891 | + |
|---|
| 892 | + VMCOREINFO_SYMBOL(prb); |
|---|
| 893 | + VMCOREINFO_SYMBOL(printk_rb_static); |
|---|
| 894 | + VMCOREINFO_SYMBOL(clear_seq); |
|---|
| 895 | + |
|---|
| 1156 | 896 | /* |
|---|
| 1157 | | - * Export struct printk_log size and field offsets. User space tools can |
|---|
| 897 | + * Export struct size and field offsets. User space tools can |
|---|
| 1158 | 898 | * parse it and detect any changes to structure down the line. |
|---|
| 1159 | 899 | */ |
|---|
| 1160 | | - VMCOREINFO_STRUCT_SIZE(printk_log); |
|---|
| 1161 | | - VMCOREINFO_OFFSET(printk_log, ts_nsec); |
|---|
| 1162 | | - VMCOREINFO_OFFSET(printk_log, len); |
|---|
| 1163 | | - VMCOREINFO_OFFSET(printk_log, text_len); |
|---|
| 1164 | | - VMCOREINFO_OFFSET(printk_log, dict_len); |
|---|
| 900 | + |
|---|
| 901 | + VMCOREINFO_STRUCT_SIZE(printk_ringbuffer); |
|---|
| 902 | + VMCOREINFO_OFFSET(printk_ringbuffer, desc_ring); |
|---|
| 903 | + VMCOREINFO_OFFSET(printk_ringbuffer, text_data_ring); |
|---|
| 904 | + VMCOREINFO_OFFSET(printk_ringbuffer, fail); |
|---|
| 905 | + |
|---|
| 906 | + VMCOREINFO_STRUCT_SIZE(prb_desc_ring); |
|---|
| 907 | + VMCOREINFO_OFFSET(prb_desc_ring, count_bits); |
|---|
| 908 | + VMCOREINFO_OFFSET(prb_desc_ring, descs); |
|---|
| 909 | + VMCOREINFO_OFFSET(prb_desc_ring, infos); |
|---|
| 910 | + VMCOREINFO_OFFSET(prb_desc_ring, head_id); |
|---|
| 911 | + VMCOREINFO_OFFSET(prb_desc_ring, tail_id); |
|---|
| 912 | + |
|---|
| 913 | + VMCOREINFO_STRUCT_SIZE(prb_desc); |
|---|
| 914 | + VMCOREINFO_OFFSET(prb_desc, state_var); |
|---|
| 915 | + VMCOREINFO_OFFSET(prb_desc, text_blk_lpos); |
|---|
| 916 | + |
|---|
| 917 | + VMCOREINFO_STRUCT_SIZE(prb_data_blk_lpos); |
|---|
| 918 | + VMCOREINFO_OFFSET(prb_data_blk_lpos, begin); |
|---|
| 919 | + VMCOREINFO_OFFSET(prb_data_blk_lpos, next); |
|---|
| 920 | + |
|---|
| 921 | + VMCOREINFO_STRUCT_SIZE(printk_info); |
|---|
| 922 | + VMCOREINFO_OFFSET(printk_info, seq); |
|---|
| 923 | + VMCOREINFO_OFFSET(printk_info, ts_nsec); |
|---|
| 924 | + VMCOREINFO_OFFSET(printk_info, text_len); |
|---|
| 925 | + VMCOREINFO_OFFSET(printk_info, caller_id); |
|---|
| 926 | + VMCOREINFO_OFFSET(printk_info, dev_info); |
|---|
| 927 | + |
|---|
| 928 | + VMCOREINFO_STRUCT_SIZE(dev_printk_info); |
|---|
| 929 | + VMCOREINFO_OFFSET(dev_printk_info, subsystem); |
|---|
| 930 | + VMCOREINFO_LENGTH(printk_info_subsystem, sizeof(dev_info->subsystem)); |
|---|
| 931 | + VMCOREINFO_OFFSET(dev_printk_info, device); |
|---|
| 932 | + VMCOREINFO_LENGTH(printk_info_device, sizeof(dev_info->device)); |
|---|
| 933 | + |
|---|
| 934 | + VMCOREINFO_STRUCT_SIZE(prb_data_ring); |
|---|
| 935 | + VMCOREINFO_OFFSET(prb_data_ring, size_bits); |
|---|
| 936 | + VMCOREINFO_OFFSET(prb_data_ring, data); |
|---|
| 937 | + VMCOREINFO_OFFSET(prb_data_ring, head_lpos); |
|---|
| 938 | + VMCOREINFO_OFFSET(prb_data_ring, tail_lpos); |
|---|
| 939 | + |
|---|
| 940 | + VMCOREINFO_SIZE(atomic_long_t); |
|---|
| 941 | + VMCOREINFO_TYPE_OFFSET(atomic_long_t, counter); |
|---|
| 942 | + |
|---|
| 943 | + VMCOREINFO_STRUCT_SIZE(latched_seq); |
|---|
| 944 | + VMCOREINFO_OFFSET(latched_seq, val); |
|---|
| 1165 | 945 | } |
|---|
| 1166 | 946 | #endif |
|---|
| 1167 | 947 | |
|---|
| .. | .. |
|---|
| 1233 | 1013 | |
|---|
| 1234 | 1014 | static void __init set_percpu_data_ready(void) |
|---|
| 1235 | 1015 | { |
|---|
| 1236 | | - printk_safe_init(); |
|---|
| 1237 | | - /* Make sure we set this flag only after printk_safe() init is done */ |
|---|
| 1238 | | - barrier(); |
|---|
| 1239 | 1016 | __printk_percpu_data_ready = true; |
|---|
| 1240 | 1017 | } |
|---|
| 1241 | 1018 | |
|---|
| 1019 | +static unsigned int __init add_to_rb(struct printk_ringbuffer *rb, |
|---|
| 1020 | + struct printk_record *r) |
|---|
| 1021 | +{ |
|---|
| 1022 | + struct prb_reserved_entry e; |
|---|
| 1023 | + struct printk_record dest_r; |
|---|
| 1024 | + |
|---|
| 1025 | + prb_rec_init_wr(&dest_r, r->info->text_len); |
|---|
| 1026 | + |
|---|
| 1027 | + if (!prb_reserve(&e, rb, &dest_r)) |
|---|
| 1028 | + return 0; |
|---|
| 1029 | + |
|---|
| 1030 | + memcpy(&dest_r.text_buf[0], &r->text_buf[0], r->info->text_len); |
|---|
| 1031 | + dest_r.info->text_len = r->info->text_len; |
|---|
| 1032 | + dest_r.info->facility = r->info->facility; |
|---|
| 1033 | + dest_r.info->level = r->info->level; |
|---|
| 1034 | + dest_r.info->flags = r->info->flags; |
|---|
| 1035 | + dest_r.info->ts_nsec = r->info->ts_nsec; |
|---|
| 1036 | + dest_r.info->caller_id = r->info->caller_id; |
|---|
| 1037 | + memcpy(&dest_r.info->dev_info, &r->info->dev_info, sizeof(dest_r.info->dev_info)); |
|---|
| 1038 | + |
|---|
| 1039 | + prb_final_commit(&e); |
|---|
| 1040 | + |
|---|
| 1041 | + return prb_record_text_space(&e); |
|---|
| 1042 | +} |
|---|
| 1043 | + |
|---|
| 1044 | +static char setup_text_buf[LOG_LINE_MAX] __initdata; |
|---|
| 1045 | + |
|---|
| 1242 | 1046 | void __init setup_log_buf(int early) |
|---|
| 1243 | 1047 | { |
|---|
| 1244 | | - unsigned long flags; |
|---|
| 1048 | + struct printk_info *new_infos; |
|---|
| 1049 | + unsigned int new_descs_count; |
|---|
| 1050 | + struct prb_desc *new_descs; |
|---|
| 1051 | + struct printk_info info; |
|---|
| 1052 | + struct printk_record r; |
|---|
| 1053 | + size_t new_descs_size; |
|---|
| 1054 | + size_t new_infos_size; |
|---|
| 1245 | 1055 | char *new_log_buf; |
|---|
| 1246 | 1056 | unsigned int free; |
|---|
| 1057 | + u64 seq; |
|---|
| 1247 | 1058 | |
|---|
| 1248 | 1059 | /* |
|---|
| 1249 | 1060 | * Some archs call setup_log_buf() multiple times - first is very |
|---|
| .. | .. |
|---|
| 1262 | 1073 | if (!new_log_buf_len) |
|---|
| 1263 | 1074 | return; |
|---|
| 1264 | 1075 | |
|---|
| 1265 | | - if (early) { |
|---|
| 1266 | | - new_log_buf = |
|---|
| 1267 | | - memblock_virt_alloc(new_log_buf_len, LOG_ALIGN); |
|---|
| 1268 | | - } else { |
|---|
| 1269 | | - new_log_buf = memblock_virt_alloc_nopanic(new_log_buf_len, |
|---|
| 1270 | | - LOG_ALIGN); |
|---|
| 1271 | | - } |
|---|
| 1272 | | - |
|---|
| 1273 | | - if (unlikely(!new_log_buf)) { |
|---|
| 1274 | | - pr_err("log_buf_len: %lu bytes not available\n", |
|---|
| 1275 | | - new_log_buf_len); |
|---|
| 1076 | + new_descs_count = new_log_buf_len >> PRB_AVGBITS; |
|---|
| 1077 | + if (new_descs_count == 0) { |
|---|
| 1078 | + pr_err("new_log_buf_len: %lu too small\n", new_log_buf_len); |
|---|
| 1276 | 1079 | return; |
|---|
| 1277 | 1080 | } |
|---|
| 1278 | 1081 | |
|---|
| 1279 | | - logbuf_lock_irqsave(flags); |
|---|
| 1082 | + new_log_buf = memblock_alloc(new_log_buf_len, LOG_ALIGN); |
|---|
| 1083 | + if (unlikely(!new_log_buf)) { |
|---|
| 1084 | + pr_err("log_buf_len: %lu text bytes not available\n", |
|---|
| 1085 | + new_log_buf_len); |
|---|
| 1086 | + return; |
|---|
| 1087 | + } |
|---|
| 1088 | + |
|---|
| 1089 | + new_descs_size = new_descs_count * sizeof(struct prb_desc); |
|---|
| 1090 | + new_descs = memblock_alloc(new_descs_size, LOG_ALIGN); |
|---|
| 1091 | + if (unlikely(!new_descs)) { |
|---|
| 1092 | + pr_err("log_buf_len: %zu desc bytes not available\n", |
|---|
| 1093 | + new_descs_size); |
|---|
| 1094 | + goto err_free_log_buf; |
|---|
| 1095 | + } |
|---|
| 1096 | + |
|---|
| 1097 | + new_infos_size = new_descs_count * sizeof(struct printk_info); |
|---|
| 1098 | + new_infos = memblock_alloc(new_infos_size, LOG_ALIGN); |
|---|
| 1099 | + if (unlikely(!new_infos)) { |
|---|
| 1100 | + pr_err("log_buf_len: %zu info bytes not available\n", |
|---|
| 1101 | + new_infos_size); |
|---|
| 1102 | + goto err_free_descs; |
|---|
| 1103 | + } |
|---|
| 1104 | + |
|---|
| 1105 | + prb_rec_init_rd(&r, &info, &setup_text_buf[0], sizeof(setup_text_buf)); |
|---|
| 1106 | + |
|---|
| 1107 | + prb_init(&printk_rb_dynamic, |
|---|
| 1108 | + new_log_buf, ilog2(new_log_buf_len), |
|---|
| 1109 | + new_descs, ilog2(new_descs_count), |
|---|
| 1110 | + new_infos); |
|---|
| 1111 | + |
|---|
| 1280 | 1112 | log_buf_len = new_log_buf_len; |
|---|
| 1281 | 1113 | log_buf = new_log_buf; |
|---|
| 1282 | 1114 | new_log_buf_len = 0; |
|---|
| 1283 | | - free = __LOG_BUF_LEN - log_next_idx; |
|---|
| 1284 | | - memcpy(log_buf, __log_buf, __LOG_BUF_LEN); |
|---|
| 1285 | | - logbuf_unlock_irqrestore(flags); |
|---|
| 1115 | + |
|---|
| 1116 | + free = __LOG_BUF_LEN; |
|---|
| 1117 | + prb_for_each_record(0, &printk_rb_static, seq, &r) |
|---|
| 1118 | + free -= add_to_rb(&printk_rb_dynamic, &r); |
|---|
| 1119 | + |
|---|
| 1120 | + /* |
|---|
| 1121 | + * This is early enough that everything is still running on the |
|---|
| 1122 | + * boot CPU and interrupts are disabled. So no new messages will |
|---|
| 1123 | + * appear during the transition to the dynamic buffer. |
|---|
| 1124 | + */ |
|---|
| 1125 | + prb = &printk_rb_dynamic; |
|---|
| 1126 | + |
|---|
| 1127 | + if (seq != prb_next_seq(&printk_rb_static)) { |
|---|
| 1128 | + pr_err("dropped %llu messages\n", |
|---|
| 1129 | + prb_next_seq(&printk_rb_static) - seq); |
|---|
| 1130 | + } |
|---|
| 1286 | 1131 | |
|---|
| 1287 | 1132 | pr_info("log_buf_len: %u bytes\n", log_buf_len); |
|---|
| 1288 | 1133 | pr_info("early log buf free: %u(%u%%)\n", |
|---|
| 1289 | 1134 | free, (free * 100) / __LOG_BUF_LEN); |
|---|
| 1135 | + return; |
|---|
| 1136 | + |
|---|
| 1137 | +err_free_descs: |
|---|
| 1138 | + memblock_free(__pa(new_descs), new_descs_size); |
|---|
| 1139 | +err_free_log_buf: |
|---|
| 1140 | + memblock_free(__pa(new_log_buf), new_log_buf_len); |
|---|
| 1290 | 1141 | } |
|---|
| 1291 | 1142 | |
|---|
| 1292 | | -#ifdef CONFIG_PSTORE_CONSOLE_FORCE_ON |
|---|
| 1293 | | -static bool __read_mostly ignore_loglevel = true; |
|---|
| 1294 | | -#else |
|---|
| 1295 | 1143 | static bool __read_mostly ignore_loglevel; |
|---|
| 1296 | | -#endif |
|---|
| 1297 | 1144 | |
|---|
| 1298 | 1145 | static int __init ignore_loglevel_setup(char *str) |
|---|
| 1299 | 1146 | { |
|---|
| .. | .. |
|---|
| 1307 | 1154 | module_param(ignore_loglevel, bool, S_IRUGO | S_IWUSR); |
|---|
| 1308 | 1155 | MODULE_PARM_DESC(ignore_loglevel, |
|---|
| 1309 | 1156 | "ignore loglevel setting (prints all kernel messages to the console)"); |
|---|
| 1310 | | - |
|---|
| 1311 | | -#ifdef CONFIG_PSTORE_CONSOLE_FORCE |
|---|
| 1312 | | -static bool __read_mostly pstore_con_force = IS_ENABLED(CONFIG_PSTORE_CONSOLE_FORCE_ON); |
|---|
| 1313 | | - |
|---|
| 1314 | | -static int __init pstore_con_force_setup(char *str) |
|---|
| 1315 | | -{ |
|---|
| 1316 | | - bool force; |
|---|
| 1317 | | - int ret = strtobool(str, &force); |
|---|
| 1318 | | - |
|---|
| 1319 | | - if (ret) |
|---|
| 1320 | | - return ret; |
|---|
| 1321 | | - |
|---|
| 1322 | | - ignore_loglevel = force; |
|---|
| 1323 | | - pstore_con_force = force; |
|---|
| 1324 | | - if (force) |
|---|
| 1325 | | - pr_info("debug: pstore console ignoring loglevel setting.\n"); |
|---|
| 1326 | | - |
|---|
| 1327 | | - return 0; |
|---|
| 1328 | | -} |
|---|
| 1329 | | - |
|---|
| 1330 | | -early_param("pstore_con_force", pstore_con_force_setup); |
|---|
| 1331 | | -module_param(pstore_con_force, bool, S_IRUGO | S_IWUSR); |
|---|
| 1332 | | -MODULE_PARM_DESC(pstore_con_force, |
|---|
| 1333 | | - "ignore loglevel setting (prints all kernel messages to the pstore console)"); |
|---|
| 1334 | | - |
|---|
| 1335 | | -static void call_console_drivers_level(int level, const char *ext_text, size_t ext_len, |
|---|
| 1336 | | - const char *text, size_t len) |
|---|
| 1337 | | -{ |
|---|
| 1338 | | - struct console *con; |
|---|
| 1339 | | - |
|---|
| 1340 | | - trace_console_rcuidle(text, len); |
|---|
| 1341 | | - |
|---|
| 1342 | | - if (!console_drivers) |
|---|
| 1343 | | - return; |
|---|
| 1344 | | - |
|---|
| 1345 | | - for_each_console(con) { |
|---|
| 1346 | | - if (pstore_con_force && |
|---|
| 1347 | | - !(con->flags & CON_PSTORE) && level >= console_loglevel) |
|---|
| 1348 | | - continue; |
|---|
| 1349 | | - if (exclusive_console && con != exclusive_console) |
|---|
| 1350 | | - continue; |
|---|
| 1351 | | - if (!(con->flags & CON_ENABLED)) |
|---|
| 1352 | | - continue; |
|---|
| 1353 | | - if (!con->write) |
|---|
| 1354 | | - continue; |
|---|
| 1355 | | - if (!cpu_online(smp_processor_id()) && |
|---|
| 1356 | | - !(con->flags & CON_ANYTIME)) |
|---|
| 1357 | | - continue; |
|---|
| 1358 | | - if (con->flags & CON_EXTENDED) |
|---|
| 1359 | | - con->write(con, ext_text, ext_len); |
|---|
| 1360 | | - else |
|---|
| 1361 | | - con->write(con, text, len); |
|---|
| 1362 | | - } |
|---|
| 1363 | | -} |
|---|
| 1364 | | -#endif |
|---|
| 1365 | 1157 | |
|---|
| 1366 | 1158 | static bool suppress_message_printing(int level) |
|---|
| 1367 | 1159 | { |
|---|
| .. | .. |
|---|
| 1426 | 1218 | static bool printk_time = IS_ENABLED(CONFIG_PRINTK_TIME); |
|---|
| 1427 | 1219 | module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR); |
|---|
| 1428 | 1220 | |
|---|
| 1221 | +static size_t print_syslog(unsigned int level, char *buf) |
|---|
| 1222 | +{ |
|---|
| 1223 | + return sprintf(buf, "<%u>", level); |
|---|
| 1224 | +} |
|---|
| 1225 | + |
|---|
| 1429 | 1226 | static size_t print_time(u64 ts, char *buf) |
|---|
| 1430 | 1227 | { |
|---|
| 1431 | | - unsigned long rem_nsec; |
|---|
| 1228 | + unsigned long rem_nsec = do_div(ts, 1000000000); |
|---|
| 1432 | 1229 | |
|---|
| 1433 | | - if (!printk_time) |
|---|
| 1434 | | - return 0; |
|---|
| 1435 | | - |
|---|
| 1436 | | - rem_nsec = do_div(ts, 1000000000); |
|---|
| 1437 | | - |
|---|
| 1438 | | - if (!buf) |
|---|
| 1439 | | - return snprintf(NULL, 0, "[%5lu.000000] ", (unsigned long)ts); |
|---|
| 1440 | | - |
|---|
| 1441 | | - return sprintf(buf, "[%5lu.%06lu] ", |
|---|
| 1230 | + return sprintf(buf, "[%5lu.%06lu]", |
|---|
| 1442 | 1231 | (unsigned long)ts, rem_nsec / 1000); |
|---|
| 1443 | 1232 | } |
|---|
| 1444 | 1233 | |
|---|
| 1445 | | -static size_t print_prefix(const struct printk_log *msg, bool syslog, char *buf) |
|---|
| 1234 | +#ifdef CONFIG_PRINTK_CALLER |
|---|
| 1235 | +static size_t print_caller(u32 id, char *buf) |
|---|
| 1236 | +{ |
|---|
| 1237 | + char caller[12]; |
|---|
| 1238 | + |
|---|
| 1239 | + snprintf(caller, sizeof(caller), "%c%u", |
|---|
| 1240 | + id & 0x80000000 ? 'C' : 'T', id & ~0x80000000); |
|---|
| 1241 | + return sprintf(buf, "[%6s]", caller); |
|---|
| 1242 | +} |
|---|
| 1243 | +#else |
|---|
| 1244 | +#define print_caller(id, buf) 0 |
|---|
| 1245 | +#endif |
|---|
| 1246 | + |
|---|
| 1247 | +static size_t info_print_prefix(const struct printk_info *info, bool syslog, |
|---|
| 1248 | + bool time, char *buf) |
|---|
| 1446 | 1249 | { |
|---|
| 1447 | 1250 | size_t len = 0; |
|---|
| 1448 | | - unsigned int prefix = (msg->facility << 3) | msg->level; |
|---|
| 1449 | 1251 | |
|---|
| 1450 | | - if (syslog) { |
|---|
| 1451 | | - if (buf) { |
|---|
| 1452 | | - len += sprintf(buf, "<%u>", prefix); |
|---|
| 1453 | | - } else { |
|---|
| 1454 | | - len += 3; |
|---|
| 1455 | | - if (prefix > 999) |
|---|
| 1456 | | - len += 3; |
|---|
| 1457 | | - else if (prefix > 99) |
|---|
| 1458 | | - len += 2; |
|---|
| 1459 | | - else if (prefix > 9) |
|---|
| 1460 | | - len++; |
|---|
| 1461 | | - } |
|---|
| 1252 | + if (syslog) |
|---|
| 1253 | + len = print_syslog((info->facility << 3) | info->level, buf); |
|---|
| 1254 | + |
|---|
| 1255 | + if (time) |
|---|
| 1256 | + len += print_time(info->ts_nsec, buf + len); |
|---|
| 1257 | + |
|---|
| 1258 | + len += print_caller(info->caller_id, buf + len); |
|---|
| 1259 | + |
|---|
| 1260 | + if (IS_ENABLED(CONFIG_PRINTK_CALLER) || time) { |
|---|
| 1261 | + buf[len++] = ' '; |
|---|
| 1262 | + buf[len] = '\0'; |
|---|
| 1462 | 1263 | } |
|---|
| 1463 | 1264 | |
|---|
| 1464 | | - len += print_time(msg->ts_nsec, buf ? buf + len : NULL); |
|---|
| 1465 | | -#ifdef CONFIG_PRINTK_PROCESS |
|---|
| 1466 | | - len += print_process(msg, buf ? buf + len : NULL); |
|---|
| 1467 | | -#endif |
|---|
| 1468 | 1265 | return len; |
|---|
| 1469 | 1266 | } |
|---|
| 1470 | 1267 | |
|---|
| 1471 | | -static size_t msg_print_text(const struct printk_log *msg, bool syslog, char *buf, size_t size) |
|---|
| 1268 | +/* |
|---|
| 1269 | + * Prepare the record for printing. The text is shifted within the given |
|---|
| 1270 | + * buffer to avoid a need for another one. The following operations are |
|---|
| 1271 | + * done: |
|---|
| 1272 | + * |
|---|
| 1273 | + * - Add prefix for each line. |
|---|
| 1274 | + * - Drop truncated lines that no longer fit into the buffer. |
|---|
| 1275 | + * - Add the trailing newline that has been removed in vprintk_store(). |
|---|
| 1276 | + * - Add a string terminator. |
|---|
| 1277 | + * |
|---|
| 1278 | + * Since the produced string is always terminated, the maximum possible |
|---|
| 1279 | + * return value is @r->text_buf_size - 1; |
|---|
| 1280 | + * |
|---|
| 1281 | + * Return: The length of the updated/prepared text, including the added |
|---|
| 1282 | + * prefixes and the newline. The terminator is not counted. The dropped |
|---|
| 1283 | + * line(s) are not counted. |
|---|
| 1284 | + */ |
|---|
| 1285 | +static size_t record_print_text(struct printk_record *r, bool syslog, |
|---|
| 1286 | + bool time) |
|---|
| 1472 | 1287 | { |
|---|
| 1473 | | - const char *text = log_text(msg); |
|---|
| 1474 | | - size_t text_size = msg->text_len; |
|---|
| 1288 | + size_t text_len = r->info->text_len; |
|---|
| 1289 | + size_t buf_size = r->text_buf_size; |
|---|
| 1290 | + char *text = r->text_buf; |
|---|
| 1291 | + char prefix[PREFIX_MAX]; |
|---|
| 1292 | + bool truncated = false; |
|---|
| 1293 | + size_t prefix_len; |
|---|
| 1294 | + size_t line_len; |
|---|
| 1475 | 1295 | size_t len = 0; |
|---|
| 1296 | + char *next; |
|---|
| 1476 | 1297 | |
|---|
| 1477 | | - do { |
|---|
| 1478 | | - const char *next = memchr(text, '\n', text_size); |
|---|
| 1479 | | - size_t text_len; |
|---|
| 1298 | + /* |
|---|
| 1299 | + * If the message was truncated because the buffer was not large |
|---|
| 1300 | + * enough, treat the available text as if it were the full text. |
|---|
| 1301 | + */ |
|---|
| 1302 | + if (text_len > buf_size) |
|---|
| 1303 | + text_len = buf_size; |
|---|
| 1480 | 1304 | |
|---|
| 1305 | + prefix_len = info_print_prefix(r->info, syslog, time, prefix); |
|---|
| 1306 | + |
|---|
| 1307 | + /* |
|---|
| 1308 | + * @text_len: bytes of unprocessed text |
|---|
| 1309 | + * @line_len: bytes of current line _without_ newline |
|---|
| 1310 | + * @text: pointer to beginning of current line |
|---|
| 1311 | + * @len: number of bytes prepared in r->text_buf |
|---|
| 1312 | + */ |
|---|
| 1313 | + for (;;) { |
|---|
| 1314 | + next = memchr(text, '\n', text_len); |
|---|
| 1481 | 1315 | if (next) { |
|---|
| 1482 | | - text_len = next - text; |
|---|
| 1483 | | - next++; |
|---|
| 1484 | | - text_size -= next - text; |
|---|
| 1316 | + line_len = next - text; |
|---|
| 1485 | 1317 | } else { |
|---|
| 1486 | | - text_len = text_size; |
|---|
| 1318 | + /* Drop truncated line(s). */ |
|---|
| 1319 | + if (truncated) |
|---|
| 1320 | + break; |
|---|
| 1321 | + line_len = text_len; |
|---|
| 1487 | 1322 | } |
|---|
| 1488 | 1323 | |
|---|
| 1489 | | - if (buf) { |
|---|
| 1490 | | - if (print_prefix(msg, syslog, NULL) + |
|---|
| 1491 | | - text_len + 1 >= size - len) |
|---|
| 1324 | + /* |
|---|
| 1325 | + * Truncate the text if there is not enough space to add the |
|---|
| 1326 | + * prefix and a trailing newline and a terminator. |
|---|
| 1327 | + */ |
|---|
| 1328 | + if (len + prefix_len + text_len + 1 + 1 > buf_size) { |
|---|
| 1329 | + /* Drop even the current line if no space. */ |
|---|
| 1330 | + if (len + prefix_len + line_len + 1 + 1 > buf_size) |
|---|
| 1492 | 1331 | break; |
|---|
| 1493 | 1332 | |
|---|
| 1494 | | - len += print_prefix(msg, syslog, buf + len); |
|---|
| 1495 | | - memcpy(buf + len, text, text_len); |
|---|
| 1496 | | - len += text_len; |
|---|
| 1497 | | - buf[len++] = '\n'; |
|---|
| 1498 | | - } else { |
|---|
| 1499 | | - /* SYSLOG_ACTION_* buffer size only calculation */ |
|---|
| 1500 | | - len += print_prefix(msg, syslog, NULL); |
|---|
| 1501 | | - len += text_len; |
|---|
| 1502 | | - len++; |
|---|
| 1333 | + text_len = buf_size - len - prefix_len - 1 - 1; |
|---|
| 1334 | + truncated = true; |
|---|
| 1503 | 1335 | } |
|---|
| 1504 | 1336 | |
|---|
| 1505 | | - text = next; |
|---|
| 1506 | | - } while (text); |
|---|
| 1337 | + memmove(text + prefix_len, text, text_len); |
|---|
| 1338 | + memcpy(text, prefix, prefix_len); |
|---|
| 1339 | + |
|---|
| 1340 | + /* |
|---|
| 1341 | + * Increment the prepared length to include the text and |
|---|
| 1342 | + * prefix that were just moved+copied. Also increment for the |
|---|
| 1343 | + * newline at the end of this line. If this is the last line, |
|---|
| 1344 | + * there is no newline, but it will be added immediately below. |
|---|
| 1345 | + */ |
|---|
| 1346 | + len += prefix_len + line_len + 1; |
|---|
| 1347 | + if (text_len == line_len) { |
|---|
| 1348 | + /* |
|---|
| 1349 | + * This is the last line. Add the trailing newline |
|---|
| 1350 | + * removed in vprintk_store(). |
|---|
| 1351 | + */ |
|---|
| 1352 | + text[prefix_len + line_len] = '\n'; |
|---|
| 1353 | + break; |
|---|
| 1354 | + } |
|---|
| 1355 | + |
|---|
| 1356 | + /* |
|---|
| 1357 | + * Advance beyond the added prefix and the related line with |
|---|
| 1358 | + * its newline. |
|---|
| 1359 | + */ |
|---|
| 1360 | + text += prefix_len + line_len + 1; |
|---|
| 1361 | + |
|---|
| 1362 | + /* |
|---|
| 1363 | + * The remaining text has only decreased by the line with its |
|---|
| 1364 | + * newline. |
|---|
| 1365 | + * |
|---|
| 1366 | + * Note that @text_len can become zero. It happens when @text |
|---|
| 1367 | + * ended with a newline (either due to truncation or the |
|---|
| 1368 | + * original string ending with "\n\n"). The loop is correctly |
|---|
| 1369 | + * repeated and (if not truncated) an empty line with a prefix |
|---|
| 1370 | + * will be prepared. |
|---|
| 1371 | + */ |
|---|
| 1372 | + text_len -= line_len + 1; |
|---|
| 1373 | + } |
|---|
| 1374 | + |
|---|
| 1375 | + /* |
|---|
| 1376 | + * If a buffer was provided, it will be terminated. Space for the |
|---|
| 1377 | + * string terminator is guaranteed to be available. The terminator is |
|---|
| 1378 | + * not counted in the return value. |
|---|
| 1379 | + */ |
|---|
| 1380 | + if (buf_size > 0) |
|---|
| 1381 | + r->text_buf[len] = 0; |
|---|
| 1507 | 1382 | |
|---|
| 1508 | 1383 | return len; |
|---|
| 1384 | +} |
|---|
| 1385 | + |
|---|
| 1386 | +static size_t get_record_print_text_size(struct printk_info *info, |
|---|
| 1387 | + unsigned int line_count, |
|---|
| 1388 | + bool syslog, bool time) |
|---|
| 1389 | +{ |
|---|
| 1390 | + char prefix[PREFIX_MAX]; |
|---|
| 1391 | + size_t prefix_len; |
|---|
| 1392 | + |
|---|
| 1393 | + prefix_len = info_print_prefix(info, syslog, time, prefix); |
|---|
| 1394 | + |
|---|
| 1395 | + /* |
|---|
| 1396 | + * Each line will be preceded with a prefix. The intermediate |
|---|
| 1397 | + * newlines are already within the text, but a final trailing |
|---|
| 1398 | + * newline will be added. |
|---|
| 1399 | + */ |
|---|
| 1400 | + return ((prefix_len * line_count) + info->text_len + 1); |
|---|
| 1401 | +} |
|---|
| 1402 | + |
|---|
| 1403 | +/* |
|---|
| 1404 | + * Beginning with @start_seq, find the first record where it and all following |
|---|
| 1405 | + * records up to (but not including) @max_seq fit into @size. |
|---|
| 1406 | + * |
|---|
| 1407 | + * @max_seq is simply an upper bound and does not need to exist. If the caller |
|---|
| 1408 | + * does not require an upper bound, -1 can be used for @max_seq. |
|---|
| 1409 | + */ |
|---|
| 1410 | +static u64 find_first_fitting_seq(u64 start_seq, u64 max_seq, size_t size, |
|---|
| 1411 | + bool syslog, bool time) |
|---|
| 1412 | +{ |
|---|
| 1413 | + struct printk_info info; |
|---|
| 1414 | + unsigned int line_count; |
|---|
| 1415 | + size_t len = 0; |
|---|
| 1416 | + u64 seq; |
|---|
| 1417 | + |
|---|
| 1418 | + /* Determine the size of the records up to @max_seq. */ |
|---|
| 1419 | + prb_for_each_info(start_seq, prb, seq, &info, &line_count) { |
|---|
| 1420 | + if (info.seq >= max_seq) |
|---|
| 1421 | + break; |
|---|
| 1422 | + len += get_record_print_text_size(&info, line_count, syslog, time); |
|---|
| 1423 | + } |
|---|
| 1424 | + |
|---|
| 1425 | + /* |
|---|
| 1426 | + * Adjust the upper bound for the next loop to avoid subtracting |
|---|
| 1427 | + * lengths that were never added. |
|---|
| 1428 | + */ |
|---|
| 1429 | + if (seq < max_seq) |
|---|
| 1430 | + max_seq = seq; |
|---|
| 1431 | + |
|---|
| 1432 | + /* |
|---|
| 1433 | + * Move first record forward until length fits into the buffer. Ignore |
|---|
| 1434 | + * newest messages that were not counted in the above cycle. Messages |
|---|
| 1435 | + * might appear and get lost in the meantime. This is a best effort |
|---|
| 1436 | + * that prevents an infinite loop that could occur with a retry. |
|---|
| 1437 | + */ |
|---|
| 1438 | + prb_for_each_info(start_seq, prb, seq, &info, &line_count) { |
|---|
| 1439 | + if (len <= size || info.seq >= max_seq) |
|---|
| 1440 | + break; |
|---|
| 1441 | + len -= get_record_print_text_size(&info, line_count, syslog, time); |
|---|
| 1442 | + } |
|---|
| 1443 | + |
|---|
| 1444 | + return seq; |
|---|
| 1509 | 1445 | } |
|---|
| 1510 | 1446 | |
|---|
| 1511 | 1447 | static int syslog_print(char __user *buf, int size) |
|---|
| 1512 | 1448 | { |
|---|
| 1449 | + struct printk_info info; |
|---|
| 1450 | + struct printk_record r; |
|---|
| 1513 | 1451 | char *text; |
|---|
| 1514 | | - struct printk_log *msg; |
|---|
| 1515 | 1452 | int len = 0; |
|---|
| 1516 | 1453 | |
|---|
| 1517 | | - text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); |
|---|
| 1454 | + text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL); |
|---|
| 1518 | 1455 | if (!text) |
|---|
| 1519 | 1456 | return -ENOMEM; |
|---|
| 1457 | + |
|---|
| 1458 | + prb_rec_init_rd(&r, &info, text, CONSOLE_LOG_MAX); |
|---|
| 1520 | 1459 | |
|---|
| 1521 | 1460 | while (size > 0) { |
|---|
| 1522 | 1461 | size_t n; |
|---|
| 1523 | 1462 | size_t skip; |
|---|
| 1524 | 1463 | |
|---|
| 1525 | | - logbuf_lock_irq(); |
|---|
| 1526 | | - if (syslog_seq < log_first_seq) { |
|---|
| 1527 | | - /* messages are gone, move to first one */ |
|---|
| 1528 | | - syslog_seq = log_first_seq; |
|---|
| 1529 | | - syslog_idx = log_first_idx; |
|---|
| 1530 | | - syslog_partial = 0; |
|---|
| 1531 | | - } |
|---|
| 1532 | | - if (syslog_seq == log_next_seq) { |
|---|
| 1533 | | - logbuf_unlock_irq(); |
|---|
| 1464 | + spin_lock_irq(&syslog_lock); |
|---|
| 1465 | + if (!prb_read_valid(prb, syslog_seq, &r)) { |
|---|
| 1466 | + spin_unlock_irq(&syslog_lock); |
|---|
| 1534 | 1467 | break; |
|---|
| 1535 | 1468 | } |
|---|
| 1469 | + if (r.info->seq != syslog_seq) { |
|---|
| 1470 | + /* message is gone, move to next valid one */ |
|---|
| 1471 | + syslog_seq = r.info->seq; |
|---|
| 1472 | + syslog_partial = 0; |
|---|
| 1473 | + } |
|---|
| 1474 | + |
|---|
| 1475 | + /* |
|---|
| 1476 | + * To keep reading/counting partial line consistent, |
|---|
| 1477 | + * use printk_time value as of the beginning of a line. |
|---|
| 1478 | + */ |
|---|
| 1479 | + if (!syslog_partial) |
|---|
| 1480 | + syslog_time = printk_time; |
|---|
| 1536 | 1481 | |
|---|
| 1537 | 1482 | skip = syslog_partial; |
|---|
| 1538 | | - msg = log_from_idx(syslog_idx); |
|---|
| 1539 | | - n = msg_print_text(msg, true, text, LOG_LINE_MAX + PREFIX_MAX); |
|---|
| 1483 | + n = record_print_text(&r, true, syslog_time); |
|---|
| 1540 | 1484 | if (n - syslog_partial <= size) { |
|---|
| 1541 | 1485 | /* message fits into buffer, move forward */ |
|---|
| 1542 | | - syslog_idx = log_next(syslog_idx); |
|---|
| 1543 | | - syslog_seq++; |
|---|
| 1486 | + syslog_seq = r.info->seq + 1; |
|---|
| 1544 | 1487 | n -= syslog_partial; |
|---|
| 1545 | 1488 | syslog_partial = 0; |
|---|
| 1546 | 1489 | } else if (!len){ |
|---|
| .. | .. |
|---|
| 1549 | 1492 | syslog_partial += n; |
|---|
| 1550 | 1493 | } else |
|---|
| 1551 | 1494 | n = 0; |
|---|
| 1552 | | - logbuf_unlock_irq(); |
|---|
| 1495 | + spin_unlock_irq(&syslog_lock); |
|---|
| 1553 | 1496 | |
|---|
| 1554 | 1497 | if (!n) |
|---|
| 1555 | 1498 | break; |
|---|
| .. | .. |
|---|
| 1571 | 1514 | |
|---|
| 1572 | 1515 | static int syslog_print_all(char __user *buf, int size, bool clear) |
|---|
| 1573 | 1516 | { |
|---|
| 1517 | + struct printk_info info; |
|---|
| 1518 | + struct printk_record r; |
|---|
| 1574 | 1519 | char *text; |
|---|
| 1575 | 1520 | int len = 0; |
|---|
| 1576 | | - u64 next_seq; |
|---|
| 1577 | 1521 | u64 seq; |
|---|
| 1578 | | - u32 idx; |
|---|
| 1579 | | - int attempts = 0; |
|---|
| 1580 | | - int num_msg; |
|---|
| 1522 | + bool time; |
|---|
| 1581 | 1523 | |
|---|
| 1582 | | - text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); |
|---|
| 1524 | + text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL); |
|---|
| 1583 | 1525 | if (!text) |
|---|
| 1584 | 1526 | return -ENOMEM; |
|---|
| 1585 | 1527 | |
|---|
| 1586 | | - logbuf_lock_irq(); |
|---|
| 1587 | | - |
|---|
| 1588 | | -try_again: |
|---|
| 1589 | | - attempts++; |
|---|
| 1590 | | - if (attempts > 10) { |
|---|
| 1591 | | - len = -EBUSY; |
|---|
| 1592 | | - goto out; |
|---|
| 1593 | | - } |
|---|
| 1594 | | - num_msg = 0; |
|---|
| 1595 | | - |
|---|
| 1528 | + time = printk_time; |
|---|
| 1596 | 1529 | /* |
|---|
| 1597 | 1530 | * Find first record that fits, including all following records, |
|---|
| 1598 | 1531 | * into the user-provided buffer for this dump. |
|---|
| 1599 | 1532 | */ |
|---|
| 1600 | | - seq = clear_seq; |
|---|
| 1601 | | - idx = clear_idx; |
|---|
| 1602 | | - while (seq < log_next_seq) { |
|---|
| 1603 | | - struct printk_log *msg = log_from_idx(idx); |
|---|
| 1533 | + seq = find_first_fitting_seq(latched_seq_read_nolock(&clear_seq), -1, |
|---|
| 1534 | + size, true, time); |
|---|
| 1604 | 1535 | |
|---|
| 1605 | | - len += msg_print_text(msg, true, NULL, 0); |
|---|
| 1606 | | - idx = log_next(idx); |
|---|
| 1607 | | - seq++; |
|---|
| 1608 | | - num_msg++; |
|---|
| 1609 | | - if (num_msg > 5) { |
|---|
| 1610 | | - num_msg = 0; |
|---|
| 1611 | | - logbuf_unlock_irq(); |
|---|
| 1612 | | - logbuf_lock_irq(); |
|---|
| 1613 | | - if (clear_seq < log_first_seq) |
|---|
| 1614 | | - goto try_again; |
|---|
| 1615 | | - } |
|---|
| 1616 | | - } |
|---|
| 1617 | | - |
|---|
| 1618 | | - /* move first record forward until length fits into the buffer */ |
|---|
| 1619 | | - seq = clear_seq; |
|---|
| 1620 | | - idx = clear_idx; |
|---|
| 1621 | | - while (len > size && seq < log_next_seq) { |
|---|
| 1622 | | - struct printk_log *msg = log_from_idx(idx); |
|---|
| 1623 | | - |
|---|
| 1624 | | - len -= msg_print_text(msg, true, NULL, 0); |
|---|
| 1625 | | - idx = log_next(idx); |
|---|
| 1626 | | - seq++; |
|---|
| 1627 | | - num_msg++; |
|---|
| 1628 | | - if (num_msg > 5) { |
|---|
| 1629 | | - num_msg = 0; |
|---|
| 1630 | | - logbuf_unlock_irq(); |
|---|
| 1631 | | - logbuf_lock_irq(); |
|---|
| 1632 | | - if (clear_seq < log_first_seq) |
|---|
| 1633 | | - goto try_again; |
|---|
| 1634 | | - } |
|---|
| 1635 | | - } |
|---|
| 1636 | | - |
|---|
| 1637 | | - /* last message fitting into this dump */ |
|---|
| 1638 | | - next_seq = log_next_seq; |
|---|
| 1536 | + prb_rec_init_rd(&r, &info, text, CONSOLE_LOG_MAX); |
|---|
| 1639 | 1537 | |
|---|
| 1640 | 1538 | len = 0; |
|---|
| 1641 | | - while (len >= 0 && seq < next_seq) { |
|---|
| 1642 | | - struct printk_log *msg = log_from_idx(idx); |
|---|
| 1539 | + prb_for_each_record(seq, prb, seq, &r) { |
|---|
| 1643 | 1540 | int textlen; |
|---|
| 1644 | 1541 | |
|---|
| 1645 | | - textlen = msg_print_text(msg, true, text, |
|---|
| 1646 | | - LOG_LINE_MAX + PREFIX_MAX); |
|---|
| 1647 | | - if (textlen < 0) { |
|---|
| 1648 | | - len = textlen; |
|---|
| 1542 | + textlen = record_print_text(&r, true, time); |
|---|
| 1543 | + |
|---|
| 1544 | + if (len + textlen > size) { |
|---|
| 1545 | + seq--; |
|---|
| 1649 | 1546 | break; |
|---|
| 1650 | 1547 | } |
|---|
| 1651 | | - idx = log_next(idx); |
|---|
| 1652 | | - seq++; |
|---|
| 1653 | 1548 | |
|---|
| 1654 | | - logbuf_unlock_irq(); |
|---|
| 1655 | 1549 | if (copy_to_user(buf + len, text, textlen)) |
|---|
| 1656 | 1550 | len = -EFAULT; |
|---|
| 1657 | 1551 | else |
|---|
| 1658 | 1552 | len += textlen; |
|---|
| 1659 | | - logbuf_lock_irq(); |
|---|
| 1660 | 1553 | |
|---|
| 1661 | | - if (seq < log_first_seq) { |
|---|
| 1662 | | - /* messages are gone, move to next one */ |
|---|
| 1663 | | - seq = log_first_seq; |
|---|
| 1664 | | - idx = log_first_idx; |
|---|
| 1665 | | - } |
|---|
| 1554 | + if (len < 0) |
|---|
| 1555 | + break; |
|---|
| 1666 | 1556 | } |
|---|
| 1667 | 1557 | |
|---|
| 1668 | 1558 | if (clear) { |
|---|
| 1669 | | - clear_seq = log_next_seq; |
|---|
| 1670 | | - clear_idx = log_next_idx; |
|---|
| 1559 | + spin_lock_irq(&syslog_lock); |
|---|
| 1560 | + latched_seq_write(&clear_seq, seq); |
|---|
| 1561 | + spin_unlock_irq(&syslog_lock); |
|---|
| 1671 | 1562 | } |
|---|
| 1672 | | -out: |
|---|
| 1673 | | - logbuf_unlock_irq(); |
|---|
| 1674 | 1563 | |
|---|
| 1675 | 1564 | kfree(text); |
|---|
| 1676 | 1565 | return len; |
|---|
| .. | .. |
|---|
| 1678 | 1567 | |
|---|
| 1679 | 1568 | static void syslog_clear(void) |
|---|
| 1680 | 1569 | { |
|---|
| 1681 | | - logbuf_lock_irq(); |
|---|
| 1682 | | - clear_seq = log_next_seq; |
|---|
| 1683 | | - clear_idx = log_next_idx; |
|---|
| 1684 | | - logbuf_unlock_irq(); |
|---|
| 1570 | + spin_lock_irq(&syslog_lock); |
|---|
| 1571 | + latched_seq_write(&clear_seq, prb_next_seq(prb)); |
|---|
| 1572 | + spin_unlock_irq(&syslog_lock); |
|---|
| 1573 | +} |
|---|
| 1574 | + |
|---|
| 1575 | +/* Return a consistent copy of @syslog_seq. */ |
|---|
| 1576 | +static u64 read_syslog_seq_irq(void) |
|---|
| 1577 | +{ |
|---|
| 1578 | + u64 seq; |
|---|
| 1579 | + |
|---|
| 1580 | + spin_lock_irq(&syslog_lock); |
|---|
| 1581 | + seq = syslog_seq; |
|---|
| 1582 | + spin_unlock_irq(&syslog_lock); |
|---|
| 1583 | + |
|---|
| 1584 | + return seq; |
|---|
| 1685 | 1585 | } |
|---|
| 1686 | 1586 | |
|---|
| 1687 | 1587 | int do_syslog(int type, char __user *buf, int len, int source) |
|---|
| 1688 | 1588 | { |
|---|
| 1589 | + struct printk_info info; |
|---|
| 1689 | 1590 | bool clear = false; |
|---|
| 1690 | 1591 | static int saved_console_loglevel = LOGLEVEL_DEFAULT; |
|---|
| 1691 | 1592 | int error; |
|---|
| .. | .. |
|---|
| 1704 | 1605 | return -EINVAL; |
|---|
| 1705 | 1606 | if (!len) |
|---|
| 1706 | 1607 | return 0; |
|---|
| 1707 | | - if (!access_ok(VERIFY_WRITE, buf, len)) |
|---|
| 1608 | + if (!access_ok(buf, len)) |
|---|
| 1708 | 1609 | return -EFAULT; |
|---|
| 1610 | + |
|---|
| 1709 | 1611 | error = wait_event_interruptible(log_wait, |
|---|
| 1710 | | - syslog_seq != log_next_seq); |
|---|
| 1612 | + prb_read_valid(prb, read_syslog_seq_irq(), NULL)); |
|---|
| 1711 | 1613 | if (error) |
|---|
| 1712 | 1614 | return error; |
|---|
| 1713 | 1615 | error = syslog_print(buf, len); |
|---|
| .. | .. |
|---|
| 1715 | 1617 | /* Read/clear last kernel messages */ |
|---|
| 1716 | 1618 | case SYSLOG_ACTION_READ_CLEAR: |
|---|
| 1717 | 1619 | clear = true; |
|---|
| 1718 | | - /* FALL THRU */ |
|---|
| 1620 | + fallthrough; |
|---|
| 1719 | 1621 | /* Read last kernel messages */ |
|---|
| 1720 | 1622 | case SYSLOG_ACTION_READ_ALL: |
|---|
| 1721 | 1623 | if (!buf || len < 0) |
|---|
| 1722 | 1624 | return -EINVAL; |
|---|
| 1723 | 1625 | if (!len) |
|---|
| 1724 | 1626 | return 0; |
|---|
| 1725 | | - if (!access_ok(VERIFY_WRITE, buf, len)) |
|---|
| 1627 | + if (!access_ok(buf, len)) |
|---|
| 1726 | 1628 | return -EFAULT; |
|---|
| 1727 | 1629 | error = syslog_print_all(buf, len, clear); |
|---|
| 1728 | 1630 | break; |
|---|
| .. | .. |
|---|
| 1755 | 1657 | break; |
|---|
| 1756 | 1658 | /* Number of chars in the log buffer */ |
|---|
| 1757 | 1659 | case SYSLOG_ACTION_SIZE_UNREAD: |
|---|
| 1758 | | - logbuf_lock_irq(); |
|---|
| 1759 | | - if (syslog_seq < log_first_seq) { |
|---|
| 1660 | + spin_lock_irq(&syslog_lock); |
|---|
| 1661 | + if (!prb_read_valid_info(prb, syslog_seq, &info, NULL)) { |
|---|
| 1662 | + /* No unread messages. */ |
|---|
| 1663 | + spin_unlock_irq(&syslog_lock); |
|---|
| 1664 | + return 0; |
|---|
| 1665 | + } |
|---|
| 1666 | + if (info.seq != syslog_seq) { |
|---|
| 1760 | 1667 | /* messages are gone, move to first one */ |
|---|
| 1761 | | - syslog_seq = log_first_seq; |
|---|
| 1762 | | - syslog_idx = log_first_idx; |
|---|
| 1668 | + syslog_seq = info.seq; |
|---|
| 1763 | 1669 | syslog_partial = 0; |
|---|
| 1764 | 1670 | } |
|---|
| 1765 | 1671 | if (source == SYSLOG_FROM_PROC) { |
|---|
| .. | .. |
|---|
| 1768 | 1674 | * for pending data, not the size; return the count of |
|---|
| 1769 | 1675 | * records, not the length. |
|---|
| 1770 | 1676 | */ |
|---|
| 1771 | | - error = log_next_seq - syslog_seq; |
|---|
| 1677 | + error = prb_next_seq(prb) - syslog_seq; |
|---|
| 1772 | 1678 | } else { |
|---|
| 1773 | | - u64 seq = syslog_seq; |
|---|
| 1774 | | - u32 idx = syslog_idx; |
|---|
| 1679 | + bool time = syslog_partial ? syslog_time : printk_time; |
|---|
| 1680 | + unsigned int line_count; |
|---|
| 1681 | + u64 seq; |
|---|
| 1775 | 1682 | |
|---|
| 1776 | | - while (seq < log_next_seq) { |
|---|
| 1777 | | - struct printk_log *msg = log_from_idx(idx); |
|---|
| 1778 | | - |
|---|
| 1779 | | - error += msg_print_text(msg, true, NULL, 0); |
|---|
| 1780 | | - idx = log_next(idx); |
|---|
| 1781 | | - seq++; |
|---|
| 1683 | + prb_for_each_info(syslog_seq, prb, seq, &info, |
|---|
| 1684 | + &line_count) { |
|---|
| 1685 | + error += get_record_print_text_size(&info, line_count, |
|---|
| 1686 | + true, time); |
|---|
| 1687 | + time = printk_time; |
|---|
| 1782 | 1688 | } |
|---|
| 1783 | 1689 | error -= syslog_partial; |
|---|
| 1784 | 1690 | } |
|---|
| 1785 | | - logbuf_unlock_irq(); |
|---|
| 1691 | + spin_unlock_irq(&syslog_lock); |
|---|
| 1786 | 1692 | break; |
|---|
| 1787 | 1693 | /* Size of the log buffer */ |
|---|
| 1788 | 1694 | case SYSLOG_ACTION_SIZE_BUFFER: |
|---|
| .. | .. |
|---|
| 1801 | 1707 | return do_syslog(type, buf, len, SYSLOG_FROM_READER); |
|---|
| 1802 | 1708 | } |
|---|
| 1803 | 1709 | |
|---|
| 1804 | | -#ifndef CONFIG_PREEMPT_RT_FULL |
|---|
| 1805 | | -/* |
|---|
| 1806 | | - * Special console_lock variants that help to reduce the risk of soft-lockups. |
|---|
| 1807 | | - * They allow to pass console_lock to another printk() call using a busy wait. |
|---|
| 1808 | | - */ |
|---|
| 1809 | | - |
|---|
| 1810 | | -#ifdef CONFIG_LOCKDEP |
|---|
| 1811 | | -static struct lockdep_map console_owner_dep_map = { |
|---|
| 1812 | | - .name = "console_owner" |
|---|
| 1813 | | -}; |
|---|
| 1814 | | -#endif |
|---|
| 1815 | | - |
|---|
| 1816 | | -static DEFINE_RAW_SPINLOCK(console_owner_lock); |
|---|
| 1817 | | -static struct task_struct *console_owner; |
|---|
| 1818 | | -static bool console_waiter; |
|---|
| 1819 | | - |
|---|
| 1820 | | -/** |
|---|
| 1821 | | - * console_lock_spinning_enable - mark beginning of code where another |
|---|
| 1822 | | - * thread might safely busy wait |
|---|
| 1823 | | - * |
|---|
| 1824 | | - * This basically converts console_lock into a spinlock. This marks |
|---|
| 1825 | | - * the section where the console_lock owner can not sleep, because |
|---|
| 1826 | | - * there may be a waiter spinning (like a spinlock). Also it must be |
|---|
| 1827 | | - * ready to hand over the lock at the end of the section. |
|---|
| 1828 | | - */ |
|---|
| 1829 | | -static void console_lock_spinning_enable(void) |
|---|
| 1830 | | -{ |
|---|
| 1831 | | - raw_spin_lock(&console_owner_lock); |
|---|
| 1832 | | - console_owner = current; |
|---|
| 1833 | | - raw_spin_unlock(&console_owner_lock); |
|---|
| 1834 | | - |
|---|
| 1835 | | - /* The waiter may spin on us after setting console_owner */ |
|---|
| 1836 | | - spin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_); |
|---|
| 1837 | | -} |
|---|
| 1838 | | - |
|---|
| 1839 | | -/** |
|---|
| 1840 | | - * console_lock_spinning_disable_and_check - mark end of code where another |
|---|
| 1841 | | - * thread was able to busy wait and check if there is a waiter |
|---|
| 1842 | | - * |
|---|
| 1843 | | - * This is called at the end of the section where spinning is allowed. |
|---|
| 1844 | | - * It has two functions. First, it is a signal that it is no longer |
|---|
| 1845 | | - * safe to start busy waiting for the lock. Second, it checks if |
|---|
| 1846 | | - * there is a busy waiter and passes the lock rights to her. |
|---|
| 1847 | | - * |
|---|
| 1848 | | - * Important: Callers lose the lock if there was a busy waiter. |
|---|
| 1849 | | - * They must not touch items synchronized by console_lock |
|---|
| 1850 | | - * in this case. |
|---|
| 1851 | | - * |
|---|
| 1852 | | - * Return: 1 if the lock rights were passed, 0 otherwise. |
|---|
| 1853 | | - */ |
|---|
| 1854 | | -static int console_lock_spinning_disable_and_check(void) |
|---|
| 1855 | | -{ |
|---|
| 1856 | | - int waiter; |
|---|
| 1857 | | - |
|---|
| 1858 | | - raw_spin_lock(&console_owner_lock); |
|---|
| 1859 | | - waiter = READ_ONCE(console_waiter); |
|---|
| 1860 | | - console_owner = NULL; |
|---|
| 1861 | | - raw_spin_unlock(&console_owner_lock); |
|---|
| 1862 | | - |
|---|
| 1863 | | - if (!waiter) { |
|---|
| 1864 | | - spin_release(&console_owner_dep_map, 1, _THIS_IP_); |
|---|
| 1865 | | - return 0; |
|---|
| 1866 | | - } |
|---|
| 1867 | | - |
|---|
| 1868 | | - /* The waiter is now free to continue */ |
|---|
| 1869 | | - WRITE_ONCE(console_waiter, false); |
|---|
| 1870 | | - |
|---|
| 1871 | | - spin_release(&console_owner_dep_map, 1, _THIS_IP_); |
|---|
| 1872 | | - |
|---|
| 1873 | | - /* |
|---|
| 1874 | | - * Hand off console_lock to waiter. The waiter will perform |
|---|
| 1875 | | - * the up(). After this, the waiter is the console_lock owner. |
|---|
| 1876 | | - */ |
|---|
| 1877 | | - mutex_release(&console_lock_dep_map, 1, _THIS_IP_); |
|---|
| 1878 | | - return 1; |
|---|
| 1879 | | -} |
|---|
| 1880 | | - |
|---|
| 1881 | | -/** |
|---|
| 1882 | | - * console_trylock_spinning - try to get console_lock by busy waiting |
|---|
| 1883 | | - * |
|---|
| 1884 | | - * This allows to busy wait for the console_lock when the current |
|---|
| 1885 | | - * owner is running in specially marked sections. It means that |
|---|
| 1886 | | - * the current owner is running and cannot reschedule until it |
|---|
| 1887 | | - * is ready to lose the lock. |
|---|
| 1888 | | - * |
|---|
| 1889 | | - * Return: 1 if we got the lock, 0 othrewise |
|---|
| 1890 | | - */ |
|---|
| 1891 | | -static int console_trylock_spinning(void) |
|---|
| 1892 | | -{ |
|---|
| 1893 | | - struct task_struct *owner = NULL; |
|---|
| 1894 | | - bool waiter; |
|---|
| 1895 | | - bool spin = false; |
|---|
| 1896 | | - unsigned long flags; |
|---|
| 1897 | | - |
|---|
| 1898 | | - if (console_trylock()) |
|---|
| 1899 | | - return 1; |
|---|
| 1900 | | - |
|---|
| 1901 | | - printk_safe_enter_irqsave(flags); |
|---|
| 1902 | | - |
|---|
| 1903 | | - raw_spin_lock(&console_owner_lock); |
|---|
| 1904 | | - owner = READ_ONCE(console_owner); |
|---|
| 1905 | | - waiter = READ_ONCE(console_waiter); |
|---|
| 1906 | | - if (!waiter && owner && owner != current) { |
|---|
| 1907 | | - WRITE_ONCE(console_waiter, true); |
|---|
| 1908 | | - spin = true; |
|---|
| 1909 | | - } |
|---|
| 1910 | | - raw_spin_unlock(&console_owner_lock); |
|---|
| 1911 | | - |
|---|
| 1912 | | - /* |
|---|
| 1913 | | - * If there is an active printk() writing to the |
|---|
| 1914 | | - * consoles, instead of having it write our data too, |
|---|
| 1915 | | - * see if we can offload that load from the active |
|---|
| 1916 | | - * printer, and do some printing ourselves. |
|---|
| 1917 | | - * Go into a spin only if there isn't already a waiter |
|---|
| 1918 | | - * spinning, and there is an active printer, and |
|---|
| 1919 | | - * that active printer isn't us (recursive printk?). |
|---|
| 1920 | | - */ |
|---|
| 1921 | | - if (!spin) { |
|---|
| 1922 | | - printk_safe_exit_irqrestore(flags); |
|---|
| 1923 | | - return 0; |
|---|
| 1924 | | - } |
|---|
| 1925 | | - |
|---|
| 1926 | | - /* We spin waiting for the owner to release us */ |
|---|
| 1927 | | - spin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_); |
|---|
| 1928 | | - /* Owner will clear console_waiter on hand off */ |
|---|
| 1929 | | - while (READ_ONCE(console_waiter)) |
|---|
| 1930 | | - cpu_relax(); |
|---|
| 1931 | | - spin_release(&console_owner_dep_map, 1, _THIS_IP_); |
|---|
| 1932 | | - |
|---|
| 1933 | | - printk_safe_exit_irqrestore(flags); |
|---|
| 1934 | | - /* |
|---|
| 1935 | | - * The owner passed the console lock to us. |
|---|
| 1936 | | - * Since we did not spin on console lock, annotate |
|---|
| 1937 | | - * this as a trylock. Otherwise lockdep will |
|---|
| 1938 | | - * complain. |
|---|
| 1939 | | - */ |
|---|
| 1940 | | - mutex_acquire(&console_lock_dep_map, 0, 1, _THIS_IP_); |
|---|
| 1941 | | - |
|---|
| 1942 | | - return 1; |
|---|
| 1943 | | -} |
|---|
| 1944 | | - |
|---|
| 1945 | | -#else |
|---|
| 1946 | | - |
|---|
| 1947 | | -static int console_trylock_spinning(void) |
|---|
| 1948 | | -{ |
|---|
| 1949 | | - return console_trylock(); |
|---|
| 1950 | | -} |
|---|
| 1951 | | - |
|---|
| 1952 | | -#endif |
|---|
| 1953 | | - |
|---|
| 1954 | | -/* |
|---|
| 1955 | | - * Call the console drivers, asking them to write out |
|---|
| 1956 | | - * log_buf[start] to log_buf[end - 1]. |
|---|
| 1957 | | - * The console_lock must be held. |
|---|
| 1958 | | - */ |
|---|
| 1959 | | -#ifdef CONFIG_PSTORE_CONSOLE_FORCE |
|---|
| 1960 | | -__maybe_unused |
|---|
| 1961 | | -#endif |
|---|
| 1962 | | -static void call_console_drivers(const char *ext_text, size_t ext_len, |
|---|
| 1963 | | - const char *text, size_t len) |
|---|
| 1964 | | -{ |
|---|
| 1965 | | - struct console *con; |
|---|
| 1966 | | - |
|---|
| 1967 | | - trace_console_rcuidle(text, len); |
|---|
| 1968 | | - |
|---|
| 1969 | | - if (!console_drivers) |
|---|
| 1970 | | - return; |
|---|
| 1971 | | - |
|---|
| 1972 | | - if (IS_ENABLED(CONFIG_PREEMPT_RT_BASE)) { |
|---|
| 1973 | | - if (in_irq() || in_nmi()) |
|---|
| 1974 | | - return; |
|---|
| 1975 | | - } |
|---|
| 1976 | | - |
|---|
| 1977 | | - migrate_disable(); |
|---|
| 1978 | | - for_each_console(con) { |
|---|
| 1979 | | - if (exclusive_console && con != exclusive_console) |
|---|
| 1980 | | - continue; |
|---|
| 1981 | | - if (!(con->flags & CON_ENABLED)) |
|---|
| 1982 | | - continue; |
|---|
| 1983 | | - if (!con->write) |
|---|
| 1984 | | - continue; |
|---|
| 1985 | | - if (!cpu_online(smp_processor_id()) && |
|---|
| 1986 | | - !(con->flags & CON_ANYTIME)) |
|---|
| 1987 | | - continue; |
|---|
| 1988 | | - if (con->flags & CON_EXTENDED) |
|---|
| 1989 | | - con->write(con, ext_text, ext_len); |
|---|
| 1990 | | - else |
|---|
| 1991 | | - con->write(con, text, len); |
|---|
| 1992 | | - } |
|---|
| 1993 | | - migrate_enable(); |
|---|
| 1994 | | -} |
|---|
| 1995 | | - |
|---|
| 1996 | 1710 | int printk_delay_msec __read_mostly; |
|---|
| 1997 | 1711 | |
|---|
| 1998 | | -static inline void printk_delay(void) |
|---|
| 1712 | +static inline void printk_delay(int level) |
|---|
| 1999 | 1713 | { |
|---|
| 1714 | + boot_delay_msec(level); |
|---|
| 1715 | + |
|---|
| 2000 | 1716 | if (unlikely(printk_delay_msec)) { |
|---|
| 2001 | 1717 | int m = printk_delay_msec; |
|---|
| 2002 | 1718 | |
|---|
| .. | .. |
|---|
| 2007 | 1723 | } |
|---|
| 2008 | 1724 | } |
|---|
| 2009 | 1725 | |
|---|
| 2010 | | -/* |
|---|
| 2011 | | - * Continuation lines are buffered, and not committed to the record buffer |
|---|
| 2012 | | - * until the line is complete, or a race forces it. The line fragments |
|---|
| 2013 | | - * though, are printed immediately to the consoles to ensure everything has |
|---|
| 2014 | | - * reached the console in case of a kernel crash. |
|---|
| 2015 | | - */ |
|---|
| 2016 | | -static struct cont { |
|---|
| 2017 | | - char buf[LOG_LINE_MAX]; |
|---|
| 2018 | | - size_t len; /* length == 0 means unused buffer */ |
|---|
| 2019 | | - struct task_struct *owner; /* task of first print*/ |
|---|
| 2020 | | - u64 ts_nsec; /* time of first print */ |
|---|
| 2021 | | - u8 level; /* log level of first message */ |
|---|
| 2022 | | - u8 facility; /* log facility of first message */ |
|---|
| 2023 | | - enum log_flags flags; /* prefix, newline flags */ |
|---|
| 2024 | | -} cont; |
|---|
| 2025 | | - |
|---|
| 2026 | | -static void cont_flush(void) |
|---|
| 1726 | +static bool kernel_sync_mode(void) |
|---|
| 2027 | 1727 | { |
|---|
| 2028 | | - if (cont.len == 0) |
|---|
| 2029 | | - return; |
|---|
| 2030 | | - |
|---|
| 2031 | | - log_store(cont.facility, cont.level, cont.flags, cont.ts_nsec, |
|---|
| 2032 | | - NULL, 0, cont.buf, cont.len); |
|---|
| 2033 | | - cont.len = 0; |
|---|
| 1728 | + return (oops_in_progress || sync_mode); |
|---|
| 2034 | 1729 | } |
|---|
| 2035 | 1730 | |
|---|
| 2036 | | -static bool cont_add(int facility, int level, enum log_flags flags, const char *text, size_t len) |
|---|
| 1731 | +static bool console_can_sync(struct console *con) |
|---|
| 2037 | 1732 | { |
|---|
| 2038 | | - /* |
|---|
| 2039 | | - * If ext consoles are present, flush and skip in-kernel |
|---|
| 2040 | | - * continuation. See nr_ext_console_drivers definition. Also, if |
|---|
| 2041 | | - * the line gets too long, split it up in separate records. |
|---|
| 2042 | | - */ |
|---|
| 2043 | | - if (nr_ext_console_drivers || cont.len + len > sizeof(cont.buf)) { |
|---|
| 2044 | | - cont_flush(); |
|---|
| 1733 | + if (!(con->flags & CON_ENABLED)) |
|---|
| 2045 | 1734 | return false; |
|---|
| 2046 | | - } |
|---|
| 1735 | + if (con->write_atomic && kernel_sync_mode()) |
|---|
| 1736 | + return true; |
|---|
| 1737 | + if (con->write_atomic && (con->flags & CON_HANDOVER) && !con->thread) |
|---|
| 1738 | + return true; |
|---|
| 1739 | + if (con->write && (con->flags & CON_BOOT) && !con->thread) |
|---|
| 1740 | + return true; |
|---|
| 1741 | + return false; |
|---|
| 1742 | +} |
|---|
| 2047 | 1743 | |
|---|
| 2048 | | - if (!cont.len) { |
|---|
| 2049 | | - cont.facility = facility; |
|---|
| 2050 | | - cont.level = level; |
|---|
| 2051 | | - cont.owner = current; |
|---|
| 2052 | | - cont.ts_nsec = get_local_clock(); |
|---|
| 2053 | | - cont.flags = flags; |
|---|
| 2054 | | - } |
|---|
| 2055 | | - |
|---|
| 2056 | | - memcpy(cont.buf + cont.len, text, len); |
|---|
| 2057 | | - cont.len += len; |
|---|
| 2058 | | - |
|---|
| 2059 | | - // The original flags come from the first line, |
|---|
| 2060 | | - // but later continuations can add a newline. |
|---|
| 2061 | | - if (flags & LOG_NEWLINE) { |
|---|
| 2062 | | - cont.flags |= LOG_NEWLINE; |
|---|
| 2063 | | - cont_flush(); |
|---|
| 2064 | | - } |
|---|
| 2065 | | - |
|---|
| 2066 | | - if (cont.len > (sizeof(cont.buf) * 80) / 100) |
|---|
| 2067 | | - cont_flush(); |
|---|
| 1744 | +static bool call_sync_console_driver(struct console *con, const char *text, size_t text_len) |
|---|
| 1745 | +{ |
|---|
| 1746 | + if (!(con->flags & CON_ENABLED)) |
|---|
| 1747 | + return false; |
|---|
| 1748 | + if (con->write_atomic && kernel_sync_mode()) |
|---|
| 1749 | + con->write_atomic(con, text, text_len); |
|---|
| 1750 | + else if (con->write_atomic && (con->flags & CON_HANDOVER) && !con->thread) |
|---|
| 1751 | + con->write_atomic(con, text, text_len); |
|---|
| 1752 | + else if (con->write && (con->flags & CON_BOOT) && !con->thread) |
|---|
| 1753 | + con->write(con, text, text_len); |
|---|
| 1754 | + else |
|---|
| 1755 | + return false; |
|---|
| 2068 | 1756 | |
|---|
| 2069 | 1757 | return true; |
|---|
| 2070 | 1758 | } |
|---|
| 2071 | 1759 | |
|---|
| 2072 | | -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) |
|---|
| 1760 | +static bool have_atomic_console(void) |
|---|
| 2073 | 1761 | { |
|---|
| 2074 | | - /* |
|---|
| 2075 | | - * If an earlier line was buffered, and we're a continuation |
|---|
| 2076 | | - * write from the same process, try to add it to the buffer. |
|---|
| 2077 | | - */ |
|---|
| 2078 | | - if (cont.len) { |
|---|
| 2079 | | - if (cont.owner == current && (lflags & LOG_CONT)) { |
|---|
| 2080 | | - if (cont_add(facility, level, lflags, text, text_len)) |
|---|
| 2081 | | - return text_len; |
|---|
| 2082 | | - } |
|---|
| 2083 | | - /* Otherwise, make sure it's flushed */ |
|---|
| 2084 | | - cont_flush(); |
|---|
| 1762 | + struct console *con; |
|---|
| 1763 | + |
|---|
| 1764 | + for_each_console(con) { |
|---|
| 1765 | + if (!(con->flags & CON_ENABLED)) |
|---|
| 1766 | + continue; |
|---|
| 1767 | + if (con->write_atomic) |
|---|
| 1768 | + return true; |
|---|
| 2085 | 1769 | } |
|---|
| 2086 | | - |
|---|
| 2087 | | - /* Skip empty continuation lines that couldn't be added - they just flush */ |
|---|
| 2088 | | - if (!text_len && (lflags & LOG_CONT)) |
|---|
| 2089 | | - return 0; |
|---|
| 2090 | | - |
|---|
| 2091 | | - /* If it doesn't end in a newline, try to buffer the current line */ |
|---|
| 2092 | | - if (!(lflags & LOG_NEWLINE)) { |
|---|
| 2093 | | - if (cont_add(facility, level, lflags, text, text_len)) |
|---|
| 2094 | | - return text_len; |
|---|
| 2095 | | - } |
|---|
| 2096 | | - |
|---|
| 2097 | | - /* Store it in the record log */ |
|---|
| 2098 | | - return log_store(facility, level, lflags, 0, dict, dictlen, text, text_len); |
|---|
| 1770 | + return false; |
|---|
| 2099 | 1771 | } |
|---|
| 2100 | 1772 | |
|---|
| 2101 | | -/* Must be called under logbuf_lock. */ |
|---|
| 2102 | | -int vprintk_store(int facility, int level, |
|---|
| 2103 | | - const char *dict, size_t dictlen, |
|---|
| 2104 | | - const char *fmt, va_list args) |
|---|
| 1773 | +static bool print_sync(struct console *con, u64 *seq) |
|---|
| 2105 | 1774 | { |
|---|
| 2106 | | - static char textbuf[LOG_LINE_MAX]; |
|---|
| 2107 | | - char *text = textbuf; |
|---|
| 1775 | + struct printk_info info; |
|---|
| 1776 | + struct printk_record r; |
|---|
| 2108 | 1777 | size_t text_len; |
|---|
| 2109 | | - enum log_flags lflags = 0; |
|---|
| 2110 | 1778 | |
|---|
| 2111 | | - /* |
|---|
| 2112 | | - * The printf needs to come first; we need the syslog |
|---|
| 2113 | | - * prefix which might be passed-in as a parameter. |
|---|
| 2114 | | - */ |
|---|
| 2115 | | - text_len = vscnprintf(text, sizeof(textbuf), fmt, args); |
|---|
| 1779 | + prb_rec_init_rd(&r, &info, &con->sync_buf[0], sizeof(con->sync_buf)); |
|---|
| 2116 | 1780 | |
|---|
| 2117 | | - /* mark and strip a trailing newline */ |
|---|
| 2118 | | - if (text_len && text[text_len-1] == '\n') { |
|---|
| 2119 | | - text_len--; |
|---|
| 2120 | | - lflags |= LOG_NEWLINE; |
|---|
| 1781 | + if (!prb_read_valid(prb, *seq, &r)) |
|---|
| 1782 | + return false; |
|---|
| 1783 | + |
|---|
| 1784 | + text_len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time); |
|---|
| 1785 | + |
|---|
| 1786 | + if (!call_sync_console_driver(con, &con->sync_buf[0], text_len)) |
|---|
| 1787 | + return false; |
|---|
| 1788 | + |
|---|
| 1789 | + *seq = r.info->seq; |
|---|
| 1790 | + |
|---|
| 1791 | + touch_softlockup_watchdog_sync(); |
|---|
| 1792 | + clocksource_touch_watchdog(); |
|---|
| 1793 | + rcu_cpu_stall_reset(); |
|---|
| 1794 | + touch_nmi_watchdog(); |
|---|
| 1795 | + |
|---|
| 1796 | + if (text_len) |
|---|
| 1797 | + printk_delay(r.info->level); |
|---|
| 1798 | + |
|---|
| 1799 | + return true; |
|---|
| 1800 | +} |
|---|
| 1801 | + |
|---|
| 1802 | +static void print_sync_until(struct console *con, u64 seq) |
|---|
| 1803 | +{ |
|---|
| 1804 | + unsigned int flags; |
|---|
| 1805 | + u64 printk_seq; |
|---|
| 1806 | + |
|---|
| 1807 | + console_atomic_lock(&flags); |
|---|
| 1808 | + for (;;) { |
|---|
| 1809 | + printk_seq = atomic64_read(&con->printk_seq); |
|---|
| 1810 | + if (printk_seq >= seq) |
|---|
| 1811 | + break; |
|---|
| 1812 | + if (!print_sync(con, &printk_seq)) |
|---|
| 1813 | + break; |
|---|
| 1814 | + atomic64_set(&con->printk_seq, printk_seq + 1); |
|---|
| 1815 | + } |
|---|
| 1816 | + console_atomic_unlock(flags); |
|---|
| 1817 | +} |
|---|
| 1818 | + |
|---|
| 1819 | +#ifdef CONFIG_PRINTK_NMI |
|---|
| 1820 | +#define NUM_RECURSION_CTX 2 |
|---|
| 1821 | +#else |
|---|
| 1822 | +#define NUM_RECURSION_CTX 1 |
|---|
| 1823 | +#endif |
|---|
| 1824 | + |
|---|
| 1825 | +struct printk_recursion { |
|---|
| 1826 | + char count[NUM_RECURSION_CTX]; |
|---|
| 1827 | +}; |
|---|
| 1828 | + |
|---|
| 1829 | +static DEFINE_PER_CPU(struct printk_recursion, percpu_printk_recursion); |
|---|
| 1830 | +static char printk_recursion_count[NUM_RECURSION_CTX]; |
|---|
| 1831 | + |
|---|
| 1832 | +static char *printk_recursion_counter(void) |
|---|
| 1833 | +{ |
|---|
| 1834 | + struct printk_recursion *rec; |
|---|
| 1835 | + char *count; |
|---|
| 1836 | + |
|---|
| 1837 | + if (!printk_percpu_data_ready()) { |
|---|
| 1838 | + count = &printk_recursion_count[0]; |
|---|
| 1839 | + } else { |
|---|
| 1840 | + rec = this_cpu_ptr(&percpu_printk_recursion); |
|---|
| 1841 | + |
|---|
| 1842 | + count = &rec->count[0]; |
|---|
| 2121 | 1843 | } |
|---|
| 2122 | 1844 | |
|---|
| 2123 | | - /* strip kernel syslog prefix and extract log level or control flags */ |
|---|
| 1845 | +#ifdef CONFIG_PRINTK_NMI |
|---|
| 1846 | + if (in_nmi()) |
|---|
| 1847 | + count++; |
|---|
| 1848 | +#endif |
|---|
| 1849 | + |
|---|
| 1850 | + return count; |
|---|
| 1851 | +} |
|---|
| 1852 | + |
|---|
| 1853 | +static bool printk_enter_irqsave(unsigned long *flags) |
|---|
| 1854 | +{ |
|---|
| 1855 | + char *count; |
|---|
| 1856 | + |
|---|
| 1857 | + local_irq_save(*flags); |
|---|
| 1858 | + count = printk_recursion_counter(); |
|---|
| 1859 | + /* Only 1 level of recursion allowed. */ |
|---|
| 1860 | + if (*count > 1) { |
|---|
| 1861 | + local_irq_restore(*flags); |
|---|
| 1862 | + return false; |
|---|
| 1863 | + } |
|---|
| 1864 | + (*count)++; |
|---|
| 1865 | + |
|---|
| 1866 | + return true; |
|---|
| 1867 | +} |
|---|
| 1868 | + |
|---|
| 1869 | +static void printk_exit_irqrestore(unsigned long flags) |
|---|
| 1870 | +{ |
|---|
| 1871 | + char *count; |
|---|
| 1872 | + |
|---|
| 1873 | + count = printk_recursion_counter(); |
|---|
| 1874 | + (*count)--; |
|---|
| 1875 | + local_irq_restore(flags); |
|---|
| 1876 | +} |
|---|
| 1877 | + |
|---|
| 1878 | +static inline u32 printk_caller_id(void) |
|---|
| 1879 | +{ |
|---|
| 1880 | + return in_task() ? task_pid_nr(current) : |
|---|
| 1881 | + 0x80000000 + raw_smp_processor_id(); |
|---|
| 1882 | +} |
|---|
| 1883 | + |
|---|
| 1884 | +/** |
|---|
| 1885 | + * parse_prefix - Parse level and control flags. |
|---|
| 1886 | + * |
|---|
| 1887 | + * @text: The terminated text message. |
|---|
| 1888 | + * @level: A pointer to the current level value, will be updated. |
|---|
| 1889 | + * @lflags: A pointer to the current log flags, will be updated. |
|---|
| 1890 | + * |
|---|
| 1891 | + * @level may be NULL if the caller is not interested in the parsed value. |
|---|
| 1892 | + * Otherwise the variable pointed to by @level must be set to |
|---|
| 1893 | + * LOGLEVEL_DEFAULT in order to be updated with the parsed value. |
|---|
| 1894 | + * |
|---|
| 1895 | + * @lflags may be NULL if the caller is not interested in the parsed value. |
|---|
| 1896 | + * Otherwise the variable pointed to by @lflags will be OR'd with the parsed |
|---|
| 1897 | + * value. |
|---|
| 1898 | + * |
|---|
| 1899 | + * Return: The length of the parsed level and control flags. |
|---|
| 1900 | + */ |
|---|
| 1901 | +static u16 parse_prefix(char *text, int *level, enum log_flags *lflags) |
|---|
| 1902 | +{ |
|---|
| 1903 | + u16 prefix_len = 0; |
|---|
| 1904 | + int kern_level; |
|---|
| 1905 | + |
|---|
| 1906 | + while (*text) { |
|---|
| 1907 | + kern_level = printk_get_level(text); |
|---|
| 1908 | + if (!kern_level) |
|---|
| 1909 | + break; |
|---|
| 1910 | + |
|---|
| 1911 | + switch (kern_level) { |
|---|
| 1912 | + case '0' ... '7': |
|---|
| 1913 | + if (level && *level == LOGLEVEL_DEFAULT) |
|---|
| 1914 | + *level = kern_level - '0'; |
|---|
| 1915 | + break; |
|---|
| 1916 | + case 'c': /* KERN_CONT */ |
|---|
| 1917 | + if (lflags) |
|---|
| 1918 | + *lflags |= LOG_CONT; |
|---|
| 1919 | + } |
|---|
| 1920 | + |
|---|
| 1921 | + prefix_len += 2; |
|---|
| 1922 | + text += 2; |
|---|
| 1923 | + } |
|---|
| 1924 | + |
|---|
| 1925 | + return prefix_len; |
|---|
| 1926 | +} |
|---|
| 1927 | + |
|---|
| 1928 | +static u16 printk_sprint(char *text, u16 size, int facility, enum log_flags *lflags, |
|---|
| 1929 | + const char *fmt, va_list args) |
|---|
| 1930 | +{ |
|---|
| 1931 | + u16 text_len; |
|---|
| 1932 | + |
|---|
| 1933 | + text_len = vscnprintf(text, size, fmt, args); |
|---|
| 1934 | + |
|---|
| 1935 | + /* Mark and strip a trailing newline. */ |
|---|
| 1936 | + if (text_len && text[text_len - 1] == '\n') { |
|---|
| 1937 | + text_len--; |
|---|
| 1938 | + *lflags |= LOG_NEWLINE; |
|---|
| 1939 | + } |
|---|
| 1940 | + |
|---|
| 1941 | + /* Strip log level and control flags. */ |
|---|
| 2124 | 1942 | if (facility == 0) { |
|---|
| 2125 | | - int kern_level; |
|---|
| 1943 | + u16 prefix_len; |
|---|
| 2126 | 1944 | |
|---|
| 2127 | | - while ((kern_level = printk_get_level(text)) != 0) { |
|---|
| 2128 | | - switch (kern_level) { |
|---|
| 2129 | | - case '0' ... '7': |
|---|
| 2130 | | - if (level == LOGLEVEL_DEFAULT) |
|---|
| 2131 | | - level = kern_level - '0'; |
|---|
| 2132 | | - /* fallthrough */ |
|---|
| 2133 | | - case 'd': /* KERN_DEFAULT */ |
|---|
| 2134 | | - lflags |= LOG_PREFIX; |
|---|
| 2135 | | - break; |
|---|
| 2136 | | - case 'c': /* KERN_CONT */ |
|---|
| 2137 | | - lflags |= LOG_CONT; |
|---|
| 2138 | | - } |
|---|
| 2139 | | - |
|---|
| 2140 | | - text_len -= 2; |
|---|
| 2141 | | - text += 2; |
|---|
| 1945 | + prefix_len = parse_prefix(text, NULL, NULL); |
|---|
| 1946 | + if (prefix_len) { |
|---|
| 1947 | + text_len -= prefix_len; |
|---|
| 1948 | + memmove(text, text + prefix_len, text_len); |
|---|
| 2142 | 1949 | } |
|---|
| 2143 | 1950 | } |
|---|
| 1951 | + |
|---|
| 1952 | + return text_len; |
|---|
| 1953 | +} |
|---|
| 1954 | + |
|---|
| 1955 | +__printf(4, 0) |
|---|
| 1956 | +static int vprintk_store(int facility, int level, |
|---|
| 1957 | + const struct dev_printk_info *dev_info, |
|---|
| 1958 | + const char *fmt, va_list args) |
|---|
| 1959 | +{ |
|---|
| 1960 | + const u32 caller_id = printk_caller_id(); |
|---|
| 1961 | + struct prb_reserved_entry e; |
|---|
| 1962 | + enum log_flags lflags = 0; |
|---|
| 1963 | + bool final_commit = false; |
|---|
| 1964 | + struct printk_record r; |
|---|
| 1965 | + unsigned long irqflags; |
|---|
| 1966 | + u16 trunc_msg_len = 0; |
|---|
| 1967 | + char prefix_buf[8]; |
|---|
| 1968 | + u16 reserve_size; |
|---|
| 1969 | + va_list args2; |
|---|
| 1970 | + u16 text_len; |
|---|
| 1971 | + int ret = 0; |
|---|
| 1972 | + u64 ts_nsec; |
|---|
| 1973 | + u64 seq; |
|---|
| 1974 | + |
|---|
| 1975 | + /* |
|---|
| 1976 | + * Since the duration of printk() can vary depending on the message |
|---|
| 1977 | + * and state of the ringbuffer, grab the timestamp now so that it is |
|---|
| 1978 | + * close to the call of printk(). This provides a more deterministic |
|---|
| 1979 | + * timestamp with respect to the caller. |
|---|
| 1980 | + */ |
|---|
| 1981 | + ts_nsec = local_clock(); |
|---|
| 1982 | + |
|---|
| 1983 | + if (!printk_enter_irqsave(&irqflags)) |
|---|
| 1984 | + return 0; |
|---|
| 1985 | + |
|---|
| 1986 | + /* |
|---|
| 1987 | + * The sprintf needs to come first since the syslog prefix might be |
|---|
| 1988 | + * passed in as a parameter. An extra byte must be reserved so that |
|---|
| 1989 | + * later the vscnprintf() into the reserved buffer has room for the |
|---|
| 1990 | + * terminating '\0', which is not counted by vsnprintf(). |
|---|
| 1991 | + */ |
|---|
| 1992 | + va_copy(args2, args); |
|---|
| 1993 | + reserve_size = vsnprintf(&prefix_buf[0], sizeof(prefix_buf), fmt, args2) + 1; |
|---|
| 1994 | + va_end(args2); |
|---|
| 1995 | + |
|---|
| 1996 | + if (reserve_size > LOG_LINE_MAX) |
|---|
| 1997 | + reserve_size = LOG_LINE_MAX; |
|---|
| 1998 | + |
|---|
| 1999 | + /* Extract log level or control flags. */ |
|---|
| 2000 | + if (facility == 0) |
|---|
| 2001 | + parse_prefix(&prefix_buf[0], &level, &lflags); |
|---|
| 2144 | 2002 | |
|---|
| 2145 | 2003 | if (level == LOGLEVEL_DEFAULT) |
|---|
| 2146 | 2004 | level = default_message_loglevel; |
|---|
| 2147 | 2005 | |
|---|
| 2148 | | - if (dict) |
|---|
| 2149 | | - lflags |= LOG_PREFIX|LOG_NEWLINE; |
|---|
| 2006 | + if (dev_info) |
|---|
| 2007 | + lflags |= LOG_NEWLINE; |
|---|
| 2150 | 2008 | |
|---|
| 2151 | | - return log_output(facility, level, lflags, |
|---|
| 2152 | | - dict, dictlen, text, text_len); |
|---|
| 2009 | + if (lflags & LOG_CONT) { |
|---|
| 2010 | + prb_rec_init_wr(&r, reserve_size); |
|---|
| 2011 | + if (prb_reserve_in_last(&e, prb, &r, caller_id, LOG_LINE_MAX)) { |
|---|
| 2012 | + seq = r.info->seq; |
|---|
| 2013 | + text_len = printk_sprint(&r.text_buf[r.info->text_len], reserve_size, |
|---|
| 2014 | + facility, &lflags, fmt, args); |
|---|
| 2015 | + r.info->text_len += text_len; |
|---|
| 2016 | + |
|---|
| 2017 | + if (lflags & LOG_NEWLINE) { |
|---|
| 2018 | + r.info->flags |= LOG_NEWLINE; |
|---|
| 2019 | + prb_final_commit(&e); |
|---|
| 2020 | + final_commit = true; |
|---|
| 2021 | + } else { |
|---|
| 2022 | + prb_commit(&e); |
|---|
| 2023 | + } |
|---|
| 2024 | + |
|---|
| 2025 | + ret = text_len; |
|---|
| 2026 | + goto out; |
|---|
| 2027 | + } |
|---|
| 2028 | + } |
|---|
| 2029 | + |
|---|
| 2030 | + /* |
|---|
| 2031 | + * Explicitly initialize the record before every prb_reserve() call. |
|---|
| 2032 | + * prb_reserve_in_last() and prb_reserve() purposely invalidate the |
|---|
| 2033 | + * structure when they fail. |
|---|
| 2034 | + */ |
|---|
| 2035 | + prb_rec_init_wr(&r, reserve_size); |
|---|
| 2036 | + if (!prb_reserve(&e, prb, &r)) { |
|---|
| 2037 | + /* truncate the message if it is too long for empty buffer */ |
|---|
| 2038 | + truncate_msg(&reserve_size, &trunc_msg_len); |
|---|
| 2039 | + |
|---|
| 2040 | + prb_rec_init_wr(&r, reserve_size + trunc_msg_len); |
|---|
| 2041 | + if (!prb_reserve(&e, prb, &r)) |
|---|
| 2042 | + goto out; |
|---|
| 2043 | + } |
|---|
| 2044 | + |
|---|
| 2045 | + seq = r.info->seq; |
|---|
| 2046 | + |
|---|
| 2047 | + /* fill message */ |
|---|
| 2048 | + text_len = printk_sprint(&r.text_buf[0], reserve_size, facility, &lflags, fmt, args); |
|---|
| 2049 | + if (trunc_msg_len) |
|---|
| 2050 | + memcpy(&r.text_buf[text_len], trunc_msg, trunc_msg_len); |
|---|
| 2051 | + r.info->text_len = text_len + trunc_msg_len; |
|---|
| 2052 | + r.info->facility = facility; |
|---|
| 2053 | + r.info->level = level & 7; |
|---|
| 2054 | + r.info->flags = lflags & 0x1f; |
|---|
| 2055 | + r.info->ts_nsec = ts_nsec; |
|---|
| 2056 | + r.info->caller_id = caller_id; |
|---|
| 2057 | + if (dev_info) |
|---|
| 2058 | + memcpy(&r.info->dev_info, dev_info, sizeof(r.info->dev_info)); |
|---|
| 2059 | + |
|---|
| 2060 | + /* A message without a trailing newline can be continued. */ |
|---|
| 2061 | + if (!(lflags & LOG_NEWLINE)) { |
|---|
| 2062 | + prb_commit(&e); |
|---|
| 2063 | + } else { |
|---|
| 2064 | + prb_final_commit(&e); |
|---|
| 2065 | + final_commit = true; |
|---|
| 2066 | + } |
|---|
| 2067 | + |
|---|
| 2068 | + ret = text_len + trunc_msg_len; |
|---|
| 2069 | +out: |
|---|
| 2070 | + /* only the kernel may perform synchronous printing */ |
|---|
| 2071 | + if (facility == 0 && final_commit) { |
|---|
| 2072 | + struct console *con; |
|---|
| 2073 | + |
|---|
| 2074 | + for_each_console(con) { |
|---|
| 2075 | + if (console_can_sync(con)) |
|---|
| 2076 | + print_sync_until(con, seq + 1); |
|---|
| 2077 | + } |
|---|
| 2078 | + } |
|---|
| 2079 | + |
|---|
| 2080 | + printk_exit_irqrestore(irqflags); |
|---|
| 2081 | + return ret; |
|---|
| 2153 | 2082 | } |
|---|
| 2154 | 2083 | |
|---|
| 2155 | 2084 | asmlinkage int vprintk_emit(int facility, int level, |
|---|
| 2156 | | - const char *dict, size_t dictlen, |
|---|
| 2085 | + const struct dev_printk_info *dev_info, |
|---|
| 2157 | 2086 | const char *fmt, va_list args) |
|---|
| 2158 | 2087 | { |
|---|
| 2159 | 2088 | int printed_len; |
|---|
| 2160 | | - bool in_sched = false, pending_output; |
|---|
| 2161 | | - unsigned long flags; |
|---|
| 2162 | | - u64 curr_log_seq; |
|---|
| 2163 | 2089 | |
|---|
| 2164 | | - /* |
|---|
| 2165 | | - * Fall back to early_printk if a debugging subsystem has |
|---|
| 2166 | | - * killed printk output |
|---|
| 2167 | | - */ |
|---|
| 2168 | | - if (unlikely(forced_early_printk(fmt, args))) |
|---|
| 2169 | | - return 1; |
|---|
| 2090 | + /* Suppress unimportant messages after panic happens */ |
|---|
| 2091 | + if (unlikely(suppress_printk)) |
|---|
| 2092 | + return 0; |
|---|
| 2170 | 2093 | |
|---|
| 2171 | | - if (level == LOGLEVEL_SCHED) { |
|---|
| 2094 | + if (level == LOGLEVEL_SCHED) |
|---|
| 2172 | 2095 | level = LOGLEVEL_DEFAULT; |
|---|
| 2173 | | - in_sched = true; |
|---|
| 2174 | | - } |
|---|
| 2175 | 2096 | |
|---|
| 2176 | | - boot_delay_msec(level); |
|---|
| 2177 | | - printk_delay(); |
|---|
| 2097 | + printed_len = vprintk_store(facility, level, dev_info, fmt, args); |
|---|
| 2178 | 2098 | |
|---|
| 2179 | | - /* This stops the holder of console_sem just where we want him */ |
|---|
| 2180 | | - logbuf_lock_irqsave(flags); |
|---|
| 2181 | | - curr_log_seq = log_next_seq; |
|---|
| 2182 | | - printed_len = vprintk_store(facility, level, dict, dictlen, fmt, args); |
|---|
| 2183 | | - pending_output = (curr_log_seq != log_next_seq); |
|---|
| 2184 | | - logbuf_unlock_irqrestore(flags); |
|---|
| 2185 | | - |
|---|
| 2186 | | - /* If called from the scheduler, we can not call up(). */ |
|---|
| 2187 | | - if (!in_sched && pending_output) { |
|---|
| 2188 | | - int may_trylock = 1; |
|---|
| 2189 | | - |
|---|
| 2190 | | -#ifdef CONFIG_PREEMPT_RT_FULL |
|---|
| 2191 | | - /* |
|---|
| 2192 | | - * we can't take a sleeping lock with IRQs or preeption disabled |
|---|
| 2193 | | - * so we can't print in these contexts |
|---|
| 2194 | | - */ |
|---|
| 2195 | | - if (!(preempt_count() == 0 && !irqs_disabled())) |
|---|
| 2196 | | - may_trylock = 0; |
|---|
| 2197 | | -#endif |
|---|
| 2198 | | - /* |
|---|
| 2199 | | - * Disable preemption to avoid being preempted while holding |
|---|
| 2200 | | - * console_sem which would prevent anyone from printing to |
|---|
| 2201 | | - * console |
|---|
| 2202 | | - */ |
|---|
| 2203 | | - migrate_disable(); |
|---|
| 2204 | | - /* |
|---|
| 2205 | | - * Try to acquire and then immediately release the console |
|---|
| 2206 | | - * semaphore. The release will print out buffers and wake up |
|---|
| 2207 | | - * /dev/kmsg and syslog() users. |
|---|
| 2208 | | - */ |
|---|
| 2209 | | - if (may_trylock && console_trylock_spinning()) |
|---|
| 2210 | | - console_unlock(); |
|---|
| 2211 | | - migrate_enable(); |
|---|
| 2212 | | - } |
|---|
| 2213 | | - |
|---|
| 2214 | | - if (pending_output) |
|---|
| 2215 | | - wake_up_klogd(); |
|---|
| 2099 | + wake_up_klogd(); |
|---|
| 2216 | 2100 | return printed_len; |
|---|
| 2217 | 2101 | } |
|---|
| 2218 | 2102 | EXPORT_SYMBOL(vprintk_emit); |
|---|
| 2103 | + |
|---|
| 2104 | +__printf(1, 0) |
|---|
| 2105 | +static int vprintk_default(const char *fmt, va_list args) |
|---|
| 2106 | +{ |
|---|
| 2107 | + return vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, fmt, args); |
|---|
| 2108 | +} |
|---|
| 2109 | +__printf(1, 0) |
|---|
| 2110 | +static int vprintk_func(const char *fmt, va_list args) |
|---|
| 2111 | +{ |
|---|
| 2112 | +#ifdef CONFIG_KGDB_KDB |
|---|
| 2113 | + /* Allow to pass printk() to kdb but avoid a recursion. */ |
|---|
| 2114 | + if (unlikely(kdb_trap_printk && kdb_printf_cpu < 0)) |
|---|
| 2115 | + return vkdb_printf(KDB_MSGSRC_PRINTK, fmt, args); |
|---|
| 2116 | +#endif |
|---|
| 2117 | + return vprintk_default(fmt, args); |
|---|
| 2118 | +} |
|---|
| 2219 | 2119 | |
|---|
| 2220 | 2120 | asmlinkage int vprintk(const char *fmt, va_list args) |
|---|
| 2221 | 2121 | { |
|---|
| 2222 | 2122 | return vprintk_func(fmt, args); |
|---|
| 2223 | 2123 | } |
|---|
| 2224 | 2124 | EXPORT_SYMBOL(vprintk); |
|---|
| 2225 | | - |
|---|
| 2226 | | -asmlinkage int printk_emit(int facility, int level, |
|---|
| 2227 | | - const char *dict, size_t dictlen, |
|---|
| 2228 | | - const char *fmt, ...) |
|---|
| 2229 | | -{ |
|---|
| 2230 | | - va_list args; |
|---|
| 2231 | | - int r; |
|---|
| 2232 | | - |
|---|
| 2233 | | - va_start(args, fmt); |
|---|
| 2234 | | - r = vprintk_emit(facility, level, dict, dictlen, fmt, args); |
|---|
| 2235 | | - va_end(args); |
|---|
| 2236 | | - |
|---|
| 2237 | | - return r; |
|---|
| 2238 | | -} |
|---|
| 2239 | | -EXPORT_SYMBOL(printk_emit); |
|---|
| 2240 | | - |
|---|
| 2241 | | -int vprintk_default(const char *fmt, va_list args) |
|---|
| 2242 | | -{ |
|---|
| 2243 | | - int r; |
|---|
| 2244 | | - |
|---|
| 2245 | | -#ifdef CONFIG_KGDB_KDB |
|---|
| 2246 | | - /* Allow to pass printk() to kdb but avoid a recursion. */ |
|---|
| 2247 | | - if (unlikely(kdb_trap_printk && kdb_printf_cpu < 0)) { |
|---|
| 2248 | | - r = vkdb_printf(KDB_MSGSRC_PRINTK, fmt, args); |
|---|
| 2249 | | - return r; |
|---|
| 2250 | | - } |
|---|
| 2251 | | -#endif |
|---|
| 2252 | | - r = vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, 0, fmt, args); |
|---|
| 2253 | | - |
|---|
| 2254 | | - return r; |
|---|
| 2255 | | -} |
|---|
| 2256 | | -EXPORT_SYMBOL_GPL(vprintk_default); |
|---|
| 2257 | 2125 | |
|---|
| 2258 | 2126 | /** |
|---|
| 2259 | 2127 | * printk - print a kernel message |
|---|
| .. | .. |
|---|
| 2289 | 2157 | } |
|---|
| 2290 | 2158 | EXPORT_SYMBOL(printk); |
|---|
| 2291 | 2159 | |
|---|
| 2160 | +static int printk_kthread_func(void *data) |
|---|
| 2161 | +{ |
|---|
| 2162 | + struct console *con = data; |
|---|
| 2163 | + unsigned long dropped = 0; |
|---|
| 2164 | + char *dropped_text = NULL; |
|---|
| 2165 | + struct printk_info info; |
|---|
| 2166 | + struct printk_record r; |
|---|
| 2167 | + char *ext_text = NULL; |
|---|
| 2168 | + size_t dropped_len; |
|---|
| 2169 | + int ret = -ENOMEM; |
|---|
| 2170 | + char *text = NULL; |
|---|
| 2171 | + char *write_text; |
|---|
| 2172 | + u64 printk_seq; |
|---|
| 2173 | + size_t len; |
|---|
| 2174 | + int error; |
|---|
| 2175 | + u64 seq; |
|---|
| 2176 | + |
|---|
| 2177 | + if (con->flags & CON_EXTENDED) { |
|---|
| 2178 | + ext_text = kmalloc(CONSOLE_EXT_LOG_MAX, GFP_KERNEL); |
|---|
| 2179 | + if (!ext_text) |
|---|
| 2180 | + goto out; |
|---|
| 2181 | + } |
|---|
| 2182 | + text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); |
|---|
| 2183 | + dropped_text = kmalloc(64, GFP_KERNEL); |
|---|
| 2184 | + if (!text || !dropped_text) |
|---|
| 2185 | + goto out; |
|---|
| 2186 | + |
|---|
| 2187 | + if (con->flags & CON_EXTENDED) |
|---|
| 2188 | + write_text = ext_text; |
|---|
| 2189 | + else |
|---|
| 2190 | + write_text = text; |
|---|
| 2191 | + |
|---|
| 2192 | + seq = atomic64_read(&con->printk_seq); |
|---|
| 2193 | + |
|---|
| 2194 | + prb_rec_init_rd(&r, &info, text, LOG_LINE_MAX + PREFIX_MAX); |
|---|
| 2195 | + |
|---|
| 2196 | + for (;;) { |
|---|
| 2197 | + error = wait_event_interruptible(log_wait, |
|---|
| 2198 | + prb_read_valid(prb, seq, &r) || kthread_should_stop()); |
|---|
| 2199 | + |
|---|
| 2200 | + if (kthread_should_stop()) |
|---|
| 2201 | + break; |
|---|
| 2202 | + |
|---|
| 2203 | + if (error) |
|---|
| 2204 | + continue; |
|---|
| 2205 | + |
|---|
| 2206 | + if (seq != r.info->seq) { |
|---|
| 2207 | + dropped += r.info->seq - seq; |
|---|
| 2208 | + seq = r.info->seq; |
|---|
| 2209 | + } |
|---|
| 2210 | + |
|---|
| 2211 | + seq++; |
|---|
| 2212 | + |
|---|
| 2213 | + if (!(con->flags & CON_ENABLED)) |
|---|
| 2214 | + continue; |
|---|
| 2215 | + |
|---|
| 2216 | + if (suppress_message_printing(r.info->level)) |
|---|
| 2217 | + continue; |
|---|
| 2218 | + |
|---|
| 2219 | + if (con->flags & CON_EXTENDED) { |
|---|
| 2220 | + len = info_print_ext_header(ext_text, |
|---|
| 2221 | + CONSOLE_EXT_LOG_MAX, |
|---|
| 2222 | + r.info); |
|---|
| 2223 | + len += msg_print_ext_body(ext_text + len, |
|---|
| 2224 | + CONSOLE_EXT_LOG_MAX - len, |
|---|
| 2225 | + &r.text_buf[0], r.info->text_len, |
|---|
| 2226 | + &r.info->dev_info); |
|---|
| 2227 | + } else { |
|---|
| 2228 | + len = record_print_text(&r, |
|---|
| 2229 | + console_msg_format & MSG_FORMAT_SYSLOG, |
|---|
| 2230 | + printk_time); |
|---|
| 2231 | + } |
|---|
| 2232 | + |
|---|
| 2233 | + printk_seq = atomic64_read(&con->printk_seq); |
|---|
| 2234 | + |
|---|
| 2235 | + console_lock(); |
|---|
| 2236 | + console_may_schedule = 0; |
|---|
| 2237 | + |
|---|
| 2238 | + if (kernel_sync_mode() && con->write_atomic) { |
|---|
| 2239 | + console_unlock(); |
|---|
| 2240 | + break; |
|---|
| 2241 | + } |
|---|
| 2242 | + |
|---|
| 2243 | + if (!(con->flags & CON_EXTENDED) && dropped) { |
|---|
| 2244 | + dropped_len = snprintf(dropped_text, 64, |
|---|
| 2245 | + "** %lu printk messages dropped **\n", |
|---|
| 2246 | + dropped); |
|---|
| 2247 | + dropped = 0; |
|---|
| 2248 | + |
|---|
| 2249 | + con->write(con, dropped_text, dropped_len); |
|---|
| 2250 | + printk_delay(r.info->level); |
|---|
| 2251 | + } |
|---|
| 2252 | + |
|---|
| 2253 | + con->write(con, write_text, len); |
|---|
| 2254 | + if (len) |
|---|
| 2255 | + printk_delay(r.info->level); |
|---|
| 2256 | + |
|---|
| 2257 | + atomic64_cmpxchg_relaxed(&con->printk_seq, printk_seq, seq); |
|---|
| 2258 | + |
|---|
| 2259 | + console_unlock(); |
|---|
| 2260 | + } |
|---|
| 2261 | +out: |
|---|
| 2262 | + kfree(dropped_text); |
|---|
| 2263 | + kfree(text); |
|---|
| 2264 | + kfree(ext_text); |
|---|
| 2265 | + pr_info("%sconsole [%s%d]: printing thread stopped\n", |
|---|
| 2266 | + (con->flags & CON_BOOT) ? "boot" : "", |
|---|
| 2267 | + con->name, con->index); |
|---|
| 2268 | + return ret; |
|---|
| 2269 | +} |
|---|
| 2270 | + |
|---|
| 2271 | +/* Must be called within console_lock(). */ |
|---|
| 2272 | +static void start_printk_kthread(struct console *con) |
|---|
| 2273 | +{ |
|---|
| 2274 | + /* No need to start a printing thread if the console cannot print. */ |
|---|
| 2275 | + if (!con->write) |
|---|
| 2276 | + return; |
|---|
| 2277 | + |
|---|
| 2278 | + con->thread = kthread_run(printk_kthread_func, con, |
|---|
| 2279 | + "pr/%s%d", con->name, con->index); |
|---|
| 2280 | + if (IS_ERR(con->thread)) { |
|---|
| 2281 | + pr_err("%sconsole [%s%d]: unable to start printing thread\n", |
|---|
| 2282 | + (con->flags & CON_BOOT) ? "boot" : "", |
|---|
| 2283 | + con->name, con->index); |
|---|
| 2284 | + return; |
|---|
| 2285 | + } |
|---|
| 2286 | + pr_info("%sconsole [%s%d]: printing thread started\n", |
|---|
| 2287 | + (con->flags & CON_BOOT) ? "boot" : "", |
|---|
| 2288 | + con->name, con->index); |
|---|
| 2289 | +} |
|---|
| 2290 | + |
|---|
| 2291 | +/* protected by console_lock */ |
|---|
| 2292 | +static bool kthreads_started; |
|---|
| 2293 | + |
|---|
| 2294 | +/* Must be called within console_lock(). */ |
|---|
| 2295 | +static void console_try_thread(struct console *con) |
|---|
| 2296 | +{ |
|---|
| 2297 | + if (kthreads_started) { |
|---|
| 2298 | + start_printk_kthread(con); |
|---|
| 2299 | + return; |
|---|
| 2300 | + } |
|---|
| 2301 | + |
|---|
| 2302 | + /* |
|---|
| 2303 | + * The printing threads have not been started yet. If this console |
|---|
| 2304 | + * can print synchronously, print all unprinted messages. |
|---|
| 2305 | + */ |
|---|
| 2306 | + if (console_can_sync(con)) |
|---|
| 2307 | + print_sync_until(con, prb_next_seq(prb)); |
|---|
| 2308 | +} |
|---|
| 2309 | + |
|---|
| 2292 | 2310 | #else /* CONFIG_PRINTK */ |
|---|
| 2293 | 2311 | |
|---|
| 2294 | | -#define LOG_LINE_MAX 0 |
|---|
| 2295 | | -#define PREFIX_MAX 0 |
|---|
| 2312 | +#define prb_first_valid_seq(rb) 0 |
|---|
| 2313 | +#define prb_next_seq(rb) 0 |
|---|
| 2296 | 2314 | |
|---|
| 2297 | | -static u64 syslog_seq; |
|---|
| 2298 | | -static u32 syslog_idx; |
|---|
| 2299 | | -static u64 console_seq; |
|---|
| 2300 | | -static u32 console_idx; |
|---|
| 2301 | | -static u64 exclusive_console_stop_seq; |
|---|
| 2302 | | -static u64 log_first_seq; |
|---|
| 2303 | | -static u32 log_first_idx; |
|---|
| 2304 | | -static u64 log_next_seq; |
|---|
| 2305 | | -static char *log_text(const struct printk_log *msg) { return NULL; } |
|---|
| 2306 | | -static char *log_dict(const struct printk_log *msg) { return NULL; } |
|---|
| 2307 | | -static struct printk_log *log_from_idx(u32 idx) { return NULL; } |
|---|
| 2308 | | -static u32 log_next(u32 idx) { return 0; } |
|---|
| 2309 | | -static ssize_t msg_print_ext_header(char *buf, size_t size, |
|---|
| 2310 | | - struct printk_log *msg, |
|---|
| 2311 | | - u64 seq) { return 0; } |
|---|
| 2312 | | -static ssize_t msg_print_ext_body(char *buf, size_t size, |
|---|
| 2313 | | - char *dict, size_t dict_len, |
|---|
| 2314 | | - char *text, size_t text_len) { return 0; } |
|---|
| 2315 | | -static void console_lock_spinning_enable(void) { } |
|---|
| 2316 | | -static int console_lock_spinning_disable_and_check(void) { return 0; } |
|---|
| 2317 | | -static void call_console_drivers(const char *ext_text, size_t ext_len, |
|---|
| 2318 | | - const char *text, size_t len) {} |
|---|
| 2319 | | -static size_t msg_print_text(const struct printk_log *msg, |
|---|
| 2320 | | - bool syslog, char *buf, size_t size) { return 0; } |
|---|
| 2321 | | -static bool suppress_message_printing(int level) { return false; } |
|---|
| 2315 | +#define console_try_thread(con) |
|---|
| 2322 | 2316 | |
|---|
| 2323 | 2317 | #endif /* CONFIG_PRINTK */ |
|---|
| 2324 | 2318 | |
|---|
| 2319 | +#ifdef CONFIG_EARLY_PRINTK |
|---|
| 2320 | +struct console *early_console; |
|---|
| 2321 | + |
|---|
| 2322 | +asmlinkage __visible void early_printk(const char *fmt, ...) |
|---|
| 2323 | +{ |
|---|
| 2324 | + va_list ap; |
|---|
| 2325 | + char buf[512]; |
|---|
| 2326 | + int n; |
|---|
| 2327 | + |
|---|
| 2328 | + if (!early_console) |
|---|
| 2329 | + return; |
|---|
| 2330 | + |
|---|
| 2331 | + va_start(ap, fmt); |
|---|
| 2332 | + n = vscnprintf(buf, sizeof(buf), fmt, ap); |
|---|
| 2333 | + va_end(ap); |
|---|
| 2334 | + |
|---|
| 2335 | + early_console->write(early_console, buf, n); |
|---|
| 2336 | +} |
|---|
| 2337 | +#endif |
|---|
| 2338 | + |
|---|
| 2325 | 2339 | static int __add_preferred_console(char *name, int idx, char *options, |
|---|
| 2326 | | - char *brl_options) |
|---|
| 2340 | + char *brl_options, bool user_specified) |
|---|
| 2327 | 2341 | { |
|---|
| 2328 | 2342 | struct console_cmdline *c; |
|---|
| 2329 | 2343 | int i; |
|---|
| .. | .. |
|---|
| 2338 | 2352 | if (strcmp(c->name, name) == 0 && c->index == idx) { |
|---|
| 2339 | 2353 | if (!brl_options) |
|---|
| 2340 | 2354 | preferred_console = i; |
|---|
| 2355 | + if (user_specified) |
|---|
| 2356 | + c->user_specified = true; |
|---|
| 2341 | 2357 | return 0; |
|---|
| 2342 | 2358 | } |
|---|
| 2343 | 2359 | } |
|---|
| .. | .. |
|---|
| 2347 | 2363 | preferred_console = i; |
|---|
| 2348 | 2364 | strlcpy(c->name, name, sizeof(c->name)); |
|---|
| 2349 | 2365 | c->options = options; |
|---|
| 2366 | + c->user_specified = user_specified; |
|---|
| 2350 | 2367 | braille_set_options(c, brl_options); |
|---|
| 2351 | 2368 | |
|---|
| 2352 | 2369 | c->index = idx; |
|---|
| .. | .. |
|---|
| 2379 | 2396 | * for exacly this purpose. |
|---|
| 2380 | 2397 | */ |
|---|
| 2381 | 2398 | if (str[0] == 0 || strcmp(str, "null") == 0) { |
|---|
| 2382 | | - __add_preferred_console("ttynull", 0, NULL, NULL); |
|---|
| 2399 | + __add_preferred_console("ttynull", 0, NULL, NULL, true); |
|---|
| 2383 | 2400 | return 1; |
|---|
| 2384 | 2401 | } |
|---|
| 2385 | 2402 | |
|---|
| .. | .. |
|---|
| 2411 | 2428 | idx = simple_strtoul(s, NULL, 10); |
|---|
| 2412 | 2429 | *s = 0; |
|---|
| 2413 | 2430 | |
|---|
| 2414 | | - __add_preferred_console(buf, idx, options, brl_options); |
|---|
| 2431 | + __add_preferred_console(buf, idx, options, brl_options, true); |
|---|
| 2415 | 2432 | console_set_on_cmdline = 1; |
|---|
| 2416 | 2433 | return 1; |
|---|
| 2417 | 2434 | } |
|---|
| .. | .. |
|---|
| 2432 | 2449 | */ |
|---|
| 2433 | 2450 | int add_preferred_console(char *name, int idx, char *options) |
|---|
| 2434 | 2451 | { |
|---|
| 2435 | | - return __add_preferred_console(name, idx, options, NULL); |
|---|
| 2452 | + return __add_preferred_console(name, idx, options, NULL, false); |
|---|
| 2436 | 2453 | } |
|---|
| 2437 | 2454 | |
|---|
| 2438 | 2455 | bool console_suspend_enabled = true; |
|---|
| .. | .. |
|---|
| 2484 | 2501 | */ |
|---|
| 2485 | 2502 | static int console_cpu_notify(unsigned int cpu) |
|---|
| 2486 | 2503 | { |
|---|
| 2504 | + int flag = 0; |
|---|
| 2505 | + |
|---|
| 2506 | + trace_android_vh_printk_hotplug(&flag); |
|---|
| 2507 | + if (flag) |
|---|
| 2508 | + return 0; |
|---|
| 2509 | + |
|---|
| 2487 | 2510 | if (!cpuhp_tasks_frozen) { |
|---|
| 2488 | 2511 | /* If trylock fails, someone else is doing the printing */ |
|---|
| 2489 | 2512 | if (console_trylock()) |
|---|
| .. | .. |
|---|
| 2540 | 2563 | } |
|---|
| 2541 | 2564 | EXPORT_SYMBOL(is_console_locked); |
|---|
| 2542 | 2565 | |
|---|
| 2543 | | -/* |
|---|
| 2544 | | - * Check if we have any console that is capable of printing while cpu is |
|---|
| 2545 | | - * booting or shutting down. Requires console_sem. |
|---|
| 2546 | | - */ |
|---|
| 2547 | | -static int have_callable_console(void) |
|---|
| 2548 | | -{ |
|---|
| 2549 | | - struct console *con; |
|---|
| 2550 | | - |
|---|
| 2551 | | - for_each_console(con) |
|---|
| 2552 | | - if ((con->flags & CON_ENABLED) && |
|---|
| 2553 | | - (con->flags & CON_ANYTIME)) |
|---|
| 2554 | | - return 1; |
|---|
| 2555 | | - |
|---|
| 2556 | | - return 0; |
|---|
| 2557 | | -} |
|---|
| 2558 | | - |
|---|
| 2559 | | -/* |
|---|
| 2560 | | - * Can we actually use the console at this time on this cpu? |
|---|
| 2561 | | - * |
|---|
| 2562 | | - * Console drivers may assume that per-cpu resources have been allocated. So |
|---|
| 2563 | | - * unless they're explicitly marked as being able to cope (CON_ANYTIME) don't |
|---|
| 2564 | | - * call them until this CPU is officially up. |
|---|
| 2565 | | - */ |
|---|
| 2566 | | -static inline int can_use_console(void) |
|---|
| 2567 | | -{ |
|---|
| 2568 | | - return cpu_online(raw_smp_processor_id()) || have_callable_console(); |
|---|
| 2569 | | -} |
|---|
| 2570 | | - |
|---|
| 2571 | 2566 | /** |
|---|
| 2572 | 2567 | * console_unlock - unlock the console system |
|---|
| 2573 | 2568 | * |
|---|
| .. | .. |
|---|
| 2584 | 2579 | */ |
|---|
| 2585 | 2580 | void console_unlock(void) |
|---|
| 2586 | 2581 | { |
|---|
| 2587 | | - static char ext_text[CONSOLE_EXT_LOG_MAX]; |
|---|
| 2588 | | - static char text[LOG_LINE_MAX + PREFIX_MAX]; |
|---|
| 2589 | | - unsigned long flags; |
|---|
| 2590 | | - bool do_cond_resched, retry; |
|---|
| 2591 | | - |
|---|
| 2592 | 2582 | if (console_suspended) { |
|---|
| 2593 | 2583 | up_console_sem(); |
|---|
| 2594 | 2584 | return; |
|---|
| 2595 | 2585 | } |
|---|
| 2596 | 2586 | |
|---|
| 2597 | | - /* |
|---|
| 2598 | | - * Console drivers are called with interrupts disabled, so |
|---|
| 2599 | | - * @console_may_schedule should be cleared before; however, we may |
|---|
| 2600 | | - * end up dumping a lot of lines, for example, if called from |
|---|
| 2601 | | - * console registration path, and should invoke cond_resched() |
|---|
| 2602 | | - * between lines if allowable. Not doing so can cause a very long |
|---|
| 2603 | | - * scheduling stall on a slow console leading to RCU stall and |
|---|
| 2604 | | - * softlockup warnings which exacerbate the issue with more |
|---|
| 2605 | | - * messages practically incapacitating the system. |
|---|
| 2606 | | - * |
|---|
| 2607 | | - * console_trylock() is not able to detect the preemptive |
|---|
| 2608 | | - * context reliably. Therefore the value must be stored before |
|---|
| 2609 | | - * and cleared after the the "again" goto label. |
|---|
| 2610 | | - */ |
|---|
| 2611 | | - do_cond_resched = console_may_schedule; |
|---|
| 2612 | | -again: |
|---|
| 2613 | | - console_may_schedule = 0; |
|---|
| 2614 | | - |
|---|
| 2615 | | - /* |
|---|
| 2616 | | - * We released the console_sem lock, so we need to recheck if |
|---|
| 2617 | | - * cpu is online and (if not) is there at least one CON_ANYTIME |
|---|
| 2618 | | - * console. |
|---|
| 2619 | | - */ |
|---|
| 2620 | | - if (!can_use_console()) { |
|---|
| 2621 | | - console_locked = 0; |
|---|
| 2622 | | - up_console_sem(); |
|---|
| 2623 | | - return; |
|---|
| 2624 | | - } |
|---|
| 2625 | | - |
|---|
| 2626 | | - for (;;) { |
|---|
| 2627 | | - struct printk_log *msg; |
|---|
| 2628 | | - size_t ext_len = 0; |
|---|
| 2629 | | - size_t len; |
|---|
| 2630 | | - |
|---|
| 2631 | | - printk_safe_enter_irqsave(flags); |
|---|
| 2632 | | - raw_spin_lock(&logbuf_lock); |
|---|
| 2633 | | - if (console_seq < log_first_seq) { |
|---|
| 2634 | | - len = sprintf(text, |
|---|
| 2635 | | - "** %llu printk messages dropped **\n", |
|---|
| 2636 | | - log_first_seq - console_seq); |
|---|
| 2637 | | - |
|---|
| 2638 | | - /* messages are gone, move to first one */ |
|---|
| 2639 | | - console_seq = log_first_seq; |
|---|
| 2640 | | - console_idx = log_first_idx; |
|---|
| 2641 | | - } else { |
|---|
| 2642 | | - len = 0; |
|---|
| 2643 | | - } |
|---|
| 2644 | | -skip: |
|---|
| 2645 | | - if (console_seq == log_next_seq) |
|---|
| 2646 | | - break; |
|---|
| 2647 | | - |
|---|
| 2648 | | - msg = log_from_idx(console_idx); |
|---|
| 2649 | | - if (suppress_message_printing(msg->level)) { |
|---|
| 2650 | | - /* |
|---|
| 2651 | | - * Skip record we have buffered and already printed |
|---|
| 2652 | | - * directly to the console when we received it, and |
|---|
| 2653 | | - * record that has level above the console loglevel. |
|---|
| 2654 | | - */ |
|---|
| 2655 | | - console_idx = log_next(console_idx); |
|---|
| 2656 | | - console_seq++; |
|---|
| 2657 | | - goto skip; |
|---|
| 2658 | | - } |
|---|
| 2659 | | - |
|---|
| 2660 | | - /* Output to all consoles once old messages replayed. */ |
|---|
| 2661 | | - if (unlikely(exclusive_console && |
|---|
| 2662 | | - console_seq >= exclusive_console_stop_seq)) { |
|---|
| 2663 | | - exclusive_console = NULL; |
|---|
| 2664 | | - } |
|---|
| 2665 | | - |
|---|
| 2666 | | - len += msg_print_text(msg, |
|---|
| 2667 | | - console_msg_format & MSG_FORMAT_SYSLOG, |
|---|
| 2668 | | - text + len, |
|---|
| 2669 | | - sizeof(text) - len); |
|---|
| 2670 | | - if (nr_ext_console_drivers) { |
|---|
| 2671 | | - ext_len = msg_print_ext_header(ext_text, |
|---|
| 2672 | | - sizeof(ext_text), |
|---|
| 2673 | | - msg, console_seq); |
|---|
| 2674 | | - ext_len += msg_print_ext_body(ext_text + ext_len, |
|---|
| 2675 | | - sizeof(ext_text) - ext_len, |
|---|
| 2676 | | - log_dict(msg), msg->dict_len, |
|---|
| 2677 | | - log_text(msg), msg->text_len); |
|---|
| 2678 | | - } |
|---|
| 2679 | | - console_idx = log_next(console_idx); |
|---|
| 2680 | | - console_seq++; |
|---|
| 2681 | | - raw_spin_unlock(&logbuf_lock); |
|---|
| 2682 | | - |
|---|
| 2683 | | -#ifdef CONFIG_PREEMPT_RT_FULL |
|---|
| 2684 | | - printk_safe_exit_irqrestore(flags); |
|---|
| 2685 | | - call_console_drivers(ext_text, ext_len, text, len); |
|---|
| 2686 | | -#else |
|---|
| 2687 | | - /* |
|---|
| 2688 | | - * While actively printing out messages, if another printk() |
|---|
| 2689 | | - * were to occur on another CPU, it may wait for this one to |
|---|
| 2690 | | - * finish. This task can not be preempted if there is a |
|---|
| 2691 | | - * waiter waiting to take over. |
|---|
| 2692 | | - */ |
|---|
| 2693 | | - console_lock_spinning_enable(); |
|---|
| 2694 | | - |
|---|
| 2695 | | - stop_critical_timings(); /* don't trace print latency */ |
|---|
| 2696 | | -#ifdef CONFIG_PSTORE_CONSOLE_FORCE |
|---|
| 2697 | | - call_console_drivers_level(msg->level, ext_text, ext_len, text, len); |
|---|
| 2698 | | -#else |
|---|
| 2699 | | - call_console_drivers(ext_text, ext_len, text, len); |
|---|
| 2700 | | -#endif |
|---|
| 2701 | | - start_critical_timings(); |
|---|
| 2702 | | - |
|---|
| 2703 | | - if (console_lock_spinning_disable_and_check()) { |
|---|
| 2704 | | - printk_safe_exit_irqrestore(flags); |
|---|
| 2705 | | - return; |
|---|
| 2706 | | - } |
|---|
| 2707 | | - |
|---|
| 2708 | | - printk_safe_exit_irqrestore(flags); |
|---|
| 2709 | | -#endif |
|---|
| 2710 | | - |
|---|
| 2711 | | - if (do_cond_resched) |
|---|
| 2712 | | - cond_resched(); |
|---|
| 2713 | | - } |
|---|
| 2714 | | - |
|---|
| 2715 | 2587 | console_locked = 0; |
|---|
| 2716 | 2588 | |
|---|
| 2717 | | - raw_spin_unlock(&logbuf_lock); |
|---|
| 2718 | | - |
|---|
| 2719 | 2589 | up_console_sem(); |
|---|
| 2720 | | - |
|---|
| 2721 | | - /* |
|---|
| 2722 | | - * Someone could have filled up the buffer again, so re-check if there's |
|---|
| 2723 | | - * something to flush. In case we cannot trylock the console_sem again, |
|---|
| 2724 | | - * there's a new owner and the console_unlock() from them will do the |
|---|
| 2725 | | - * flush, no worries. |
|---|
| 2726 | | - */ |
|---|
| 2727 | | - raw_spin_lock(&logbuf_lock); |
|---|
| 2728 | | - retry = console_seq != log_next_seq; |
|---|
| 2729 | | - raw_spin_unlock(&logbuf_lock); |
|---|
| 2730 | | - printk_safe_exit_irqrestore(flags); |
|---|
| 2731 | | - |
|---|
| 2732 | | - if (retry && console_trylock()) |
|---|
| 2733 | | - goto again; |
|---|
| 2734 | 2590 | } |
|---|
| 2735 | 2591 | EXPORT_SYMBOL(console_unlock); |
|---|
| 2736 | 2592 | |
|---|
| .. | .. |
|---|
| 2754 | 2610 | { |
|---|
| 2755 | 2611 | struct console *c; |
|---|
| 2756 | 2612 | |
|---|
| 2757 | | - if (IS_ENABLED(CONFIG_PREEMPT_RT_BASE)) { |
|---|
| 2758 | | - if (in_irq() || in_nmi()) |
|---|
| 2759 | | - return; |
|---|
| 2760 | | - } |
|---|
| 2761 | | - |
|---|
| 2762 | 2613 | /* |
|---|
| 2763 | 2614 | * console_unblank can no longer be called in interrupt context unless |
|---|
| 2764 | 2615 | * oops_in_progress is set to 1.. |
|---|
| .. | .. |
|---|
| 2779 | 2630 | |
|---|
| 2780 | 2631 | /** |
|---|
| 2781 | 2632 | * console_flush_on_panic - flush console content on panic |
|---|
| 2633 | + * @mode: flush all messages in buffer or just the pending ones |
|---|
| 2782 | 2634 | * |
|---|
| 2783 | 2635 | * Immediately output all pending messages no matter what. |
|---|
| 2784 | 2636 | */ |
|---|
| 2785 | | -void console_flush_on_panic(void) |
|---|
| 2637 | +void console_flush_on_panic(enum con_flush_mode mode) |
|---|
| 2786 | 2638 | { |
|---|
| 2787 | | - /* |
|---|
| 2788 | | - * If someone else is holding the console lock, trylock will fail |
|---|
| 2789 | | - * and may_schedule may be set. Ignore and proceed to unlock so |
|---|
| 2790 | | - * that messages are flushed out. As this can be called from any |
|---|
| 2791 | | - * context and we don't want to get preempted while flushing, |
|---|
| 2792 | | - * ensure may_schedule is cleared. |
|---|
| 2793 | | - */ |
|---|
| 2794 | | - console_trylock(); |
|---|
| 2639 | + struct console *c; |
|---|
| 2640 | + u64 seq; |
|---|
| 2641 | + |
|---|
| 2642 | + if (!console_trylock()) |
|---|
| 2643 | + return; |
|---|
| 2644 | + |
|---|
| 2795 | 2645 | console_may_schedule = 0; |
|---|
| 2646 | + |
|---|
| 2647 | + if (mode == CONSOLE_REPLAY_ALL) { |
|---|
| 2648 | + seq = prb_first_valid_seq(prb); |
|---|
| 2649 | + for_each_console(c) |
|---|
| 2650 | + atomic64_set(&c->printk_seq, seq); |
|---|
| 2651 | + } |
|---|
| 2652 | + |
|---|
| 2796 | 2653 | console_unlock(); |
|---|
| 2797 | 2654 | } |
|---|
| 2798 | 2655 | |
|---|
| .. | .. |
|---|
| 2850 | 2707 | early_param("keep_bootcon", keep_bootcon_setup); |
|---|
| 2851 | 2708 | |
|---|
| 2852 | 2709 | /* |
|---|
| 2710 | + * This is called by register_console() to try to match |
|---|
| 2711 | + * the newly registered console with any of the ones selected |
|---|
| 2712 | + * by either the command line or add_preferred_console() and |
|---|
| 2713 | + * setup/enable it. |
|---|
| 2714 | + * |
|---|
| 2715 | + * Care need to be taken with consoles that are statically |
|---|
| 2716 | + * enabled such as netconsole |
|---|
| 2717 | + */ |
|---|
| 2718 | +static int try_enable_new_console(struct console *newcon, bool user_specified) |
|---|
| 2719 | +{ |
|---|
| 2720 | + struct console_cmdline *c; |
|---|
| 2721 | + int i, err; |
|---|
| 2722 | + |
|---|
| 2723 | + for (i = 0, c = console_cmdline; |
|---|
| 2724 | + i < MAX_CMDLINECONSOLES && c->name[0]; |
|---|
| 2725 | + i++, c++) { |
|---|
| 2726 | + if (c->user_specified != user_specified) |
|---|
| 2727 | + continue; |
|---|
| 2728 | + if (!newcon->match || |
|---|
| 2729 | + newcon->match(newcon, c->name, c->index, c->options) != 0) { |
|---|
| 2730 | + /* default matching */ |
|---|
| 2731 | + BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name)); |
|---|
| 2732 | + if (strcmp(c->name, newcon->name) != 0) |
|---|
| 2733 | + continue; |
|---|
| 2734 | + if (newcon->index >= 0 && |
|---|
| 2735 | + newcon->index != c->index) |
|---|
| 2736 | + continue; |
|---|
| 2737 | + if (newcon->index < 0) |
|---|
| 2738 | + newcon->index = c->index; |
|---|
| 2739 | + |
|---|
| 2740 | + if (_braille_register_console(newcon, c)) |
|---|
| 2741 | + return 0; |
|---|
| 2742 | + |
|---|
| 2743 | + if (newcon->setup && |
|---|
| 2744 | + (err = newcon->setup(newcon, c->options)) != 0) |
|---|
| 2745 | + return err; |
|---|
| 2746 | + } |
|---|
| 2747 | + newcon->flags |= CON_ENABLED; |
|---|
| 2748 | + if (i == preferred_console) { |
|---|
| 2749 | + newcon->flags |= CON_CONSDEV; |
|---|
| 2750 | + has_preferred_console = true; |
|---|
| 2751 | + } |
|---|
| 2752 | + return 0; |
|---|
| 2753 | + } |
|---|
| 2754 | + |
|---|
| 2755 | + /* |
|---|
| 2756 | + * Some consoles, such as pstore and netconsole, can be enabled even |
|---|
| 2757 | + * without matching. Accept the pre-enabled consoles only when match() |
|---|
| 2758 | + * and setup() had a chance to be called. |
|---|
| 2759 | + */ |
|---|
| 2760 | + if (newcon->flags & CON_ENABLED && c->user_specified == user_specified) |
|---|
| 2761 | + return 0; |
|---|
| 2762 | + |
|---|
| 2763 | + return -ENOENT; |
|---|
| 2764 | +} |
|---|
| 2765 | + |
|---|
| 2766 | +/* |
|---|
| 2853 | 2767 | * The console driver calls this routine during kernel initialization |
|---|
| 2854 | 2768 | * to register the console printing procedure with printk() and to |
|---|
| 2855 | 2769 | * print any messages that were printed by the kernel before the |
|---|
| .. | .. |
|---|
| 2870 | 2784 | */ |
|---|
| 2871 | 2785 | void register_console(struct console *newcon) |
|---|
| 2872 | 2786 | { |
|---|
| 2873 | | - int i; |
|---|
| 2874 | | - unsigned long flags; |
|---|
| 2875 | 2787 | struct console *bcon = NULL; |
|---|
| 2876 | | - struct console_cmdline *c; |
|---|
| 2877 | | - static bool has_preferred; |
|---|
| 2788 | + int err; |
|---|
| 2878 | 2789 | |
|---|
| 2879 | | - if (console_drivers) |
|---|
| 2880 | | - for_each_console(bcon) |
|---|
| 2881 | | - if (WARN(bcon == newcon, |
|---|
| 2882 | | - "console '%s%d' already registered\n", |
|---|
| 2883 | | - bcon->name, bcon->index)) |
|---|
| 2884 | | - return; |
|---|
| 2790 | + for_each_console(bcon) { |
|---|
| 2791 | + if (WARN(bcon == newcon, "console '%s%d' already registered\n", |
|---|
| 2792 | + bcon->name, bcon->index)) |
|---|
| 2793 | + return; |
|---|
| 2794 | + } |
|---|
| 2885 | 2795 | |
|---|
| 2886 | 2796 | /* |
|---|
| 2887 | 2797 | * before we register a new CON_BOOT console, make sure we don't |
|---|
| 2888 | 2798 | * already have a valid console |
|---|
| 2889 | 2799 | */ |
|---|
| 2890 | | - if (console_drivers && newcon->flags & CON_BOOT) { |
|---|
| 2891 | | - /* find the last or real console */ |
|---|
| 2800 | + if (newcon->flags & CON_BOOT) { |
|---|
| 2892 | 2801 | for_each_console(bcon) { |
|---|
| 2893 | 2802 | if (!(bcon->flags & CON_BOOT)) { |
|---|
| 2894 | 2803 | pr_info("Too late to register bootconsole %s%d\n", |
|---|
| .. | .. |
|---|
| 2898 | 2807 | } |
|---|
| 2899 | 2808 | } |
|---|
| 2900 | 2809 | |
|---|
| 2810 | + newcon->thread = NULL; |
|---|
| 2811 | + |
|---|
| 2901 | 2812 | if (console_drivers && console_drivers->flags & CON_BOOT) |
|---|
| 2902 | 2813 | bcon = console_drivers; |
|---|
| 2903 | 2814 | |
|---|
| 2904 | | - if (!has_preferred || bcon || !console_drivers) |
|---|
| 2905 | | - has_preferred = preferred_console >= 0; |
|---|
| 2815 | + if (!has_preferred_console || bcon || !console_drivers) |
|---|
| 2816 | + has_preferred_console = preferred_console >= 0; |
|---|
| 2906 | 2817 | |
|---|
| 2907 | 2818 | /* |
|---|
| 2908 | 2819 | * See if we want to use this console driver. If we |
|---|
| 2909 | 2820 | * didn't select a console we take the first one |
|---|
| 2910 | 2821 | * that registers here. |
|---|
| 2911 | 2822 | */ |
|---|
| 2912 | | - if (!has_preferred) { |
|---|
| 2823 | + if (!has_preferred_console) { |
|---|
| 2913 | 2824 | if (newcon->index < 0) |
|---|
| 2914 | 2825 | newcon->index = 0; |
|---|
| 2915 | 2826 | if (newcon->setup == NULL || |
|---|
| .. | .. |
|---|
| 2917 | 2828 | newcon->flags |= CON_ENABLED; |
|---|
| 2918 | 2829 | if (newcon->device) { |
|---|
| 2919 | 2830 | newcon->flags |= CON_CONSDEV; |
|---|
| 2920 | | - has_preferred = true; |
|---|
| 2831 | + has_preferred_console = true; |
|---|
| 2921 | 2832 | } |
|---|
| 2922 | 2833 | } |
|---|
| 2923 | 2834 | } |
|---|
| 2924 | 2835 | |
|---|
| 2925 | | - /* |
|---|
| 2926 | | - * See if this console matches one we selected on |
|---|
| 2927 | | - * the command line. |
|---|
| 2928 | | - */ |
|---|
| 2929 | | - for (i = 0, c = console_cmdline; |
|---|
| 2930 | | - i < MAX_CMDLINECONSOLES && c->name[0]; |
|---|
| 2931 | | - i++, c++) { |
|---|
| 2932 | | - if (!newcon->match || |
|---|
| 2933 | | - newcon->match(newcon, c->name, c->index, c->options) != 0) { |
|---|
| 2934 | | - /* default matching */ |
|---|
| 2935 | | - BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name)); |
|---|
| 2936 | | - if (strcmp(c->name, newcon->name) != 0) |
|---|
| 2937 | | - continue; |
|---|
| 2938 | | - if (newcon->index >= 0 && |
|---|
| 2939 | | - newcon->index != c->index) |
|---|
| 2940 | | - continue; |
|---|
| 2941 | | - if (newcon->index < 0) |
|---|
| 2942 | | - newcon->index = c->index; |
|---|
| 2836 | + /* See if this console matches one we selected on the command line */ |
|---|
| 2837 | + err = try_enable_new_console(newcon, true); |
|---|
| 2943 | 2838 | |
|---|
| 2944 | | - if (_braille_register_console(newcon, c)) |
|---|
| 2945 | | - return; |
|---|
| 2839 | + /* If not, try to match against the platform default(s) */ |
|---|
| 2840 | + if (err == -ENOENT) |
|---|
| 2841 | + err = try_enable_new_console(newcon, false); |
|---|
| 2946 | 2842 | |
|---|
| 2947 | | - if (newcon->setup && |
|---|
| 2948 | | - newcon->setup(newcon, c->options) != 0) |
|---|
| 2949 | | - break; |
|---|
| 2950 | | - } |
|---|
| 2951 | | - |
|---|
| 2952 | | - newcon->flags |= CON_ENABLED; |
|---|
| 2953 | | - if (i == preferred_console) { |
|---|
| 2954 | | - newcon->flags |= CON_CONSDEV; |
|---|
| 2955 | | - has_preferred = true; |
|---|
| 2956 | | - } |
|---|
| 2957 | | - break; |
|---|
| 2958 | | - } |
|---|
| 2959 | | - |
|---|
| 2960 | | - if (!(newcon->flags & CON_ENABLED)) |
|---|
| 2843 | + /* printk() messages are not printed to the Braille console. */ |
|---|
| 2844 | + if (err || newcon->flags & CON_BRL) |
|---|
| 2961 | 2845 | return; |
|---|
| 2962 | 2846 | |
|---|
| 2963 | 2847 | /* |
|---|
| .. | .. |
|---|
| 2966 | 2850 | * the real console are the same physical device, it's annoying to |
|---|
| 2967 | 2851 | * see the beginning boot messages twice |
|---|
| 2968 | 2852 | */ |
|---|
| 2969 | | - if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV)) |
|---|
| 2853 | + if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV)) { |
|---|
| 2970 | 2854 | newcon->flags &= ~CON_PRINTBUFFER; |
|---|
| 2855 | + newcon->flags |= CON_HANDOVER; |
|---|
| 2856 | + } |
|---|
| 2971 | 2857 | |
|---|
| 2972 | 2858 | /* |
|---|
| 2973 | 2859 | * Put this console in the list - keep the |
|---|
| .. | .. |
|---|
| 2979 | 2865 | console_drivers = newcon; |
|---|
| 2980 | 2866 | if (newcon->next) |
|---|
| 2981 | 2867 | newcon->next->flags &= ~CON_CONSDEV; |
|---|
| 2868 | + /* Ensure this flag is always set for the head of the list */ |
|---|
| 2869 | + newcon->flags |= CON_CONSDEV; |
|---|
| 2982 | 2870 | } else { |
|---|
| 2983 | 2871 | newcon->next = console_drivers->next; |
|---|
| 2984 | 2872 | console_drivers->next = newcon; |
|---|
| 2985 | 2873 | } |
|---|
| 2986 | 2874 | |
|---|
| 2987 | 2875 | if (newcon->flags & CON_EXTENDED) |
|---|
| 2988 | | - if (!nr_ext_console_drivers++) |
|---|
| 2989 | | - pr_info("printk: continuation disabled due to ext consoles, expect more fragments in /dev/kmsg\n"); |
|---|
| 2876 | + nr_ext_console_drivers++; |
|---|
| 2990 | 2877 | |
|---|
| 2991 | | - if (newcon->flags & CON_PRINTBUFFER) { |
|---|
| 2992 | | - /* |
|---|
| 2993 | | - * console_unlock(); will print out the buffered messages |
|---|
| 2994 | | - * for us. |
|---|
| 2995 | | - */ |
|---|
| 2996 | | - logbuf_lock_irqsave(flags); |
|---|
| 2997 | | - /* |
|---|
| 2998 | | - * We're about to replay the log buffer. Only do this to the |
|---|
| 2999 | | - * just-registered console to avoid excessive message spam to |
|---|
| 3000 | | - * the already-registered consoles. |
|---|
| 3001 | | - * |
|---|
| 3002 | | - * Set exclusive_console with disabled interrupts to reduce |
|---|
| 3003 | | - * race window with eventual console_flush_on_panic() that |
|---|
| 3004 | | - * ignores console_lock. |
|---|
| 3005 | | - */ |
|---|
| 3006 | | - exclusive_console = newcon; |
|---|
| 3007 | | - exclusive_console_stop_seq = console_seq; |
|---|
| 3008 | | - console_seq = syslog_seq; |
|---|
| 3009 | | - console_idx = syslog_idx; |
|---|
| 3010 | | - logbuf_unlock_irqrestore(flags); |
|---|
| 3011 | | - } |
|---|
| 2878 | + if (newcon->flags & CON_PRINTBUFFER) |
|---|
| 2879 | + atomic64_set(&newcon->printk_seq, 0); |
|---|
| 2880 | + else |
|---|
| 2881 | + atomic64_set(&newcon->printk_seq, prb_next_seq(prb)); |
|---|
| 2882 | + |
|---|
| 2883 | + console_try_thread(newcon); |
|---|
| 3012 | 2884 | console_unlock(); |
|---|
| 3013 | 2885 | console_sysfs_notify(); |
|---|
| 3014 | 2886 | |
|---|
| .. | .. |
|---|
| 3037 | 2909 | |
|---|
| 3038 | 2910 | int unregister_console(struct console *console) |
|---|
| 3039 | 2911 | { |
|---|
| 3040 | | - struct console *a, *b; |
|---|
| 2912 | + struct console *con; |
|---|
| 3041 | 2913 | int res; |
|---|
| 3042 | 2914 | |
|---|
| 3043 | 2915 | pr_info("%sconsole [%s%d] disabled\n", |
|---|
| .. | .. |
|---|
| 3045 | 2917 | console->name, console->index); |
|---|
| 3046 | 2918 | |
|---|
| 3047 | 2919 | res = _braille_unregister_console(console); |
|---|
| 3048 | | - if (res) |
|---|
| 2920 | + if (res < 0) |
|---|
| 3049 | 2921 | return res; |
|---|
| 2922 | + if (res > 0) |
|---|
| 2923 | + return 0; |
|---|
| 3050 | 2924 | |
|---|
| 3051 | | - res = 1; |
|---|
| 2925 | + res = -ENODEV; |
|---|
| 3052 | 2926 | console_lock(); |
|---|
| 3053 | 2927 | if (console_drivers == console) { |
|---|
| 3054 | 2928 | console_drivers=console->next; |
|---|
| 3055 | 2929 | res = 0; |
|---|
| 3056 | | - } else if (console_drivers) { |
|---|
| 3057 | | - for (a=console_drivers->next, b=console_drivers ; |
|---|
| 3058 | | - a; b=a, a=b->next) { |
|---|
| 3059 | | - if (a == console) { |
|---|
| 3060 | | - b->next = a->next; |
|---|
| 2930 | + } else { |
|---|
| 2931 | + for_each_console(con) { |
|---|
| 2932 | + if (con->next == console) { |
|---|
| 2933 | + con->next = console->next; |
|---|
| 3061 | 2934 | res = 0; |
|---|
| 3062 | 2935 | break; |
|---|
| 3063 | 2936 | } |
|---|
| 3064 | 2937 | } |
|---|
| 3065 | 2938 | } |
|---|
| 3066 | 2939 | |
|---|
| 3067 | | - if (!res && (console->flags & CON_EXTENDED)) |
|---|
| 2940 | + if (res) |
|---|
| 2941 | + goto out_disable_unlock; |
|---|
| 2942 | + |
|---|
| 2943 | + if (console->flags & CON_EXTENDED) |
|---|
| 3068 | 2944 | nr_ext_console_drivers--; |
|---|
| 3069 | 2945 | |
|---|
| 3070 | 2946 | /* |
|---|
| .. | .. |
|---|
| 3077 | 2953 | console->flags &= ~CON_ENABLED; |
|---|
| 3078 | 2954 | console_unlock(); |
|---|
| 3079 | 2955 | console_sysfs_notify(); |
|---|
| 2956 | + |
|---|
| 2957 | + if (console->thread && !IS_ERR(console->thread)) |
|---|
| 2958 | + kthread_stop(console->thread); |
|---|
| 2959 | + |
|---|
| 2960 | + if (console->exit) |
|---|
| 2961 | + res = console->exit(console); |
|---|
| 2962 | + |
|---|
| 2963 | + return res; |
|---|
| 2964 | + |
|---|
| 2965 | +out_disable_unlock: |
|---|
| 2966 | + console->flags &= ~CON_ENABLED; |
|---|
| 2967 | + console_unlock(); |
|---|
| 2968 | + |
|---|
| 3080 | 2969 | return res; |
|---|
| 3081 | 2970 | } |
|---|
| 3082 | 2971 | EXPORT_SYMBOL(unregister_console); |
|---|
| .. | .. |
|---|
| 3150 | 3039 | unregister_console(con); |
|---|
| 3151 | 3040 | } |
|---|
| 3152 | 3041 | } |
|---|
| 3042 | + |
|---|
| 3043 | +#ifdef CONFIG_PRINTK |
|---|
| 3044 | + console_lock(); |
|---|
| 3045 | + for_each_console(con) |
|---|
| 3046 | + start_printk_kthread(con); |
|---|
| 3047 | + kthreads_started = true; |
|---|
| 3048 | + console_unlock(); |
|---|
| 3049 | +#endif |
|---|
| 3050 | + |
|---|
| 3153 | 3051 | ret = cpuhp_setup_state_nocalls(CPUHP_PRINTK_DEAD, "printk:dead", NULL, |
|---|
| 3154 | 3052 | console_cpu_notify); |
|---|
| 3155 | 3053 | WARN_ON(ret < 0); |
|---|
| .. | .. |
|---|
| 3165 | 3063 | * Delayed printk version, for scheduler-internal messages: |
|---|
| 3166 | 3064 | */ |
|---|
| 3167 | 3065 | #define PRINTK_PENDING_WAKEUP 0x01 |
|---|
| 3168 | | -#define PRINTK_PENDING_OUTPUT 0x02 |
|---|
| 3169 | 3066 | |
|---|
| 3170 | 3067 | static DEFINE_PER_CPU(int, printk_pending); |
|---|
| 3171 | 3068 | |
|---|
| .. | .. |
|---|
| 3173 | 3070 | { |
|---|
| 3174 | 3071 | int pending = __this_cpu_xchg(printk_pending, 0); |
|---|
| 3175 | 3072 | |
|---|
| 3176 | | - if (pending & PRINTK_PENDING_OUTPUT) { |
|---|
| 3177 | | - /* If trylock fails, someone else is doing the printing */ |
|---|
| 3178 | | - if (console_trylock()) |
|---|
| 3179 | | - console_unlock(); |
|---|
| 3180 | | - } |
|---|
| 3181 | | - |
|---|
| 3182 | 3073 | if (pending & PRINTK_PENDING_WAKEUP) |
|---|
| 3183 | | - wake_up_interruptible(&log_wait); |
|---|
| 3074 | + wake_up_interruptible_all(&log_wait); |
|---|
| 3184 | 3075 | } |
|---|
| 3185 | 3076 | |
|---|
| 3186 | 3077 | static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = { |
|---|
| 3187 | 3078 | .func = wake_up_klogd_work_func, |
|---|
| 3188 | | - .flags = IRQ_WORK_LAZY, |
|---|
| 3079 | + .flags = ATOMIC_INIT(IRQ_WORK_LAZY), |
|---|
| 3189 | 3080 | }; |
|---|
| 3190 | 3081 | |
|---|
| 3191 | 3082 | void wake_up_klogd(void) |
|---|
| .. | .. |
|---|
| 3201 | 3092 | preempt_enable(); |
|---|
| 3202 | 3093 | } |
|---|
| 3203 | 3094 | |
|---|
| 3204 | | -void defer_console_output(void) |
|---|
| 3095 | +__printf(1, 0) |
|---|
| 3096 | +static int vprintk_deferred(const char *fmt, va_list args) |
|---|
| 3205 | 3097 | { |
|---|
| 3206 | | - if (!printk_percpu_data_ready()) |
|---|
| 3207 | | - return; |
|---|
| 3208 | | - |
|---|
| 3209 | | - preempt_disable(); |
|---|
| 3210 | | - __this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT); |
|---|
| 3211 | | - irq_work_queue(this_cpu_ptr(&wake_up_klogd_work)); |
|---|
| 3212 | | - preempt_enable(); |
|---|
| 3213 | | -} |
|---|
| 3214 | | - |
|---|
| 3215 | | -int vprintk_deferred(const char *fmt, va_list args) |
|---|
| 3216 | | -{ |
|---|
| 3217 | | - int r; |
|---|
| 3218 | | - |
|---|
| 3219 | | - r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, 0, fmt, args); |
|---|
| 3220 | | - defer_console_output(); |
|---|
| 3221 | | - |
|---|
| 3222 | | - return r; |
|---|
| 3098 | + return vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, fmt, args); |
|---|
| 3223 | 3099 | } |
|---|
| 3224 | 3100 | |
|---|
| 3225 | 3101 | int printk_deferred(const char *fmt, ...) |
|---|
| .. | .. |
|---|
| 3233 | 3109 | |
|---|
| 3234 | 3110 | return r; |
|---|
| 3235 | 3111 | } |
|---|
| 3112 | +EXPORT_SYMBOL_GPL(printk_deferred); |
|---|
| 3236 | 3113 | |
|---|
| 3237 | 3114 | /* |
|---|
| 3238 | 3115 | * printk rate limiting, lifted from the networking subsystem. |
|---|
| .. | .. |
|---|
| 3331 | 3208 | static bool always_kmsg_dump; |
|---|
| 3332 | 3209 | module_param_named(always_kmsg_dump, always_kmsg_dump, bool, S_IRUGO | S_IWUSR); |
|---|
| 3333 | 3210 | |
|---|
| 3211 | +const char *kmsg_dump_reason_str(enum kmsg_dump_reason reason) |
|---|
| 3212 | +{ |
|---|
| 3213 | + switch (reason) { |
|---|
| 3214 | + case KMSG_DUMP_PANIC: |
|---|
| 3215 | + return "Panic"; |
|---|
| 3216 | + case KMSG_DUMP_OOPS: |
|---|
| 3217 | + return "Oops"; |
|---|
| 3218 | + case KMSG_DUMP_EMERG: |
|---|
| 3219 | + return "Emergency"; |
|---|
| 3220 | + case KMSG_DUMP_SHUTDOWN: |
|---|
| 3221 | + return "Shutdown"; |
|---|
| 3222 | + default: |
|---|
| 3223 | + return "Unknown"; |
|---|
| 3224 | + } |
|---|
| 3225 | +} |
|---|
| 3226 | +EXPORT_SYMBOL_GPL(kmsg_dump_reason_str); |
|---|
| 3227 | + |
|---|
| 3334 | 3228 | /** |
|---|
| 3335 | 3229 | * kmsg_dump - dump kernel log to kernel message dumpers. |
|---|
| 3336 | 3230 | * @reason: the reason (oops, panic etc) for dumping |
|---|
| .. | .. |
|---|
| 3341 | 3235 | */ |
|---|
| 3342 | 3236 | void kmsg_dump(enum kmsg_dump_reason reason) |
|---|
| 3343 | 3237 | { |
|---|
| 3238 | + struct kmsg_dumper_iter iter; |
|---|
| 3344 | 3239 | struct kmsg_dumper *dumper; |
|---|
| 3345 | | - unsigned long flags; |
|---|
| 3346 | 3240 | |
|---|
| 3347 | | - if ((reason > KMSG_DUMP_OOPS) && !always_kmsg_dump) |
|---|
| 3348 | | - return; |
|---|
| 3241 | + if (!oops_in_progress) { |
|---|
| 3242 | + /* |
|---|
| 3243 | + * If atomic consoles are available, activate kernel sync mode |
|---|
| 3244 | + * to make sure any final messages are visible. The trailing |
|---|
| 3245 | + * printk message is important to flush any pending messages. |
|---|
| 3246 | + */ |
|---|
| 3247 | + if (have_atomic_console()) { |
|---|
| 3248 | + sync_mode = true; |
|---|
| 3249 | + pr_info("enabled sync mode\n"); |
|---|
| 3250 | + } |
|---|
| 3251 | + |
|---|
| 3252 | + /* |
|---|
| 3253 | + * Give the printing threads time to flush, allowing up to |
|---|
| 3254 | + * 1s of no printing forward progress before giving up. |
|---|
| 3255 | + */ |
|---|
| 3256 | + pr_flush(1000, true); |
|---|
| 3257 | + } |
|---|
| 3349 | 3258 | |
|---|
| 3350 | 3259 | rcu_read_lock(); |
|---|
| 3351 | 3260 | list_for_each_entry_rcu(dumper, &dump_list, list) { |
|---|
| 3352 | | - if (dumper->max_reason && reason > dumper->max_reason) |
|---|
| 3261 | + enum kmsg_dump_reason max_reason = dumper->max_reason; |
|---|
| 3262 | + |
|---|
| 3263 | + /* |
|---|
| 3264 | + * If client has not provided a specific max_reason, default |
|---|
| 3265 | + * to KMSG_DUMP_OOPS, unless always_kmsg_dump was set. |
|---|
| 3266 | + */ |
|---|
| 3267 | + if (max_reason == KMSG_DUMP_UNDEF) { |
|---|
| 3268 | + max_reason = always_kmsg_dump ? KMSG_DUMP_MAX : |
|---|
| 3269 | + KMSG_DUMP_OOPS; |
|---|
| 3270 | + } |
|---|
| 3271 | + if (reason > max_reason) |
|---|
| 3353 | 3272 | continue; |
|---|
| 3354 | 3273 | |
|---|
| 3355 | 3274 | /* initialize iterator with data about the stored records */ |
|---|
| 3356 | | - dumper->active = true; |
|---|
| 3357 | | - |
|---|
| 3358 | | - logbuf_lock_irqsave(flags); |
|---|
| 3359 | | - dumper->cur_seq = clear_seq; |
|---|
| 3360 | | - dumper->cur_idx = clear_idx; |
|---|
| 3361 | | - dumper->next_seq = log_next_seq; |
|---|
| 3362 | | - dumper->next_idx = log_next_idx; |
|---|
| 3363 | | - logbuf_unlock_irqrestore(flags); |
|---|
| 3275 | + iter.active = true; |
|---|
| 3276 | + kmsg_dump_rewind(&iter); |
|---|
| 3364 | 3277 | |
|---|
| 3365 | 3278 | /* invoke dumper which will iterate over records */ |
|---|
| 3366 | | - dumper->dump(dumper, reason); |
|---|
| 3367 | | - |
|---|
| 3368 | | - /* reset iterator */ |
|---|
| 3369 | | - dumper->active = false; |
|---|
| 3279 | + dumper->dump(dumper, reason, &iter); |
|---|
| 3370 | 3280 | } |
|---|
| 3371 | 3281 | rcu_read_unlock(); |
|---|
| 3372 | 3282 | } |
|---|
| 3373 | 3283 | |
|---|
| 3374 | 3284 | /** |
|---|
| 3375 | | - * kmsg_dump_get_line_nolock - retrieve one kmsg log line (unlocked version) |
|---|
| 3376 | | - * @dumper: registered kmsg dumper |
|---|
| 3285 | + * kmsg_dump_get_line - retrieve one kmsg log line |
|---|
| 3286 | + * @iter: kmsg dumper iterator |
|---|
| 3377 | 3287 | * @syslog: include the "<4>" prefixes |
|---|
| 3378 | 3288 | * @line: buffer to copy the line to |
|---|
| 3379 | 3289 | * @size: maximum size of the buffer |
|---|
| .. | .. |
|---|
| 3387 | 3297 | * |
|---|
| 3388 | 3298 | * A return value of FALSE indicates that there are no more records to |
|---|
| 3389 | 3299 | * read. |
|---|
| 3390 | | - * |
|---|
| 3391 | | - * The function is similar to kmsg_dump_get_line(), but grabs no locks. |
|---|
| 3392 | 3300 | */ |
|---|
| 3393 | | -bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog, |
|---|
| 3394 | | - char *line, size_t size, size_t *len) |
|---|
| 3301 | +bool kmsg_dump_get_line(struct kmsg_dumper_iter *iter, bool syslog, |
|---|
| 3302 | + char *line, size_t size, size_t *len) |
|---|
| 3395 | 3303 | { |
|---|
| 3396 | | - struct printk_log *msg; |
|---|
| 3304 | + struct printk_info info; |
|---|
| 3305 | + unsigned int line_count; |
|---|
| 3306 | + struct printk_record r; |
|---|
| 3397 | 3307 | size_t l = 0; |
|---|
| 3398 | 3308 | bool ret = false; |
|---|
| 3399 | 3309 | |
|---|
| 3400 | | - if (!dumper->active) |
|---|
| 3310 | + prb_rec_init_rd(&r, &info, line, size); |
|---|
| 3311 | + |
|---|
| 3312 | + if (!iter->active) |
|---|
| 3401 | 3313 | goto out; |
|---|
| 3402 | 3314 | |
|---|
| 3403 | | - if (dumper->cur_seq < log_first_seq) { |
|---|
| 3404 | | - /* messages are gone, move to first available one */ |
|---|
| 3405 | | - dumper->cur_seq = log_first_seq; |
|---|
| 3406 | | - dumper->cur_idx = log_first_idx; |
|---|
| 3315 | + /* Read text or count text lines? */ |
|---|
| 3316 | + if (line) { |
|---|
| 3317 | + if (!prb_read_valid(prb, iter->cur_seq, &r)) |
|---|
| 3318 | + goto out; |
|---|
| 3319 | + l = record_print_text(&r, syslog, printk_time); |
|---|
| 3320 | + } else { |
|---|
| 3321 | + if (!prb_read_valid_info(prb, iter->cur_seq, |
|---|
| 3322 | + &info, &line_count)) { |
|---|
| 3323 | + goto out; |
|---|
| 3324 | + } |
|---|
| 3325 | + l = get_record_print_text_size(&info, line_count, syslog, |
|---|
| 3326 | + printk_time); |
|---|
| 3327 | + |
|---|
| 3407 | 3328 | } |
|---|
| 3408 | 3329 | |
|---|
| 3409 | | - /* last entry */ |
|---|
| 3410 | | - if (dumper->cur_seq >= log_next_seq) |
|---|
| 3411 | | - goto out; |
|---|
| 3412 | | - |
|---|
| 3413 | | - msg = log_from_idx(dumper->cur_idx); |
|---|
| 3414 | | - l = msg_print_text(msg, syslog, line, size); |
|---|
| 3415 | | - |
|---|
| 3416 | | - dumper->cur_idx = log_next(dumper->cur_idx); |
|---|
| 3417 | | - dumper->cur_seq++; |
|---|
| 3330 | + iter->cur_seq = r.info->seq + 1; |
|---|
| 3418 | 3331 | ret = true; |
|---|
| 3419 | 3332 | out: |
|---|
| 3420 | 3333 | if (len) |
|---|
| 3421 | 3334 | *len = l; |
|---|
| 3422 | 3335 | return ret; |
|---|
| 3423 | 3336 | } |
|---|
| 3424 | | - |
|---|
| 3425 | | -/** |
|---|
| 3426 | | - * kmsg_dump_get_line - retrieve one kmsg log line |
|---|
| 3427 | | - * @dumper: registered kmsg dumper |
|---|
| 3428 | | - * @syslog: include the "<4>" prefixes |
|---|
| 3429 | | - * @line: buffer to copy the line to |
|---|
| 3430 | | - * @size: maximum size of the buffer |
|---|
| 3431 | | - * @len: length of line placed into buffer |
|---|
| 3432 | | - * |
|---|
| 3433 | | - * Start at the beginning of the kmsg buffer, with the oldest kmsg |
|---|
| 3434 | | - * record, and copy one record into the provided buffer. |
|---|
| 3435 | | - * |
|---|
| 3436 | | - * Consecutive calls will return the next available record moving |
|---|
| 3437 | | - * towards the end of the buffer with the youngest messages. |
|---|
| 3438 | | - * |
|---|
| 3439 | | - * A return value of FALSE indicates that there are no more records to |
|---|
| 3440 | | - * read. |
|---|
| 3441 | | - */ |
|---|
| 3442 | | -bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, |
|---|
| 3443 | | - char *line, size_t size, size_t *len) |
|---|
| 3444 | | -{ |
|---|
| 3445 | | - unsigned long flags; |
|---|
| 3446 | | - bool ret; |
|---|
| 3447 | | - |
|---|
| 3448 | | - logbuf_lock_irqsave(flags); |
|---|
| 3449 | | - ret = kmsg_dump_get_line_nolock(dumper, syslog, line, size, len); |
|---|
| 3450 | | - logbuf_unlock_irqrestore(flags); |
|---|
| 3451 | | - |
|---|
| 3452 | | - return ret; |
|---|
| 3453 | | -} |
|---|
| 3454 | 3337 | EXPORT_SYMBOL_GPL(kmsg_dump_get_line); |
|---|
| 3455 | 3338 | |
|---|
| 3456 | 3339 | /** |
|---|
| 3457 | 3340 | * kmsg_dump_get_buffer - copy kmsg log lines |
|---|
| 3458 | | - * @dumper: registered kmsg dumper |
|---|
| 3341 | + * @iter: kmsg dumper iterator |
|---|
| 3459 | 3342 | * @syslog: include the "<4>" prefixes |
|---|
| 3460 | 3343 | * @buf: buffer to copy the line to |
|---|
| 3461 | 3344 | * @size: maximum size of the buffer |
|---|
| 3462 | 3345 | * @len: length of line placed into buffer |
|---|
| 3463 | 3346 | * |
|---|
| 3464 | 3347 | * Start at the end of the kmsg buffer and fill the provided buffer |
|---|
| 3465 | | - * with as many of the the *youngest* kmsg records that fit into it. |
|---|
| 3348 | + * with as many of the *youngest* kmsg records that fit into it. |
|---|
| 3466 | 3349 | * If the buffer is large enough, all available kmsg records will be |
|---|
| 3467 | 3350 | * copied with a single call. |
|---|
| 3468 | 3351 | * |
|---|
| .. | .. |
|---|
| 3472 | 3355 | * A return value of FALSE indicates that there are no more records to |
|---|
| 3473 | 3356 | * read. |
|---|
| 3474 | 3357 | */ |
|---|
| 3475 | | -bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, |
|---|
| 3476 | | - char *buf, size_t size, size_t *len) |
|---|
| 3358 | +bool kmsg_dump_get_buffer(struct kmsg_dumper_iter *iter, bool syslog, |
|---|
| 3359 | + char *buf, size_t size, size_t *len_out) |
|---|
| 3477 | 3360 | { |
|---|
| 3478 | | - unsigned long flags; |
|---|
| 3361 | + struct printk_info info; |
|---|
| 3362 | + struct printk_record r; |
|---|
| 3479 | 3363 | u64 seq; |
|---|
| 3480 | | - u32 idx; |
|---|
| 3481 | 3364 | u64 next_seq; |
|---|
| 3482 | | - u32 next_idx; |
|---|
| 3483 | | - size_t l = 0; |
|---|
| 3365 | + size_t len = 0; |
|---|
| 3484 | 3366 | bool ret = false; |
|---|
| 3367 | + bool time = printk_time; |
|---|
| 3485 | 3368 | |
|---|
| 3486 | | - if (!dumper->active) |
|---|
| 3369 | + if (!iter->active || !buf || !size) |
|---|
| 3487 | 3370 | goto out; |
|---|
| 3488 | 3371 | |
|---|
| 3489 | | - logbuf_lock_irqsave(flags); |
|---|
| 3490 | | - if (dumper->cur_seq < log_first_seq) { |
|---|
| 3491 | | - /* messages are gone, move to first available one */ |
|---|
| 3492 | | - dumper->cur_seq = log_first_seq; |
|---|
| 3493 | | - dumper->cur_idx = log_first_idx; |
|---|
| 3372 | + if (prb_read_valid_info(prb, iter->cur_seq, &info, NULL)) { |
|---|
| 3373 | + if (info.seq != iter->cur_seq) { |
|---|
| 3374 | + /* messages are gone, move to first available one */ |
|---|
| 3375 | + iter->cur_seq = info.seq; |
|---|
| 3376 | + } |
|---|
| 3494 | 3377 | } |
|---|
| 3495 | 3378 | |
|---|
| 3496 | 3379 | /* last entry */ |
|---|
| 3497 | | - if (dumper->cur_seq >= dumper->next_seq) { |
|---|
| 3498 | | - logbuf_unlock_irqrestore(flags); |
|---|
| 3380 | + if (iter->cur_seq >= iter->next_seq) |
|---|
| 3499 | 3381 | goto out; |
|---|
| 3500 | | - } |
|---|
| 3501 | 3382 | |
|---|
| 3502 | | - /* calculate length of entire buffer */ |
|---|
| 3503 | | - seq = dumper->cur_seq; |
|---|
| 3504 | | - idx = dumper->cur_idx; |
|---|
| 3505 | | - while (seq < dumper->next_seq) { |
|---|
| 3506 | | - struct printk_log *msg = log_from_idx(idx); |
|---|
| 3383 | + /* |
|---|
| 3384 | + * Find first record that fits, including all following records, |
|---|
| 3385 | + * into the user-provided buffer for this dump. Pass in size-1 |
|---|
| 3386 | + * because this function (by way of record_print_text()) will |
|---|
| 3387 | + * not write more than size-1 bytes of text into @buf. |
|---|
| 3388 | + */ |
|---|
| 3389 | + seq = find_first_fitting_seq(iter->cur_seq, iter->next_seq, |
|---|
| 3390 | + size - 1, syslog, time); |
|---|
| 3507 | 3391 | |
|---|
| 3508 | | - l += msg_print_text(msg, true, NULL, 0); |
|---|
| 3509 | | - idx = log_next(idx); |
|---|
| 3510 | | - seq++; |
|---|
| 3511 | | - } |
|---|
| 3512 | | - |
|---|
| 3513 | | - /* move first record forward until length fits into the buffer */ |
|---|
| 3514 | | - seq = dumper->cur_seq; |
|---|
| 3515 | | - idx = dumper->cur_idx; |
|---|
| 3516 | | - while (l >= size && seq < dumper->next_seq) { |
|---|
| 3517 | | - struct printk_log *msg = log_from_idx(idx); |
|---|
| 3518 | | - |
|---|
| 3519 | | - l -= msg_print_text(msg, true, NULL, 0); |
|---|
| 3520 | | - idx = log_next(idx); |
|---|
| 3521 | | - seq++; |
|---|
| 3522 | | - } |
|---|
| 3523 | | - |
|---|
| 3524 | | - /* last message in next interation */ |
|---|
| 3392 | + /* |
|---|
| 3393 | + * Next kmsg_dump_get_buffer() invocation will dump block of |
|---|
| 3394 | + * older records stored right before this one. |
|---|
| 3395 | + */ |
|---|
| 3525 | 3396 | next_seq = seq; |
|---|
| 3526 | | - next_idx = idx; |
|---|
| 3527 | 3397 | |
|---|
| 3528 | | - l = 0; |
|---|
| 3529 | | - while (seq < dumper->next_seq) { |
|---|
| 3530 | | - struct printk_log *msg = log_from_idx(idx); |
|---|
| 3398 | + prb_rec_init_rd(&r, &info, buf, size); |
|---|
| 3531 | 3399 | |
|---|
| 3532 | | - l += msg_print_text(msg, syslog, buf + l, size - l); |
|---|
| 3533 | | - idx = log_next(idx); |
|---|
| 3534 | | - seq++; |
|---|
| 3400 | + len = 0; |
|---|
| 3401 | + prb_for_each_record(seq, prb, seq, &r) { |
|---|
| 3402 | + if (r.info->seq >= iter->next_seq) |
|---|
| 3403 | + break; |
|---|
| 3404 | + |
|---|
| 3405 | + len += record_print_text(&r, syslog, time); |
|---|
| 3406 | + |
|---|
| 3407 | + /* Adjust record to store to remaining buffer space. */ |
|---|
| 3408 | + prb_rec_init_rd(&r, &info, buf + len, size - len); |
|---|
| 3535 | 3409 | } |
|---|
| 3536 | 3410 | |
|---|
| 3537 | | - dumper->next_seq = next_seq; |
|---|
| 3538 | | - dumper->next_idx = next_idx; |
|---|
| 3411 | + iter->next_seq = next_seq; |
|---|
| 3539 | 3412 | ret = true; |
|---|
| 3540 | | - logbuf_unlock_irqrestore(flags); |
|---|
| 3541 | 3413 | out: |
|---|
| 3542 | | - if (len) |
|---|
| 3543 | | - *len = l; |
|---|
| 3414 | + if (len_out) |
|---|
| 3415 | + *len_out = len; |
|---|
| 3544 | 3416 | return ret; |
|---|
| 3545 | 3417 | } |
|---|
| 3546 | 3418 | EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); |
|---|
| 3547 | 3419 | |
|---|
| 3548 | 3420 | /** |
|---|
| 3549 | | - * kmsg_dump_rewind_nolock - reset the interator (unlocked version) |
|---|
| 3550 | | - * @dumper: registered kmsg dumper |
|---|
| 3551 | | - * |
|---|
| 3552 | | - * Reset the dumper's iterator so that kmsg_dump_get_line() and |
|---|
| 3553 | | - * kmsg_dump_get_buffer() can be called again and used multiple |
|---|
| 3554 | | - * times within the same dumper.dump() callback. |
|---|
| 3555 | | - * |
|---|
| 3556 | | - * The function is similar to kmsg_dump_rewind(), but grabs no locks. |
|---|
| 3557 | | - */ |
|---|
| 3558 | | -void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper) |
|---|
| 3559 | | -{ |
|---|
| 3560 | | - dumper->cur_seq = clear_seq; |
|---|
| 3561 | | - dumper->cur_idx = clear_idx; |
|---|
| 3562 | | - dumper->next_seq = log_next_seq; |
|---|
| 3563 | | - dumper->next_idx = log_next_idx; |
|---|
| 3564 | | -} |
|---|
| 3565 | | - |
|---|
| 3566 | | -/** |
|---|
| 3567 | | - * kmsg_dump_rewind - reset the interator |
|---|
| 3568 | | - * @dumper: registered kmsg dumper |
|---|
| 3421 | + * kmsg_dump_rewind - reset the iterator |
|---|
| 3422 | + * @iter: kmsg dumper iterator |
|---|
| 3569 | 3423 | * |
|---|
| 3570 | 3424 | * Reset the dumper's iterator so that kmsg_dump_get_line() and |
|---|
| 3571 | 3425 | * kmsg_dump_get_buffer() can be called again and used multiple |
|---|
| 3572 | 3426 | * times within the same dumper.dump() callback. |
|---|
| 3573 | 3427 | */ |
|---|
| 3574 | | -void kmsg_dump_rewind(struct kmsg_dumper *dumper) |
|---|
| 3428 | +void kmsg_dump_rewind(struct kmsg_dumper_iter *iter) |
|---|
| 3575 | 3429 | { |
|---|
| 3576 | | - unsigned long flags; |
|---|
| 3577 | | - |
|---|
| 3578 | | - logbuf_lock_irqsave(flags); |
|---|
| 3579 | | - kmsg_dump_rewind_nolock(dumper); |
|---|
| 3580 | | - logbuf_unlock_irqrestore(flags); |
|---|
| 3430 | + iter->cur_seq = latched_seq_read_nolock(&clear_seq); |
|---|
| 3431 | + iter->next_seq = prb_next_seq(prb); |
|---|
| 3581 | 3432 | } |
|---|
| 3582 | 3433 | EXPORT_SYMBOL_GPL(kmsg_dump_rewind); |
|---|
| 3583 | 3434 | |
|---|
| 3584 | 3435 | #endif |
|---|
| 3436 | + |
|---|
| 3437 | +struct prb_cpulock { |
|---|
| 3438 | + atomic_t owner; |
|---|
| 3439 | + unsigned long __percpu *irqflags; |
|---|
| 3440 | +}; |
|---|
| 3441 | + |
|---|
| 3442 | +#define DECLARE_STATIC_PRINTKRB_CPULOCK(name) \ |
|---|
| 3443 | +static DEFINE_PER_CPU(unsigned long, _##name##_percpu_irqflags); \ |
|---|
| 3444 | +static struct prb_cpulock name = { \ |
|---|
| 3445 | + .owner = ATOMIC_INIT(-1), \ |
|---|
| 3446 | + .irqflags = &_##name##_percpu_irqflags, \ |
|---|
| 3447 | +} |
|---|
| 3448 | + |
|---|
| 3449 | +static bool __prb_trylock(struct prb_cpulock *cpu_lock, |
|---|
| 3450 | + unsigned int *cpu_store) |
|---|
| 3451 | +{ |
|---|
| 3452 | + unsigned long *flags; |
|---|
| 3453 | + unsigned int cpu; |
|---|
| 3454 | + |
|---|
| 3455 | + cpu = get_cpu(); |
|---|
| 3456 | + |
|---|
| 3457 | + *cpu_store = atomic_read(&cpu_lock->owner); |
|---|
| 3458 | + /* memory barrier to ensure the current lock owner is visible */ |
|---|
| 3459 | + smp_rmb(); |
|---|
| 3460 | + if (*cpu_store == -1) { |
|---|
| 3461 | + flags = per_cpu_ptr(cpu_lock->irqflags, cpu); |
|---|
| 3462 | + local_irq_save(*flags); |
|---|
| 3463 | + if (atomic_try_cmpxchg_acquire(&cpu_lock->owner, |
|---|
| 3464 | + cpu_store, cpu)) { |
|---|
| 3465 | + return true; |
|---|
| 3466 | + } |
|---|
| 3467 | + local_irq_restore(*flags); |
|---|
| 3468 | + } else if (*cpu_store == cpu) { |
|---|
| 3469 | + return true; |
|---|
| 3470 | + } |
|---|
| 3471 | + |
|---|
| 3472 | + put_cpu(); |
|---|
| 3473 | + return false; |
|---|
| 3474 | +} |
|---|
| 3475 | + |
|---|
| 3476 | +/* |
|---|
| 3477 | + * prb_lock: Perform a processor-reentrant spin lock. |
|---|
| 3478 | + * @cpu_lock: A pointer to the lock object. |
|---|
| 3479 | + * @cpu_store: A "flags" pointer to store lock status information. |
|---|
| 3480 | + * |
|---|
| 3481 | + * If no processor has the lock, the calling processor takes the lock and |
|---|
| 3482 | + * becomes the owner. If the calling processor is already the owner of the |
|---|
| 3483 | + * lock, this function succeeds immediately. If lock is locked by another |
|---|
| 3484 | + * processor, this function spins until the calling processor becomes the |
|---|
| 3485 | + * owner. |
|---|
| 3486 | + * |
|---|
| 3487 | + * It is safe to call this function from any context and state. |
|---|
| 3488 | + */ |
|---|
| 3489 | +static void prb_lock(struct prb_cpulock *cpu_lock, unsigned int *cpu_store) |
|---|
| 3490 | +{ |
|---|
| 3491 | + for (;;) { |
|---|
| 3492 | + if (__prb_trylock(cpu_lock, cpu_store)) |
|---|
| 3493 | + break; |
|---|
| 3494 | + cpu_relax(); |
|---|
| 3495 | + } |
|---|
| 3496 | +} |
|---|
| 3497 | + |
|---|
| 3498 | +/* |
|---|
| 3499 | + * prb_unlock: Perform a processor-reentrant spin unlock. |
|---|
| 3500 | + * @cpu_lock: A pointer to the lock object. |
|---|
| 3501 | + * @cpu_store: A "flags" object storing lock status information. |
|---|
| 3502 | + * |
|---|
| 3503 | + * Release the lock. The calling processor must be the owner of the lock. |
|---|
| 3504 | + * |
|---|
| 3505 | + * It is safe to call this function from any context and state. |
|---|
| 3506 | + */ |
|---|
| 3507 | +static void prb_unlock(struct prb_cpulock *cpu_lock, unsigned int cpu_store) |
|---|
| 3508 | +{ |
|---|
| 3509 | + unsigned long *flags; |
|---|
| 3510 | + unsigned int cpu; |
|---|
| 3511 | + |
|---|
| 3512 | + cpu = atomic_read(&cpu_lock->owner); |
|---|
| 3513 | + atomic_set_release(&cpu_lock->owner, cpu_store); |
|---|
| 3514 | + |
|---|
| 3515 | + if (cpu_store == -1) { |
|---|
| 3516 | + flags = per_cpu_ptr(cpu_lock->irqflags, cpu); |
|---|
| 3517 | + local_irq_restore(*flags); |
|---|
| 3518 | + } |
|---|
| 3519 | + |
|---|
| 3520 | + put_cpu(); |
|---|
| 3521 | +} |
|---|
| 3522 | + |
|---|
| 3523 | +DECLARE_STATIC_PRINTKRB_CPULOCK(printk_cpulock); |
|---|
| 3524 | + |
|---|
| 3525 | +void console_atomic_lock(unsigned int *flags) |
|---|
| 3526 | +{ |
|---|
| 3527 | + prb_lock(&printk_cpulock, flags); |
|---|
| 3528 | +} |
|---|
| 3529 | +EXPORT_SYMBOL(console_atomic_lock); |
|---|
| 3530 | + |
|---|
| 3531 | +void console_atomic_unlock(unsigned int flags) |
|---|
| 3532 | +{ |
|---|
| 3533 | + prb_unlock(&printk_cpulock, flags); |
|---|
| 3534 | +} |
|---|
| 3535 | +EXPORT_SYMBOL(console_atomic_unlock); |
|---|
| 3536 | + |
|---|
| 3537 | +static void pr_msleep(bool may_sleep, int ms) |
|---|
| 3538 | +{ |
|---|
| 3539 | + if (may_sleep) { |
|---|
| 3540 | + msleep(ms); |
|---|
| 3541 | + } else { |
|---|
| 3542 | + while (ms--) |
|---|
| 3543 | + udelay(1000); |
|---|
| 3544 | + } |
|---|
| 3545 | +} |
|---|
| 3546 | + |
|---|
| 3547 | +/** |
|---|
| 3548 | + * pr_flush() - Wait for printing threads to catch up. |
|---|
| 3549 | + * |
|---|
| 3550 | + * @timeout_ms: The maximum time (in ms) to wait. |
|---|
| 3551 | + * @reset_on_progress: Reset the timeout if forward progress is seen. |
|---|
| 3552 | + * |
|---|
| 3553 | + * A value of 0 for @timeout_ms means no waiting will occur. A value of -1 |
|---|
| 3554 | + * represents infinite waiting. |
|---|
| 3555 | + * |
|---|
| 3556 | + * If @reset_on_progress is true, the timeout will be reset whenever any |
|---|
| 3557 | + * printer has been seen to make some forward progress. |
|---|
| 3558 | + * |
|---|
| 3559 | + * Context: Any context. |
|---|
| 3560 | + * Return: true if all enabled printers are caught up. |
|---|
| 3561 | + */ |
|---|
| 3562 | +bool pr_flush(int timeout_ms, bool reset_on_progress) |
|---|
| 3563 | +{ |
|---|
| 3564 | + int remaining = timeout_ms; |
|---|
| 3565 | + struct console *con; |
|---|
| 3566 | + u64 last_diff = 0; |
|---|
| 3567 | + bool may_sleep; |
|---|
| 3568 | + u64 printk_seq; |
|---|
| 3569 | + u64 diff; |
|---|
| 3570 | + u64 seq; |
|---|
| 3571 | + |
|---|
| 3572 | + may_sleep = (preemptible() && |
|---|
| 3573 | + !in_softirq() && |
|---|
| 3574 | + system_state >= SYSTEM_RUNNING); |
|---|
| 3575 | + |
|---|
| 3576 | + seq = prb_next_seq(prb); |
|---|
| 3577 | + |
|---|
| 3578 | + for (;;) { |
|---|
| 3579 | + diff = 0; |
|---|
| 3580 | + |
|---|
| 3581 | + for_each_console(con) { |
|---|
| 3582 | + if (!(con->flags & CON_ENABLED)) |
|---|
| 3583 | + continue; |
|---|
| 3584 | + if (!con->write && !con->write_atomic) |
|---|
| 3585 | + continue; |
|---|
| 3586 | + printk_seq = atomic64_read(&con->printk_seq); |
|---|
| 3587 | + if (printk_seq < seq) |
|---|
| 3588 | + diff += seq - printk_seq; |
|---|
| 3589 | + } |
|---|
| 3590 | + |
|---|
| 3591 | + if (diff != last_diff && reset_on_progress) |
|---|
| 3592 | + remaining = timeout_ms; |
|---|
| 3593 | + |
|---|
| 3594 | + if (!diff || remaining == 0) |
|---|
| 3595 | + break; |
|---|
| 3596 | + |
|---|
| 3597 | + if (remaining < 0) { |
|---|
| 3598 | + pr_msleep(may_sleep, 100); |
|---|
| 3599 | + } else if (remaining < 100) { |
|---|
| 3600 | + pr_msleep(may_sleep, remaining); |
|---|
| 3601 | + remaining = 0; |
|---|
| 3602 | + } else { |
|---|
| 3603 | + pr_msleep(may_sleep, 100); |
|---|
| 3604 | + remaining -= 100; |
|---|
| 3605 | + } |
|---|
| 3606 | + |
|---|
| 3607 | + last_diff = diff; |
|---|
| 3608 | + } |
|---|
| 3609 | + |
|---|
| 3610 | + return (diff == 0); |
|---|
| 3611 | +} |
|---|
| 3612 | +EXPORT_SYMBOL(pr_flush); |
|---|