lkml.org 
[lkml]   [1997]   [Apr]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectMemory 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 ;-).

\
 
 \ /
  Last update: 2005-03-22 13:39    [W:0.475 / U:0.016 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site