diff -ur linux.suse.1/drivers/char/Config.in linux.suse/drivers/char/Config.in --- linux.suse.1/drivers/char/Config.in 2003-10-08 09:17:39.000000000 -0400 +++ linux.suse/drivers/char/Config.in 2003-10-07 11:04:56.000000000 -0400 @@ -357,4 +357,6 @@ tristate 'ACP Modem (Mwave) support' CONFIG_MWAVE fi +tristate 'Crashing module' CONFIG_CRASHER + endmenu diff -ur linux.suse.1/drivers/char/Makefile linux.suse/drivers/char/Makefile --- linux.suse.1/drivers/char/Makefile 2003-10-08 09:17:39.000000000 -0400 +++ linux.suse/drivers/char/Makefile 2003-10-07 11:04:56.000000000 -0400 @@ -294,6 +294,7 @@ obj-$(CONFIG_MIXCOMWD) += mixcomwd.o obj-$(CONFIG_DEADMAN) += deadman.o obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o +obj-$(CONFIG_CRASHER) += crasher.o obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o obj-$(CONFIG_SC520_WDT) += sc520_wdt.o diff -ur linux.suse.1/drivers/char/crasher.c linux.suse/drivers/char/crasher.c --- linux.suse.1/drivers/char/crasher.c 2003-10-08 09:18:20.000000000 -0400 +++ linux.suse/drivers/char/crasher.c 2003-10-07 11:40:07.000000000 -0400 @@ -0,0 +1,145 @@ +/* + * crasher.c, it breaks things + */ + + +#include +#include +#include +#include +#include +#include + +static int module_exiting; +static struct completion startup = COMPLETION_INITIALIZER(startup); + +MODULE_PARM_DESC(seed, "random seed for memory tests"); +MODULE_LICENSE("GPL"); + +static unsigned long rand_seed = 152L; + +#define NUM_ALLOC 24 +#define NUM_SIZES 3 +static int sizes[] = { 128, 256, 4096 }; + +struct mem_buf { + char *buf; + int size; +}; + +static unsigned long crasher_random(void) +{ + rand_seed = rand_seed*69069L+1; + return rand_seed^jiffies; +} + +void crasher_srandom(unsigned long entropy) +{ + rand_seed ^= entropy; + crasher_random(); +} + +static char *mem_alloc(int size) { + char *p = kmalloc(size, GFP_KERNEL); + int i; + if (!p) + return p; + for (i = 0 ; i < size; i++) + p[i] = (i % 119) + 8; + return p; +} + +static void mem_check(char *p, int size) { + int i; + if (!p) + return; + for (i = 0 ; i < size; i++) { + if (p[i] != ((i % 119) + 8)) { + printk(KERN_CRIT "verify error at %lX offset %d " + " wanted %d found %d size %d\n", + (unsigned long)(p + i), i, (i % 119) + 8, + p[i], size); + } + } +} + +static void mem_verify(void) { + struct mem_buf bufs[NUM_ALLOC]; + struct mem_buf *b; + int index; + int size; + unsigned long sleep; + crasher_srandom(rand_seed); + + printk("crasher module memory testing, sizes: "); + for (index = 0 ; index < NUM_SIZES ; index++) + printk("%d ", sizes[index]); + printk("\n"); + + memset(bufs, 0, sizeof(struct mem_buf) * NUM_ALLOC); + while(!module_exiting) { + index = crasher_random() % NUM_ALLOC; + b = bufs + index; + if (b->size) { + mem_check(b->buf, b->size); + kfree(b->buf); + b->buf = NULL; + b->size = 0; + } else { + size = crasher_random() % NUM_SIZES; + size = sizes[size]; + b->buf = mem_alloc(size); + b->size = size; + } + sleep = crasher_random() % (HZ / 10); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(sleep); + set_current_state(TASK_RUNNING); + } + for (index = 0 ; index < NUM_ALLOC ; index++) { + b = bufs + index; + if (b->size) { + mem_check(b->buf, b->size); + kfree(b->buf); + } + } + printk("crasher done\n"); +} + +static int crasher_thread(void *unused) { + + struct task_struct *tsk = current; + + daemonize(); + strcpy(tsk->comm, "crasher"); + + /* avoid getting signals */ + spin_lock_irq(&tsk->sigmask_lock); + flush_signals(tsk); + sigfillset(&tsk->blocked); + recalc_sigpending(tsk); + spin_unlock_irq(&tsk->sigmask_lock); + + complete(&startup); + mem_verify(); + complete(&startup); + return 0; +} +static int __init crasher_init(void) +{ + kernel_thread(crasher_thread, crasher_thread, CLONE_FS | CLONE_FILES | + CLONE_SIGNAL) ; + + wait_for_completion(&startup); + return 0; +} + +static void __exit crasher_exit(void) +{ + module_exiting = 1; + wait_for_completion(&startup); + return; +} + +module_init(crasher_init); +module_exit(crasher_exit);