diff options
author | Vladimir Davydov <vdavydov@virtuozzo.com> | 2016-07-26 18:22:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-26 19:19:19 -0400 |
commit | 2a966b77ae3ede207e787e7538b87d1011c4364e (patch) | |
tree | b6fe80a56c921cb230443eff6bee65aa2372883c | |
parent | 798fd756952c4b6cb7dfe6f6437e9f02da79a5bc (diff) |
mm: oom: add memcg to oom_control
It's a part of oom context just like allocation order and nodemask, so
let's move it to oom_control instead of passing it in the argument list.
Link: http://lkml.kernel.org/r/40e03fd7aaf1f55c75d787128d6d17c5a71226c2.1464358556.git.vdavydov@virtuozzo.com
Signed-off-by: Vladimir Davydov <vdavydov@virtuozzo.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Cc: David Rientjes <rientjes@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/tty/sysrq.c | 1 | ||||
-rw-r--r-- | include/linux/oom.h | 8 | ||||
-rw-r--r-- | mm/memcontrol.c | 5 | ||||
-rw-r--r-- | mm/oom_kill.c | 32 | ||||
-rw-r--r-- | mm/page_alloc.c | 1 |
5 files changed, 25 insertions, 22 deletions
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index e5139402e7f8..52bbd27e93ae 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c | |||
@@ -363,6 +363,7 @@ static void moom_callback(struct work_struct *ignored) | |||
363 | struct oom_control oc = { | 363 | struct oom_control oc = { |
364 | .zonelist = node_zonelist(first_memory_node, gfp_mask), | 364 | .zonelist = node_zonelist(first_memory_node, gfp_mask), |
365 | .nodemask = NULL, | 365 | .nodemask = NULL, |
366 | .memcg = NULL, | ||
366 | .gfp_mask = gfp_mask, | 367 | .gfp_mask = gfp_mask, |
367 | .order = -1, | 368 | .order = -1, |
368 | }; | 369 | }; |
diff --git a/include/linux/oom.h b/include/linux/oom.h index 83469522690a..cbc24a5fe28d 100644 --- a/include/linux/oom.h +++ b/include/linux/oom.h | |||
@@ -23,6 +23,9 @@ struct oom_control { | |||
23 | /* Used to determine mempolicy */ | 23 | /* Used to determine mempolicy */ |
24 | nodemask_t *nodemask; | 24 | nodemask_t *nodemask; |
25 | 25 | ||
26 | /* Memory cgroup in which oom is invoked, or NULL for global oom */ | ||
27 | struct mem_cgroup *memcg; | ||
28 | |||
26 | /* Used to determine cpuset and node locality requirement */ | 29 | /* Used to determine cpuset and node locality requirement */ |
27 | const gfp_t gfp_mask; | 30 | const gfp_t gfp_mask; |
28 | 31 | ||
@@ -83,11 +86,10 @@ extern unsigned long oom_badness(struct task_struct *p, | |||
83 | 86 | ||
84 | extern void oom_kill_process(struct oom_control *oc, struct task_struct *p, | 87 | extern void oom_kill_process(struct oom_control *oc, struct task_struct *p, |
85 | unsigned int points, unsigned long totalpages, | 88 | unsigned int points, unsigned long totalpages, |
86 | struct mem_cgroup *memcg, const char *message); | 89 | const char *message); |
87 | 90 | ||
88 | extern void check_panic_on_oom(struct oom_control *oc, | 91 | extern void check_panic_on_oom(struct oom_control *oc, |
89 | enum oom_constraint constraint, | 92 | enum oom_constraint constraint); |
90 | struct mem_cgroup *memcg); | ||
91 | 93 | ||
92 | extern enum oom_scan_t oom_scan_process_thread(struct oom_control *oc, | 94 | extern enum oom_scan_t oom_scan_process_thread(struct oom_control *oc, |
93 | struct task_struct *task, unsigned long totalpages); | 95 | struct task_struct *task, unsigned long totalpages); |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 3a755212448e..caea25a21c70 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -1259,6 +1259,7 @@ static bool mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, | |||
1259 | struct oom_control oc = { | 1259 | struct oom_control oc = { |
1260 | .zonelist = NULL, | 1260 | .zonelist = NULL, |
1261 | .nodemask = NULL, | 1261 | .nodemask = NULL, |
1262 | .memcg = memcg, | ||
1262 | .gfp_mask = gfp_mask, | 1263 | .gfp_mask = gfp_mask, |
1263 | .order = order, | 1264 | .order = order, |
1264 | }; | 1265 | }; |
@@ -1281,7 +1282,7 @@ static bool mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, | |||
1281 | goto unlock; | 1282 | goto unlock; |
1282 | } | 1283 | } |
1283 | 1284 | ||
1284 | check_panic_on_oom(&oc, CONSTRAINT_MEMCG, memcg); | 1285 | check_panic_on_oom(&oc, CONSTRAINT_MEMCG); |
1285 | totalpages = mem_cgroup_get_limit(memcg) ? : 1; | 1286 | totalpages = mem_cgroup_get_limit(memcg) ? : 1; |
1286 | for_each_mem_cgroup_tree(iter, memcg) { | 1287 | for_each_mem_cgroup_tree(iter, memcg) { |
1287 | struct css_task_iter it; | 1288 | struct css_task_iter it; |
@@ -1329,7 +1330,7 @@ static bool mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, | |||
1329 | 1330 | ||
1330 | if (chosen) { | 1331 | if (chosen) { |
1331 | points = chosen_points * 1000 / totalpages; | 1332 | points = chosen_points * 1000 / totalpages; |
1332 | oom_kill_process(&oc, chosen, points, totalpages, memcg, | 1333 | oom_kill_process(&oc, chosen, points, totalpages, |
1333 | "Memory cgroup out of memory"); | 1334 | "Memory cgroup out of memory"); |
1334 | } | 1335 | } |
1335 | unlock: | 1336 | unlock: |
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 398c245a484a..a376f1ebdad5 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -383,8 +383,7 @@ static void dump_tasks(struct mem_cgroup *memcg, const nodemask_t *nodemask) | |||
383 | rcu_read_unlock(); | 383 | rcu_read_unlock(); |
384 | } | 384 | } |
385 | 385 | ||
386 | static void dump_header(struct oom_control *oc, struct task_struct *p, | 386 | static void dump_header(struct oom_control *oc, struct task_struct *p) |
387 | struct mem_cgroup *memcg) | ||
388 | { | 387 | { |
389 | pr_warn("%s invoked oom-killer: gfp_mask=%#x(%pGg), order=%d, oom_score_adj=%hd\n", | 388 | pr_warn("%s invoked oom-killer: gfp_mask=%#x(%pGg), order=%d, oom_score_adj=%hd\n", |
390 | current->comm, oc->gfp_mask, &oc->gfp_mask, oc->order, | 389 | current->comm, oc->gfp_mask, &oc->gfp_mask, oc->order, |
@@ -392,12 +391,12 @@ static void dump_header(struct oom_control *oc, struct task_struct *p, | |||
392 | 391 | ||
393 | cpuset_print_current_mems_allowed(); | 392 | cpuset_print_current_mems_allowed(); |
394 | dump_stack(); | 393 | dump_stack(); |
395 | if (memcg) | 394 | if (oc->memcg) |
396 | mem_cgroup_print_oom_info(memcg, p); | 395 | mem_cgroup_print_oom_info(oc->memcg, p); |
397 | else | 396 | else |
398 | show_mem(SHOW_MEM_FILTER_NODES); | 397 | show_mem(SHOW_MEM_FILTER_NODES); |
399 | if (sysctl_oom_dump_tasks) | 398 | if (sysctl_oom_dump_tasks) |
400 | dump_tasks(memcg, oc->nodemask); | 399 | dump_tasks(oc->memcg, oc->nodemask); |
401 | } | 400 | } |
402 | 401 | ||
403 | /* | 402 | /* |
@@ -739,7 +738,7 @@ void oom_killer_enable(void) | |||
739 | */ | 738 | */ |
740 | void oom_kill_process(struct oom_control *oc, struct task_struct *p, | 739 | void oom_kill_process(struct oom_control *oc, struct task_struct *p, |
741 | unsigned int points, unsigned long totalpages, | 740 | unsigned int points, unsigned long totalpages, |
742 | struct mem_cgroup *memcg, const char *message) | 741 | const char *message) |
743 | { | 742 | { |
744 | struct task_struct *victim = p; | 743 | struct task_struct *victim = p; |
745 | struct task_struct *child; | 744 | struct task_struct *child; |
@@ -765,7 +764,7 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p, | |||
765 | task_unlock(p); | 764 | task_unlock(p); |
766 | 765 | ||
767 | if (__ratelimit(&oom_rs)) | 766 | if (__ratelimit(&oom_rs)) |
768 | dump_header(oc, p, memcg); | 767 | dump_header(oc, p); |
769 | 768 | ||
770 | pr_err("%s: Kill process %d (%s) score %u or sacrifice child\n", | 769 | pr_err("%s: Kill process %d (%s) score %u or sacrifice child\n", |
771 | message, task_pid_nr(p), p->comm, points); | 770 | message, task_pid_nr(p), p->comm, points); |
@@ -786,8 +785,8 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p, | |||
786 | /* | 785 | /* |
787 | * oom_badness() returns 0 if the thread is unkillable | 786 | * oom_badness() returns 0 if the thread is unkillable |
788 | */ | 787 | */ |
789 | child_points = oom_badness(child, memcg, oc->nodemask, | 788 | child_points = oom_badness(child, |
790 | totalpages); | 789 | oc->memcg, oc->nodemask, totalpages); |
791 | if (child_points > victim_points) { | 790 | if (child_points > victim_points) { |
792 | put_task_struct(victim); | 791 | put_task_struct(victim); |
793 | victim = child; | 792 | victim = child; |
@@ -865,8 +864,7 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p, | |||
865 | /* | 864 | /* |
866 | * Determines whether the kernel must panic because of the panic_on_oom sysctl. | 865 | * Determines whether the kernel must panic because of the panic_on_oom sysctl. |
867 | */ | 866 | */ |
868 | void check_panic_on_oom(struct oom_control *oc, enum oom_constraint constraint, | 867 | void check_panic_on_oom(struct oom_control *oc, enum oom_constraint constraint) |
869 | struct mem_cgroup *memcg) | ||
870 | { | 868 | { |
871 | if (likely(!sysctl_panic_on_oom)) | 869 | if (likely(!sysctl_panic_on_oom)) |
872 | return; | 870 | return; |
@@ -882,7 +880,7 @@ void check_panic_on_oom(struct oom_control *oc, enum oom_constraint constraint, | |||
882 | /* Do not panic for oom kills triggered by sysrq */ | 880 | /* Do not panic for oom kills triggered by sysrq */ |
883 | if (is_sysrq_oom(oc)) | 881 | if (is_sysrq_oom(oc)) |
884 | return; | 882 | return; |
885 | dump_header(oc, NULL, memcg); | 883 | dump_header(oc, NULL); |
886 | panic("Out of memory: %s panic_on_oom is enabled\n", | 884 | panic("Out of memory: %s panic_on_oom is enabled\n", |
887 | sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide"); | 885 | sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide"); |
888 | } | 886 | } |
@@ -957,13 +955,13 @@ bool out_of_memory(struct oom_control *oc) | |||
957 | constraint = constrained_alloc(oc, &totalpages); | 955 | constraint = constrained_alloc(oc, &totalpages); |
958 | if (constraint != CONSTRAINT_MEMORY_POLICY) | 956 | if (constraint != CONSTRAINT_MEMORY_POLICY) |
959 | oc->nodemask = NULL; | 957 | oc->nodemask = NULL; |
960 | check_panic_on_oom(oc, constraint, NULL); | 958 | check_panic_on_oom(oc, constraint); |
961 | 959 | ||
962 | if (sysctl_oom_kill_allocating_task && current->mm && | 960 | if (sysctl_oom_kill_allocating_task && current->mm && |
963 | !oom_unkillable_task(current, NULL, oc->nodemask) && | 961 | !oom_unkillable_task(current, NULL, oc->nodemask) && |
964 | current->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) { | 962 | current->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) { |
965 | get_task_struct(current); | 963 | get_task_struct(current); |
966 | oom_kill_process(oc, current, 0, totalpages, NULL, | 964 | oom_kill_process(oc, current, 0, totalpages, |
967 | "Out of memory (oom_kill_allocating_task)"); | 965 | "Out of memory (oom_kill_allocating_task)"); |
968 | return true; | 966 | return true; |
969 | } | 967 | } |
@@ -971,12 +969,11 @@ bool out_of_memory(struct oom_control *oc) | |||
971 | p = select_bad_process(oc, &points, totalpages); | 969 | p = select_bad_process(oc, &points, totalpages); |
972 | /* Found nothing?!?! Either we hang forever, or we panic. */ | 970 | /* Found nothing?!?! Either we hang forever, or we panic. */ |
973 | if (!p && !is_sysrq_oom(oc)) { | 971 | if (!p && !is_sysrq_oom(oc)) { |
974 | dump_header(oc, NULL, NULL); | 972 | dump_header(oc, NULL); |
975 | panic("Out of memory and no killable processes...\n"); | 973 | panic("Out of memory and no killable processes...\n"); |
976 | } | 974 | } |
977 | if (p && p != (void *)-1UL) { | 975 | if (p && p != (void *)-1UL) { |
978 | oom_kill_process(oc, p, points, totalpages, NULL, | 976 | oom_kill_process(oc, p, points, totalpages, "Out of memory"); |
979 | "Out of memory"); | ||
980 | /* | 977 | /* |
981 | * Give the killed process a good chance to exit before trying | 978 | * Give the killed process a good chance to exit before trying |
982 | * to allocate memory again. | 979 | * to allocate memory again. |
@@ -996,6 +993,7 @@ void pagefault_out_of_memory(void) | |||
996 | struct oom_control oc = { | 993 | struct oom_control oc = { |
997 | .zonelist = NULL, | 994 | .zonelist = NULL, |
998 | .nodemask = NULL, | 995 | .nodemask = NULL, |
996 | .memcg = NULL, | ||
999 | .gfp_mask = 0, | 997 | .gfp_mask = 0, |
1000 | .order = 0, | 998 | .order = 0, |
1001 | }; | 999 | }; |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 8129922a1504..f7bb1aef54f2 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -3105,6 +3105,7 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order, | |||
3105 | struct oom_control oc = { | 3105 | struct oom_control oc = { |
3106 | .zonelist = ac->zonelist, | 3106 | .zonelist = ac->zonelist, |
3107 | .nodemask = ac->nodemask, | 3107 | .nodemask = ac->nodemask, |
3108 | .memcg = NULL, | ||
3108 | .gfp_mask = gfp_mask, | 3109 | .gfp_mask = gfp_mask, |
3109 | .order = order, | 3110 | .order = order, |
3110 | }; | 3111 | }; |