Messages in this thread Patch in this message | | | Date | Sun, 27 Apr 1997 17:43:57 +0200 | From | Pavel Machek <> | Subject | Memory managment bug with heavy atomic kmallocs, emacs problem |
| |
Hi!
I suspect linux mm to have a (non-fatal but strange) bug inside. Take a machine with 16M ram, log-in twice, and eat all available memory from interrupt. (kmalloc(..., GFP_ATOMIC) until it returns NULL). Repeat kmalloc few times. Where there's really no more memory, try ls on other console. [there's bug in sysrq patches which forces you to change consoles]. It says bash: fork: not enough memory. But system does NOT start swapping - and I think that it should since it has no memory for atomic allocations. You can wait quite a long time, but system will not recover. Login on other console, system will start swapping and everything will be ok.
[If you want to try this, install mj's Magic SysRq keys, patch them with following patch, and SysRq-W is what you need to hold to eat memory.]
[mj: Please apply this to patch your SysRq patch :-) ]
Also, there's a problem with emacs under 2.1.3X+ kernels: While you hold a ^P then only the first two lines change. (Load this mail in emacs, press ESC->, hold ^P and bug will be obvious. It will not refresh even after you reach start of file...). I suspect kernel since this has not happened in previous versions.
Pavel
--- kbd_sysrq.c.ofic Mon Apr 21 22:35:40 1997 +++ kbd_sysrq.c Wed Apr 23 11:22:57 1997 @@ -4,11 +4,15 @@ * * (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> * based on ideas by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz> + * Distribute under GPL + * + * Modified by Pavel Machek to include stress keys. */ #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/mm.h> +#include <linux/malloc.h> #include <linux/fs.h> #include <linux/mount.h> #include <linux/kdev_t.h> @@ -22,6 +26,14 @@ #include "kbd_kern.h" +/* + * Define this if you want to be able to do *NASTY* things to + * linux. Like eating all pages available, + * setting jiffies to pre to defined value etc. Useful for + * stress testing. + */ +#define CONFIG_STRESS + //extern void hard_reset_now(void); extern void wakeup_bdflush(int); extern void reset_vc(unsigned int); @@ -29,6 +41,10 @@ extern int console_loglevel; extern struct vfsmount *vfsmntlist; +#ifdef CONFIG_STRESS +static void **eaten_memory = NULL; +#endif + #ifdef __sparc__ extern void halt_now(void); #endif @@ -46,9 +62,6 @@ force_sig(sig, p); } } - - if (console_loglevel < 7) /* We might have killed syslogd */ - console_loglevel = 7; } /* @@ -59,8 +72,50 @@ void handle_sysrq(int key, struct pt_regs *pt_regs, struct kbd_struct *kbd, struct tty_struct *tty) { + int saved_loglevel = console_loglevel; /* We want user to know what he did */ + console_loglevel = 8; + printk(KERN_INFO "SysRq: "); switch (key) { +#ifdef CONFIG_STRESS + case 17: /* W -- eat physical memory */ + { + int i = 0; + void **c= eaten_memory, *m; + printk( "Eating pages " ); + while ((m = kmalloc( 4096, GFP_ATOMIC ))) + { + eaten_memory = m; + printk( "." ); + *eaten_memory = c; + c = eaten_memory; + i++; + } + printk( "(%dK)\n", i*4 ); + } + break; + case 16: /* Q -- return physical memory */ + { + int i = 0; + void **c = eaten_memory, *f; + printk( "Freeing pages " ); + while (c) + { + printk( "." ); + f = *c; + c = *c; + kfree( f ); + i++; + } + printk( "(%dK)\n", i*4 ); + eaten_memory = NULL; + } + break; + case 36: /* J -- Set jiffies to -10 sec */ + printk( "Setting Jiffies\n" ); + jiffies = 0xFFFFFFFF - 10*HZ; + break; +#endif case 19: /* R -- Reset raw mode */ kbd->kbdmode = VC_XLATE; printk("Keyboard mode set to XLATE\n"); @@ -112,23 +167,26 @@ break; case 2: /* 1 -- set console logging to max */ printk("Maximum Logging\n"); - console_loglevel = 8; + saved_loglevel = 8; break; case 11: /* 0 -- set console logging to normal */ printk("Normal Logging\n"); - console_loglevel = 7; + saved_loglevel = 7; break; case 18: /* E -- terminate all user processes */ printk("Terminate All Tasks\n"); send_sig_all(SIGTERM, 0); + saved_loglevel = 8; break; case 37: /* K -- kill all user processes */ printk("Kill All Tasks\n"); send_sig_all(SIGKILL, 0); + saved_loglevel = 8; break; case 38: /* L -- kill all processes including init */ printk("Kill ALL Tasks (even init)\n"); send_sig_all(SIGKILL, 1); + saved_loglevel = 8; break; default: /* Unknown: help */ printk("unRaw sAk Boot " @@ -138,8 +196,12 @@ #ifdef CONFIG_APM "Off " #endif +#ifdef CONFIG_STRESS + "W:eat Q:return Jiffies " +#endif "Sync Unmount showPc showTasks showMem debuglog1/0 tErm Kill killalL\n"); } + console_loglevel = saved_loglevel; } /* Aux routines for the syncer */
-- I'm really pavel@atrey.karlin.mff.cuni.cz. Pavel Look at http://atrey.karlin.mff.cuni.cz/~pavel ;-).
| |