diff options
Diffstat (limited to 'mm/memcontrol.c')
| -rw-r--r-- | mm/memcontrol.c | 61 | 
1 files changed, 60 insertions, 1 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 4f73c823c59..b78972e2f43 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1453,7 +1453,7 @@ static int mem_cgroup_count_children(struct mem_cgroup *memcg)  /*   * Return the memory (and swap, if configured) limit for a memcg.   */ -u64 mem_cgroup_get_limit(struct mem_cgroup *memcg) +static u64 mem_cgroup_get_limit(struct mem_cgroup *memcg)  {  	u64 limit;  	u64 memsw; @@ -1469,6 +1469,65 @@ u64 mem_cgroup_get_limit(struct mem_cgroup *memcg)  	return min(limit, memsw);  } +void __mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, +				int order) +{ +	struct mem_cgroup *iter; +	unsigned long chosen_points = 0; +	unsigned long totalpages; +	unsigned int points = 0; +	struct task_struct *chosen = NULL; + +	totalpages = mem_cgroup_get_limit(memcg) >> PAGE_SHIFT ? : 1; +	for_each_mem_cgroup_tree(iter, memcg) { +		struct cgroup *cgroup = iter->css.cgroup; +		struct cgroup_iter it; +		struct task_struct *task; + +		cgroup_iter_start(cgroup, &it); +		while ((task = cgroup_iter_next(cgroup, &it))) { +			switch (oom_scan_process_thread(task, totalpages, NULL, +							false)) { +			case OOM_SCAN_SELECT: +				if (chosen) +					put_task_struct(chosen); +				chosen = task; +				chosen_points = ULONG_MAX; +				get_task_struct(chosen); +				/* fall through */ +			case OOM_SCAN_CONTINUE: +				continue; +			case OOM_SCAN_ABORT: +				cgroup_iter_end(cgroup, &it); +				mem_cgroup_iter_break(memcg, iter); +				if (chosen) +					put_task_struct(chosen); +				return; +			case OOM_SCAN_OK: +				break; +			}; +			points = oom_badness(task, memcg, NULL, totalpages); +			if (points > chosen_points) { +				if (chosen) +					put_task_struct(chosen); +				chosen = task; +				chosen_points = points; +				get_task_struct(chosen); +			} +		} +		cgroup_iter_end(cgroup, &it); +	} + +	if (!chosen) +		return; +	points = chosen_points * 1000 / totalpages; +	read_lock(&tasklist_lock); +	oom_kill_process(chosen, gfp_mask, order, points, totalpages, memcg, +			 NULL, "Memory cgroup out of memory"); +	read_unlock(&tasklist_lock); +	put_task_struct(chosen); +} +  static unsigned long mem_cgroup_reclaim(struct mem_cgroup *memcg,  					gfp_t gfp_mask,  					unsigned long flags)  |