From: Hugh Dickins <hugh@veritas.com>

The current behaviour is that once swapoff has filled memory, other tasks get
OOMkilled one by one until swapoff completes, or more likely hangs.  It is
better that swapoff be the first choice for OOMkill.

The patch changes the oom-killer so that it will kill off any
currently-swapoff instance before killing any other task.



 25-akpm/include/linux/sched.h |    1 +
 25-akpm/mm/oom_kill.c         |    2 ++
 25-akpm/mm/swapfile.c         |    2 ++
 3 files changed, 5 insertions(+)

diff -puN include/linux/sched.h~oomkill-swapoff include/linux/sched.h
--- 25/include/linux/sched.h~oomkill-swapoff	Thu Apr 17 16:23:52 2003
+++ 25-akpm/include/linux/sched.h	Thu Apr 17 16:23:52 2003
@@ -472,6 +472,7 @@ do { if (atomic_dec_and_test(&(tsk)->usa
 #define PF_FROZEN	0x00010000	/* frozen for system suspend */
 #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
 #define PF_KSWAPD	0x00040000	/* I am kswapd */
+#define PF_SWAPOFF	0x00080000	/* I am in swapoff */
 
 #if CONFIG_SMP
 extern void set_cpus_allowed(task_t *p, unsigned long new_mask);
diff -puN mm/oom_kill.c~oomkill-swapoff mm/oom_kill.c
--- 25/mm/oom_kill.c~oomkill-swapoff	Thu Apr 17 16:23:52 2003
+++ 25-akpm/mm/oom_kill.c	Thu Apr 17 16:23:52 2003
@@ -129,6 +129,8 @@ static struct task_struct * select_bad_p
 				chosen = p;
 				maxpoints = points;
 			}
+			if (p->flags & PF_SWAPOFF)
+				return p;
 		}
 	while_each_thread(g, p);
 	return chosen;
diff -puN mm/swapfile.c~oomkill-swapoff mm/swapfile.c
--- 25/mm/swapfile.c~oomkill-swapoff	Thu Apr 17 16:23:52 2003
+++ 25-akpm/mm/swapfile.c	Thu Apr 17 16:23:52 2003
@@ -1059,7 +1059,9 @@ asmlinkage long sys_swapoff(const char _
 	total_swap_pages -= p->pages;
 	p->flags &= ~SWP_WRITEOK;
 	swap_list_unlock();
+	current->flags |= PF_SWAPOFF;
 	err = try_to_unuse(type);
+	current->flags &= ~PF_SWAPOFF;
 	if (err) {
 		/* re-insert swap space back into swap_list */
 		swap_list_lock();

_