| --- |
| drivers/misc/Makefile | 2 + |
| drivers/misc/dump-test.c | 72 +++++++++++++++++++++++++++++++++++++++++++++ |
| drivers/misc/printk-race.c | 70 +++++++++++++++++++++++++++++++++++++++++++ |
| 3 files changed, 144 insertions(+) |
| |
| --- a/drivers/misc/Makefile |
| +++ b/drivers/misc/Makefile |
| @@ -51,3 +51,5 @@ obj-y += carma/ |
| obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o |
| obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ |
| obj-$(CONFIG_INTEL_MEI) += mei/ |
| +obj-m += printk-race.o |
| +obj-y += dump-test.o |
| --- /dev/null |
| +++ b/drivers/misc/dump-test.c |
| @@ -0,0 +1,72 @@ |
| +#include <linux/module.h> |
| +#include <linux/kernel.h> |
| +#include <linux/init.h> |
| +#include <linux/kmsg_dump.h> |
| + |
| +static char buf[64 * 1024]; |
| + |
| +static int trigger_dump(const char *str, struct kernel_param *kp) |
| +{ |
| + kmsg_dump(KMSG_DUMP_OOPS); |
| + return 0; |
| +} |
| +module_param_call(dump, trigger_dump, NULL, NULL, 0600); |
| + |
| +static void test_dump(struct kmsg_dumper *dumper, |
| + enum kmsg_dump_reason reason) |
| +{ |
| + char s[512]; |
| + size_t len = 0; |
| + size_t l; |
| + int i = 0; |
| + |
| +#if 0 |
| + while (kmsg_dump_get_line(dumper, true, buf + len, sizeof(buf) - len, &l)) { |
| + i++; |
| + len += l; |
| + } |
| +#else |
| + while (len < sizeof(buf)) { |
| + len += sprintf(buf + len, "#### Dump %i at %zi\n", i, len); |
| + |
| + if (!kmsg_dump_get_buffer(dumper, true, buf + len, sizeof(buf), &l)) |
| + break; |
| + |
| + len += l; |
| + i++; |
| + } |
| +#endif |
| + |
| + printk("#### dumped %i pages, and %zi bytes\n", i, len); |
| + |
| + memcpy(s, buf, 511); |
| + s[511] = '\0'; |
| + printk("#### '%s'\n", s); |
| + |
| + memcpy(s, buf + (len-512), 511); |
| + s[511] = '\0'; |
| + printk("#### '%s'\n", s); |
| +} |
| + |
| +static struct kmsg_dumper test_dumper = { |
| + .dump = test_dump, |
| +}; |
| + |
| +static int __init test_init(void) |
| +{ |
| + printk(KERN_DEFAULT "dump test init\n"); |
| + kmsg_dump_register(&test_dumper); |
| + return 0; |
| +} |
| + |
| +static void __exit test_exit(void) |
| +{ |
| + kmsg_dump_unregister(&test_dumper); |
| + printk(KERN_DEFAULT "dump test cleanup\n"); |
| +} |
| + |
| +module_init(test_init); |
| +module_exit(test_exit); |
| +MODULE_LICENSE("GPL"); |
| +MODULE_AUTHOR("Kay Sievers <kay@vrfy.org>"); |
| +MODULE_DESCRIPTION("kmsg dump test"); |
| --- /dev/null |
| +++ b/drivers/misc/printk-race.c |
| @@ -0,0 +1,70 @@ |
| +#include <linux/module.h> |
| +#include <linux/kernel.h> |
| +#include <linux/init.h> |
| +#include <linux/delay.h> |
| + |
| +static void print_cont(char c) |
| +{ |
| + int i; |
| + |
| + for (i = 0; i < 100; i++) { |
| + int k; |
| + |
| + printk("(%c", c); |
| + for (k = 0; k < 58; k++) { |
| + printk(KERN_CONT "%c", c); |
| + msleep(1); |
| + } |
| + printk(KERN_CONT "%c)\n", c); |
| + } |
| +} |
| + |
| +static void print_c(struct work_struct *work) |
| +{ |
| + print_cont('C'); |
| +} |
| + |
| +static void print_x(struct work_struct *work) |
| +{ |
| + print_cont('X'); |
| +} |
| + |
| +static void print_atomic(struct work_struct *work) |
| +{ |
| + int i; |
| + |
| + for (i = 0; i < 100; i++) { |
| + printk("(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)\n"); |
| + msleep(1); |
| + } |
| +} |
| + |
| + |
| +static int __init printk_race_init(void) |
| +{ |
| + struct work_struct a_work; |
| + struct work_struct c_work; |
| + struct work_struct x_work; |
| + |
| + printk(KERN_DEFAULT "printk test init\n"); |
| + |
| + INIT_WORK(&a_work, print_atomic); |
| + INIT_WORK(&c_work, print_c); |
| + INIT_WORK(&x_work, print_x); |
| + |
| + schedule_work(&a_work); |
| + schedule_work(&c_work); |
| + //schedule_work(&x_work); |
| + |
| + flush_work_sync(&a_work); |
| + flush_work_sync(&c_work); |
| + flush_work_sync(&x_work); |
| + |
| + printk(KERN_DEFAULT "printk test cleanup\n"); |
| + return -EINVAL; |
| +} |
| + |
| +module_init(printk_race_init); |
| +MODULE_LICENSE("GPL"); |
| +MODULE_AUTHOR("Kay Sievers <kay@vrfy.org>"); |
| +MODULE_DESCRIPTION("printk race test"); |