diff options
author | Oleg Nesterov <oleg@redhat.com> | 2011-03-14 15:05:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-14 16:38:35 -0400 |
commit | dc1b83ab08f1954335692cdcd499f78c94f4c42a (patch) | |
tree | e05f9760a40c2560e500762b13ef81b37f153b9d | |
parent | 5f40d4209461f23a15d88c6b55993bb8b0fa2670 (diff) |
oom: oom_kill_process: fix the child_points logic
oom_kill_process() starts with victim_points == 0. This means that
(most likely) any child has more points and can be killed erroneously.
Also, "children has a different mm" doesn't match the reality, we should
check child->mm != t->mm. This check is not exactly correct if t->mm ==
NULL but this doesn't really matter, oom_kill_task() will kill them
anyway.
Note: "Kill all processes sharing p->mm" in oom_kill_task() is wrong
too.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | mm/oom_kill.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 7dcca55ede7c..b19c78eb74c0 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -458,10 +458,10 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, | |||
458 | struct mem_cgroup *mem, nodemask_t *nodemask, | 458 | struct mem_cgroup *mem, nodemask_t *nodemask, |
459 | const char *message) | 459 | const char *message) |
460 | { | 460 | { |
461 | struct task_struct *victim = p; | 461 | struct task_struct *victim; |
462 | struct task_struct *child; | 462 | struct task_struct *child; |
463 | struct task_struct *t = p; | 463 | struct task_struct *t; |
464 | unsigned int victim_points = 0; | 464 | unsigned int victim_points; |
465 | 465 | ||
466 | if (printk_ratelimit()) | 466 | if (printk_ratelimit()) |
467 | dump_header(p, gfp_mask, order, mem, nodemask); | 467 | dump_header(p, gfp_mask, order, mem, nodemask); |
@@ -487,10 +487,15 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, | |||
487 | * parent. This attempts to lose the minimal amount of work done while | 487 | * parent. This attempts to lose the minimal amount of work done while |
488 | * still freeing memory. | 488 | * still freeing memory. |
489 | */ | 489 | */ |
490 | victim_points = oom_badness(p, mem, nodemask, totalpages); | ||
491 | victim = p; | ||
492 | t = p; | ||
490 | do { | 493 | do { |
491 | list_for_each_entry(child, &t->children, sibling) { | 494 | list_for_each_entry(child, &t->children, sibling) { |
492 | unsigned int child_points; | 495 | unsigned int child_points; |
493 | 496 | ||
497 | if (child->mm == t->mm) | ||
498 | continue; | ||
494 | /* | 499 | /* |
495 | * oom_badness() returns 0 if the thread is unkillable | 500 | * oom_badness() returns 0 if the thread is unkillable |
496 | */ | 501 | */ |