Blame view
mm/oom_kill.c
30.2 KB
457c89965 treewide: Add SPD... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 |
/* * linux/mm/oom_kill.c * * Copyright (C) 1998,2000 Rik van Riel * Thanks go out to Claus Fischer for some serious inspiration and * for goading me into coding this file... |
a63d83f42 oom: badness heur... |
8 9 |
* Copyright (C) 2010 Google, Inc. * Rewritten by David Rientjes |
1da177e4c Linux-2.6.12-rc2 |
10 11 |
* * The routines in this file are used to kill a process when |
a49335cce [PATCH] cpusets: ... |
12 13 |
* we're seriously out of memory. This gets called from __alloc_pages() * in mm/page_alloc.c when we really run out of memory. |
1da177e4c Linux-2.6.12-rc2 |
14 15 16 17 18 19 |
* * Since we won't call these routines often (on a well-configured * machine) this file will double as a 'coding guide' and a signpost * for newbie kernel hackers. It features several pointers to major * kernel subsystems and hints as to where to find out what things do. */ |
8ac773b4f [PATCH] OOM kille... |
20 |
#include <linux/oom.h> |
1da177e4c Linux-2.6.12-rc2 |
21 |
#include <linux/mm.h> |
4e950f6f0 Remove fs.h from ... |
22 |
#include <linux/err.h> |
5a0e3ad6a include cleanup: ... |
23 |
#include <linux/gfp.h> |
1da177e4c Linux-2.6.12-rc2 |
24 |
#include <linux/sched.h> |
6e84f3152 sched/headers: Pr... |
25 |
#include <linux/sched/mm.h> |
f7ccbae45 sched/headers: Pr... |
26 |
#include <linux/sched/coredump.h> |
299300258 sched/headers: Pr... |
27 |
#include <linux/sched/task.h> |
1da177e4c Linux-2.6.12-rc2 |
28 29 30 |
#include <linux/swap.h> #include <linux/timex.h> #include <linux/jiffies.h> |
ef08e3b49 [PATCH] cpusets: ... |
31 |
#include <linux/cpuset.h> |
b95f1b31b mm: Map most file... |
32 |
#include <linux/export.h> |
8bc719d3c [PATCH] out of me... |
33 |
#include <linux/notifier.h> |
c7ba5c9e8 Memory controller... |
34 |
#include <linux/memcontrol.h> |
6f48d0ebd oom: select task ... |
35 |
#include <linux/mempolicy.h> |
5cd9c58fb security: Fix set... |
36 |
#include <linux/security.h> |
edd45544c oom: avoid deferr... |
37 |
#include <linux/ptrace.h> |
f660daac4 oom: thaw threads... |
38 |
#include <linux/freezer.h> |
43d2b1132 tracepoint: add t... |
39 |
#include <linux/ftrace.h> |
dc3f21ead mm, oom: introduc... |
40 |
#include <linux/ratelimit.h> |
aac453635 mm, oom: introduc... |
41 42 |
#include <linux/kthread.h> #include <linux/init.h> |
4d4bbd852 mm, oom_reaper: s... |
43 |
#include <linux/mmu_notifier.h> |
aac453635 mm, oom: introduc... |
44 45 46 |
#include <asm/tlb.h> #include "internal.h" |
852d8be0a mm: oom: show unr... |
47 |
#include "slab.h" |
43d2b1132 tracepoint: add t... |
48 49 50 |
#define CREATE_TRACE_POINTS #include <trace/events/oom.h> |
1da177e4c Linux-2.6.12-rc2 |
51 |
|
fadd8fbd1 [PATCH] support f... |
52 |
int sysctl_panic_on_oom; |
fe071d7e8 oom: add oom_kill... |
53 |
int sysctl_oom_kill_allocating_task; |
ad915c432 oom: enable oom t... |
54 |
int sysctl_oom_dump_tasks = 1; |
dc56401fc mm: oom_kill: sim... |
55 |
|
a195d3f5b mm/oom_kill.c: do... |
56 57 58 59 60 61 62 63 |
/* * Serializes oom killer invocations (out_of_memory()) from all contexts to * prevent from over eager oom killing (e.g. when the oom killer is invoked * from different domains). * * oom_killer_disable() relies on this lock to stabilize oom_killer_disabled * and mark_oom_victim */ |
dc56401fc mm: oom_kill: sim... |
64 |
DEFINE_MUTEX(oom_lock); |
1da177e4c Linux-2.6.12-rc2 |
65 |
|
ac311a14c oom: decouple mem... |
66 67 68 69 |
static inline bool is_memcg_oom(struct oom_control *oc) { return oc->memcg != NULL; } |
6f48d0ebd oom: select task ... |
70 71 |
#ifdef CONFIG_NUMA /** |
ac311a14c oom: decouple mem... |
72 |
* oom_cpuset_eligible() - check task eligiblity for kill |
ad9624417 oom_kill: has_int... |
73 |
* @start: task struct of which task to consider |
f364f06b3 mm/oom_kill.c: fi... |
74 |
* @oc: pointer to struct oom_control |
6f48d0ebd oom: select task ... |
75 76 77 78 |
* * Task eligibility is determined by whether or not a candidate task, @tsk, * shares the same mempolicy nodes as current if it is bound by such a policy * and whether or not it has the same set of allowed cpuset nodes. |
ac311a14c oom: decouple mem... |
79 80 81 |
* * This function is assuming oom-killer context and 'current' has triggered * the oom-killer. |
495789a51 oom: make oom_sco... |
82 |
*/ |
ac311a14c oom: decouple mem... |
83 84 |
static bool oom_cpuset_eligible(struct task_struct *start, struct oom_control *oc) |
495789a51 oom: make oom_sco... |
85 |
{ |
ad9624417 oom_kill: has_int... |
86 87 |
struct task_struct *tsk; bool ret = false; |
ac311a14c oom: decouple mem... |
88 89 90 91 |
const nodemask_t *mask = oc->nodemask; if (is_memcg_oom(oc)) return true; |
495789a51 oom: make oom_sco... |
92 |
|
ad9624417 oom_kill: has_int... |
93 |
rcu_read_lock(); |
1da4db0cd oom_kill: change ... |
94 |
for_each_thread(start, tsk) { |
6f48d0ebd oom: select task ... |
95 96 97 98 99 100 101 |
if (mask) { /* * If this is a mempolicy constrained oom, tsk's * cpuset is irrelevant. Only return true if its * mempolicy intersects current, otherwise it may be * needlessly killed. */ |
ad9624417 oom_kill: has_int... |
102 |
ret = mempolicy_nodemask_intersects(tsk, mask); |
6f48d0ebd oom: select task ... |
103 104 105 106 107 |
} else { /* * This is not a mempolicy constrained oom, so only * check the mems of tsk's cpuset. */ |
ad9624417 oom_kill: has_int... |
108 |
ret = cpuset_mems_allowed_intersects(current, tsk); |
6f48d0ebd oom: select task ... |
109 |
} |
ad9624417 oom_kill: has_int... |
110 111 |
if (ret) break; |
1da4db0cd oom_kill: change ... |
112 |
} |
ad9624417 oom_kill: has_int... |
113 |
rcu_read_unlock(); |
df1090a8d oom: cleanup has_... |
114 |
|
ad9624417 oom_kill: has_int... |
115 |
return ret; |
6f48d0ebd oom: select task ... |
116 117 |
} #else |
ac311a14c oom: decouple mem... |
118 |
static bool oom_cpuset_eligible(struct task_struct *tsk, struct oom_control *oc) |
6f48d0ebd oom: select task ... |
119 120 |
{ return true; |
495789a51 oom: make oom_sco... |
121 |
} |
6f48d0ebd oom: select task ... |
122 |
#endif /* CONFIG_NUMA */ |
495789a51 oom: make oom_sco... |
123 |
|
6f48d0ebd oom: select task ... |
124 125 126 127 128 129 |
/* * The process p may have detached its own ->mm while exiting or through * use_mm(), but one or more of its subthreads may still have a valid * pointer. Return p, or any of its subthreads with a valid ->mm, with * task_lock() held. */ |
158e0a2d1 memcg: use find_l... |
130 |
struct task_struct *find_lock_task_mm(struct task_struct *p) |
dd8e8f405 oom: introduce fi... |
131 |
{ |
1da4db0cd oom_kill: change ... |
132 |
struct task_struct *t; |
dd8e8f405 oom: introduce fi... |
133 |
|
4d4048be8 oom_kill: add rcu... |
134 |
rcu_read_lock(); |
1da4db0cd oom_kill: change ... |
135 |
for_each_thread(p, t) { |
dd8e8f405 oom: introduce fi... |
136 137 |
task_lock(t); if (likely(t->mm)) |
4d4048be8 oom_kill: add rcu... |
138 |
goto found; |
dd8e8f405 oom: introduce fi... |
139 |
task_unlock(t); |
1da4db0cd oom_kill: change ... |
140 |
} |
4d4048be8 oom_kill: add rcu... |
141 142 143 |
t = NULL; found: rcu_read_unlock(); |
dd8e8f405 oom: introduce fi... |
144 |
|
4d4048be8 oom_kill: add rcu... |
145 |
return t; |
dd8e8f405 oom: introduce fi... |
146 |
} |
db2a0dd7a mm/oom_kill.c: in... |
147 148 149 150 151 152 153 154 |
/* * order == -1 means the oom kill is required by sysrq, otherwise only * for display purposes. */ static inline bool is_sysrq_oom(struct oom_control *oc) { return oc->order == -1; } |
ab290adba oom: make oom_unk... |
155 |
/* return true if the task is not adequate as candidate victim task. */ |
ac311a14c oom: decouple mem... |
156 |
static bool oom_unkillable_task(struct task_struct *p) |
ab290adba oom: make oom_unk... |
157 158 159 160 161 |
{ if (is_global_init(p)) return true; if (p->flags & PF_KTHREAD) return true; |
ab290adba oom: make oom_unk... |
162 163 |
return false; } |
852d8be0a mm: oom: show unr... |
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
/* * Print out unreclaimble slabs info when unreclaimable slabs amount is greater * than all user memory (LRU pages) */ static bool is_dump_unreclaim_slabs(void) { unsigned long nr_lru; nr_lru = global_node_page_state(NR_ACTIVE_ANON) + global_node_page_state(NR_INACTIVE_ANON) + global_node_page_state(NR_ACTIVE_FILE) + global_node_page_state(NR_INACTIVE_FILE) + global_node_page_state(NR_ISOLATED_ANON) + global_node_page_state(NR_ISOLATED_FILE) + global_node_page_state(NR_UNEVICTABLE); return (global_node_page_state(NR_SLAB_UNRECLAIMABLE) > nr_lru); } |
1da177e4c Linux-2.6.12-rc2 |
182 |
/** |
a63d83f42 oom: badness heur... |
183 |
* oom_badness - heuristic function to determine which candidate task to kill |
1da177e4c Linux-2.6.12-rc2 |
184 |
* @p: task struct of which task we should calculate |
a63d83f42 oom: badness heur... |
185 |
* @totalpages: total present RAM allowed for page allocation |
1da177e4c Linux-2.6.12-rc2 |
186 |
* |
a63d83f42 oom: badness heur... |
187 188 189 |
* The heuristic for determining which task to kill is made to be as simple and * predictable as possible. The goal is to return the highest value for the * task consuming the most memory to avoid subsequent oom failures. |
1da177e4c Linux-2.6.12-rc2 |
190 |
*/ |
ac311a14c oom: decouple mem... |
191 |
unsigned long oom_badness(struct task_struct *p, unsigned long totalpages) |
1da177e4c Linux-2.6.12-rc2 |
192 |
{ |
1e11ad8dc mm, oom: fix badn... |
193 |
long points; |
61eafb00d mm, oom: fix and ... |
194 |
long adj; |
28b83c519 oom: move oom_adj... |
195 |
|
ac311a14c oom: decouple mem... |
196 |
if (oom_unkillable_task(p)) |
26ebc9849 oom: /proc/<pid>/... |
197 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
198 |
|
dd8e8f405 oom: introduce fi... |
199 200 |
p = find_lock_task_mm(p); if (!p) |
1da177e4c Linux-2.6.12-rc2 |
201 |
return 0; |
bb8a4b7fd mm, oom_reaper: h... |
202 203 |
/* * Do not even consider tasks which are explicitly marked oom |
b18dc5f29 mm, oom: skip vfo... |
204 205 |
* unkillable or have been already oom reaped or the are in * the middle of vfork |
bb8a4b7fd mm, oom_reaper: h... |
206 |
*/ |
a9c58b907 mm, oom: change t... |
207 |
adj = (long)p->signal->oom_score_adj; |
bb8a4b7fd mm, oom_reaper: h... |
208 |
if (adj == OOM_SCORE_ADJ_MIN || |
862e3073b mm, oom: get rid ... |
209 |
test_bit(MMF_OOM_SKIP, &p->mm->flags) || |
b18dc5f29 mm, oom: skip vfo... |
210 |
in_vfork(p)) { |
5aecc85ab oom: do not kill ... |
211 212 213 |
task_unlock(p); return 0; } |
1da177e4c Linux-2.6.12-rc2 |
214 |
/* |
a63d83f42 oom: badness heur... |
215 |
* The baseline for the badness score is the proportion of RAM that each |
f755a042d oom: use pte page... |
216 |
* task's rss, pagetable and swap space use. |
1da177e4c Linux-2.6.12-rc2 |
217 |
*/ |
dc6c9a35b mm: account pmd p... |
218 |
points = get_mm_rss(p->mm) + get_mm_counter(p->mm, MM_SWAPENTS) + |
af5b0f6a0 mm: consolidate p... |
219 |
mm_pgtables_bytes(p->mm) / PAGE_SIZE; |
a63d83f42 oom: badness heur... |
220 |
task_unlock(p); |
1da177e4c Linux-2.6.12-rc2 |
221 |
|
61eafb00d mm, oom: fix and ... |
222 223 224 |
/* Normalize to oom_score_adj units */ adj *= totalpages / 1000; points += adj; |
1da177e4c Linux-2.6.12-rc2 |
225 |
|
f19e8aa11 oom: always retur... |
226 |
/* |
a7f638f99 mm, oom: normaliz... |
227 228 |
* 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). |
f19e8aa11 oom: always retur... |
229 |
*/ |
1e11ad8dc mm, oom: fix badn... |
230 |
return points > 0 ? points : 1; |
1da177e4c Linux-2.6.12-rc2 |
231 |
} |
ef8444ea0 mm, oom: reorgani... |
232 233 234 235 236 |
static const char * const oom_constraint_text[] = { [CONSTRAINT_NONE] = "CONSTRAINT_NONE", [CONSTRAINT_CPUSET] = "CONSTRAINT_CPUSET", [CONSTRAINT_MEMORY_POLICY] = "CONSTRAINT_MEMORY_POLICY", [CONSTRAINT_MEMCG] = "CONSTRAINT_MEMCG", |
7c5f64f84 mm: oom: deduplic... |
237 |
}; |
1da177e4c Linux-2.6.12-rc2 |
238 |
/* |
9b0f8b040 [PATCH] Terminate... |
239 240 |
* Determine the type of allocation constraint. */ |
7c5f64f84 mm: oom: deduplic... |
241 |
static enum oom_constraint constrained_alloc(struct oom_control *oc) |
4365a5676 oom-kill: fix NUM... |
242 |
{ |
54a6eb5c4 mm: use two zonel... |
243 |
struct zone *zone; |
dd1a239f6 mm: have zonelist... |
244 |
struct zoneref *z; |
6e0fc46dc mm, oom: organize... |
245 |
enum zone_type high_zoneidx = gfp_zone(oc->gfp_mask); |
a63d83f42 oom: badness heur... |
246 247 |
bool cpuset_limited = false; int nid; |
9b0f8b040 [PATCH] Terminate... |
248 |
|
7c5f64f84 mm: oom: deduplic... |
249 |
if (is_memcg_oom(oc)) { |
bbec2e151 mm: rename page_c... |
250 |
oc->totalpages = mem_cgroup_get_max(oc->memcg) ?: 1; |
7c5f64f84 mm: oom: deduplic... |
251 252 |
return CONSTRAINT_MEMCG; } |
a63d83f42 oom: badness heur... |
253 |
/* Default to all available memory */ |
ca79b0c21 mm: convert total... |
254 |
oc->totalpages = totalram_pages() + total_swap_pages; |
7c5f64f84 mm: oom: deduplic... |
255 256 257 |
if (!IS_ENABLED(CONFIG_NUMA)) return CONSTRAINT_NONE; |
a63d83f42 oom: badness heur... |
258 |
|
6e0fc46dc mm, oom: organize... |
259 |
if (!oc->zonelist) |
a63d83f42 oom: badness heur... |
260 |
return CONSTRAINT_NONE; |
4365a5676 oom-kill: fix NUM... |
261 262 263 264 265 |
/* * Reach here only when __GFP_NOFAIL is used. So, we should avoid * to kill current.We have to random task kill in this case. * Hopefully, CONSTRAINT_THISNODE...but no way to handle it, now. */ |
6e0fc46dc mm, oom: organize... |
266 |
if (oc->gfp_mask & __GFP_THISNODE) |
4365a5676 oom-kill: fix NUM... |
267 |
return CONSTRAINT_NONE; |
9b0f8b040 [PATCH] Terminate... |
268 |
|
4365a5676 oom-kill: fix NUM... |
269 |
/* |
a63d83f42 oom: badness heur... |
270 271 272 |
* This is not a __GFP_THISNODE allocation, so a truncated nodemask in * the page allocator means a mempolicy is in effect. Cpuset policy * is enforced in get_page_from_freelist(). |
4365a5676 oom-kill: fix NUM... |
273 |
*/ |
6e0fc46dc mm, oom: organize... |
274 275 |
if (oc->nodemask && !nodes_subset(node_states[N_MEMORY], *oc->nodemask)) { |
7c5f64f84 mm: oom: deduplic... |
276 |
oc->totalpages = total_swap_pages; |
6e0fc46dc mm, oom: organize... |
277 |
for_each_node_mask(nid, *oc->nodemask) |
1eb41bb07 mm, oom: consider... |
278 |
oc->totalpages += node_present_pages(nid); |
9b0f8b040 [PATCH] Terminate... |
279 |
return CONSTRAINT_MEMORY_POLICY; |
a63d83f42 oom: badness heur... |
280 |
} |
4365a5676 oom-kill: fix NUM... |
281 282 |
/* Check this allocation failure is caused by cpuset's wall function */ |
6e0fc46dc mm, oom: organize... |
283 284 285 |
for_each_zone_zonelist_nodemask(zone, z, oc->zonelist, high_zoneidx, oc->nodemask) if (!cpuset_zone_allowed(zone, oc->gfp_mask)) |
a63d83f42 oom: badness heur... |
286 |
cpuset_limited = true; |
9b0f8b040 [PATCH] Terminate... |
287 |
|
a63d83f42 oom: badness heur... |
288 |
if (cpuset_limited) { |
7c5f64f84 mm: oom: deduplic... |
289 |
oc->totalpages = total_swap_pages; |
a63d83f42 oom: badness heur... |
290 |
for_each_node_mask(nid, cpuset_current_mems_allowed) |
1eb41bb07 mm, oom: consider... |
291 |
oc->totalpages += node_present_pages(nid); |
a63d83f42 oom: badness heur... |
292 293 |
return CONSTRAINT_CPUSET; } |
9b0f8b040 [PATCH] Terminate... |
294 295 |
return CONSTRAINT_NONE; } |
7c5f64f84 mm: oom: deduplic... |
296 |
static int oom_evaluate_task(struct task_struct *task, void *arg) |
462607ecc mm, oom: introduc... |
297 |
{ |
7c5f64f84 mm: oom: deduplic... |
298 299 |
struct oom_control *oc = arg; unsigned long points; |
ac311a14c oom: decouple mem... |
300 301 302 303 304 |
if (oom_unkillable_task(task)) goto next; /* p may not have freeable memory in nodemask */ if (!is_memcg_oom(oc) && !oom_cpuset_eligible(task, oc)) |
7c5f64f84 mm: oom: deduplic... |
305 |
goto next; |
462607ecc mm, oom: introduc... |
306 307 308 |
/* * This task already has access to memory reserves and is being killed. |
a373966d1 mm, oom: hide mm ... |
309 |
* Don't allow any other task to have access to the reserves unless |
862e3073b mm, oom: get rid ... |
310 |
* the task has MMF_OOM_SKIP because chances that it would release |
a373966d1 mm, oom: hide mm ... |
311 |
* any memory is quite low. |
462607ecc mm, oom: introduc... |
312 |
*/ |
862e3073b mm, oom: get rid ... |
313 314 |
if (!is_sysrq_oom(oc) && tsk_is_oom_victim(task)) { if (test_bit(MMF_OOM_SKIP, &task->signal->oom_mm->flags)) |
7c5f64f84 mm: oom: deduplic... |
315 316 |
goto next; goto abort; |
a373966d1 mm, oom: hide mm ... |
317 |
} |
462607ecc mm, oom: introduc... |
318 |
|
e1e12d2f3 mm, oom: fix race... |
319 320 321 322 |
/* * If task is allocating a lot of memory and has been marked to be * killed first if it triggers an oom, then select it. */ |
7c5f64f84 mm: oom: deduplic... |
323 324 325 326 |
if (oom_task_origin(task)) { points = ULONG_MAX; goto select; } |
e1e12d2f3 mm, oom: fix race... |
327 |
|
ac311a14c oom: decouple mem... |
328 |
points = oom_badness(task, oc->totalpages); |
7c5f64f84 mm: oom: deduplic... |
329 330 |
if (!points || points < oc->chosen_points) goto next; |
7c5f64f84 mm: oom: deduplic... |
331 332 333 334 335 336 337 338 339 340 341 342 343 |
select: if (oc->chosen) put_task_struct(oc->chosen); get_task_struct(task); oc->chosen = task; oc->chosen_points = points; next: return 0; abort: if (oc->chosen) put_task_struct(oc->chosen); oc->chosen = (void *)-1UL; return 1; |
462607ecc mm, oom: introduc... |
344 |
} |
9b0f8b040 [PATCH] Terminate... |
345 |
/* |
7c5f64f84 mm: oom: deduplic... |
346 347 |
* Simple selection loop. We choose the process with the highest number of * 'points'. In case scan was aborted, oc->chosen is set to -1. |
1da177e4c Linux-2.6.12-rc2 |
348 |
*/ |
7c5f64f84 mm: oom: deduplic... |
349 |
static void select_bad_process(struct oom_control *oc) |
1da177e4c Linux-2.6.12-rc2 |
350 |
{ |
7c5f64f84 mm: oom: deduplic... |
351 352 353 354 |
if (is_memcg_oom(oc)) mem_cgroup_scan_tasks(oc->memcg, oom_evaluate_task, oc); else { struct task_struct *p; |
d49ad9355 mm, oom: prefer t... |
355 |
|
7c5f64f84 mm: oom: deduplic... |
356 357 358 359 360 |
rcu_read_lock(); for_each_process(p) if (oom_evaluate_task(p, oc)) break; rcu_read_unlock(); |
1da4db0cd oom_kill: change ... |
361 |
} |
1da177e4c Linux-2.6.12-rc2 |
362 |
} |
5eee7e1cd mm, oom: refactor... |
363 364 365 366 |
static int dump_task(struct task_struct *p, void *arg) { struct oom_control *oc = arg; struct task_struct *task; |
ac311a14c oom: decouple mem... |
367 368 369 370 371 |
if (oom_unkillable_task(p)) return 0; /* p may not have freeable memory in nodemask */ if (!is_memcg_oom(oc) && !oom_cpuset_eligible(p, oc)) |
5eee7e1cd mm, oom: refactor... |
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 |
return 0; task = find_lock_task_mm(p); if (!task) { /* * This is a kthread or all of p's threads have already * detached their mm's. There's no need to report * them; they can't be oom killed anyway. */ return 0; } pr_info("[%7d] %5d %5d %8lu %8lu %8ld %8lu %5hd %s ", task->pid, from_kuid(&init_user_ns, task_uid(task)), task->tgid, task->mm->total_vm, get_mm_rss(task->mm), mm_pgtables_bytes(task->mm), get_mm_counter(task->mm, MM_SWAPENTS), task->signal->oom_score_adj, task->comm); task_unlock(task); return 0; } |
1da177e4c Linux-2.6.12-rc2 |
395 |
/** |
1b578df02 mm/oom_kill: fix ... |
396 |
* dump_tasks - dump current memory state of all system tasks |
5eee7e1cd mm, oom: refactor... |
397 |
* @oc: pointer to struct oom_control |
1b578df02 mm/oom_kill: fix ... |
398 |
* |
e85bfd3aa oom: filter unkil... |
399 400 401 |
* Dumps the current memory state of all eligible tasks. Tasks not in the same * memcg, not in the same cpuset, or bound to a disjoint set of mempolicy nodes * are not shown. |
af5b0f6a0 mm: consolidate p... |
402 403 |
* State information includes task's pid, uid, tgid, vm size, rss, * pgtables_bytes, swapents, oom_score_adj value, and name. |
fef1bdd68 oom: add sysctl t... |
404 |
*/ |
5eee7e1cd mm, oom: refactor... |
405 |
static void dump_tasks(struct oom_control *oc) |
fef1bdd68 oom: add sysctl t... |
406 |
{ |
c3b78b11e mm, oom: describe... |
407 408 409 410 |
pr_info("Tasks state (memory values in pages): "); pr_info("[ pid ] uid tgid total_vm rss pgtables_bytes swapents oom_score_adj name "); |
fef1bdd68 oom: add sysctl t... |
411 |
|
5eee7e1cd mm, oom: refactor... |
412 413 414 415 |
if (is_memcg_oom(oc)) mem_cgroup_scan_tasks(oc->memcg, dump_task, oc); else { struct task_struct *p; |
c55db9578 oom: dump_tasks u... |
416 |
|
5eee7e1cd mm, oom: refactor... |
417 418 419 420 |
rcu_read_lock(); for_each_process(p) dump_task(p, oc); rcu_read_unlock(); |
c55db9578 oom: dump_tasks u... |
421 |
} |
fef1bdd68 oom: add sysctl t... |
422 |
} |
ef8444ea0 mm, oom: reorgani... |
423 424 425 426 427 428 429 |
static void dump_oom_summary(struct oom_control *oc, struct task_struct *victim) { /* one line summary of the oom killer context. */ pr_info("oom-kill:constraint=%s,nodemask=%*pbl", oom_constraint_text[oc->constraint], nodemask_pr_args(oc->nodemask)); cpuset_print_current_mems_allowed(); |
f0c867d95 mm, oom: add oom ... |
430 |
mem_cgroup_print_oom_context(oc->memcg, victim); |
ef8444ea0 mm, oom: reorgani... |
431 432 433 434 |
pr_cont(",task=%s,pid=%d,uid=%d ", victim->comm, victim->pid, from_kuid(&init_user_ns, task_uid(victim))); } |
2a966b77a mm: oom: add memc... |
435 |
static void dump_header(struct oom_control *oc, struct task_struct *p) |
1b604d75b oom: dump stack a... |
436 |
{ |
ef8444ea0 mm, oom: reorgani... |
437 438 439 |
pr_warn("%s invoked oom-killer: gfp_mask=%#x(%pGg), order=%d, oom_score_adj=%hd ", current->comm, oc->gfp_mask, &oc->gfp_mask, oc->order, |
0205f7557 mm: simplify node... |
440 |
current->signal->oom_score_adj); |
9254990fb oom: warn if we g... |
441 442 443 |
if (!IS_ENABLED(CONFIG_COMPACTION) && oc->order) pr_warn("COMPACTION is disabled!!! "); |
a0795cd41 mm, oom: print sy... |
444 |
|
1b604d75b oom: dump stack a... |
445 |
dump_stack(); |
852d8be0a mm: oom: show unr... |
446 |
if (is_memcg_oom(oc)) |
f0c867d95 mm, oom: add oom ... |
447 |
mem_cgroup_print_oom_meminfo(oc->memcg); |
852d8be0a mm: oom: show unr... |
448 |
else { |
299c517ad mm, oom: header n... |
449 |
show_mem(SHOW_MEM_FILTER_NODES, oc->nodemask); |
852d8be0a mm: oom: show unr... |
450 451 452 |
if (is_dump_unreclaim_slabs()) dump_unreclaimable_slab(); } |
1b604d75b oom: dump stack a... |
453 |
if (sysctl_oom_dump_tasks) |
5eee7e1cd mm, oom: refactor... |
454 |
dump_tasks(oc); |
ef8444ea0 mm, oom: reorgani... |
455 456 |
if (p) dump_oom_summary(oc, p); |
1b604d75b oom: dump stack a... |
457 |
} |
5695be142 OOM, PM: OOM kill... |
458 |
/* |
c32b3cbe0 oom, PM: make OOM... |
459 |
* Number of OOM victims in flight |
5695be142 OOM, PM: OOM kill... |
460 |
*/ |
c32b3cbe0 oom, PM: make OOM... |
461 462 |
static atomic_t oom_victims = ATOMIC_INIT(0); static DECLARE_WAIT_QUEUE_HEAD(oom_victims_wait); |
5695be142 OOM, PM: OOM kill... |
463 |
|
7c5f64f84 mm: oom: deduplic... |
464 |
static bool oom_killer_disabled __read_mostly; |
5695be142 OOM, PM: OOM kill... |
465 |
|
bc448e897 mm, oom_reaper: r... |
466 |
#define K(x) ((x) << (PAGE_SHIFT-10)) |
3ef22dfff oom, oom_reaper: ... |
467 468 469 470 471 472 |
/* * task->mm can be NULL if the task is the exited group leader. So to * determine whether the task is using a particular mm, we examine all the * task's threads: if one of those is using this mm then this task was also * using it. */ |
44a70adec mm, oom_adj: make... |
473 |
bool process_shares_mm(struct task_struct *p, struct mm_struct *mm) |
3ef22dfff oom, oom_reaper: ... |
474 475 476 477 478 479 480 481 482 483 |
{ struct task_struct *t; for_each_thread(p, t) { struct mm_struct *t_mm = READ_ONCE(t->mm); if (t_mm) return t_mm == mm; } return false; } |
aac453635 mm, oom: introduc... |
484 485 486 487 488 489 |
#ifdef CONFIG_MMU /* * OOM Reaper kernel thread which tries to reap the memory used by the OOM * victim (if that is possible) to help the OOM killer to move on. */ static struct task_struct *oom_reaper_th; |
aac453635 mm, oom: introduc... |
490 |
static DECLARE_WAIT_QUEUE_HEAD(oom_reaper_wait); |
29c696e1c oom: make oom_rea... |
491 |
static struct task_struct *oom_reaper_list; |
03049269d mm, oom_reaper: i... |
492 |
static DEFINE_SPINLOCK(oom_reaper_lock); |
93065ac75 mm, oom: distingu... |
493 |
bool __oom_reap_task_mm(struct mm_struct *mm) |
aac453635 mm, oom: introduc... |
494 |
{ |
aac453635 mm, oom: introduc... |
495 |
struct vm_area_struct *vma; |
93065ac75 mm, oom: distingu... |
496 |
bool ret = true; |
27ae357fa mm, oom: fix conc... |
497 498 499 500 501 502 503 504 505 506 |
/* * Tell all users of get_user/copy_from_user etc... that the content * is no longer stable. No barriers really needed because unmapping * should imply barriers already and the reader would hit a page fault * if it stumbled over a reaped memory. */ set_bit(MMF_UNSTABLE, &mm->flags); for (vma = mm->mmap ; vma; vma = vma->vm_next) { |
9c276cc65 mm: introduce MAD... |
507 |
if (!can_madv_lru_vma(vma)) |
27ae357fa mm, oom: fix conc... |
508 509 510 511 512 513 514 515 516 517 518 519 520 |
continue; /* * Only anonymous pages have a good chance to be dropped * without additional steps which we cannot afford as we * are OOM already. * * We do not even care about fs backed pages because all * which are reclaimable have already been reclaimed and * we do not want to block exit_mmap by keeping mm ref * count elevated without a good reason. */ if (vma_is_anonymous(vma) || !(vma->vm_flags & VM_SHARED)) { |
ac46d4f3c mm/mmu_notifier: ... |
521 |
struct mmu_notifier_range range; |
27ae357fa mm, oom: fix conc... |
522 |
struct mmu_gather tlb; |
6f4f13e8d mm/mmu_notifier: ... |
523 524 |
mmu_notifier_range_init(&range, MMU_NOTIFY_UNMAP, 0, vma, mm, vma->vm_start, |
ac46d4f3c mm/mmu_notifier: ... |
525 526 527 528 |
vma->vm_end); tlb_gather_mmu(&tlb, mm, range.start, range.end); if (mmu_notifier_invalidate_range_start_nonblock(&range)) { tlb_finish_mmu(&tlb, range.start, range.end); |
93065ac75 mm, oom: distingu... |
529 530 531 |
ret = false; continue; } |
ac46d4f3c mm/mmu_notifier: ... |
532 533 534 |
unmap_page_range(&tlb, vma, range.start, range.end, NULL); mmu_notifier_invalidate_range_end(&range); tlb_finish_mmu(&tlb, range.start, range.end); |
27ae357fa mm, oom: fix conc... |
535 536 |
} } |
93065ac75 mm, oom: distingu... |
537 538 |
return ret; |
27ae357fa mm, oom: fix conc... |
539 |
} |
431f42fdf mm/oom_kill.c: cl... |
540 541 542 543 544 545 |
/* * Reaps the address space of the give task. * * Returns true on success and false if none or part of the address space * has been reclaimed and the caller should retry later. */ |
27ae357fa mm, oom: fix conc... |
546 547 |
static bool oom_reap_task_mm(struct task_struct *tsk, struct mm_struct *mm) { |
aac453635 mm, oom: introduc... |
548 |
bool ret = true; |
aac453635 mm, oom: introduc... |
549 |
if (!down_read_trylock(&mm->mmap_sem)) { |
422580c3c mm/oom_kill.c: ad... |
550 |
trace_skip_task_reaping(tsk->pid); |
af5679fbc mm, oom: remove o... |
551 |
return false; |
4d4bbd852 mm, oom_reaper: s... |
552 553 554 |
} /* |
212925802 mm: oom: let oom_... |
555 556 557 558 |
* MMF_OOM_SKIP is set by exit_mmap when the OOM reaper can't * work on the mm anymore. The check for MMF_OOM_SKIP must run * under mmap_sem for reading because it serializes against the * down_write();up_write() cycle in exit_mmap(). |
e5e3f4c4f mm, oom_reaper: m... |
559 |
*/ |
212925802 mm: oom: let oom_... |
560 |
if (test_bit(MMF_OOM_SKIP, &mm->flags)) { |
422580c3c mm/oom_kill.c: ad... |
561 |
trace_skip_task_reaping(tsk->pid); |
431f42fdf mm/oom_kill.c: cl... |
562 |
goto out_unlock; |
aac453635 mm, oom: introduc... |
563 |
} |
422580c3c mm/oom_kill.c: ad... |
564 |
trace_start_task_reaping(tsk->pid); |
93065ac75 mm, oom: distingu... |
565 |
/* failed to reap part of the address space. Try again later */ |
431f42fdf mm/oom_kill.c: cl... |
566 567 568 |
ret = __oom_reap_task_mm(mm); if (!ret) goto out_finish; |
aac453635 mm, oom: introduc... |
569 |
|
bc448e897 mm, oom_reaper: r... |
570 571 572 573 574 575 |
pr_info("oom_reaper: reaped process %d (%s), now anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB ", task_pid_nr(tsk), tsk->comm, K(get_mm_counter(mm, MM_ANONPAGES)), K(get_mm_counter(mm, MM_FILEPAGES)), K(get_mm_counter(mm, MM_SHMEMPAGES))); |
431f42fdf mm/oom_kill.c: cl... |
576 577 578 |
out_finish: trace_finish_task_reaping(tsk->pid); out_unlock: |
aac453635 mm, oom: introduc... |
579 |
up_read(&mm->mmap_sem); |
36324a990 oom: clear TIF_ME... |
580 |
|
aac453635 mm, oom: introduc... |
581 582 |
return ret; } |
bc448e897 mm, oom_reaper: r... |
583 |
#define MAX_OOM_REAP_RETRIES 10 |
36324a990 oom: clear TIF_ME... |
584 |
static void oom_reap_task(struct task_struct *tsk) |
aac453635 mm, oom: introduc... |
585 586 |
{ int attempts = 0; |
26db62f17 oom: keep mm of t... |
587 |
struct mm_struct *mm = tsk->signal->oom_mm; |
aac453635 mm, oom: introduc... |
588 589 |
/* Retry the down_read_trylock(mmap_sem) a few times */ |
27ae357fa mm, oom: fix conc... |
590 |
while (attempts++ < MAX_OOM_REAP_RETRIES && !oom_reap_task_mm(tsk, mm)) |
aac453635 mm, oom: introduc... |
591 |
schedule_timeout_idle(HZ/10); |
97b1255cb mm,oom_reaper: ch... |
592 593 |
if (attempts <= MAX_OOM_REAP_RETRIES || test_bit(MMF_OOM_SKIP, &mm->flags)) |
7ebffa455 mm,oom_reaper: re... |
594 |
goto done; |
11a410d51 mm, oom_reaper: d... |
595 |
|
7ebffa455 mm,oom_reaper: re... |
596 597 598 |
pr_info("oom_reaper: unable to reap pid:%d (%s) ", task_pid_nr(tsk), tsk->comm); |
7ebffa455 mm,oom_reaper: re... |
599 |
debug_show_all_locks(); |
bc448e897 mm, oom_reaper: r... |
600 |
|
7ebffa455 mm,oom_reaper: re... |
601 |
done: |
449d777d7 mm, oom_reaper: c... |
602 |
tsk->oom_reaper_list = NULL; |
449d777d7 mm, oom_reaper: c... |
603 |
|
26db62f17 oom: keep mm of t... |
604 605 606 607 |
/* * Hide this mm from OOM killer because it has been either reaped or * somebody can't call up_write(mmap_sem). */ |
862e3073b mm, oom: get rid ... |
608 |
set_bit(MMF_OOM_SKIP, &mm->flags); |
26db62f17 oom: keep mm of t... |
609 |
|
aac453635 mm, oom: introduc... |
610 |
/* Drop a reference taken by wake_oom_reaper */ |
36324a990 oom: clear TIF_ME... |
611 |
put_task_struct(tsk); |
aac453635 mm, oom: introduc... |
612 613 614 615 616 |
} static int oom_reaper(void *unused) { while (true) { |
03049269d mm, oom_reaper: i... |
617 |
struct task_struct *tsk = NULL; |
aac453635 mm, oom: introduc... |
618 |
|
29c696e1c oom: make oom_rea... |
619 |
wait_event_freezable(oom_reaper_wait, oom_reaper_list != NULL); |
03049269d mm, oom_reaper: i... |
620 |
spin_lock(&oom_reaper_lock); |
29c696e1c oom: make oom_rea... |
621 622 623 |
if (oom_reaper_list != NULL) { tsk = oom_reaper_list; oom_reaper_list = tsk->oom_reaper_list; |
03049269d mm, oom_reaper: i... |
624 625 626 627 628 |
} spin_unlock(&oom_reaper_lock); if (tsk) oom_reap_task(tsk); |
aac453635 mm, oom: introduc... |
629 630 631 632 |
} return 0; } |
7c5f64f84 mm: oom: deduplic... |
633 |
static void wake_oom_reaper(struct task_struct *tsk) |
aac453635 mm, oom: introduc... |
634 |
{ |
9bcdeb51b oom, oom_reaper: ... |
635 636 |
/* mm is already queued? */ if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags)) |
aac453635 mm, oom: introduc... |
637 |
return; |
36324a990 oom: clear TIF_ME... |
638 |
get_task_struct(tsk); |
aac453635 mm, oom: introduc... |
639 |
|
03049269d mm, oom_reaper: i... |
640 |
spin_lock(&oom_reaper_lock); |
29c696e1c oom: make oom_rea... |
641 642 |
tsk->oom_reaper_list = oom_reaper_list; oom_reaper_list = tsk; |
03049269d mm, oom_reaper: i... |
643 |
spin_unlock(&oom_reaper_lock); |
422580c3c mm/oom_kill.c: ad... |
644 |
trace_wake_reaper(tsk->pid); |
03049269d mm, oom_reaper: i... |
645 |
wake_up(&oom_reaper_wait); |
aac453635 mm, oom: introduc... |
646 647 648 649 650 |
} static int __init oom_init(void) { oom_reaper_th = kthread_run(oom_reaper, NULL, "oom_reaper"); |
aac453635 mm, oom: introduc... |
651 652 653 |
return 0; } subsys_initcall(oom_init) |
7c5f64f84 mm: oom: deduplic... |
654 655 656 657 658 |
#else static inline void wake_oom_reaper(struct task_struct *tsk) { } #endif /* CONFIG_MMU */ |
aac453635 mm, oom: introduc... |
659 |
|
49550b605 oom: add helpers ... |
660 |
/** |
16e951966 mm: oom_kill: cle... |
661 |
* mark_oom_victim - mark the given task as OOM victim |
49550b605 oom: add helpers ... |
662 |
* @tsk: task to mark |
c32b3cbe0 oom, PM: make OOM... |
663 |
* |
dc56401fc mm: oom_kill: sim... |
664 |
* Has to be called with oom_lock held and never after |
c32b3cbe0 oom, PM: make OOM... |
665 |
* oom has been disabled already. |
26db62f17 oom: keep mm of t... |
666 667 668 |
* * tsk->mm has to be non NULL and caller has to guarantee it is stable (either * under task_lock or operate on the current). |
49550b605 oom: add helpers ... |
669 |
*/ |
7c5f64f84 mm: oom: deduplic... |
670 |
static void mark_oom_victim(struct task_struct *tsk) |
49550b605 oom: add helpers ... |
671 |
{ |
26db62f17 oom: keep mm of t... |
672 |
struct mm_struct *mm = tsk->mm; |
c32b3cbe0 oom, PM: make OOM... |
673 674 675 676 |
WARN_ON(oom_killer_disabled); /* OOM killer might race with memcg OOM */ if (test_and_set_tsk_thread_flag(tsk, TIF_MEMDIE)) return; |
26db62f17 oom: keep mm of t... |
677 |
|
26db62f17 oom: keep mm of t... |
678 |
/* oom_mm is bound to the signal struct life time. */ |
4837fe37a mm, oom_reaper: f... |
679 |
if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm)) { |
f1f100764 mm: add new mmgra... |
680 |
mmgrab(tsk->signal->oom_mm); |
4837fe37a mm, oom_reaper: f... |
681 682 |
set_bit(MMF_OOM_VICTIM, &mm->flags); } |
26db62f17 oom: keep mm of t... |
683 |
|
63a8ca9b2 oom: thaw the OOM... |
684 685 686 687 688 689 690 |
/* * Make sure that the task is woken up from uninterruptible sleep * if it is frozen because OOM killer wouldn't be able to free * any memory and livelock. freezing_slow_path will tell the freezer * that TIF_MEMDIE tasks should be ignored. */ __thaw_task(tsk); |
c32b3cbe0 oom, PM: make OOM... |
691 |
atomic_inc(&oom_victims); |
422580c3c mm/oom_kill.c: ad... |
692 |
trace_mark_victim(tsk->pid); |
49550b605 oom: add helpers ... |
693 694 695 |
} /** |
16e951966 mm: oom_kill: cle... |
696 |
* exit_oom_victim - note the exit of an OOM victim |
49550b605 oom: add helpers ... |
697 |
*/ |
38531201c mm, oom: enforce ... |
698 |
void exit_oom_victim(void) |
49550b605 oom: add helpers ... |
699 |
{ |
38531201c mm, oom: enforce ... |
700 |
clear_thread_flag(TIF_MEMDIE); |
c32b3cbe0 oom, PM: make OOM... |
701 |
|
c38f1025f mm: oom_kill: gen... |
702 |
if (!atomic_dec_return(&oom_victims)) |
c32b3cbe0 oom, PM: make OOM... |
703 |
wake_up_all(&oom_victims_wait); |
c32b3cbe0 oom, PM: make OOM... |
704 705 706 |
} /** |
7d2e7a22c oom, suspend: fix... |
707 708 709 710 711 |
* oom_killer_enable - enable OOM killer */ void oom_killer_enable(void) { oom_killer_disabled = false; |
d75da004c oom: improve oom ... |
712 713 |
pr_info("OOM killer enabled. "); |
7d2e7a22c oom, suspend: fix... |
714 715 716 |
} /** |
c32b3cbe0 oom, PM: make OOM... |
717 |
* oom_killer_disable - disable OOM killer |
7d2e7a22c oom, suspend: fix... |
718 |
* @timeout: maximum timeout to wait for oom victims in jiffies |
c32b3cbe0 oom, PM: make OOM... |
719 720 |
* * Forces all page allocations to fail rather than trigger OOM killer. |
7d2e7a22c oom, suspend: fix... |
721 722 |
* Will block and wait until all OOM victims are killed or the given * timeout expires. |
c32b3cbe0 oom, PM: make OOM... |
723 724 725 726 727 728 729 730 |
* * The function cannot be called when there are runnable user tasks because * the userspace would see unexpected allocation failures as a result. Any * new usage of this function should be consulted with MM people. * * Returns true if successful and false if the OOM killer cannot be * disabled. */ |
7d2e7a22c oom, suspend: fix... |
731 |
bool oom_killer_disable(signed long timeout) |
c32b3cbe0 oom, PM: make OOM... |
732 |
{ |
7d2e7a22c oom, suspend: fix... |
733 |
signed long ret; |
c32b3cbe0 oom, PM: make OOM... |
734 |
/* |
6afcf2895 mm,oom: make oom_... |
735 736 |
* Make sure to not race with an ongoing OOM killer. Check that the * current is not killed (possibly due to sharing the victim's memory). |
c32b3cbe0 oom, PM: make OOM... |
737 |
*/ |
6afcf2895 mm,oom: make oom_... |
738 |
if (mutex_lock_killable(&oom_lock)) |
c32b3cbe0 oom, PM: make OOM... |
739 |
return false; |
c32b3cbe0 oom, PM: make OOM... |
740 |
oom_killer_disabled = true; |
dc56401fc mm: oom_kill: sim... |
741 |
mutex_unlock(&oom_lock); |
c32b3cbe0 oom, PM: make OOM... |
742 |
|
7d2e7a22c oom, suspend: fix... |
743 744 745 746 747 748 |
ret = wait_event_interruptible_timeout(oom_victims_wait, !atomic_read(&oom_victims), timeout); if (ret <= 0) { oom_killer_enable(); return false; } |
d75da004c oom: improve oom ... |
749 750 |
pr_info("OOM killer disabled. "); |
c32b3cbe0 oom, PM: make OOM... |
751 752 753 |
return true; } |
1af8bb432 mm, oom: fortify ... |
754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 |
static inline bool __task_will_free_mem(struct task_struct *task) { struct signal_struct *sig = task->signal; /* * A coredumping process may sleep for an extended period in exit_mm(), * so the oom killer cannot assume that the process will promptly exit * and release memory. */ if (sig->flags & SIGNAL_GROUP_COREDUMP) return false; if (sig->flags & SIGNAL_GROUP_EXIT) return true; if (thread_group_empty(task) && (task->flags & PF_EXITING)) return true; return false; } /* * Checks whether the given task is dying or exiting and likely to * release its address space. This means that all threads and processes * sharing the same mm have to be killed or exiting. |
091f362c5 mm, oom: tighten ... |
779 780 |
* Caller has to make sure that task->mm is stable (hold task_lock or * it operates on the current). |
1af8bb432 mm, oom: fortify ... |
781 |
*/ |
7c5f64f84 mm: oom: deduplic... |
782 |
static bool task_will_free_mem(struct task_struct *task) |
1af8bb432 mm, oom: fortify ... |
783 |
{ |
091f362c5 mm, oom: tighten ... |
784 |
struct mm_struct *mm = task->mm; |
1af8bb432 mm, oom: fortify ... |
785 |
struct task_struct *p; |
f33e6f067 mm, oom: fix unin... |
786 |
bool ret = true; |
1af8bb432 mm, oom: fortify ... |
787 |
|
1af8bb432 mm, oom: fortify ... |
788 |
/* |
091f362c5 mm, oom: tighten ... |
789 790 791 |
* Skip tasks without mm because it might have passed its exit_mm and * exit_oom_victim. oom_reaper could have rescued that but do not rely * on that for now. We can consider find_lock_task_mm in future. |
1af8bb432 mm, oom: fortify ... |
792 |
*/ |
091f362c5 mm, oom: tighten ... |
793 |
if (!mm) |
1af8bb432 mm, oom: fortify ... |
794 |
return false; |
091f362c5 mm, oom: tighten ... |
795 796 |
if (!__task_will_free_mem(task)) return false; |
696453e66 mm, oom: task_wil... |
797 798 799 800 801 |
/* * This task has already been drained by the oom reaper so there are * only small chances it will free some more */ |
862e3073b mm, oom: get rid ... |
802 |
if (test_bit(MMF_OOM_SKIP, &mm->flags)) |
696453e66 mm, oom: task_wil... |
803 |
return false; |
696453e66 mm, oom: task_wil... |
804 |
|
091f362c5 mm, oom: tighten ... |
805 |
if (atomic_read(&mm->mm_users) <= 1) |
1af8bb432 mm, oom: fortify ... |
806 |
return true; |
1af8bb432 mm, oom: fortify ... |
807 808 |
/* |
5870c2e1d mm/oom_kill.c: fi... |
809 810 811 |
* Make sure that all tasks which share the mm with the given tasks * are dying as well to make sure that a) nobody pins its mm and * b) the task is also reapable by the oom reaper. |
1af8bb432 mm, oom: fortify ... |
812 813 814 815 816 817 818 819 820 821 822 823 |
*/ rcu_read_lock(); for_each_process(p) { if (!process_shares_mm(p, mm)) continue; if (same_thread_group(task, p)) continue; ret = __task_will_free_mem(p); if (!ret) break; } rcu_read_unlock(); |
1af8bb432 mm, oom: fortify ... |
824 825 826 |
return ret; } |
bbbe48029 mm, oom: remove '... |
827 |
static void __oom_kill_process(struct task_struct *victim, const char *message) |
1da177e4c Linux-2.6.12-rc2 |
828 |
{ |
5989ad7b5 mm, oom: refactor... |
829 |
struct task_struct *p; |
647f2bdf4 mm, oom: fold oom... |
830 |
struct mm_struct *mm; |
bb29902a7 oom, oom_reaper: ... |
831 |
bool can_oom_reap = true; |
1da177e4c Linux-2.6.12-rc2 |
832 |
|
6b0c81b3b mm, oom: reduce d... |
833 834 |
p = find_lock_task_mm(victim); if (!p) { |
6b0c81b3b mm, oom: reduce d... |
835 |
put_task_struct(victim); |
647f2bdf4 mm, oom: fold oom... |
836 |
return; |
6b0c81b3b mm, oom: reduce d... |
837 838 839 840 841 |
} else if (victim != p) { get_task_struct(p); put_task_struct(victim); victim = p; } |
647f2bdf4 mm, oom: fold oom... |
842 |
|
880b76893 mm/oom_kill.c: fi... |
843 |
/* Get a reference to safely compare mm after task_unlock(victim) */ |
647f2bdf4 mm, oom: fold oom... |
844 |
mm = victim->mm; |
f1f100764 mm: add new mmgra... |
845 |
mmgrab(mm); |
8e675f7af mm/oom_kill: coun... |
846 847 848 |
/* Raise event before sending signal: task reaper must see this */ count_vm_event(OOM_KILL); |
fe6bdfc8e mm: fix oom_kill ... |
849 |
memcg_memory_event_mm(mm, MEMCG_OOM_KILL); |
8e675f7af mm/oom_kill: coun... |
850 |
|
426fb5e72 mm/oom_kill.c: re... |
851 |
/* |
cd04ae1e2 mm, oom: do not r... |
852 853 854 |
* We should send SIGKILL before granting access to memory reserves * in order to prevent the OOM victim from depleting the memory * reserves from the user space under its control. |
426fb5e72 mm/oom_kill.c: re... |
855 |
*/ |
079b22dc9 signal: Use SEND_... |
856 |
do_send_sig_info(SIGKILL, SEND_SIG_PRIV, victim, PIDTYPE_TGID); |
16e951966 mm: oom_kill: cle... |
857 |
mark_oom_victim(victim); |
70cb6d267 mm/oom: add oom_s... |
858 859 860 861 862 863 864 |
pr_err("%s: Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB, UID:%u pgtables:%lukB oom_score_adj:%hd ", message, task_pid_nr(victim), victim->comm, K(mm->total_vm), K(get_mm_counter(mm, MM_ANONPAGES)), K(get_mm_counter(mm, MM_FILEPAGES)), K(get_mm_counter(mm, MM_SHMEMPAGES)), from_kuid(&init_user_ns, task_uid(victim)), |
7123ee7b3 mm/oom: fix pgtab... |
865 |
mm_pgtables_bytes(mm) >> 10, victim->signal->oom_score_adj); |
647f2bdf4 mm, oom: fold oom... |
866 867 868 869 870 871 872 873 874 875 876 |
task_unlock(victim); /* * Kill all user processes sharing victim->mm in other thread groups, if * any. They don't get access to memory reserves, though, to avoid * depletion of all memory. This prevents mm->mmap_sem livelock when an * oom killed thread cannot exit because it requires the semaphore and * its contended by another thread trying to allocate memory itself. * That thread will now get access to memory reserves since it has a * pending fatal signal. */ |
4d4048be8 oom_kill: add rcu... |
877 |
rcu_read_lock(); |
c319025a6 mm/oom_kill: clea... |
878 |
for_each_process(p) { |
4d7b3394f mm/oom_kill: fix ... |
879 |
if (!process_shares_mm(p, mm)) |
c319025a6 mm/oom_kill: clea... |
880 881 882 |
continue; if (same_thread_group(p, victim)) continue; |
1b51e65ea oom, oom_reaper: ... |
883 |
if (is_global_init(p)) { |
aac453635 mm, oom: introduc... |
884 |
can_oom_reap = false; |
862e3073b mm, oom: get rid ... |
885 |
set_bit(MMF_OOM_SKIP, &mm->flags); |
a373966d1 mm, oom: hide mm ... |
886 887 888 889 |
pr_info("oom killer %d (%s) has mm pinned by %d (%s) ", task_pid_nr(victim), victim->comm, task_pid_nr(p), p->comm); |
c319025a6 mm/oom_kill: clea... |
890 |
continue; |
aac453635 mm, oom: introduc... |
891 |
} |
1b51e65ea oom, oom_reaper: ... |
892 893 894 895 896 897 |
/* * No use_mm() user needs to read from the userspace so we are * ok to reap it. */ if (unlikely(p->flags & PF_KTHREAD)) continue; |
079b22dc9 signal: Use SEND_... |
898 |
do_send_sig_info(SIGKILL, SEND_SIG_PRIV, p, PIDTYPE_TGID); |
c319025a6 mm/oom_kill: clea... |
899 |
} |
6b0c81b3b mm, oom: reduce d... |
900 |
rcu_read_unlock(); |
647f2bdf4 mm, oom: fold oom... |
901 |
|
aac453635 mm, oom: introduc... |
902 |
if (can_oom_reap) |
36324a990 oom: clear TIF_ME... |
903 |
wake_oom_reaper(victim); |
aac453635 mm, oom: introduc... |
904 |
|
880b76893 mm/oom_kill.c: fi... |
905 |
mmdrop(mm); |
6b0c81b3b mm, oom: reduce d... |
906 |
put_task_struct(victim); |
1da177e4c Linux-2.6.12-rc2 |
907 |
} |
647f2bdf4 mm, oom: fold oom... |
908 |
#undef K |
1da177e4c Linux-2.6.12-rc2 |
909 |
|
309ed8825 oom: extract pani... |
910 |
/* |
3d8b38eb8 mm, oom: introduc... |
911 912 913 |
* Kill provided task unless it's secured by setting * oom_score_adj to OOM_SCORE_ADJ_MIN. */ |
bbbe48029 mm, oom: remove '... |
914 |
static int oom_kill_memcg_member(struct task_struct *task, void *message) |
3d8b38eb8 mm, oom: introduc... |
915 |
{ |
d342a0b38 mm,oom: don't kil... |
916 917 |
if (task->signal->oom_score_adj != OOM_SCORE_ADJ_MIN && !is_global_init(task)) { |
3d8b38eb8 mm, oom: introduc... |
918 |
get_task_struct(task); |
bbbe48029 mm, oom: remove '... |
919 |
__oom_kill_process(task, message); |
3d8b38eb8 mm, oom: introduc... |
920 921 922 |
} return 0; } |
5989ad7b5 mm, oom: refactor... |
923 924 |
static void oom_kill_process(struct oom_control *oc, const char *message) { |
bbbe48029 mm, oom: remove '... |
925 |
struct task_struct *victim = oc->chosen; |
3d8b38eb8 mm, oom: introduc... |
926 |
struct mem_cgroup *oom_group; |
5989ad7b5 mm, oom: refactor... |
927 928 929 930 931 932 933 934 |
static DEFINE_RATELIMIT_STATE(oom_rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); /* * If the task is already exiting, don't alarm the sysadmin or kill * its children or threads, just give it access to memory reserves * so it can die quickly */ |
bbbe48029 mm, oom: remove '... |
935 936 937 938 939 940 |
task_lock(victim); if (task_will_free_mem(victim)) { mark_oom_victim(victim); wake_oom_reaper(victim); task_unlock(victim); put_task_struct(victim); |
5989ad7b5 mm, oom: refactor... |
941 942 |
return; } |
bbbe48029 mm, oom: remove '... |
943 |
task_unlock(victim); |
5989ad7b5 mm, oom: refactor... |
944 945 |
if (__ratelimit(&oom_rs)) |
bbbe48029 mm, oom: remove '... |
946 |
dump_header(oc, victim); |
5989ad7b5 mm, oom: refactor... |
947 |
|
3d8b38eb8 mm, oom: introduc... |
948 949 950 951 952 953 |
/* * Do we need to kill the entire memory cgroup? * Or even one of the ancestor memory cgroups? * Check this out before killing the victim task. */ oom_group = mem_cgroup_get_oom_group(victim, oc->memcg); |
bbbe48029 mm, oom: remove '... |
954 |
__oom_kill_process(victim, message); |
3d8b38eb8 mm, oom: introduc... |
955 956 957 958 959 960 |
/* * If necessary, kill all tasks in the selected memory cgroup. */ if (oom_group) { mem_cgroup_print_oom_group(oom_group); |
bbbe48029 mm, oom: remove '... |
961 962 |
mem_cgroup_scan_tasks(oom_group, oom_kill_memcg_member, (void*)message); |
3d8b38eb8 mm, oom: introduc... |
963 964 |
mem_cgroup_put(oom_group); } |
5989ad7b5 mm, oom: refactor... |
965 |
} |
309ed8825 oom: extract pani... |
966 967 968 |
/* * Determines whether the kernel must panic because of the panic_on_oom sysctl. */ |
432b1de0d mm/oom_kill.c: fi... |
969 |
static void check_panic_on_oom(struct oom_control *oc) |
309ed8825 oom: extract pani... |
970 971 972 973 974 975 976 977 978 |
{ if (likely(!sysctl_panic_on_oom)) return; if (sysctl_panic_on_oom != 2) { /* * panic_on_oom == 1 only affects CONSTRAINT_NONE, the kernel * does not panic for cpuset, mempolicy, or memcg allocation * failures. */ |
432b1de0d mm/oom_kill.c: fi... |
979 |
if (oc->constraint != CONSTRAINT_NONE) |
309ed8825 oom: extract pani... |
980 981 |
return; } |
071a4befe mm, oom: do not p... |
982 |
/* Do not panic for oom kills triggered by sysrq */ |
db2a0dd7a mm/oom_kill.c: in... |
983 |
if (is_sysrq_oom(oc)) |
071a4befe mm, oom: do not p... |
984 |
return; |
2a966b77a mm: oom: add memc... |
985 |
dump_header(oc, NULL); |
309ed8825 oom: extract pani... |
986 987 988 989 |
panic("Out of memory: %s panic_on_oom is enabled ", sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide"); } |
8bc719d3c [PATCH] out of me... |
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 |
static BLOCKING_NOTIFIER_HEAD(oom_notify_list); int register_oom_notifier(struct notifier_block *nb) { return blocking_notifier_chain_register(&oom_notify_list, nb); } EXPORT_SYMBOL_GPL(register_oom_notifier); int unregister_oom_notifier(struct notifier_block *nb) { return blocking_notifier_chain_unregister(&oom_notify_list, nb); } EXPORT_SYMBOL_GPL(unregister_oom_notifier); |
1da177e4c Linux-2.6.12-rc2 |
1003 |
/** |
6e0fc46dc mm, oom: organize... |
1004 1005 |
* out_of_memory - kill the "best" process when we run out of memory * @oc: pointer to struct oom_control |
1da177e4c Linux-2.6.12-rc2 |
1006 1007 1008 1009 1010 1011 |
* * If we run out of memory, we have the choice between either * killing a random task (bad), letting the system crash (worse) * OR try to be smart about which process to kill. Note that we * don't have to be perfect here, we just have to be good. */ |
6e0fc46dc mm, oom: organize... |
1012 |
bool out_of_memory(struct oom_control *oc) |
1da177e4c Linux-2.6.12-rc2 |
1013 |
{ |
8bc719d3c [PATCH] out of me... |
1014 |
unsigned long freed = 0; |
dc56401fc mm: oom_kill: sim... |
1015 1016 |
if (oom_killer_disabled) return false; |
7c5f64f84 mm: oom: deduplic... |
1017 1018 1019 1020 1021 1022 |
if (!is_memcg_oom(oc)) { blocking_notifier_call_chain(&oom_notify_list, 0, &freed); if (freed > 0) /* Got some memory back in the last second. */ return true; } |
1da177e4c Linux-2.6.12-rc2 |
1023 |
|
7b98c2e40 oom: give current... |
1024 |
/* |
9ff4868e3 mm, oom: allow ex... |
1025 1026 1027 |
* If current has a pending SIGKILL or is exiting, then automatically * select it. The goal is to allow it to allocate so that it may * quickly exit and free its memory. |
7b98c2e40 oom: give current... |
1028 |
*/ |
091f362c5 mm, oom: tighten ... |
1029 |
if (task_will_free_mem(current)) { |
16e951966 mm: oom_kill: cle... |
1030 |
mark_oom_victim(current); |
1af8bb432 mm, oom: fortify ... |
1031 |
wake_oom_reaper(current); |
75e8f8b24 mm, oom: remove u... |
1032 |
return true; |
7b98c2e40 oom: give current... |
1033 |
} |
9b0f8b040 [PATCH] Terminate... |
1034 |
/* |
3da88fb3b mm, oom: move GFP... |
1035 1036 1037 |
* The OOM killer does not compensate for IO-less reclaim. * pagefault_out_of_memory lost its gfp context so we have to * make sure exclude 0 mask - all other users should have at least |
f9c645621 memcg, oom: don't... |
1038 1039 |
* ___GFP_DIRECT_RECLAIM to get here. But mem_cgroup_oom() has to * invoke the OOM killer even if it is a GFP_NOFS allocation. |
3da88fb3b mm, oom: move GFP... |
1040 |
*/ |
f9c645621 memcg, oom: don't... |
1041 |
if (oc->gfp_mask && !(oc->gfp_mask & __GFP_FS) && !is_memcg_oom(oc)) |
3da88fb3b mm, oom: move GFP... |
1042 1043 1044 |
return true; /* |
9b0f8b040 [PATCH] Terminate... |
1045 |
* Check if there were limitations on the allocation (only relevant for |
7c5f64f84 mm: oom: deduplic... |
1046 |
* NUMA and memcg) that may require different handling. |
9b0f8b040 [PATCH] Terminate... |
1047 |
*/ |
432b1de0d mm/oom_kill.c: fi... |
1048 1049 |
oc->constraint = constrained_alloc(oc); if (oc->constraint != CONSTRAINT_MEMORY_POLICY) |
6e0fc46dc mm, oom: organize... |
1050 |
oc->nodemask = NULL; |
432b1de0d mm/oom_kill.c: fi... |
1051 |
check_panic_on_oom(oc); |
0aad4b312 oom: fold __out_o... |
1052 |
|
7c5f64f84 mm: oom: deduplic... |
1053 |
if (!is_memcg_oom(oc) && sysctl_oom_kill_allocating_task && |
ac311a14c oom: decouple mem... |
1054 1055 |
current->mm && !oom_unkillable_task(current) && oom_cpuset_eligible(current, oc) && |
121d1ba0a mm, oom: fix pote... |
1056 |
current->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) { |
6b0c81b3b mm, oom: reduce d... |
1057 |
get_task_struct(current); |
7c5f64f84 mm: oom: deduplic... |
1058 1059 |
oc->chosen = current; oom_kill_process(oc, "Out of memory (oom_kill_allocating_task)"); |
75e8f8b24 mm, oom: remove u... |
1060 |
return true; |
0aad4b312 oom: fold __out_o... |
1061 |
} |
7c5f64f84 mm: oom: deduplic... |
1062 |
select_bad_process(oc); |
3100dab2a mm: memcontrol: p... |
1063 1064 |
/* Found nothing?!?! */ if (!oc->chosen) { |
2a966b77a mm: oom: add memc... |
1065 |
dump_header(oc, NULL); |
3100dab2a mm: memcontrol: p... |
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 |
pr_warn("Out of memory and no killable processes... "); /* * If we got here due to an actual allocation at the * system level, we cannot survive this and will enter * an endless loop in the allocator. Bail out now. */ if (!is_sysrq_oom(oc) && !is_memcg_oom(oc)) panic("System is deadlocked on memory "); |
0aad4b312 oom: fold __out_o... |
1076 |
} |
9bfe5ded0 mm, oom: remove s... |
1077 |
if (oc->chosen && oc->chosen != (void *)-1UL) |
7c5f64f84 mm: oom: deduplic... |
1078 1079 |
oom_kill_process(oc, !is_memcg_oom(oc) ? "Out of memory" : "Memory cgroup out of memory"); |
7c5f64f84 mm: oom: deduplic... |
1080 |
return !!oc->chosen; |
c32b3cbe0 oom, PM: make OOM... |
1081 |
} |
e36589323 oom: remove speci... |
1082 1083 |
/* * The pagefault handler calls here because it is out of memory, so kill a |
798fd7569 mm: zap ZONE_OOM_... |
1084 1085 |
* memory-hogging task. If oom_lock is held by somebody else, a parallel oom * killing is already in progress so do nothing. |
e36589323 oom: remove speci... |
1086 1087 1088 |
*/ void pagefault_out_of_memory(void) { |
6e0fc46dc mm, oom: organize... |
1089 1090 1091 |
struct oom_control oc = { .zonelist = NULL, .nodemask = NULL, |
2a966b77a mm: oom: add memc... |
1092 |
.memcg = NULL, |
6e0fc46dc mm, oom: organize... |
1093 1094 |
.gfp_mask = 0, .order = 0, |
6e0fc46dc mm, oom: organize... |
1095 |
}; |
494264208 mm: memcg: handle... |
1096 |
if (mem_cgroup_oom_synchronize(true)) |
dc56401fc mm: oom_kill: sim... |
1097 |
return; |
3812c8c8f mm: memcg: do not... |
1098 |
|
dc56401fc mm: oom_kill: sim... |
1099 1100 |
if (!mutex_trylock(&oom_lock)) return; |
a104808e2 mm: don't emit wa... |
1101 |
out_of_memory(&oc); |
dc56401fc mm: oom_kill: sim... |
1102 |
mutex_unlock(&oom_lock); |
e36589323 oom: remove speci... |
1103 |
} |