The kmsg_dumper can be called from any context and CPU, possibly from multiple CPUs simultaneously. Since a static buffer is used to retrieve the kernel logs, this buffer must be protected against simultaneous dumping. Skip dumping if another context is already dumping.
Unified · Split
| @@ -1,5 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | #include <linux/kmsg_dump.h> |
| 3 | +#include <linux/spinlock.h> | |
| 3 | 4 | #include <linux/console.h> |
| 4 | 5 | #include <linux/string.h> |
| 5 | 6 | #include <shared/init.h> |
| @@ -9,8 +10,10 @@ · 3 unmodified lines | ||
| 9 | 10 | static void kmsg_dumper_stdout(struct kmsg_dumper *dumper, |
| 10 | 11 | enum kmsg_dump_reason reason) |
| 11 | 12 | { |
| 13 | + static DEFINE_SPINLOCK(lock); | |
| 12 | 14 | static char line[1024]; |
| 13 | 15 | struct console *con; |
| 16 | + unsigned long flags; | |
| 14 | 17 | size_t len = 0; |
| 15 | 18 | |
| 16 | 19 | /* only dump kmsg when no console is available */ |
| @@ -29,11 +32,16 @@ static void kmsg_dumper_stdout(struct kmsg_dumper *dumper, · 12 unmodified lines | ||
| 29 | 32 | if (con) |
| 30 | 33 | return; |
| 31 | 34 | |
| 35 | + if (!spin_trylock_irqsave(&lock, flags)) | |
| 36 | + return; | |
| 37 | + | |
| 32 | 38 | printf("kmsg_dump:\n"); |
| 33 | 39 | while (kmsg_dump_get_line(dumper, true, line, sizeof(line), &len)) { |
| 34 | 40 | line[len] = '\0'; |
| 35 | 41 | printf("%s", line); |
| 36 | 42 | } |
| 43 | + | |
| 44 | + spin_unlock_irqrestore(&lock, flags); | |
| 37 | 45 | } |
| 38 | 46 | |
| 39 | 47 | static struct kmsg_dumper kmsg_dumper = { |