Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

printk: Add a short description string to kmsg_dump()

kmsg_dump doesn't forward the panic reason string to the kmsg_dumper
callback.
This patch adds a new struct kmsg_dump_detail, that will hold the
reason and description, and pass it to the dump() callback.

To avoid updating all kmsg_dump() call, it adds a kmsg_dump_desc()
function and a macro for backward compatibility.

I've written this for drm_panic, but it can be useful for other
kmsg_dumper.
It allows to see the panic reason, like "sysrq triggered crash"
or "VFS: Unable to mount root fs on xxxx" on the drm panic screen.

v2:
* Use a struct kmsg_dump_detail to hold the reason and description
pointer, for more flexibility if we want to add other parameters.
(Kees Cook)
* Fix powerpc/nvram_64 build, as I didn't update the forward
declaration of oops_to_nvram()

Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
Acked-by: Petr Mladek <pmladek@suse.com>
Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
Acked-by: Kees Cook <kees@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20240702122639.248110-1-jfalempe@redhat.com

+45 -24
+4 -4
arch/powerpc/kernel/nvram_64.c
··· 73 73 }; 74 74 75 75 static void oops_to_nvram(struct kmsg_dumper *dumper, 76 - enum kmsg_dump_reason reason); 76 + struct kmsg_dump_detail *detail); 77 77 78 78 static struct kmsg_dumper nvram_kmsg_dumper = { 79 79 .dump = oops_to_nvram ··· 643 643 * partition. If that's too much, go back and capture uncompressed text. 644 644 */ 645 645 static void oops_to_nvram(struct kmsg_dumper *dumper, 646 - enum kmsg_dump_reason reason) 646 + struct kmsg_dump_detail *detail) 647 647 { 648 648 struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf; 649 649 static unsigned int oops_count = 0; ··· 655 655 unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ; 656 656 int rc = -1; 657 657 658 - switch (reason) { 658 + switch (detail->reason) { 659 659 case KMSG_DUMP_SHUTDOWN: 660 660 /* These are almost always orderly shutdowns. */ 661 661 return; ··· 671 671 break; 672 672 default: 673 673 pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n", 674 - __func__, (int) reason); 674 + __func__, (int) detail->reason); 675 675 return; 676 676 } 677 677
+2 -2
arch/powerpc/platforms/powernv/opal-kmsg.c
··· 20 20 * message, it just ensures that OPAL completely flushes the console buffer. 21 21 */ 22 22 static void kmsg_dump_opal_console_flush(struct kmsg_dumper *dumper, 23 - enum kmsg_dump_reason reason) 23 + struct kmsg_dump_detail *detail) 24 24 { 25 25 /* 26 26 * Outside of a panic context the pollers will continue to run, 27 27 * so we don't need to do any special flushing. 28 28 */ 29 - if (reason != KMSG_DUMP_PANIC) 29 + if (detail->reason != KMSG_DUMP_PANIC) 30 30 return; 31 31 32 32 opal_flush_console(0);
+1 -1
arch/um/kernel/kmsg_dump.c
··· 8 8 #include <os.h> 9 9 10 10 static void kmsg_dumper_stdout(struct kmsg_dumper *dumper, 11 - enum kmsg_dump_reason reason) 11 + struct kmsg_dump_detail *detail) 12 12 { 13 13 static struct kmsg_dump_iter iter; 14 14 static DEFINE_SPINLOCK(lock);
+2 -2
drivers/gpu/drm/drm_panic.c
··· 655 655 return container_of(kd, struct drm_plane, kmsg_panic); 656 656 } 657 657 658 - static void drm_panic(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason) 658 + static void drm_panic(struct kmsg_dumper *dumper, struct kmsg_dump_detail *detail) 659 659 { 660 660 struct drm_plane *plane = to_drm_plane(dumper); 661 661 662 - if (reason == KMSG_DUMP_PANIC) 662 + if (detail->reason == KMSG_DUMP_PANIC) 663 663 draw_panic_plane(plane); 664 664 } 665 665
+2 -2
drivers/hv/hv_common.c
··· 207 207 * buffer and call into Hyper-V to transfer the data. 208 208 */ 209 209 static void hv_kmsg_dump(struct kmsg_dumper *dumper, 210 - enum kmsg_dump_reason reason) 210 + struct kmsg_dump_detail *detail) 211 211 { 212 212 struct kmsg_dump_iter iter; 213 213 size_t bytes_written; 214 214 215 215 /* We are only interested in panics. */ 216 - if (reason != KMSG_DUMP_PANIC || !sysctl_record_panic_msg) 216 + if (detail->reason != KMSG_DUMP_PANIC || !sysctl_record_panic_msg) 217 217 return; 218 218 219 219 /*
+1 -1
drivers/mtd/mtdoops.c
··· 298 298 } 299 299 300 300 static void mtdoops_do_dump(struct kmsg_dumper *dumper, 301 - enum kmsg_dump_reason reason) 301 + struct kmsg_dump_detail *detail) 302 302 { 303 303 struct mtdoops_context *cxt = container_of(dumper, 304 304 struct mtdoops_context, dump);
+5 -5
fs/pstore/platform.c
··· 275 275 * end of the buffer. 276 276 */ 277 277 static void pstore_dump(struct kmsg_dumper *dumper, 278 - enum kmsg_dump_reason reason) 278 + struct kmsg_dump_detail *detail) 279 279 { 280 280 struct kmsg_dump_iter iter; 281 281 unsigned long total = 0; ··· 285 285 int saved_ret = 0; 286 286 int ret; 287 287 288 - why = kmsg_dump_reason_str(reason); 288 + why = kmsg_dump_reason_str(detail->reason); 289 289 290 - if (pstore_cannot_block_path(reason)) { 290 + if (pstore_cannot_block_path(detail->reason)) { 291 291 if (!spin_trylock_irqsave(&psinfo->buf_lock, flags)) { 292 292 pr_err("dump skipped in %s path because of concurrent dump\n", 293 293 in_nmi() ? "NMI" : why); ··· 311 311 pstore_record_init(&record, psinfo); 312 312 record.type = PSTORE_TYPE_DMESG; 313 313 record.count = oopscount; 314 - record.reason = reason; 314 + record.reason = detail->reason; 315 315 record.part = part; 316 316 record.buf = psinfo->buf; 317 317 ··· 352 352 } 353 353 354 354 ret = psinfo->write(&record); 355 - if (ret == 0 && reason == KMSG_DUMP_OOPS) { 355 + if (ret == 0 && detail->reason == KMSG_DUMP_OOPS) { 356 356 pstore_new_entry = 1; 357 357 pstore_timer_kick(); 358 358 } else {
+19 -3
include/linux/kmsg_dump.h
··· 40 40 }; 41 41 42 42 /** 43 + * struct kmsg_dump_detail - kernel crash detail 44 + * @reason: reason for the crash, see kmsg_dump_reason. 45 + * @description: optional short string, to provide additional information. 46 + */ 47 + 48 + struct kmsg_dump_detail { 49 + enum kmsg_dump_reason reason; 50 + const char *description; 51 + }; 52 + 53 + /** 43 54 * struct kmsg_dumper - kernel crash message dumper structure 44 55 * @list: Entry in the dumper list (private) 45 56 * @dump: Call into dumping code which will retrieve the data with ··· 60 49 */ 61 50 struct kmsg_dumper { 62 51 struct list_head list; 63 - void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason); 52 + void (*dump)(struct kmsg_dumper *dumper, struct kmsg_dump_detail *detail); 64 53 enum kmsg_dump_reason max_reason; 65 54 bool registered; 66 55 }; 67 56 68 57 #ifdef CONFIG_PRINTK 69 - void kmsg_dump(enum kmsg_dump_reason reason); 58 + void kmsg_dump_desc(enum kmsg_dump_reason reason, const char *desc); 70 59 71 60 bool kmsg_dump_get_line(struct kmsg_dump_iter *iter, bool syslog, 72 61 char *line, size_t size, size_t *len); ··· 82 71 83 72 const char *kmsg_dump_reason_str(enum kmsg_dump_reason reason); 84 73 #else 85 - static inline void kmsg_dump(enum kmsg_dump_reason reason) 74 + static inline void kmsg_dump_desc(enum kmsg_dump_reason reason, const char *desc) 86 75 { 87 76 } 88 77 ··· 117 106 return "Disabled"; 118 107 } 119 108 #endif 109 + 110 + static inline void kmsg_dump(enum kmsg_dump_reason reason) 111 + { 112 + kmsg_dump_desc(reason, NULL); 113 + } 120 114 121 115 #endif /* _LINUX_KMSG_DUMP_H */
+1 -1
kernel/panic.c
··· 375 375 376 376 panic_print_sys_info(false); 377 377 378 - kmsg_dump(KMSG_DUMP_PANIC); 378 + kmsg_dump_desc(KMSG_DUMP_PANIC, buf); 379 379 380 380 /* 381 381 * If you doubt kdump always works fine in any situation,
+8 -3
kernel/printk/printk.c
··· 4126 4126 EXPORT_SYMBOL_GPL(kmsg_dump_reason_str); 4127 4127 4128 4128 /** 4129 - * kmsg_dump - dump kernel log to kernel message dumpers. 4129 + * kmsg_dump_desc - dump kernel log to kernel message dumpers. 4130 4130 * @reason: the reason (oops, panic etc) for dumping 4131 + * @desc: a short string to describe what caused the panic or oops. Can be NULL 4132 + * if no additional description is available. 4131 4133 * 4132 4134 * Call each of the registered dumper's dump() callback, which can 4133 4135 * retrieve the kmsg records with kmsg_dump_get_line() or 4134 4136 * kmsg_dump_get_buffer(). 4135 4137 */ 4136 - void kmsg_dump(enum kmsg_dump_reason reason) 4138 + void kmsg_dump_desc(enum kmsg_dump_reason reason, const char *desc) 4137 4139 { 4138 4140 struct kmsg_dumper *dumper; 4141 + struct kmsg_dump_detail detail = { 4142 + .reason = reason, 4143 + .description = desc}; 4139 4144 4140 4145 rcu_read_lock(); 4141 4146 list_for_each_entry_rcu(dumper, &dump_list, list) { ··· 4158 4153 continue; 4159 4154 4160 4155 /* invoke dumper which will iterate over records */ 4161 - dumper->dump(dumper, reason); 4156 + dumper->dump(dumper, &detail); 4162 4157 } 4163 4158 rcu_read_unlock(); 4164 4159 }