[AVR32] Use ARRAY_SIZE macro when appropriate
[sfrench/cifs-2.6.git] / mm / oom_kill.c
index 20f41b082e16484a8c52aa04272bf4f30359593c..b278b8d60eee4ac13bba50222c478901cff39a60 100644 (file)
@@ -15,6 +15,7 @@
  *  kernel subsystems and hints as to where to find out what things do.
  */
 
+#include <linux/oom.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/swap.h>
@@ -59,12 +60,6 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
                return 0;
        }
 
-       /*
-        * swapoff can easily use up all memory, so kill those first.
-        */
-       if (p->flags & PF_SWAPOFF)
-               return ULONG_MAX;
-
        /*
         * The memory size of the process is the basis for the badness.
         */
@@ -75,6 +70,12 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
         */
        task_unlock(p);
 
+       /*
+        * swapoff can easily use up all memory, so kill those first.
+        */
+       if (p->flags & PF_SWAPOFF)
+               return ULONG_MAX;
+
        /*
         * Processes which fork a lot of child processes are likely
         * a good choice. We add half the vmsize of the children if they
@@ -173,10 +174,15 @@ static inline int constrained_alloc(struct zonelist *zonelist, gfp_t gfp_mask)
 {
 #ifdef CONFIG_NUMA
        struct zone **z;
-       nodemask_t nodes = node_online_map;
+       nodemask_t nodes;
+       int node;
+       /* node has memory ? */
+       for_each_online_node(node)
+               if (NODE_DATA(node)->node_present_pages)
+                       node_set(node, nodes);
 
        for (z = zonelist->zones; *z; z++)
-               if (cpuset_zone_allowed(*z, gfp_mask))
+               if (cpuset_zone_allowed_softwall(*z, gfp_mask))
                        node_clear(zone_to_nid(*z), nodes);
                else
                        return CONSTRAINT_CPUSET;
@@ -263,7 +269,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints)
  * flag though it's unlikely that  we select a process with CAP_SYS_RAW_IO
  * set.
  */
-static void __oom_kill_task(struct task_struct *p, const char *message)
+static void __oom_kill_task(struct task_struct *p, int verbose)
 {
        if (is_init(p)) {
                WARN_ON(1);
@@ -277,10 +283,8 @@ static void __oom_kill_task(struct task_struct *p, const char *message)
                return;
        }
 
-       if (message) {
-               printk(KERN_ERR "%s: Killed process %d (%s).\n",
-                               message, p->pid, p->comm);
-       }
+       if (verbose)
+               printk(KERN_ERR "Killed process %d (%s)\n", p->pid, p->comm);
 
        /*
         * We give our sacrificial lamb high priority and access to
@@ -293,7 +297,7 @@ static void __oom_kill_task(struct task_struct *p, const char *message)
        force_sig(SIGKILL, p);
 }
 
-static int oom_kill_task(struct task_struct *p, const char *message)
+static int oom_kill_task(struct task_struct *p)
 {
        struct mm_struct *mm;
        struct task_struct *g, *q;
@@ -312,15 +316,25 @@ static int oom_kill_task(struct task_struct *p, const char *message)
        if (mm == NULL)
                return 1;
 
-       __oom_kill_task(p, message);
+       /*
+        * Don't kill the process if any threads are set to OOM_DISABLE
+        */
+       do_each_thread(g, q) {
+               if (q->mm == mm && p->oomkilladj == OOM_DISABLE)
+                       return 1;
+       } while_each_thread(g, q);
+
+       __oom_kill_task(p, 1);
+
        /*
         * kill all processes that share the ->mm (i.e. all threads),
-        * but are in a different thread group
+        * but are in a different thread group. Don't let them have access
+        * to memory reserves though, otherwise we might deplete all memory.
         */
-       do_each_thread(g, q)
+       do_each_thread(g, q) {
                if (q->mm == mm && q->tgid != p->tgid)
-                       __oom_kill_task(q, message);
-       while_each_thread(g, q);
+                       force_sig(SIGKILL, p);
+       while_each_thread(g, q);
 
        return 0;
 }
@@ -336,21 +350,22 @@ static int oom_kill_process(struct task_struct *p, unsigned long points,
         * its children or threads, just set TIF_MEMDIE so it can die quickly
         */
        if (p->flags & PF_EXITING) {
-               __oom_kill_task(p, NULL);
+               __oom_kill_task(p, 0);
                return 0;
        }
 
-       printk(KERN_ERR "Out of Memory: Kill process %d (%s) score %li"
-                       " and children.\n", p->pid, p->comm, points);
+       printk(KERN_ERR "%s: kill process %d (%s) score %li or a child\n",
+                                       message, p->pid, p->comm, points);
+
        /* Try to kill a child first */
        list_for_each(tsk, &p->children) {
                c = list_entry(tsk, struct task_struct, sibling);
                if (c->mm == p->mm)
                        continue;
-               if (!oom_kill_task(c, message))
+               if (!oom_kill_task(c))
                        return 0;
        }
-       return oom_kill_task(p, message);
+       return oom_kill_task(p);
 }
 
 static BLOCKING_NOTIFIER_HEAD(oom_notify_list);