|
@@ -180,10 +180,10 @@ static bool oom_unkillable_task(struct task_struct *p,
|
|
|
* predictable as possible. The goal is to return the highest value for the
|
|
|
* task consuming the most memory to avoid subsequent oom failures.
|
|
|
*/
|
|
|
-unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *memcg,
|
|
|
- const nodemask_t *nodemask, unsigned long totalpages)
|
|
|
+unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg,
|
|
|
+ const nodemask_t *nodemask, unsigned long totalpages)
|
|
|
{
|
|
|
- long points;
|
|
|
+ unsigned long points;
|
|
|
|
|
|
if (oom_unkillable_task(p, memcg, nodemask))
|
|
|
return 0;
|
|
@@ -197,22 +197,12 @@ unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *memcg,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * The memory controller may have a limit of 0 bytes, so avoid a divide
|
|
|
- * by zero, if necessary.
|
|
|
- */
|
|
|
- if (!totalpages)
|
|
|
- totalpages = 1;
|
|
|
-
|
|
|
/*
|
|
|
* The baseline for the badness score is the proportion of RAM that each
|
|
|
* task's rss, pagetable and swap space use.
|
|
|
*/
|
|
|
- points = get_mm_rss(p->mm) + p->mm->nr_ptes;
|
|
|
- points += get_mm_counter(p->mm, MM_SWAPENTS);
|
|
|
-
|
|
|
- points *= 1000;
|
|
|
- points /= totalpages;
|
|
|
+ points = get_mm_rss(p->mm) + p->mm->nr_ptes +
|
|
|
+ get_mm_counter(p->mm, MM_SWAPENTS);
|
|
|
task_unlock(p);
|
|
|
|
|
|
/*
|
|
@@ -220,23 +210,20 @@ unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *memcg,
|
|
|
* implementation used by LSMs.
|
|
|
*/
|
|
|
if (has_capability_noaudit(p, CAP_SYS_ADMIN))
|
|
|
- points -= 30;
|
|
|
+ points -= 30 * totalpages / 1000;
|
|
|
|
|
|
/*
|
|
|
* /proc/pid/oom_score_adj ranges from -1000 to +1000 such that it may
|
|
|
* either completely disable oom killing or always prefer a certain
|
|
|
* task.
|
|
|
*/
|
|
|
- points += p->signal->oom_score_adj;
|
|
|
+ points += p->signal->oom_score_adj * totalpages / 1000;
|
|
|
|
|
|
/*
|
|
|
- * Never return 0 for an eligible task that may be killed since it's
|
|
|
- * possible that no single user task uses more than 0.1% of memory and
|
|
|
- * no single admin tasks uses more than 3.0%.
|
|
|
+ * Never return 0 for an eligible task regardless of the root bonus and
|
|
|
+ * oom_score_adj (oom_score_adj can't be OOM_SCORE_ADJ_MIN here).
|
|
|
*/
|
|
|
- if (points <= 0)
|
|
|
- return 1;
|
|
|
- return (points < 1000) ? points : 1000;
|
|
|
+ return points ? points : 1;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -314,7 +301,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
|
|
|
{
|
|
|
struct task_struct *g, *p;
|
|
|
struct task_struct *chosen = NULL;
|
|
|
- *ppoints = 0;
|
|
|
+ unsigned long chosen_points = 0;
|
|
|
|
|
|
do_each_thread(g, p) {
|
|
|
unsigned int points;
|
|
@@ -354,7 +341,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
|
|
|
*/
|
|
|
if (p == current) {
|
|
|
chosen = p;
|
|
|
- *ppoints = 1000;
|
|
|
+ chosen_points = ULONG_MAX;
|
|
|
} else if (!force_kill) {
|
|
|
/*
|
|
|
* If this task is not being ptraced on exit,
|
|
@@ -367,12 +354,13 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
|
|
|
}
|
|
|
|
|
|
points = oom_badness(p, memcg, nodemask, totalpages);
|
|
|
- if (points > *ppoints) {
|
|
|
+ if (points > chosen_points) {
|
|
|
chosen = p;
|
|
|
- *ppoints = points;
|
|
|
+ chosen_points = points;
|
|
|
}
|
|
|
} while_each_thread(g, p);
|
|
|
|
|
|
+ *ppoints = chosen_points * 1000 / totalpages;
|
|
|
return chosen;
|
|
|
}
|
|
|
|
|
@@ -572,7 +560,7 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
|
|
|
}
|
|
|
|
|
|
check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, order, NULL);
|
|
|
- limit = mem_cgroup_get_limit(memcg) >> PAGE_SHIFT;
|
|
|
+ limit = mem_cgroup_get_limit(memcg) >> PAGE_SHIFT ? : 1;
|
|
|
read_lock(&tasklist_lock);
|
|
|
p = select_bad_process(&points, limit, memcg, NULL, false);
|
|
|
if (p && PTR_ERR(p) != -1UL)
|