aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorDavid Rientjes <rientjes@google.com>2011-03-22 19:30:09 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-22 20:43:58 -0400
commit3a5dda7a17cf3706f79b86293f29db02d61e0d48 (patch)
tree0d173f484968b7e08cf3f75006450b62e1521227 /mm
parent52c50567d8ab0a0a87f12cceaa4194967854f0bd (diff)
oom: prevent unnecessary oom kills or kernel panics
This patch prevents unnecessary oom kills or kernel panics by reverting two commits: 495789a5 (oom: make oom_score to per-process value) cef1d352 (oom: multi threaded process coredump don't make deadlock) First, 495789a5 (oom: make oom_score to per-process value) ignores the fact that all threads in a thread group do not necessarily exit at the same time. It is imperative that select_bad_process() detect threads that are in the exit path, specifically those with PF_EXITING set, to prevent needlessly killing additional tasks. If a process is oom killed and the thread group leader exits, select_bad_process() cannot detect the other threads that are PF_EXITING by iterating over only processes. Thus, it currently chooses another task unnecessarily for oom kill or panics the machine when nothing else is eligible. By iterating over threads instead, it is possible to detect threads that are exiting and nominate them for oom kill so they get access to memory reserves. Second, cef1d352 (oom: multi threaded process coredump don't make deadlock) erroneously avoids making the oom killer a no-op when an eligible thread other than current isfound to be exiting. We want to detect this situation so that we may allow that exiting thread time to exit and free its memory; if it is able to exit on its own, that should free memory so current is no loner oom. If it is not able to exit on its own, the oom killer will nominate it for oom kill which, in this case, only means it will get access to memory reserves. Without this change, it is easy for the oom killer to unnecessarily target tasks when all threads of a victim don't exit before the thread group leader or, in the worst case, panic the machine. Signed-off-by: David Rientjes <rientjes@google.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Hugh Dickins <hughd@google.com> Cc: Andrey Vagin <avagin@openvz.org> Cc: <stable@kernel.org> [2.6.38.x] Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/oom_kill.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 7dcca55ede7c..b5a7b5f46e7a 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -292,11 +292,11 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
292 unsigned long totalpages, struct mem_cgroup *mem, 292 unsigned long totalpages, struct mem_cgroup *mem,
293 const nodemask_t *nodemask) 293 const nodemask_t *nodemask)
294{ 294{
295 struct task_struct *p; 295 struct task_struct *g, *p;
296 struct task_struct *chosen = NULL; 296 struct task_struct *chosen = NULL;
297 *ppoints = 0; 297 *ppoints = 0;
298 298
299 for_each_process(p) { 299 do_each_thread(g, p) {
300 unsigned int points; 300 unsigned int points;
301 301
302 if (oom_unkillable_task(p, mem, nodemask)) 302 if (oom_unkillable_task(p, mem, nodemask))
@@ -324,7 +324,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
324 * the process of exiting and releasing its resources. 324 * the process of exiting and releasing its resources.
325 * Otherwise we could get an easy OOM deadlock. 325 * Otherwise we could get an easy OOM deadlock.
326 */ 326 */
327 if (thread_group_empty(p) && (p->flags & PF_EXITING) && p->mm) { 327 if ((p->flags & PF_EXITING) && p->mm) {
328 if (p != current) 328 if (p != current)
329 return ERR_PTR(-1UL); 329 return ERR_PTR(-1UL);
330 330
@@ -337,7 +337,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
337 chosen = p; 337 chosen = p;
338 *ppoints = points; 338 *ppoints = points;
339 } 339 }
340 } 340 } while_each_thread(g, p);
341 341
342 return chosen; 342 return chosen;
343} 343}