summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Rientjes <rientjes@google.com>2014-01-23 15:53:34 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-23 16:36:53 -0800
commitd49ad9355420c743c736bfd1dee9eaa5b1a7722a (patch)
treeedd5f00d2e7e6b2414f7063e3393934dc74e5c9b
parentc3ac14b2677e0bc130238c5d01856592ac7a584b (diff)
downloadlinux-stable-d49ad9355420c743c736bfd1dee9eaa5b1a7722a.tar.gz
linux-stable-d49ad9355420c743c736bfd1dee9eaa5b1a7722a.tar.bz2
linux-stable-d49ad9355420c743c736bfd1dee9eaa5b1a7722a.zip
mm, oom: prefer thread group leaders for display purposes
When two threads have the same badness score, it's preferable to kill the thread group leader so that the actual process name is printed to the kernel log rather than the thread group name which may be shared amongst several processes. This was the behavior when select_bad_process() used to do for_each_process(), but it now iterates threads instead and leads to ambiguity. Signed-off-by: David Rientjes <rientjes@google.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@suse.cz> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Greg Thelen <gthelen@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/memcontrol.c19
-rw-r--r--mm/oom_kill.c12
2 files changed, 20 insertions, 11 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 9537e1389ee6..c8336e8f8df0 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1841,13 +1841,18 @@ static void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
break;
};
points = oom_badness(task, memcg, NULL, totalpages);
- if (points > chosen_points) {
- if (chosen)
- put_task_struct(chosen);
- chosen = task;
- chosen_points = points;
- get_task_struct(chosen);
- }
+ if (!points || points < chosen_points)
+ continue;
+ /* Prefer thread group leaders for display purposes */
+ if (points == chosen_points &&
+ thread_group_leader(chosen))
+ continue;
+
+ if (chosen)
+ put_task_struct(chosen);
+ chosen = task;
+ chosen_points = points;
+ get_task_struct(chosen);
}
css_task_iter_end(&it);
}
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 054ff47c4478..37b1b1903fb2 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -327,10 +327,14 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
break;
};
points = oom_badness(p, NULL, nodemask, totalpages);
- if (points > chosen_points) {
- chosen = p;
- chosen_points = points;
- }
+ if (!points || points < chosen_points)
+ continue;
+ /* Prefer thread group leaders for display purposes */
+ if (points == chosen_points && thread_group_leader(chosen))
+ continue;
+
+ chosen = p;
+ chosen_points = points;
}
if (chosen)
get_task_struct(chosen);