diff options
Diffstat (limited to 'mm/oom_kill.c')
-rw-r--r-- | mm/oom_kill.c | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index b05ab8f2a562..949eba1d5ba3 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -58,15 +58,17 @@ unsigned long badness(struct task_struct *p, unsigned long uptime) | |||
58 | 58 | ||
59 | /* | 59 | /* |
60 | * Processes which fork a lot of child processes are likely | 60 | * Processes which fork a lot of child processes are likely |
61 | * a good choice. We add the vmsize of the children if they | 61 | * a good choice. We add half the vmsize of the children if they |
62 | * have an own mm. This prevents forking servers to flood the | 62 | * have an own mm. This prevents forking servers to flood the |
63 | * machine with an endless amount of children | 63 | * machine with an endless amount of children. In case a single |
64 | * child is eating the vast majority of memory, adding only half | ||
65 | * to the parents will make the child our kill candidate of choice. | ||
64 | */ | 66 | */ |
65 | list_for_each(tsk, &p->children) { | 67 | list_for_each(tsk, &p->children) { |
66 | struct task_struct *chld; | 68 | struct task_struct *chld; |
67 | chld = list_entry(tsk, struct task_struct, sibling); | 69 | chld = list_entry(tsk, struct task_struct, sibling); |
68 | if (chld->mm != p->mm && chld->mm) | 70 | if (chld->mm != p->mm && chld->mm) |
69 | points += chld->mm->total_vm; | 71 | points += chld->mm->total_vm/2 + 1; |
70 | } | 72 | } |
71 | 73 | ||
72 | /* | 74 | /* |
@@ -136,12 +138,12 @@ unsigned long badness(struct task_struct *p, unsigned long uptime) | |||
136 | * | 138 | * |
137 | * (not docbooked, we don't want this one cluttering up the manual) | 139 | * (not docbooked, we don't want this one cluttering up the manual) |
138 | */ | 140 | */ |
139 | static struct task_struct * select_bad_process(void) | 141 | static struct task_struct *select_bad_process(unsigned long *ppoints) |
140 | { | 142 | { |
141 | unsigned long maxpoints = 0; | ||
142 | struct task_struct *g, *p; | 143 | struct task_struct *g, *p; |
143 | struct task_struct *chosen = NULL; | 144 | struct task_struct *chosen = NULL; |
144 | struct timespec uptime; | 145 | struct timespec uptime; |
146 | *ppoints = 0; | ||
145 | 147 | ||
146 | do_posix_clock_monotonic_gettime(&uptime); | 148 | do_posix_clock_monotonic_gettime(&uptime); |
147 | do_each_thread(g, p) { | 149 | do_each_thread(g, p) { |
@@ -169,9 +171,9 @@ static struct task_struct * select_bad_process(void) | |||
169 | return p; | 171 | return p; |
170 | 172 | ||
171 | points = badness(p, uptime.tv_sec); | 173 | points = badness(p, uptime.tv_sec); |
172 | if (points > maxpoints || !chosen) { | 174 | if (points > *ppoints || !chosen) { |
173 | chosen = p; | 175 | chosen = p; |
174 | maxpoints = points; | 176 | *ppoints = points; |
175 | } | 177 | } |
176 | } while_each_thread(g, p); | 178 | } while_each_thread(g, p); |
177 | return chosen; | 179 | return chosen; |
@@ -237,12 +239,15 @@ static struct mm_struct *oom_kill_task(task_t *p) | |||
237 | return mm; | 239 | return mm; |
238 | } | 240 | } |
239 | 241 | ||
240 | static struct mm_struct *oom_kill_process(struct task_struct *p) | 242 | static struct mm_struct *oom_kill_process(struct task_struct *p, |
243 | unsigned long points) | ||
241 | { | 244 | { |
242 | struct mm_struct *mm; | 245 | struct mm_struct *mm; |
243 | struct task_struct *c; | 246 | struct task_struct *c; |
244 | struct list_head *tsk; | 247 | struct list_head *tsk; |
245 | 248 | ||
249 | printk(KERN_ERR "Out of Memory: Kill process %d (%s) score %li and " | ||
250 | "children.\n", p->pid, p->comm, points); | ||
246 | /* Try to kill a child first */ | 251 | /* Try to kill a child first */ |
247 | list_for_each(tsk, &p->children) { | 252 | list_for_each(tsk, &p->children) { |
248 | c = list_entry(tsk, struct task_struct, sibling); | 253 | c = list_entry(tsk, struct task_struct, sibling); |
@@ -267,6 +272,7 @@ void out_of_memory(gfp_t gfp_mask, int order) | |||
267 | { | 272 | { |
268 | struct mm_struct *mm = NULL; | 273 | struct mm_struct *mm = NULL; |
269 | task_t * p; | 274 | task_t * p; |
275 | unsigned long points; | ||
270 | 276 | ||
271 | if (printk_ratelimit()) { | 277 | if (printk_ratelimit()) { |
272 | printk("oom-killer: gfp_mask=0x%x, order=%d\n", | 278 | printk("oom-killer: gfp_mask=0x%x, order=%d\n", |
@@ -278,7 +284,7 @@ void out_of_memory(gfp_t gfp_mask, int order) | |||
278 | cpuset_lock(); | 284 | cpuset_lock(); |
279 | read_lock(&tasklist_lock); | 285 | read_lock(&tasklist_lock); |
280 | retry: | 286 | retry: |
281 | p = select_bad_process(); | 287 | p = select_bad_process(&points); |
282 | 288 | ||
283 | if (PTR_ERR(p) == -1UL) | 289 | if (PTR_ERR(p) == -1UL) |
284 | goto out; | 290 | goto out; |
@@ -290,7 +296,7 @@ retry: | |||
290 | panic("Out of memory and no killable processes...\n"); | 296 | panic("Out of memory and no killable processes...\n"); |
291 | } | 297 | } |
292 | 298 | ||
293 | mm = oom_kill_process(p); | 299 | mm = oom_kill_process(p, points); |
294 | if (!mm) | 300 | if (!mm) |
295 | goto retry; | 301 | goto retry; |
296 | 302 | ||