diff options
Diffstat (limited to 'mm/oom_kill.c')
| -rw-r--r-- | mm/oom_kill.c | 49 |
1 files changed, 26 insertions, 23 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index fc81cb22869e..4029583a1024 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
| @@ -121,8 +121,8 @@ struct task_struct *find_lock_task_mm(struct task_struct *p) | |||
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | /* return true if the task is not adequate as candidate victim task. */ | 123 | /* return true if the task is not adequate as candidate victim task. */ |
| 124 | static bool oom_unkillable_task(struct task_struct *p, struct mem_cgroup *mem, | 124 | static bool oom_unkillable_task(struct task_struct *p, |
| 125 | const nodemask_t *nodemask) | 125 | const struct mem_cgroup *mem, const nodemask_t *nodemask) |
| 126 | { | 126 | { |
| 127 | if (is_global_init(p)) | 127 | if (is_global_init(p)) |
| 128 | return true; | 128 | return true; |
| @@ -208,8 +208,13 @@ unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem, | |||
| 208 | */ | 208 | */ |
| 209 | points += p->signal->oom_score_adj; | 209 | points += p->signal->oom_score_adj; |
| 210 | 210 | ||
| 211 | if (points < 0) | 211 | /* |
| 212 | return 0; | 212 | * Never return 0 for an eligible task that may be killed since it's |
| 213 | * possible that no single user task uses more than 0.1% of memory and | ||
| 214 | * no single admin tasks uses more than 3.0%. | ||
| 215 | */ | ||
| 216 | if (points <= 0) | ||
| 217 | return 1; | ||
| 213 | return (points < 1000) ? points : 1000; | 218 | return (points < 1000) ? points : 1000; |
| 214 | } | 219 | } |
| 215 | 220 | ||
| @@ -339,26 +344,24 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, | |||
| 339 | /** | 344 | /** |
| 340 | * dump_tasks - dump current memory state of all system tasks | 345 | * dump_tasks - dump current memory state of all system tasks |
| 341 | * @mem: current's memory controller, if constrained | 346 | * @mem: current's memory controller, if constrained |
| 347 | * @nodemask: nodemask passed to page allocator for mempolicy ooms | ||
| 342 | * | 348 | * |
| 343 | * Dumps the current memory state of all system tasks, excluding kernel threads. | 349 | * Dumps the current memory state of all eligible tasks. Tasks not in the same |
| 350 | * memcg, not in the same cpuset, or bound to a disjoint set of mempolicy nodes | ||
| 351 | * are not shown. | ||
| 344 | * State information includes task's pid, uid, tgid, vm size, rss, cpu, oom_adj | 352 | * State information includes task's pid, uid, tgid, vm size, rss, cpu, oom_adj |
| 345 | * value, oom_score_adj value, and name. | 353 | * value, oom_score_adj value, and name. |
| 346 | * | 354 | * |
| 347 | * If the actual is non-NULL, only tasks that are a member of the mem_cgroup are | ||
| 348 | * shown. | ||
| 349 | * | ||
| 350 | * Call with tasklist_lock read-locked. | 355 | * Call with tasklist_lock read-locked. |
| 351 | */ | 356 | */ |
| 352 | static void dump_tasks(const struct mem_cgroup *mem) | 357 | static void dump_tasks(const struct mem_cgroup *mem, const nodemask_t *nodemask) |
| 353 | { | 358 | { |
| 354 | struct task_struct *p; | 359 | struct task_struct *p; |
| 355 | struct task_struct *task; | 360 | struct task_struct *task; |
| 356 | 361 | ||
| 357 | pr_info("[ pid ] uid tgid total_vm rss cpu oom_adj oom_score_adj name\n"); | 362 | pr_info("[ pid ] uid tgid total_vm rss cpu oom_adj oom_score_adj name\n"); |
| 358 | for_each_process(p) { | 363 | for_each_process(p) { |
| 359 | if (p->flags & PF_KTHREAD) | 364 | if (oom_unkillable_task(p, mem, nodemask)) |
| 360 | continue; | ||
| 361 | if (mem && !task_in_mem_cgroup(p, mem)) | ||
| 362 | continue; | 365 | continue; |
| 363 | 366 | ||
| 364 | task = find_lock_task_mm(p); | 367 | task = find_lock_task_mm(p); |
| @@ -381,7 +384,7 @@ static void dump_tasks(const struct mem_cgroup *mem) | |||
| 381 | } | 384 | } |
| 382 | 385 | ||
| 383 | static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order, | 386 | static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order, |
| 384 | struct mem_cgroup *mem) | 387 | struct mem_cgroup *mem, const nodemask_t *nodemask) |
| 385 | { | 388 | { |
| 386 | task_lock(current); | 389 | task_lock(current); |
| 387 | pr_warning("%s invoked oom-killer: gfp_mask=0x%x, order=%d, " | 390 | pr_warning("%s invoked oom-killer: gfp_mask=0x%x, order=%d, " |
| @@ -394,7 +397,7 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order, | |||
| 394 | mem_cgroup_print_oom_info(mem, p); | 397 | mem_cgroup_print_oom_info(mem, p); |
| 395 | show_mem(); | 398 | show_mem(); |
| 396 | if (sysctl_oom_dump_tasks) | 399 | if (sysctl_oom_dump_tasks) |
| 397 | dump_tasks(mem); | 400 | dump_tasks(mem, nodemask); |
| 398 | } | 401 | } |
| 399 | 402 | ||
| 400 | #define K(x) ((x) << (PAGE_SHIFT-10)) | 403 | #define K(x) ((x) << (PAGE_SHIFT-10)) |
| @@ -436,7 +439,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, | |||
| 436 | unsigned int victim_points = 0; | 439 | unsigned int victim_points = 0; |
| 437 | 440 | ||
| 438 | if (printk_ratelimit()) | 441 | if (printk_ratelimit()) |
| 439 | dump_header(p, gfp_mask, order, mem); | 442 | dump_header(p, gfp_mask, order, mem, nodemask); |
| 440 | 443 | ||
| 441 | /* | 444 | /* |
| 442 | * If the task is already exiting, don't alarm the sysadmin or kill | 445 | * If the task is already exiting, don't alarm the sysadmin or kill |
| @@ -482,7 +485,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, | |||
| 482 | * Determines whether the kernel must panic because of the panic_on_oom sysctl. | 485 | * Determines whether the kernel must panic because of the panic_on_oom sysctl. |
| 483 | */ | 486 | */ |
| 484 | static void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask, | 487 | static void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask, |
| 485 | int order) | 488 | int order, const nodemask_t *nodemask) |
| 486 | { | 489 | { |
| 487 | if (likely(!sysctl_panic_on_oom)) | 490 | if (likely(!sysctl_panic_on_oom)) |
| 488 | return; | 491 | return; |
| @@ -496,7 +499,7 @@ static void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask, | |||
| 496 | return; | 499 | return; |
| 497 | } | 500 | } |
| 498 | read_lock(&tasklist_lock); | 501 | read_lock(&tasklist_lock); |
| 499 | dump_header(NULL, gfp_mask, order, NULL); | 502 | dump_header(NULL, gfp_mask, order, NULL, nodemask); |
| 500 | read_unlock(&tasklist_lock); | 503 | read_unlock(&tasklist_lock); |
| 501 | panic("Out of memory: %s panic_on_oom is enabled\n", | 504 | panic("Out of memory: %s panic_on_oom is enabled\n", |
| 502 | sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide"); | 505 | sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide"); |
| @@ -509,7 +512,7 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask) | |||
| 509 | unsigned int points = 0; | 512 | unsigned int points = 0; |
| 510 | struct task_struct *p; | 513 | struct task_struct *p; |
| 511 | 514 | ||
| 512 | check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, 0); | 515 | check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, 0, NULL); |
| 513 | limit = mem_cgroup_get_limit(mem) >> PAGE_SHIFT; | 516 | limit = mem_cgroup_get_limit(mem) >> PAGE_SHIFT; |
| 514 | read_lock(&tasklist_lock); | 517 | read_lock(&tasklist_lock); |
| 515 | retry: | 518 | retry: |
| @@ -641,6 +644,7 @@ static void clear_system_oom(void) | |||
| 641 | void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, | 644 | void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, |
| 642 | int order, nodemask_t *nodemask) | 645 | int order, nodemask_t *nodemask) |
| 643 | { | 646 | { |
| 647 | const nodemask_t *mpol_mask; | ||
| 644 | struct task_struct *p; | 648 | struct task_struct *p; |
| 645 | unsigned long totalpages; | 649 | unsigned long totalpages; |
| 646 | unsigned long freed = 0; | 650 | unsigned long freed = 0; |
| @@ -670,7 +674,8 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, | |||
| 670 | */ | 674 | */ |
| 671 | constraint = constrained_alloc(zonelist, gfp_mask, nodemask, | 675 | constraint = constrained_alloc(zonelist, gfp_mask, nodemask, |
| 672 | &totalpages); | 676 | &totalpages); |
| 673 | check_panic_on_oom(constraint, gfp_mask, order); | 677 | mpol_mask = (constraint == CONSTRAINT_MEMORY_POLICY) ? nodemask : NULL; |
| 678 | check_panic_on_oom(constraint, gfp_mask, order, mpol_mask); | ||
| 674 | 679 | ||
| 675 | read_lock(&tasklist_lock); | 680 | read_lock(&tasklist_lock); |
| 676 | if (sysctl_oom_kill_allocating_task && | 681 | if (sysctl_oom_kill_allocating_task && |
| @@ -688,15 +693,13 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, | |||
| 688 | } | 693 | } |
| 689 | 694 | ||
| 690 | retry: | 695 | retry: |
| 691 | p = select_bad_process(&points, totalpages, NULL, | 696 | p = select_bad_process(&points, totalpages, NULL, mpol_mask); |
| 692 | constraint == CONSTRAINT_MEMORY_POLICY ? nodemask : | ||
| 693 | NULL); | ||
| 694 | if (PTR_ERR(p) == -1UL) | 697 | if (PTR_ERR(p) == -1UL) |
| 695 | goto out; | 698 | goto out; |
| 696 | 699 | ||
| 697 | /* Found nothing?!?! Either we hang forever, or we panic. */ | 700 | /* Found nothing?!?! Either we hang forever, or we panic. */ |
| 698 | if (!p) { | 701 | if (!p) { |
| 699 | dump_header(NULL, gfp_mask, order, NULL); | 702 | dump_header(NULL, gfp_mask, order, NULL, mpol_mask); |
| 700 | read_unlock(&tasklist_lock); | 703 | read_unlock(&tasklist_lock); |
| 701 | panic("Out of memory and no killable processes...\n"); | 704 | panic("Out of memory and no killable processes...\n"); |
| 702 | } | 705 | } |
