diff options
Diffstat (limited to 'mm/oom_kill.c')
-rw-r--r-- | mm/oom_kill.c | 59 |
1 files changed, 23 insertions, 36 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 46bf2ed5594c..ac300c99baf6 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -180,10 +180,11 @@ static bool oom_unkillable_task(struct task_struct *p, | |||
180 | * predictable as possible. The goal is to return the highest value for the | 180 | * predictable as possible. The goal is to return the highest value for the |
181 | * task consuming the most memory to avoid subsequent oom failures. | 181 | * task consuming the most memory to avoid subsequent oom failures. |
182 | */ | 182 | */ |
183 | unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *memcg, | 183 | unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg, |
184 | const nodemask_t *nodemask, unsigned long totalpages) | 184 | const nodemask_t *nodemask, unsigned long totalpages) |
185 | { | 185 | { |
186 | long points; | 186 | long points; |
187 | long adj; | ||
187 | 188 | ||
188 | if (oom_unkillable_task(p, memcg, nodemask)) | 189 | if (oom_unkillable_task(p, memcg, nodemask)) |
189 | return 0; | 190 | return 0; |
@@ -192,27 +193,18 @@ unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *memcg, | |||
192 | if (!p) | 193 | if (!p) |
193 | return 0; | 194 | return 0; |
194 | 195 | ||
195 | if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) { | 196 | adj = p->signal->oom_score_adj; |
197 | if (adj == OOM_SCORE_ADJ_MIN) { | ||
196 | task_unlock(p); | 198 | task_unlock(p); |
197 | return 0; | 199 | return 0; |
198 | } | 200 | } |
199 | 201 | ||
200 | /* | 202 | /* |
201 | * The memory controller may have a limit of 0 bytes, so avoid a divide | ||
202 | * by zero, if necessary. | ||
203 | */ | ||
204 | if (!totalpages) | ||
205 | totalpages = 1; | ||
206 | |||
207 | /* | ||
208 | * The baseline for the badness score is the proportion of RAM that each | 203 | * The baseline for the badness score is the proportion of RAM that each |
209 | * task's rss, pagetable and swap space use. | 204 | * task's rss, pagetable and swap space use. |
210 | */ | 205 | */ |
211 | points = get_mm_rss(p->mm) + p->mm->nr_ptes; | 206 | points = get_mm_rss(p->mm) + p->mm->nr_ptes + |
212 | points += get_mm_counter(p->mm, MM_SWAPENTS); | 207 | get_mm_counter(p->mm, MM_SWAPENTS); |
213 | |||
214 | points *= 1000; | ||
215 | points /= totalpages; | ||
216 | task_unlock(p); | 208 | task_unlock(p); |
217 | 209 | ||
218 | /* | 210 | /* |
@@ -220,23 +212,17 @@ unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *memcg, | |||
220 | * implementation used by LSMs. | 212 | * implementation used by LSMs. |
221 | */ | 213 | */ |
222 | if (has_capability_noaudit(p, CAP_SYS_ADMIN)) | 214 | if (has_capability_noaudit(p, CAP_SYS_ADMIN)) |
223 | points -= 30; | 215 | adj -= 30; |
224 | 216 | ||
225 | /* | 217 | /* Normalize to oom_score_adj units */ |
226 | * /proc/pid/oom_score_adj ranges from -1000 to +1000 such that it may | 218 | adj *= totalpages / 1000; |
227 | * either completely disable oom killing or always prefer a certain | 219 | points += adj; |
228 | * task. | ||
229 | */ | ||
230 | points += p->signal->oom_score_adj; | ||
231 | 220 | ||
232 | /* | 221 | /* |
233 | * Never return 0 for an eligible task that may be killed since it's | 222 | * Never return 0 for an eligible task regardless of the root bonus and |
234 | * possible that no single user task uses more than 0.1% of memory and | 223 | * oom_score_adj (oom_score_adj can't be OOM_SCORE_ADJ_MIN here). |
235 | * no single admin tasks uses more than 3.0%. | ||
236 | */ | 224 | */ |
237 | if (points <= 0) | 225 | return points > 0 ? points : 1; |
238 | return 1; | ||
239 | return (points < 1000) ? points : 1000; | ||
240 | } | 226 | } |
241 | 227 | ||
242 | /* | 228 | /* |
@@ -314,7 +300,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, | |||
314 | { | 300 | { |
315 | struct task_struct *g, *p; | 301 | struct task_struct *g, *p; |
316 | struct task_struct *chosen = NULL; | 302 | struct task_struct *chosen = NULL; |
317 | *ppoints = 0; | 303 | unsigned long chosen_points = 0; |
318 | 304 | ||
319 | do_each_thread(g, p) { | 305 | do_each_thread(g, p) { |
320 | unsigned int points; | 306 | unsigned int points; |
@@ -354,7 +340,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, | |||
354 | */ | 340 | */ |
355 | if (p == current) { | 341 | if (p == current) { |
356 | chosen = p; | 342 | chosen = p; |
357 | *ppoints = 1000; | 343 | chosen_points = ULONG_MAX; |
358 | } else if (!force_kill) { | 344 | } else if (!force_kill) { |
359 | /* | 345 | /* |
360 | * If this task is not being ptraced on exit, | 346 | * If this task is not being ptraced on exit, |
@@ -367,18 +353,19 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, | |||
367 | } | 353 | } |
368 | 354 | ||
369 | points = oom_badness(p, memcg, nodemask, totalpages); | 355 | points = oom_badness(p, memcg, nodemask, totalpages); |
370 | if (points > *ppoints) { | 356 | if (points > chosen_points) { |
371 | chosen = p; | 357 | chosen = p; |
372 | *ppoints = points; | 358 | chosen_points = points; |
373 | } | 359 | } |
374 | } while_each_thread(g, p); | 360 | } while_each_thread(g, p); |
375 | 361 | ||
362 | *ppoints = chosen_points * 1000 / totalpages; | ||
376 | return chosen; | 363 | return chosen; |
377 | } | 364 | } |
378 | 365 | ||
379 | /** | 366 | /** |
380 | * dump_tasks - dump current memory state of all system tasks | 367 | * dump_tasks - dump current memory state of all system tasks |
381 | * @mem: current's memory controller, if constrained | 368 | * @memcg: current's memory controller, if constrained |
382 | * @nodemask: nodemask passed to page allocator for mempolicy ooms | 369 | * @nodemask: nodemask passed to page allocator for mempolicy ooms |
383 | * | 370 | * |
384 | * Dumps the current memory state of all eligible tasks. Tasks not in the same | 371 | * Dumps the current memory state of all eligible tasks. Tasks not in the same |
@@ -410,8 +397,8 @@ static void dump_tasks(const struct mem_cgroup *memcg, const nodemask_t *nodemas | |||
410 | } | 397 | } |
411 | 398 | ||
412 | pr_info("[%5d] %5d %5d %8lu %8lu %3u %3d %5d %s\n", | 399 | pr_info("[%5d] %5d %5d %8lu %8lu %3u %3d %5d %s\n", |
413 | task->pid, task_uid(task), task->tgid, | 400 | task->pid, from_kuid(&init_user_ns, task_uid(task)), |
414 | task->mm->total_vm, get_mm_rss(task->mm), | 401 | task->tgid, task->mm->total_vm, get_mm_rss(task->mm), |
415 | task_cpu(task), task->signal->oom_adj, | 402 | task_cpu(task), task->signal->oom_adj, |
416 | task->signal->oom_score_adj, task->comm); | 403 | task->signal->oom_score_adj, task->comm); |
417 | task_unlock(task); | 404 | task_unlock(task); |
@@ -572,7 +559,7 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, | |||
572 | } | 559 | } |
573 | 560 | ||
574 | check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, order, NULL); | 561 | check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, order, NULL); |
575 | limit = mem_cgroup_get_limit(memcg) >> PAGE_SHIFT; | 562 | limit = mem_cgroup_get_limit(memcg) >> PAGE_SHIFT ? : 1; |
576 | read_lock(&tasklist_lock); | 563 | read_lock(&tasklist_lock); |
577 | p = select_bad_process(&points, limit, memcg, NULL, false); | 564 | p = select_bad_process(&points, limit, memcg, NULL, false); |
578 | if (p && PTR_ERR(p) != -1UL) | 565 | if (p && PTR_ERR(p) != -1UL) |