diff options
Diffstat (limited to 'mm/oom_kill.c')
-rw-r--r-- | mm/oom_kill.c | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 2e3ce3a928b9..223d9ccb7d64 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -264,7 +264,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints) | |||
264 | * flag though it's unlikely that we select a process with CAP_SYS_RAW_IO | 264 | * flag though it's unlikely that we select a process with CAP_SYS_RAW_IO |
265 | * set. | 265 | * set. |
266 | */ | 266 | */ |
267 | static void __oom_kill_task(struct task_struct *p, const char *message) | 267 | static void __oom_kill_task(struct task_struct *p, int verbose) |
268 | { | 268 | { |
269 | if (is_init(p)) { | 269 | if (is_init(p)) { |
270 | WARN_ON(1); | 270 | WARN_ON(1); |
@@ -278,10 +278,8 @@ static void __oom_kill_task(struct task_struct *p, const char *message) | |||
278 | return; | 278 | return; |
279 | } | 279 | } |
280 | 280 | ||
281 | if (message) { | 281 | if (verbose) |
282 | printk(KERN_ERR "%s: Killed process %d (%s).\n", | 282 | printk(KERN_ERR "Killed process %d (%s)\n", p->pid, p->comm); |
283 | message, p->pid, p->comm); | ||
284 | } | ||
285 | 283 | ||
286 | /* | 284 | /* |
287 | * We give our sacrificial lamb high priority and access to | 285 | * We give our sacrificial lamb high priority and access to |
@@ -294,7 +292,7 @@ static void __oom_kill_task(struct task_struct *p, const char *message) | |||
294 | force_sig(SIGKILL, p); | 292 | force_sig(SIGKILL, p); |
295 | } | 293 | } |
296 | 294 | ||
297 | static int oom_kill_task(struct task_struct *p, const char *message) | 295 | static int oom_kill_task(struct task_struct *p) |
298 | { | 296 | { |
299 | struct mm_struct *mm; | 297 | struct mm_struct *mm; |
300 | struct task_struct *g, *q; | 298 | struct task_struct *g, *q; |
@@ -313,15 +311,25 @@ static int oom_kill_task(struct task_struct *p, const char *message) | |||
313 | if (mm == NULL) | 311 | if (mm == NULL) |
314 | return 1; | 312 | return 1; |
315 | 313 | ||
316 | __oom_kill_task(p, message); | 314 | /* |
315 | * Don't kill the process if any threads are set to OOM_DISABLE | ||
316 | */ | ||
317 | do_each_thread(g, q) { | ||
318 | if (q->mm == mm && p->oomkilladj == OOM_DISABLE) | ||
319 | return 1; | ||
320 | } while_each_thread(g, q); | ||
321 | |||
322 | __oom_kill_task(p, 1); | ||
323 | |||
317 | /* | 324 | /* |
318 | * kill all processes that share the ->mm (i.e. all threads), | 325 | * kill all processes that share the ->mm (i.e. all threads), |
319 | * but are in a different thread group | 326 | * but are in a different thread group. Don't let them have access |
327 | * to memory reserves though, otherwise we might deplete all memory. | ||
320 | */ | 328 | */ |
321 | do_each_thread(g, q) | 329 | do_each_thread(g, q) { |
322 | if (q->mm == mm && q->tgid != p->tgid) | 330 | if (q->mm == mm && q->tgid != p->tgid) |
323 | __oom_kill_task(q, message); | 331 | force_sig(SIGKILL, p); |
324 | while_each_thread(g, q); | 332 | } while_each_thread(g, q); |
325 | 333 | ||
326 | return 0; | 334 | return 0; |
327 | } | 335 | } |
@@ -337,21 +345,22 @@ static int oom_kill_process(struct task_struct *p, unsigned long points, | |||
337 | * its children or threads, just set TIF_MEMDIE so it can die quickly | 345 | * its children or threads, just set TIF_MEMDIE so it can die quickly |
338 | */ | 346 | */ |
339 | if (p->flags & PF_EXITING) { | 347 | if (p->flags & PF_EXITING) { |
340 | __oom_kill_task(p, NULL); | 348 | __oom_kill_task(p, 0); |
341 | return 0; | 349 | return 0; |
342 | } | 350 | } |
343 | 351 | ||
344 | printk(KERN_ERR "Out of Memory: Kill process %d (%s) score %li" | 352 | printk(KERN_ERR "%s: kill process %d (%s) score %li or a child\n", |
345 | " and children.\n", p->pid, p->comm, points); | 353 | message, p->pid, p->comm, points); |
354 | |||
346 | /* Try to kill a child first */ | 355 | /* Try to kill a child first */ |
347 | list_for_each(tsk, &p->children) { | 356 | list_for_each(tsk, &p->children) { |
348 | c = list_entry(tsk, struct task_struct, sibling); | 357 | c = list_entry(tsk, struct task_struct, sibling); |
349 | if (c->mm == p->mm) | 358 | if (c->mm == p->mm) |
350 | continue; | 359 | continue; |
351 | if (!oom_kill_task(c, message)) | 360 | if (!oom_kill_task(c)) |
352 | return 0; | 361 | return 0; |
353 | } | 362 | } |
354 | return oom_kill_task(p, message); | 363 | return oom_kill_task(p); |
355 | } | 364 | } |
356 | 365 | ||
357 | static BLOCKING_NOTIFIER_HEAD(oom_notify_list); | 366 | static BLOCKING_NOTIFIER_HEAD(oom_notify_list); |