From: Christian Leber <christian@leber.de>

Ky box (2.6.9-final) was yesterday completly stalled (mouse movable and
stupid loadmeter was still working) after starting mutt and was swapping
for half an hour until I sent SIGTERM to all processes.  I suspect it was a
2 GB big galeon process that was the problem.

I think sysrq needs a key to call oom_kill manually.

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/Documentation/sysrq.txt |    2 ++
 25-akpm/drivers/char/sysrq.c    |   16 ++++++++++++++--
 25-akpm/include/linux/swap.h    |    1 +
 25-akpm/mm/oom_kill.c           |   15 +++++++--------
 4 files changed, 24 insertions(+), 10 deletions(-)

diff -puN Documentation/sysrq.txt~make-sysrq-f-call-oom_kill Documentation/sysrq.txt
--- 25/Documentation/sysrq.txt~make-sysrq-f-call-oom_kill	2004-11-09 01:18:24.053537280 -0800
+++ 25-akpm/Documentation/sysrq.txt	2004-11-09 01:18:24.062535912 -0800
@@ -73,6 +73,8 @@ On all -  write a character to /proc/sys
           it so that only emergency messages like PANICs or OOPSes would
           make it to your console.)
 
+'f'	- Will call oom_kill to kill a memory hog process
+
 'e'     - Send a SIGTERM to all processes, except for init.
 
 'i'     - Send a SIGKILL to all processes, except for init.
diff -puN drivers/char/sysrq.c~make-sysrq-f-call-oom_kill drivers/char/sysrq.c
--- 25/drivers/char/sysrq.c~make-sysrq-f-call-oom_kill	2004-11-09 01:18:24.055536976 -0800
+++ 25-akpm/drivers/char/sysrq.c	2004-11-09 01:18:24.063535760 -0800
@@ -31,7 +31,7 @@
 #include <linux/suspend.h>
 #include <linux/writeback.h>
 #include <linux/buffer_head.h>		/* for fsync_bdev() */
-
+#include <linux/swap.h>
 #include <linux/spinlock.h>
 
 #include <asm/ptrace.h>
@@ -202,6 +202,18 @@ static struct sysrq_key_op sysrq_term_op
 	.action_msg	= "Terminate All Tasks",
 };
 
+static void sysrq_handle_moom(int key, struct pt_regs *pt_regs,
+			      struct tty_struct *tty)
+{
+	oom_kill();
+//	console_loglevel = 8;
+}
+static struct sysrq_key_op sysrq_moom_op = {
+	.handler	= sysrq_handle_moom,
+	.help_msg	= "Full",
+	.action_msg	= "Manual OOM execution",
+};
+
 static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
 			      struct tty_struct *tty) 
 {
@@ -248,7 +260,7 @@ static struct sysrq_key_op *sysrq_key_ta
 /* c */ NULL,
 /* d */	NULL,
 /* e */	&sysrq_term_op,
-/* f */	NULL,
+/* f */	&sysrq_moom_op,
 /* g */	NULL,
 /* h */	NULL,
 /* i */	&sysrq_kill_op,
diff -puN include/linux/swap.h~make-sysrq-f-call-oom_kill include/linux/swap.h
--- 25/include/linux/swap.h~make-sysrq-f-call-oom_kill	2004-11-09 01:18:24.056536824 -0800
+++ 25-akpm/include/linux/swap.h	2004-11-09 01:18:24.063535760 -0800
@@ -149,6 +149,7 @@ struct swap_list_t {
 
 /* linux/mm/oom_kill.c */
 extern void out_of_memory(int gfp_mask);
+void oom_kill(void);
 
 /* linux/mm/memory.c */
 extern void swapin_readahead(swp_entry_t, unsigned long, struct vm_area_struct *);
diff -puN mm/oom_kill.c~make-sysrq-f-call-oom_kill mm/oom_kill.c
--- 25/mm/oom_kill.c~make-sysrq-f-call-oom_kill	2004-11-09 01:18:24.058536520 -0800
+++ 25-akpm/mm/oom_kill.c	2004-11-09 01:18:24.064535608 -0800
@@ -184,7 +184,7 @@ static struct mm_struct *oom_kill_task(t
  * OR try to be smart about which process to kill. Note that we
  * don't have to be perfect here, we just have to be good.
  */
-static void oom_kill(void)
+void oom_kill(void)
 {
 	struct mm_struct *mm;
 	struct task_struct *g, *p, *q;
@@ -214,13 +214,6 @@ retry:
 		printk(KERN_INFO "Fixed up OOM kill of mm-less task\n");
 	read_unlock(&tasklist_lock);
 	mmput(mm);
-
-	/*
-	 * Make kswapd go out of the way, so "p" has a good chance of
-	 * killing itself before someone else gets the chance to ask
-	 * for more memory.
-	 */
-	yield();
 	return;
 }
 
@@ -284,6 +277,12 @@ void out_of_memory(int gfp_mask)
 	/* oom_kill() sleeps */
 	spin_unlock(&oom_lock);
 	oom_kill();
+	/*
+	 * Make kswapd go out of the way, so "p" has a good chance of
+	 * killing itself before someone else gets the chance to ask
+	 * for more memory.
+	 */
+	yield();
 	spin_lock(&oom_lock);
 
 reset:
_