diff options
| -rw-r--r-- | mm/oom_kill.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 78747afad6b0..9a643c4bf77c 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
| @@ -46,15 +46,25 @@ | |||
| 46 | unsigned long badness(struct task_struct *p, unsigned long uptime) | 46 | unsigned long badness(struct task_struct *p, unsigned long uptime) |
| 47 | { | 47 | { |
| 48 | unsigned long points, cpu_time, run_time, s; | 48 | unsigned long points, cpu_time, run_time, s; |
| 49 | struct list_head *tsk; | 49 | struct mm_struct *mm; |
| 50 | struct task_struct *child; | ||
| 50 | 51 | ||
| 51 | if (!p->mm) | 52 | task_lock(p); |
| 53 | mm = p->mm; | ||
| 54 | if (!mm) { | ||
| 55 | task_unlock(p); | ||
| 52 | return 0; | 56 | return 0; |
| 57 | } | ||
| 53 | 58 | ||
| 54 | /* | 59 | /* |
| 55 | * The memory size of the process is the basis for the badness. | 60 | * The memory size of the process is the basis for the badness. |
| 56 | */ | 61 | */ |
| 57 | points = p->mm->total_vm; | 62 | points = mm->total_vm; |
| 63 | |||
| 64 | /* | ||
| 65 | * After this unlock we can no longer dereference local variable `mm' | ||
| 66 | */ | ||
| 67 | task_unlock(p); | ||
| 58 | 68 | ||
| 59 | /* | 69 | /* |
| 60 | * Processes which fork a lot of child processes are likely | 70 | * Processes which fork a lot of child processes are likely |
| @@ -64,11 +74,11 @@ unsigned long badness(struct task_struct *p, unsigned long uptime) | |||
| 64 | * child is eating the vast majority of memory, adding only half | 74 | * child is eating the vast majority of memory, adding only half |
| 65 | * to the parents will make the child our kill candidate of choice. | 75 | * to the parents will make the child our kill candidate of choice. |
| 66 | */ | 76 | */ |
| 67 | list_for_each(tsk, &p->children) { | 77 | list_for_each_entry(child, &p->children, sibling) { |
| 68 | struct task_struct *chld; | 78 | task_lock(child); |
| 69 | chld = list_entry(tsk, struct task_struct, sibling); | 79 | if (child->mm != mm && child->mm) |
| 70 | if (chld->mm != p->mm && chld->mm) | 80 | points += child->mm->total_vm/2 + 1; |
| 71 | points += chld->mm->total_vm/2 + 1; | 81 | task_unlock(child); |
| 72 | } | 82 | } |
| 73 | 83 | ||
| 74 | /* | 84 | /* |
