Commit 2a966b77 authored by Vladimir Davydov's avatar Vladimir Davydov Committed by Linus Torvalds

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.comSigned-off-by: default avatarVladimir Davydov <vdavydov@virtuozzo.com>
Acked-by: default avatarMichal Hocko <mhocko@suse.com>
Acked-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Cc: David Rientjes <rientjes@google.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 798fd756
...@@ -363,6 +363,7 @@ static void moom_callback(struct work_struct *ignored) ...@@ -363,6 +363,7 @@ static void moom_callback(struct work_struct *ignored)
struct oom_control oc = { struct oom_control oc = {
.zonelist = node_zonelist(first_memory_node, gfp_mask), .zonelist = node_zonelist(first_memory_node, gfp_mask),
.nodemask = NULL, .nodemask = NULL,
.memcg = NULL,
.gfp_mask = gfp_mask, .gfp_mask = gfp_mask,
.order = -1, .order = -1,
}; };
......
...@@ -23,6 +23,9 @@ struct oom_control { ...@@ -23,6 +23,9 @@ struct oom_control {
/* Used to determine mempolicy */ /* Used to determine mempolicy */
nodemask_t *nodemask; nodemask_t *nodemask;
/* Memory cgroup in which oom is invoked, or NULL for global oom */
struct mem_cgroup *memcg;
/* Used to determine cpuset and node locality requirement */ /* Used to determine cpuset and node locality requirement */
const gfp_t gfp_mask; const gfp_t gfp_mask;
...@@ -83,11 +86,10 @@ extern unsigned long oom_badness(struct task_struct *p, ...@@ -83,11 +86,10 @@ extern unsigned long oom_badness(struct task_struct *p,
extern void oom_kill_process(struct oom_control *oc, struct task_struct *p, extern void oom_kill_process(struct oom_control *oc, struct task_struct *p,
unsigned int points, unsigned long totalpages, unsigned int points, unsigned long totalpages,
struct mem_cgroup *memcg, const char *message); const char *message);
extern void check_panic_on_oom(struct oom_control *oc, extern void check_panic_on_oom(struct oom_control *oc,
enum oom_constraint constraint, enum oom_constraint constraint);
struct mem_cgroup *memcg);
extern enum oom_scan_t oom_scan_process_thread(struct oom_control *oc, extern enum oom_scan_t oom_scan_process_thread(struct oom_control *oc,
struct task_struct *task, unsigned long totalpages); struct task_struct *task, unsigned long totalpages);
......
...@@ -1259,6 +1259,7 @@ static bool mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, ...@@ -1259,6 +1259,7 @@ static bool mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
struct oom_control oc = { struct oom_control oc = {
.zonelist = NULL, .zonelist = NULL,
.nodemask = NULL, .nodemask = NULL,
.memcg = memcg,
.gfp_mask = gfp_mask, .gfp_mask = gfp_mask,
.order = order, .order = order,
}; };
...@@ -1281,7 +1282,7 @@ static bool mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, ...@@ -1281,7 +1282,7 @@ static bool mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
goto unlock; goto unlock;
} }
check_panic_on_oom(&oc, CONSTRAINT_MEMCG, memcg); check_panic_on_oom(&oc, CONSTRAINT_MEMCG);
totalpages = mem_cgroup_get_limit(memcg) ? : 1; totalpages = mem_cgroup_get_limit(memcg) ? : 1;
for_each_mem_cgroup_tree(iter, memcg) { for_each_mem_cgroup_tree(iter, memcg) {
struct css_task_iter it; 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,7 +1330,7 @@ static bool mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
if (chosen) { if (chosen) {
points = chosen_points * 1000 / totalpages; points = chosen_points * 1000 / totalpages;
oom_kill_process(&oc, chosen, points, totalpages, memcg, oom_kill_process(&oc, chosen, points, totalpages,
"Memory cgroup out of memory"); "Memory cgroup out of memory");
} }
unlock: unlock:
......
...@@ -383,8 +383,7 @@ static void dump_tasks(struct mem_cgroup *memcg, const nodemask_t *nodemask) ...@@ -383,8 +383,7 @@ static void dump_tasks(struct mem_cgroup *memcg, const nodemask_t *nodemask)
rcu_read_unlock(); rcu_read_unlock();
} }
static void dump_header(struct oom_control *oc, struct task_struct *p, static void dump_header(struct oom_control *oc, struct task_struct *p)
struct mem_cgroup *memcg)
{ {
pr_warn("%s invoked oom-killer: gfp_mask=%#x(%pGg), order=%d, oom_score_adj=%hd\n", pr_warn("%s invoked oom-killer: gfp_mask=%#x(%pGg), order=%d, oom_score_adj=%hd\n",
current->comm, oc->gfp_mask, &oc->gfp_mask, oc->order, 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,12 +391,12 @@ static void dump_header(struct oom_control *oc, struct task_struct *p,
cpuset_print_current_mems_allowed(); cpuset_print_current_mems_allowed();
dump_stack(); dump_stack();
if (memcg) if (oc->memcg)
mem_cgroup_print_oom_info(memcg, p); mem_cgroup_print_oom_info(oc->memcg, p);
else else
show_mem(SHOW_MEM_FILTER_NODES); show_mem(SHOW_MEM_FILTER_NODES);
if (sysctl_oom_dump_tasks) if (sysctl_oom_dump_tasks)
dump_tasks(memcg, oc->nodemask); dump_tasks(oc->memcg, oc->nodemask);
} }
/* /*
...@@ -739,7 +738,7 @@ void oom_killer_enable(void) ...@@ -739,7 +738,7 @@ void oom_killer_enable(void)
*/ */
void oom_kill_process(struct oom_control *oc, struct task_struct *p, void oom_kill_process(struct oom_control *oc, struct task_struct *p,
unsigned int points, unsigned long totalpages, unsigned int points, unsigned long totalpages,
struct mem_cgroup *memcg, const char *message) const char *message)
{ {
struct task_struct *victim = p; struct task_struct *victim = p;
struct task_struct *child; struct task_struct *child;
...@@ -765,7 +764,7 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p, ...@@ -765,7 +764,7 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p,
task_unlock(p); task_unlock(p);
if (__ratelimit(&oom_rs)) if (__ratelimit(&oom_rs))
dump_header(oc, p, memcg); dump_header(oc, p);
pr_err("%s: Kill process %d (%s) score %u or sacrifice child\n", pr_err("%s: Kill process %d (%s) score %u or sacrifice child\n",
message, task_pid_nr(p), p->comm, points); 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,8 +785,8 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p,
/* /*
* oom_badness() returns 0 if the thread is unkillable * oom_badness() returns 0 if the thread is unkillable
*/ */
child_points = oom_badness(child, memcg, oc->nodemask, child_points = oom_badness(child,
totalpages); oc->memcg, oc->nodemask, totalpages);
if (child_points > victim_points) { if (child_points > victim_points) {
put_task_struct(victim); put_task_struct(victim);
victim = child; victim = child;
...@@ -865,8 +864,7 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p, ...@@ -865,8 +864,7 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p,
/* /*
* Determines whether the kernel must panic because of the panic_on_oom sysctl. * Determines whether the kernel must panic because of the panic_on_oom sysctl.
*/ */
void check_panic_on_oom(struct oom_control *oc, enum oom_constraint constraint, void check_panic_on_oom(struct oom_control *oc, enum oom_constraint constraint)
struct mem_cgroup *memcg)
{ {
if (likely(!sysctl_panic_on_oom)) if (likely(!sysctl_panic_on_oom))
return; return;
...@@ -882,7 +880,7 @@ void check_panic_on_oom(struct oom_control *oc, enum oom_constraint constraint, ...@@ -882,7 +880,7 @@ void check_panic_on_oom(struct oom_control *oc, enum oom_constraint constraint,
/* Do not panic for oom kills triggered by sysrq */ /* Do not panic for oom kills triggered by sysrq */
if (is_sysrq_oom(oc)) if (is_sysrq_oom(oc))
return; return;
dump_header(oc, NULL, memcg); dump_header(oc, NULL);
panic("Out of memory: %s panic_on_oom is enabled\n", panic("Out of memory: %s panic_on_oom is enabled\n",
sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide"); sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide");
} }
...@@ -957,13 +955,13 @@ bool out_of_memory(struct oom_control *oc) ...@@ -957,13 +955,13 @@ bool out_of_memory(struct oom_control *oc)
constraint = constrained_alloc(oc, &totalpages); constraint = constrained_alloc(oc, &totalpages);
if (constraint != CONSTRAINT_MEMORY_POLICY) if (constraint != CONSTRAINT_MEMORY_POLICY)
oc->nodemask = NULL; oc->nodemask = NULL;
check_panic_on_oom(oc, constraint, NULL); check_panic_on_oom(oc, constraint);
if (sysctl_oom_kill_allocating_task && current->mm && if (sysctl_oom_kill_allocating_task && current->mm &&
!oom_unkillable_task(current, NULL, oc->nodemask) && !oom_unkillable_task(current, NULL, oc->nodemask) &&
current->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) { current->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) {
get_task_struct(current); get_task_struct(current);
oom_kill_process(oc, current, 0, totalpages, NULL, oom_kill_process(oc, current, 0, totalpages,
"Out of memory (oom_kill_allocating_task)"); "Out of memory (oom_kill_allocating_task)");
return true; return true;
} }
...@@ -971,12 +969,11 @@ bool out_of_memory(struct oom_control *oc) ...@@ -971,12 +969,11 @@ bool out_of_memory(struct oom_control *oc)
p = select_bad_process(oc, &points, totalpages); p = select_bad_process(oc, &points, totalpages);
/* Found nothing?!?! Either we hang forever, or we panic. */ /* Found nothing?!?! Either we hang forever, or we panic. */
if (!p && !is_sysrq_oom(oc)) { if (!p && !is_sysrq_oom(oc)) {
dump_header(oc, NULL, NULL); dump_header(oc, NULL);
panic("Out of memory and no killable processes...\n"); panic("Out of memory and no killable processes...\n");
} }
if (p && p != (void *)-1UL) { if (p && p != (void *)-1UL) {
oom_kill_process(oc, p, points, totalpages, NULL, oom_kill_process(oc, p, points, totalpages, "Out of memory");
"Out of memory");
/* /*
* Give the killed process a good chance to exit before trying * Give the killed process a good chance to exit before trying
* to allocate memory again. * to allocate memory again.
...@@ -996,6 +993,7 @@ void pagefault_out_of_memory(void) ...@@ -996,6 +993,7 @@ void pagefault_out_of_memory(void)
struct oom_control oc = { struct oom_control oc = {
.zonelist = NULL, .zonelist = NULL,
.nodemask = NULL, .nodemask = NULL,
.memcg = NULL,
.gfp_mask = 0, .gfp_mask = 0,
.order = 0, .order = 0,
}; };
......
...@@ -3105,6 +3105,7 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order, ...@@ -3105,6 +3105,7 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
struct oom_control oc = { struct oom_control oc = {
.zonelist = ac->zonelist, .zonelist = ac->zonelist,
.nodemask = ac->nodemask, .nodemask = ac->nodemask,
.memcg = NULL,
.gfp_mask = gfp_mask, .gfp_mask = gfp_mask,
.order = order, .order = order,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment