Blame view
mm/oom_kill.c
31.8 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> |
8a7ff02ac mm, oom: dump sta... |
28 |
#include <linux/sched/debug.h> |
1da177e4c Linux-2.6.12-rc2 |
29 30 31 |
#include <linux/swap.h> #include <linux/timex.h> #include <linux/jiffies.h> |
ef08e3b49 [PATCH] cpusets: ... |
32 |
#include <linux/cpuset.h> |
b95f1b31b mm: Map most file... |
33 |
#include <linux/export.h> |
8bc719d3c [PATCH] out of me... |
34 |
#include <linux/notifier.h> |
c7ba5c9e8 Memory controller... |
35 |
#include <linux/memcontrol.h> |
6f48d0ebd oom: select task ... |
36 |
#include <linux/mempolicy.h> |
5cd9c58fb security: Fix set... |
37 |
#include <linux/security.h> |
edd45544c oom: avoid deferr... |
38 |
#include <linux/ptrace.h> |
f660daac4 oom: thaw threads... |
39 |
#include <linux/freezer.h> |
43d2b1132 tracepoint: add t... |
40 |
#include <linux/ftrace.h> |
dc3f21ead mm, oom: introduc... |
41 |
#include <linux/ratelimit.h> |
aac453635 mm, oom: introduc... |
42 43 |
#include <linux/kthread.h> #include <linux/init.h> |
4d4bbd852 mm, oom_reaper: s... |
44 |
#include <linux/mmu_notifier.h> |
aac453635 mm, oom: introduc... |
45 46 47 |
#include <asm/tlb.h> #include "internal.h" |
852d8be0a mm: oom: show unr... |
48 |
#include "slab.h" |
43d2b1132 tracepoint: add t... |
49 50 51 |
#define CREATE_TRACE_POINTS #include <trace/events/oom.h> |
1da177e4c Linux-2.6.12-rc2 |
52 |
|
fadd8fbd1 [PATCH] support f... |
53 |
int sysctl_panic_on_oom; |
fe071d7e8 oom: add oom_kill... |
54 |
int sysctl_oom_kill_allocating_task; |
ad915c432 oom: enable oom t... |
55 |
int sysctl_oom_dump_tasks = 1; |
dc56401fc mm: oom_kill: sim... |
56 |
|
a195d3f5b mm/oom_kill.c: do... |
57 58 59 60 61 62 63 64 |
/* * 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... |
65 |
DEFINE_MUTEX(oom_lock); |
67197a4f2 mm, oom_adj: don'... |
66 67 |
/* Serializes oom_score_adj and oom_score_adj_min updates */ DEFINE_MUTEX(oom_adj_mutex); |
1da177e4c Linux-2.6.12-rc2 |
68 |
|
ac311a14c oom: decouple mem... |
69 70 71 72 |
static inline bool is_memcg_oom(struct oom_control *oc) { return oc->memcg != NULL; } |
6f48d0ebd oom: select task ... |
73 74 |
#ifdef CONFIG_NUMA /** |
ac311a14c oom: decouple mem... |
75 |
* oom_cpuset_eligible() - check task eligiblity for kill |
ad9624417 oom_kill: has_int... |
76 |
* @start: task struct of which task to consider |
f364f06b3 mm/oom_kill.c: fi... |
77 |
* @oc: pointer to struct oom_control |
6f48d0ebd oom: select task ... |
78 79 80 81 |
* * 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... |
82 83 84 |
* * This function is assuming oom-killer context and 'current' has triggered * the oom-killer. |
495789a51 oom: make oom_sco... |
85 |
*/ |
ac311a14c oom: decouple mem... |
86 87 |
static bool oom_cpuset_eligible(struct task_struct *start, struct oom_control *oc) |
495789a51 oom: make oom_sco... |
88 |
{ |
ad9624417 oom_kill: has_int... |
89 90 |
struct task_struct *tsk; bool ret = false; |
ac311a14c oom: decouple mem... |
91 92 93 94 |
const nodemask_t *mask = oc->nodemask; if (is_memcg_oom(oc)) return true; |
495789a51 oom: make oom_sco... |
95 |
|
ad9624417 oom_kill: has_int... |
96 |
rcu_read_lock(); |
1da4db0cd oom_kill: change ... |
97 |
for_each_thread(start, tsk) { |
6f48d0ebd oom: select task ... |
98 99 100 101 102 103 104 |
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... |
105 |
ret = mempolicy_nodemask_intersects(tsk, mask); |
6f48d0ebd oom: select task ... |
106 107 108 109 110 |
} else { /* * This is not a mempolicy constrained oom, so only * check the mems of tsk's cpuset. */ |
ad9624417 oom_kill: has_int... |
111 |
ret = cpuset_mems_allowed_intersects(current, tsk); |
6f48d0ebd oom: select task ... |
112 |
} |
ad9624417 oom_kill: has_int... |
113 114 |
if (ret) break; |
1da4db0cd oom_kill: change ... |
115 |
} |
ad9624417 oom_kill: has_int... |
116 |
rcu_read_unlock(); |
df1090a8d oom: cleanup has_... |
117 |
|
ad9624417 oom_kill: has_int... |
118 |
return ret; |
6f48d0ebd oom: select task ... |
119 120 |
} #else |
ac311a14c oom: decouple mem... |
121 |
static bool oom_cpuset_eligible(struct task_struct *tsk, struct oom_control *oc) |
6f48d0ebd oom: select task ... |
122 123 |
{ return true; |
495789a51 oom: make oom_sco... |
124 |
} |
6f48d0ebd oom: select task ... |
125 |
#endif /* CONFIG_NUMA */ |
495789a51 oom: make oom_sco... |
126 |
|
6f48d0ebd oom: select task ... |
127 128 |
/* * The process p may have detached its own ->mm while exiting or through |
f5678e7f2 kernel: better do... |
129 |
* kthread_use_mm(), but one or more of its subthreads may still have a valid |
6f48d0ebd oom: select task ... |
130 131 132 |
* pointer. Return p, or any of its subthreads with a valid ->mm, with * task_lock() held. */ |
158e0a2d1 memcg: use find_l... |
133 |
struct task_struct *find_lock_task_mm(struct task_struct *p) |
dd8e8f405 oom: introduce fi... |
134 |
{ |
1da4db0cd oom_kill: change ... |
135 |
struct task_struct *t; |
dd8e8f405 oom: introduce fi... |
136 |
|
4d4048be8 oom_kill: add rcu... |
137 |
rcu_read_lock(); |
1da4db0cd oom_kill: change ... |
138 |
for_each_thread(p, t) { |
dd8e8f405 oom: introduce fi... |
139 140 |
task_lock(t); if (likely(t->mm)) |
4d4048be8 oom_kill: add rcu... |
141 |
goto found; |
dd8e8f405 oom: introduce fi... |
142 |
task_unlock(t); |
1da4db0cd oom_kill: change ... |
143 |
} |
4d4048be8 oom_kill: add rcu... |
144 145 146 |
t = NULL; found: rcu_read_unlock(); |
dd8e8f405 oom: introduce fi... |
147 |
|
4d4048be8 oom_kill: add rcu... |
148 |
return t; |
dd8e8f405 oom: introduce fi... |
149 |
} |
db2a0dd7a mm/oom_kill.c: in... |
150 151 152 153 154 155 156 157 |
/* * 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... |
158 |
/* return true if the task is not adequate as candidate victim task. */ |
ac311a14c oom: decouple mem... |
159 |
static bool oom_unkillable_task(struct task_struct *p) |
ab290adba oom: make oom_unk... |
160 161 162 163 164 |
{ if (is_global_init(p)) return true; if (p->flags & PF_KTHREAD) return true; |
ab290adba oom: make oom_unk... |
165 166 |
return false; } |
852d8be0a mm: oom: show unr... |
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); |
d42f3245c mm: memcg: conver... |
182 |
return (global_node_page_state_pages(NR_SLAB_UNRECLAIMABLE_B) > nr_lru); |
852d8be0a mm: oom: show unr... |
183 |
} |
1da177e4c Linux-2.6.12-rc2 |
184 |
/** |
a63d83f42 oom: badness heur... |
185 |
* oom_badness - heuristic function to determine which candidate task to kill |
1da177e4c Linux-2.6.12-rc2 |
186 |
* @p: task struct of which task we should calculate |
a63d83f42 oom: badness heur... |
187 |
* @totalpages: total present RAM allowed for page allocation |
1da177e4c Linux-2.6.12-rc2 |
188 |
* |
a63d83f42 oom: badness heur... |
189 190 191 |
* 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 |
192 |
*/ |
9066e5cfb mm, oom: make the... |
193 |
long oom_badness(struct task_struct *p, unsigned long totalpages) |
1da177e4c Linux-2.6.12-rc2 |
194 |
{ |
1e11ad8dc mm, oom: fix badn... |
195 |
long points; |
61eafb00d mm, oom: fix and ... |
196 |
long adj; |
28b83c519 oom: move oom_adj... |
197 |
|
ac311a14c oom: decouple mem... |
198 |
if (oom_unkillable_task(p)) |
9066e5cfb mm, oom: make the... |
199 |
return LONG_MIN; |
1da177e4c Linux-2.6.12-rc2 |
200 |
|
dd8e8f405 oom: introduce fi... |
201 202 |
p = find_lock_task_mm(p); if (!p) |
9066e5cfb mm, oom: make the... |
203 |
return LONG_MIN; |
1da177e4c Linux-2.6.12-rc2 |
204 |
|
bb8a4b7fd mm, oom_reaper: h... |
205 206 |
/* * Do not even consider tasks which are explicitly marked oom |
b18dc5f29 mm, oom: skip vfo... |
207 208 |
* unkillable or have been already oom reaped or the are in * the middle of vfork |
bb8a4b7fd mm, oom_reaper: h... |
209 |
*/ |
a9c58b907 mm, oom: change t... |
210 |
adj = (long)p->signal->oom_score_adj; |
bb8a4b7fd mm, oom_reaper: h... |
211 |
if (adj == OOM_SCORE_ADJ_MIN || |
862e3073b mm, oom: get rid ... |
212 |
test_bit(MMF_OOM_SKIP, &p->mm->flags) || |
b18dc5f29 mm, oom: skip vfo... |
213 |
in_vfork(p)) { |
5aecc85ab oom: do not kill ... |
214 |
task_unlock(p); |
9066e5cfb mm, oom: make the... |
215 |
return LONG_MIN; |
5aecc85ab oom: do not kill ... |
216 |
} |
1da177e4c Linux-2.6.12-rc2 |
217 |
/* |
a63d83f42 oom: badness heur... |
218 |
* The baseline for the badness score is the proportion of RAM that each |
f755a042d oom: use pte page... |
219 |
* task's rss, pagetable and swap space use. |
1da177e4c Linux-2.6.12-rc2 |
220 |
*/ |
dc6c9a35b mm: account pmd p... |
221 |
points = get_mm_rss(p->mm) + get_mm_counter(p->mm, MM_SWAPENTS) + |
af5b0f6a0 mm: consolidate p... |
222 |
mm_pgtables_bytes(p->mm) / PAGE_SIZE; |
a63d83f42 oom: badness heur... |
223 |
task_unlock(p); |
1da177e4c Linux-2.6.12-rc2 |
224 |
|
61eafb00d mm, oom: fix and ... |
225 226 227 |
/* Normalize to oom_score_adj units */ adj *= totalpages / 1000; points += adj; |
1da177e4c Linux-2.6.12-rc2 |
228 |
|
9066e5cfb mm, oom: make the... |
229 |
return points; |
1da177e4c Linux-2.6.12-rc2 |
230 |
} |
ef8444ea0 mm, oom: reorgani... |
231 232 233 234 235 |
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... |
236 |
}; |
1da177e4c Linux-2.6.12-rc2 |
237 |
/* |
9b0f8b040 [PATCH] Terminate... |
238 239 |
* Determine the type of allocation constraint. */ |
7c5f64f84 mm: oom: deduplic... |
240 |
static enum oom_constraint constrained_alloc(struct oom_control *oc) |
4365a5676 oom-kill: fix NUM... |
241 |
{ |
54a6eb5c4 mm: use two zonel... |
242 |
struct zone *zone; |
dd1a239f6 mm: have zonelist... |
243 |
struct zoneref *z; |
97a225e69 mm/page_alloc: in... |
244 |
enum zone_type highest_zoneidx = gfp_zone(oc->gfp_mask); |
a63d83f42 oom: badness heur... |
245 246 |
bool cpuset_limited = false; int nid; |
9b0f8b040 [PATCH] Terminate... |
247 |
|
7c5f64f84 mm: oom: deduplic... |
248 |
if (is_memcg_oom(oc)) { |
bbec2e151 mm: rename page_c... |
249 |
oc->totalpages = mem_cgroup_get_max(oc->memcg) ?: 1; |
7c5f64f84 mm: oom: deduplic... |
250 251 |
return CONSTRAINT_MEMCG; } |
a63d83f42 oom: badness heur... |
252 |
/* Default to all available memory */ |
ca79b0c21 mm: convert total... |
253 |
oc->totalpages = totalram_pages() + total_swap_pages; |
7c5f64f84 mm: oom: deduplic... |
254 255 256 |
if (!IS_ENABLED(CONFIG_NUMA)) return CONSTRAINT_NONE; |
a63d83f42 oom: badness heur... |
257 |
|
6e0fc46dc mm, oom: organize... |
258 |
if (!oc->zonelist) |
a63d83f42 oom: badness heur... |
259 |
return CONSTRAINT_NONE; |
4365a5676 oom-kill: fix NUM... |
260 261 262 263 264 |
/* * 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... |
265 |
if (oc->gfp_mask & __GFP_THISNODE) |
4365a5676 oom-kill: fix NUM... |
266 |
return CONSTRAINT_NONE; |
9b0f8b040 [PATCH] Terminate... |
267 |
|
4365a5676 oom-kill: fix NUM... |
268 |
/* |
a63d83f42 oom: badness heur... |
269 270 271 |
* 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... |
272 |
*/ |
6e0fc46dc mm, oom: organize... |
273 274 |
if (oc->nodemask && !nodes_subset(node_states[N_MEMORY], *oc->nodemask)) { |
7c5f64f84 mm: oom: deduplic... |
275 |
oc->totalpages = total_swap_pages; |
6e0fc46dc mm, oom: organize... |
276 |
for_each_node_mask(nid, *oc->nodemask) |
1eb41bb07 mm, oom: consider... |
277 |
oc->totalpages += node_present_pages(nid); |
9b0f8b040 [PATCH] Terminate... |
278 |
return CONSTRAINT_MEMORY_POLICY; |
a63d83f42 oom: badness heur... |
279 |
} |
4365a5676 oom-kill: fix NUM... |
280 281 |
/* Check this allocation failure is caused by cpuset's wall function */ |
6e0fc46dc mm, oom: organize... |
282 |
for_each_zone_zonelist_nodemask(zone, z, oc->zonelist, |
97a225e69 mm/page_alloc: in... |
283 |
highest_zoneidx, oc->nodemask) |
6e0fc46dc mm, oom: organize... |
284 |
if (!cpuset_zone_allowed(zone, oc->gfp_mask)) |
a63d83f42 oom: badness heur... |
285 |
cpuset_limited = true; |
9b0f8b040 [PATCH] Terminate... |
286 |
|
a63d83f42 oom: badness heur... |
287 |
if (cpuset_limited) { |
7c5f64f84 mm: oom: deduplic... |
288 |
oc->totalpages = total_swap_pages; |
a63d83f42 oom: badness heur... |
289 |
for_each_node_mask(nid, cpuset_current_mems_allowed) |
1eb41bb07 mm, oom: consider... |
290 |
oc->totalpages += node_present_pages(nid); |
a63d83f42 oom: badness heur... |
291 292 |
return CONSTRAINT_CPUSET; } |
9b0f8b040 [PATCH] Terminate... |
293 294 |
return CONSTRAINT_NONE; } |
7c5f64f84 mm: oom: deduplic... |
295 |
static int oom_evaluate_task(struct task_struct *task, void *arg) |
462607ecc mm, oom: introduc... |
296 |
{ |
7c5f64f84 mm: oom: deduplic... |
297 |
struct oom_control *oc = arg; |
9066e5cfb mm, oom: make the... |
298 |
long points; |
7c5f64f84 mm: oom: deduplic... |
299 |
|
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 |
if (oom_task_origin(task)) { |
9066e5cfb mm, oom: make the... |
324 |
points = LONG_MAX; |
7c5f64f84 mm: oom: deduplic... |
325 326 |
goto select; } |
e1e12d2f3 mm, oom: fix race... |
327 |
|
ac311a14c oom: decouple mem... |
328 |
points = oom_badness(task, oc->totalpages); |
91ce4829f ANDROID: mm, oom:... |
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 |
if (points == LONG_MIN) goto next; /* * Check to see if this is the worst task with a non-negative * ADJ score seen so far */ if (task->signal->oom_score_adj >= 0 && points > oc->chosen_non_negative_adj_points) { if (oc->chosen_non_negative_adj) put_task_struct(oc->chosen_non_negative_adj); get_task_struct(task); oc->chosen_non_negative_adj = task; oc->chosen_non_negative_adj_points = points; } if (points < oc->chosen_points) |
7c5f64f84 mm: oom: deduplic... |
347 |
goto next; |
7c5f64f84 mm: oom: deduplic... |
348 349 350 351 352 353 354 355 356 |
select: if (oc->chosen) put_task_struct(oc->chosen); get_task_struct(task); oc->chosen = task; oc->chosen_points = points; next: return 0; abort: |
91ce4829f ANDROID: mm, oom:... |
357 358 |
if (oc->chosen_non_negative_adj) put_task_struct(oc->chosen_non_negative_adj); |
7c5f64f84 mm: oom: deduplic... |
359 360 361 362 |
if (oc->chosen) put_task_struct(oc->chosen); oc->chosen = (void *)-1UL; return 1; |
462607ecc mm, oom: introduc... |
363 |
} |
9b0f8b040 [PATCH] Terminate... |
364 |
/* |
7c5f64f84 mm: oom: deduplic... |
365 366 |
* 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 |
367 |
*/ |
7c5f64f84 mm: oom: deduplic... |
368 |
static void select_bad_process(struct oom_control *oc) |
1da177e4c Linux-2.6.12-rc2 |
369 |
{ |
9066e5cfb mm, oom: make the... |
370 |
oc->chosen_points = LONG_MIN; |
91ce4829f ANDROID: mm, oom:... |
371 372 |
oc->chosen_non_negative_adj_points = LONG_MIN; oc->chosen_non_negative_adj = NULL; |
9066e5cfb mm, oom: make the... |
373 |
|
7c5f64f84 mm: oom: deduplic... |
374 375 376 377 |
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... |
378 |
|
7c5f64f84 mm: oom: deduplic... |
379 380 381 382 383 |
rcu_read_lock(); for_each_process(p) if (oom_evaluate_task(p, oc)) break; rcu_read_unlock(); |
1da4db0cd oom_kill: change ... |
384 |
} |
91ce4829f ANDROID: mm, oom:... |
385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
if (oc->chosen_non_negative_adj) { /* * If oc->chosen has a negative ADJ, and we found a task with * a postive ADJ to kill, kill the task with the positive ADJ * instead. */ if (oc->chosen && oc->chosen->signal->oom_score_adj < 0) { put_task_struct(oc->chosen); oc->chosen = oc->chosen_non_negative_adj; oc->chosen_points = oc->chosen_non_negative_adj_points; } else put_task_struct(oc->chosen_non_negative_adj); } |
1da177e4c Linux-2.6.12-rc2 |
399 |
} |
5eee7e1cd mm, oom: refactor... |
400 401 402 403 |
static int dump_task(struct task_struct *p, void *arg) { struct oom_control *oc = arg; struct task_struct *task; |
ac311a14c oom: decouple mem... |
404 405 406 407 408 |
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... |
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 |
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 |
432 |
/** |
1b578df02 mm/oom_kill: fix ... |
433 |
* dump_tasks - dump current memory state of all system tasks |
5eee7e1cd mm, oom: refactor... |
434 |
* @oc: pointer to struct oom_control |
1b578df02 mm/oom_kill: fix ... |
435 |
* |
e85bfd3aa oom: filter unkil... |
436 437 438 |
* 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... |
439 440 |
* 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... |
441 |
*/ |
5eee7e1cd mm, oom: refactor... |
442 |
static void dump_tasks(struct oom_control *oc) |
fef1bdd68 oom: add sysctl t... |
443 |
{ |
c3b78b11e mm, oom: describe... |
444 445 446 447 |
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... |
448 |
|
5eee7e1cd mm, oom: refactor... |
449 450 451 452 |
if (is_memcg_oom(oc)) mem_cgroup_scan_tasks(oc->memcg, dump_task, oc); else { struct task_struct *p; |
c55db9578 oom: dump_tasks u... |
453 |
|
5eee7e1cd mm, oom: refactor... |
454 455 456 457 |
rcu_read_lock(); for_each_process(p) dump_task(p, oc); rcu_read_unlock(); |
c55db9578 oom: dump_tasks u... |
458 |
} |
fef1bdd68 oom: add sysctl t... |
459 |
} |
ef8444ea0 mm, oom: reorgani... |
460 461 462 463 464 465 466 |
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 ... |
467 |
mem_cgroup_print_oom_context(oc->memcg, victim); |
ef8444ea0 mm, oom: reorgani... |
468 469 470 471 |
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... |
472 |
static void dump_header(struct oom_control *oc, struct task_struct *p) |
1b604d75b oom: dump stack a... |
473 |
{ |
ef8444ea0 mm, oom: reorgani... |
474 475 476 |
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... |
477 |
current->signal->oom_score_adj); |
9254990fb oom: warn if we g... |
478 479 480 |
if (!IS_ENABLED(CONFIG_COMPACTION) && oc->order) pr_warn("COMPACTION is disabled!!! "); |
a0795cd41 mm, oom: print sy... |
481 |
|
1b604d75b oom: dump stack a... |
482 |
dump_stack(); |
852d8be0a mm: oom: show unr... |
483 |
if (is_memcg_oom(oc)) |
f0c867d95 mm, oom: add oom ... |
484 |
mem_cgroup_print_oom_meminfo(oc->memcg); |
852d8be0a mm: oom: show unr... |
485 |
else { |
299c517ad mm, oom: header n... |
486 |
show_mem(SHOW_MEM_FILTER_NODES, oc->nodemask); |
852d8be0a mm: oom: show unr... |
487 488 489 |
if (is_dump_unreclaim_slabs()) dump_unreclaimable_slab(); } |
1b604d75b oom: dump stack a... |
490 |
if (sysctl_oom_dump_tasks) |
5eee7e1cd mm, oom: refactor... |
491 |
dump_tasks(oc); |
ef8444ea0 mm, oom: reorgani... |
492 493 |
if (p) dump_oom_summary(oc, p); |
1b604d75b oom: dump stack a... |
494 |
} |
5695be142 OOM, PM: OOM kill... |
495 |
/* |
c32b3cbe0 oom, PM: make OOM... |
496 |
* Number of OOM victims in flight |
5695be142 OOM, PM: OOM kill... |
497 |
*/ |
c32b3cbe0 oom, PM: make OOM... |
498 499 |
static atomic_t oom_victims = ATOMIC_INIT(0); static DECLARE_WAIT_QUEUE_HEAD(oom_victims_wait); |
5695be142 OOM, PM: OOM kill... |
500 |
|
7c5f64f84 mm: oom: deduplic... |
501 |
static bool oom_killer_disabled __read_mostly; |
5695be142 OOM, PM: OOM kill... |
502 |
|
bc448e897 mm, oom_reaper: r... |
503 |
#define K(x) ((x) << (PAGE_SHIFT-10)) |
3ef22dfff oom, oom_reaper: ... |
504 505 506 507 508 509 |
/* * 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... |
510 |
bool process_shares_mm(struct task_struct *p, struct mm_struct *mm) |
3ef22dfff oom, oom_reaper: ... |
511 512 513 514 515 516 517 518 519 520 |
{ 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... |
521 522 523 524 525 526 |
#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... |
527 |
static DECLARE_WAIT_QUEUE_HEAD(oom_reaper_wait); |
29c696e1c oom: make oom_rea... |
528 |
static struct task_struct *oom_reaper_list; |
03049269d mm, oom_reaper: i... |
529 |
static DEFINE_SPINLOCK(oom_reaper_lock); |
93065ac75 mm, oom: distingu... |
530 |
bool __oom_reap_task_mm(struct mm_struct *mm) |
aac453635 mm, oom: introduc... |
531 |
{ |
aac453635 mm, oom: introduc... |
532 |
struct vm_area_struct *vma; |
93065ac75 mm, oom: distingu... |
533 |
bool ret = true; |
27ae357fa mm, oom: fix conc... |
534 535 536 537 538 539 540 541 542 543 |
/* * 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... |
544 |
if (!can_madv_lru_vma(vma)) |
27ae357fa mm, oom: fix conc... |
545 546 547 548 549 550 551 552 553 554 555 556 557 |
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: ... |
558 |
struct mmu_notifier_range range; |
27ae357fa mm, oom: fix conc... |
559 |
struct mmu_gather tlb; |
6f4f13e8d mm/mmu_notifier: ... |
560 561 |
mmu_notifier_range_init(&range, MMU_NOTIFY_UNMAP, 0, vma, mm, vma->vm_start, |
ac46d4f3c mm/mmu_notifier: ... |
562 563 564 565 |
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... |
566 567 568 |
ret = false; continue; } |
ac46d4f3c mm/mmu_notifier: ... |
569 570 571 |
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... |
572 573 |
} } |
93065ac75 mm, oom: distingu... |
574 575 |
return ret; |
27ae357fa mm, oom: fix conc... |
576 |
} |
431f42fdf mm/oom_kill.c: cl... |
577 578 579 580 581 582 |
/* * 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... |
583 584 |
static bool oom_reap_task_mm(struct task_struct *tsk, struct mm_struct *mm) { |
aac453635 mm, oom: introduc... |
585 |
bool ret = true; |
d8ed45c5d mmap locking API:... |
586 |
if (!mmap_read_trylock(mm)) { |
422580c3c mm/oom_kill.c: ad... |
587 |
trace_skip_task_reaping(tsk->pid); |
af5679fbc mm, oom: remove o... |
588 |
return false; |
4d4bbd852 mm, oom_reaper: s... |
589 590 591 |
} /* |
212925802 mm: oom: let oom_... |
592 593 |
* 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 |
3e4e28c5a mmap locking API:... |
594 595 |
* under mmap_lock for reading because it serializes against the * mmap_write_lock();mmap_write_unlock() cycle in exit_mmap(). |
e5e3f4c4f mm, oom_reaper: m... |
596 |
*/ |
212925802 mm: oom: let oom_... |
597 |
if (test_bit(MMF_OOM_SKIP, &mm->flags)) { |
422580c3c mm/oom_kill.c: ad... |
598 |
trace_skip_task_reaping(tsk->pid); |
431f42fdf mm/oom_kill.c: cl... |
599 |
goto out_unlock; |
aac453635 mm, oom: introduc... |
600 |
} |
422580c3c mm/oom_kill.c: ad... |
601 |
trace_start_task_reaping(tsk->pid); |
93065ac75 mm, oom: distingu... |
602 |
/* failed to reap part of the address space. Try again later */ |
431f42fdf mm/oom_kill.c: cl... |
603 604 605 |
ret = __oom_reap_task_mm(mm); if (!ret) goto out_finish; |
aac453635 mm, oom: introduc... |
606 |
|
bc448e897 mm, oom_reaper: r... |
607 608 609 610 611 612 |
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... |
613 614 615 |
out_finish: trace_finish_task_reaping(tsk->pid); out_unlock: |
d8ed45c5d mmap locking API:... |
616 |
mmap_read_unlock(mm); |
36324a990 oom: clear TIF_ME... |
617 |
|
aac453635 mm, oom: introduc... |
618 619 |
return ret; } |
bc448e897 mm, oom_reaper: r... |
620 |
#define MAX_OOM_REAP_RETRIES 10 |
36324a990 oom: clear TIF_ME... |
621 |
static void oom_reap_task(struct task_struct *tsk) |
aac453635 mm, oom: introduc... |
622 623 |
{ int attempts = 0; |
26db62f17 oom: keep mm of t... |
624 |
struct mm_struct *mm = tsk->signal->oom_mm; |
aac453635 mm, oom: introduc... |
625 |
|
3e4e28c5a mmap locking API:... |
626 |
/* Retry the mmap_read_trylock(mm) a few times */ |
27ae357fa mm, oom: fix conc... |
627 |
while (attempts++ < MAX_OOM_REAP_RETRIES && !oom_reap_task_mm(tsk, mm)) |
aac453635 mm, oom: introduc... |
628 |
schedule_timeout_idle(HZ/10); |
97b1255cb mm,oom_reaper: ch... |
629 630 |
if (attempts <= MAX_OOM_REAP_RETRIES || test_bit(MMF_OOM_SKIP, &mm->flags)) |
7ebffa455 mm,oom_reaper: re... |
631 |
goto done; |
11a410d51 mm, oom_reaper: d... |
632 |
|
7ebffa455 mm,oom_reaper: re... |
633 634 635 |
pr_info("oom_reaper: unable to reap pid:%d (%s) ", task_pid_nr(tsk), tsk->comm); |
8a7ff02ac mm, oom: dump sta... |
636 |
sched_show_task(tsk); |
7ebffa455 mm,oom_reaper: re... |
637 |
debug_show_all_locks(); |
bc448e897 mm, oom_reaper: r... |
638 |
|
7ebffa455 mm,oom_reaper: re... |
639 |
done: |
449d777d7 mm, oom_reaper: c... |
640 |
tsk->oom_reaper_list = NULL; |
449d777d7 mm, oom_reaper: c... |
641 |
|
26db62f17 oom: keep mm of t... |
642 643 |
/* * Hide this mm from OOM killer because it has been either reaped or |
3e4e28c5a mmap locking API:... |
644 |
* somebody can't call mmap_write_unlock(mm). |
26db62f17 oom: keep mm of t... |
645 |
*/ |
862e3073b mm, oom: get rid ... |
646 |
set_bit(MMF_OOM_SKIP, &mm->flags); |
26db62f17 oom: keep mm of t... |
647 |
|
aac453635 mm, oom: introduc... |
648 |
/* Drop a reference taken by wake_oom_reaper */ |
36324a990 oom: clear TIF_ME... |
649 |
put_task_struct(tsk); |
aac453635 mm, oom: introduc... |
650 651 652 653 654 |
} static int oom_reaper(void *unused) { while (true) { |
03049269d mm, oom_reaper: i... |
655 |
struct task_struct *tsk = NULL; |
aac453635 mm, oom: introduc... |
656 |
|
29c696e1c oom: make oom_rea... |
657 |
wait_event_freezable(oom_reaper_wait, oom_reaper_list != NULL); |
03049269d mm, oom_reaper: i... |
658 |
spin_lock(&oom_reaper_lock); |
29c696e1c oom: make oom_rea... |
659 660 661 |
if (oom_reaper_list != NULL) { tsk = oom_reaper_list; oom_reaper_list = tsk->oom_reaper_list; |
03049269d mm, oom_reaper: i... |
662 663 664 665 666 |
} spin_unlock(&oom_reaper_lock); if (tsk) oom_reap_task(tsk); |
aac453635 mm, oom: introduc... |
667 668 669 670 |
} return 0; } |
7c5f64f84 mm: oom: deduplic... |
671 |
static void wake_oom_reaper(struct task_struct *tsk) |
aac453635 mm, oom: introduc... |
672 |
{ |
9bcdeb51b oom, oom_reaper: ... |
673 674 |
/* mm is already queued? */ if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags)) |
aac453635 mm, oom: introduc... |
675 |
return; |
36324a990 oom: clear TIF_ME... |
676 |
get_task_struct(tsk); |
aac453635 mm, oom: introduc... |
677 |
|
03049269d mm, oom_reaper: i... |
678 |
spin_lock(&oom_reaper_lock); |
29c696e1c oom: make oom_rea... |
679 680 |
tsk->oom_reaper_list = oom_reaper_list; oom_reaper_list = tsk; |
03049269d mm, oom_reaper: i... |
681 |
spin_unlock(&oom_reaper_lock); |
422580c3c mm/oom_kill.c: ad... |
682 |
trace_wake_reaper(tsk->pid); |
03049269d mm, oom_reaper: i... |
683 |
wake_up(&oom_reaper_wait); |
aac453635 mm, oom: introduc... |
684 685 686 687 688 |
} static int __init oom_init(void) { oom_reaper_th = kthread_run(oom_reaper, NULL, "oom_reaper"); |
aac453635 mm, oom: introduc... |
689 690 691 |
return 0; } subsys_initcall(oom_init) |
7c5f64f84 mm: oom: deduplic... |
692 693 694 695 696 |
#else static inline void wake_oom_reaper(struct task_struct *tsk) { } #endif /* CONFIG_MMU */ |
aac453635 mm, oom: introduc... |
697 |
|
49550b605 oom: add helpers ... |
698 |
/** |
a7af91adc ANDROID: mm: oom_... |
699 700 701 702 703 704 705 706 707 708 709 710 711 712 |
* tsk->mm has to be non NULL and caller has to guarantee it is stable (either * under task_lock or operate on the current). */ static void __mark_oom_victim(struct task_struct *tsk) { struct mm_struct *mm = tsk->mm; if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm)) { mmgrab(tsk->signal->oom_mm); set_bit(MMF_OOM_VICTIM, &mm->flags); } } /** |
16e951966 mm: oom_kill: cle... |
713 |
* mark_oom_victim - mark the given task as OOM victim |
49550b605 oom: add helpers ... |
714 |
* @tsk: task to mark |
c32b3cbe0 oom, PM: make OOM... |
715 |
* |
dc56401fc mm: oom_kill: sim... |
716 |
* Has to be called with oom_lock held and never after |
c32b3cbe0 oom, PM: make OOM... |
717 |
* oom has been disabled already. |
26db62f17 oom: keep mm of t... |
718 719 720 |
* * 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 ... |
721 |
*/ |
7c5f64f84 mm: oom: deduplic... |
722 |
static void mark_oom_victim(struct task_struct *tsk) |
49550b605 oom: add helpers ... |
723 |
{ |
c32b3cbe0 oom, PM: make OOM... |
724 725 726 727 |
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... |
728 |
|
26db62f17 oom: keep mm of t... |
729 |
/* oom_mm is bound to the signal struct life time. */ |
a7af91adc ANDROID: mm: oom_... |
730 |
__mark_oom_victim(tsk); |
26db62f17 oom: keep mm of t... |
731 |
|
63a8ca9b2 oom: thaw the OOM... |
732 733 734 735 736 737 738 |
/* * 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... |
739 |
atomic_inc(&oom_victims); |
422580c3c mm/oom_kill.c: ad... |
740 |
trace_mark_victim(tsk->pid); |
49550b605 oom: add helpers ... |
741 742 743 |
} /** |
16e951966 mm: oom_kill: cle... |
744 |
* exit_oom_victim - note the exit of an OOM victim |
49550b605 oom: add helpers ... |
745 |
*/ |
38531201c mm, oom: enforce ... |
746 |
void exit_oom_victim(void) |
49550b605 oom: add helpers ... |
747 |
{ |
38531201c mm, oom: enforce ... |
748 |
clear_thread_flag(TIF_MEMDIE); |
c32b3cbe0 oom, PM: make OOM... |
749 |
|
c38f1025f mm: oom_kill: gen... |
750 |
if (!atomic_dec_return(&oom_victims)) |
c32b3cbe0 oom, PM: make OOM... |
751 |
wake_up_all(&oom_victims_wait); |
c32b3cbe0 oom, PM: make OOM... |
752 753 754 |
} /** |
7d2e7a22c oom, suspend: fix... |
755 756 757 758 759 |
* oom_killer_enable - enable OOM killer */ void oom_killer_enable(void) { oom_killer_disabled = false; |
d75da004c oom: improve oom ... |
760 761 |
pr_info("OOM killer enabled. "); |
7d2e7a22c oom, suspend: fix... |
762 763 764 |
} /** |
c32b3cbe0 oom, PM: make OOM... |
765 |
* oom_killer_disable - disable OOM killer |
7d2e7a22c oom, suspend: fix... |
766 |
* @timeout: maximum timeout to wait for oom victims in jiffies |
c32b3cbe0 oom, PM: make OOM... |
767 768 |
* * Forces all page allocations to fail rather than trigger OOM killer. |
7d2e7a22c oom, suspend: fix... |
769 770 |
* Will block and wait until all OOM victims are killed or the given * timeout expires. |
c32b3cbe0 oom, PM: make OOM... |
771 772 773 774 775 776 777 778 |
* * 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... |
779 |
bool oom_killer_disable(signed long timeout) |
c32b3cbe0 oom, PM: make OOM... |
780 |
{ |
7d2e7a22c oom, suspend: fix... |
781 |
signed long ret; |
c32b3cbe0 oom, PM: make OOM... |
782 |
/* |
6afcf2895 mm,oom: make oom_... |
783 784 |
* 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... |
785 |
*/ |
6afcf2895 mm,oom: make oom_... |
786 |
if (mutex_lock_killable(&oom_lock)) |
c32b3cbe0 oom, PM: make OOM... |
787 |
return false; |
c32b3cbe0 oom, PM: make OOM... |
788 |
oom_killer_disabled = true; |
dc56401fc mm: oom_kill: sim... |
789 |
mutex_unlock(&oom_lock); |
c32b3cbe0 oom, PM: make OOM... |
790 |
|
7d2e7a22c oom, suspend: fix... |
791 792 793 794 795 796 |
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 ... |
797 798 |
pr_info("OOM killer disabled. "); |
c32b3cbe0 oom, PM: make OOM... |
799 800 801 |
return true; } |
1af8bb432 mm, oom: fortify ... |
802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 |
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 ... |
827 828 |
* Caller has to make sure that task->mm is stable (hold task_lock or * it operates on the current). |
1af8bb432 mm, oom: fortify ... |
829 |
*/ |
7c5f64f84 mm: oom: deduplic... |
830 |
static bool task_will_free_mem(struct task_struct *task) |
1af8bb432 mm, oom: fortify ... |
831 |
{ |
091f362c5 mm, oom: tighten ... |
832 |
struct mm_struct *mm = task->mm; |
1af8bb432 mm, oom: fortify ... |
833 |
struct task_struct *p; |
f33e6f067 mm, oom: fix unin... |
834 |
bool ret = true; |
1af8bb432 mm, oom: fortify ... |
835 |
|
1af8bb432 mm, oom: fortify ... |
836 |
/* |
091f362c5 mm, oom: tighten ... |
837 838 839 |
* 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 ... |
840 |
*/ |
091f362c5 mm, oom: tighten ... |
841 |
if (!mm) |
1af8bb432 mm, oom: fortify ... |
842 |
return false; |
091f362c5 mm, oom: tighten ... |
843 844 |
if (!__task_will_free_mem(task)) return false; |
696453e66 mm, oom: task_wil... |
845 846 847 848 849 |
/* * 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 ... |
850 |
if (test_bit(MMF_OOM_SKIP, &mm->flags)) |
696453e66 mm, oom: task_wil... |
851 |
return false; |
696453e66 mm, oom: task_wil... |
852 |
|
091f362c5 mm, oom: tighten ... |
853 |
if (atomic_read(&mm->mm_users) <= 1) |
1af8bb432 mm, oom: fortify ... |
854 |
return true; |
1af8bb432 mm, oom: fortify ... |
855 856 |
/* |
5870c2e1d mm/oom_kill.c: fi... |
857 858 859 |
* 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 ... |
860 861 862 863 864 865 866 867 868 869 870 871 |
*/ 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 ... |
872 873 874 |
return ret; } |
bbbe48029 mm, oom: remove '... |
875 |
static void __oom_kill_process(struct task_struct *victim, const char *message) |
1da177e4c Linux-2.6.12-rc2 |
876 |
{ |
5989ad7b5 mm, oom: refactor... |
877 |
struct task_struct *p; |
647f2bdf4 mm, oom: fold oom... |
878 |
struct mm_struct *mm; |
bb29902a7 oom, oom_reaper: ... |
879 |
bool can_oom_reap = true; |
1da177e4c Linux-2.6.12-rc2 |
880 |
|
6b0c81b3b mm, oom: reduce d... |
881 882 |
p = find_lock_task_mm(victim); if (!p) { |
619b5b469 mm, oom: show pro... |
883 884 885 |
pr_info("%s: OOM victim %d (%s) is already exiting. Skip killing the task ", message, task_pid_nr(victim), victim->comm); |
6b0c81b3b mm, oom: reduce d... |
886 |
put_task_struct(victim); |
647f2bdf4 mm, oom: fold oom... |
887 |
return; |
6b0c81b3b mm, oom: reduce d... |
888 889 890 891 892 |
} else if (victim != p) { get_task_struct(p); put_task_struct(victim); victim = p; } |
647f2bdf4 mm, oom: fold oom... |
893 |
|
880b76893 mm/oom_kill.c: fi... |
894 |
/* Get a reference to safely compare mm after task_unlock(victim) */ |
647f2bdf4 mm, oom: fold oom... |
895 |
mm = victim->mm; |
f1f100764 mm: add new mmgra... |
896 |
mmgrab(mm); |
8e675f7af mm/oom_kill: coun... |
897 898 899 |
/* Raise event before sending signal: task reaper must see this */ count_vm_event(OOM_KILL); |
fe6bdfc8e mm: fix oom_kill ... |
900 |
memcg_memory_event_mm(mm, MEMCG_OOM_KILL); |
8e675f7af mm/oom_kill: coun... |
901 |
|
426fb5e72 mm/oom_kill.c: re... |
902 |
/* |
cd04ae1e2 mm, oom: do not r... |
903 904 905 |
* 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... |
906 |
*/ |
079b22dc9 signal: Use SEND_... |
907 |
do_send_sig_info(SIGKILL, SEND_SIG_PRIV, victim, PIDTYPE_TGID); |
16e951966 mm: oom_kill: cle... |
908 |
mark_oom_victim(victim); |
70cb6d267 mm/oom: add oom_s... |
909 910 911 912 913 914 915 |
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)), |
941f762bc mm/oom: fix pgtab... |
916 |
mm_pgtables_bytes(mm) >> 10, victim->signal->oom_score_adj); |
647f2bdf4 mm, oom: fold oom... |
917 918 919 920 921 |
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 |
c1e8d7c6a mmap locking API:... |
922 |
* depletion of all memory. This prevents mm->mmap_lock livelock when an |
647f2bdf4 mm, oom: fold oom... |
923 924 925 926 927 |
* 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... |
928 |
rcu_read_lock(); |
c319025a6 mm/oom_kill: clea... |
929 |
for_each_process(p) { |
4d7b3394f mm/oom_kill: fix ... |
930 |
if (!process_shares_mm(p, mm)) |
c319025a6 mm/oom_kill: clea... |
931 932 933 |
continue; if (same_thread_group(p, victim)) continue; |
1b51e65ea oom, oom_reaper: ... |
934 |
if (is_global_init(p)) { |
aac453635 mm, oom: introduc... |
935 |
can_oom_reap = false; |
862e3073b mm, oom: get rid ... |
936 |
set_bit(MMF_OOM_SKIP, &mm->flags); |
a373966d1 mm, oom: hide mm ... |
937 938 939 940 |
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... |
941 |
continue; |
aac453635 mm, oom: introduc... |
942 |
} |
1b51e65ea oom, oom_reaper: ... |
943 |
/* |
f5678e7f2 kernel: better do... |
944 945 |
* No kthead_use_mm() user needs to read from the userspace so * we are ok to reap it. |
1b51e65ea oom, oom_reaper: ... |
946 947 948 |
*/ if (unlikely(p->flags & PF_KTHREAD)) continue; |
079b22dc9 signal: Use SEND_... |
949 |
do_send_sig_info(SIGKILL, SEND_SIG_PRIV, p, PIDTYPE_TGID); |
c319025a6 mm/oom_kill: clea... |
950 |
} |
6b0c81b3b mm, oom: reduce d... |
951 |
rcu_read_unlock(); |
647f2bdf4 mm, oom: fold oom... |
952 |
|
aac453635 mm, oom: introduc... |
953 |
if (can_oom_reap) |
36324a990 oom: clear TIF_ME... |
954 |
wake_oom_reaper(victim); |
aac453635 mm, oom: introduc... |
955 |
|
880b76893 mm/oom_kill.c: fi... |
956 |
mmdrop(mm); |
6b0c81b3b mm, oom: reduce d... |
957 |
put_task_struct(victim); |
1da177e4c Linux-2.6.12-rc2 |
958 |
} |
647f2bdf4 mm, oom: fold oom... |
959 |
#undef K |
1da177e4c Linux-2.6.12-rc2 |
960 |
|
309ed8825 oom: extract pani... |
961 |
/* |
3d8b38eb8 mm, oom: introduc... |
962 963 964 |
* Kill provided task unless it's secured by setting * oom_score_adj to OOM_SCORE_ADJ_MIN. */ |
bbbe48029 mm, oom: remove '... |
965 |
static int oom_kill_memcg_member(struct task_struct *task, void *message) |
3d8b38eb8 mm, oom: introduc... |
966 |
{ |
d342a0b38 mm,oom: don't kil... |
967 968 |
if (task->signal->oom_score_adj != OOM_SCORE_ADJ_MIN && !is_global_init(task)) { |
3d8b38eb8 mm, oom: introduc... |
969 |
get_task_struct(task); |
bbbe48029 mm, oom: remove '... |
970 |
__oom_kill_process(task, message); |
3d8b38eb8 mm, oom: introduc... |
971 972 973 |
} return 0; } |
5989ad7b5 mm, oom: refactor... |
974 975 |
static void oom_kill_process(struct oom_control *oc, const char *message) { |
bbbe48029 mm, oom: remove '... |
976 |
struct task_struct *victim = oc->chosen; |
3d8b38eb8 mm, oom: introduc... |
977 |
struct mem_cgroup *oom_group; |
5989ad7b5 mm, oom: refactor... |
978 979 980 981 982 983 984 985 |
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 '... |
986 987 988 989 990 991 |
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... |
992 993 |
return; } |
bbbe48029 mm, oom: remove '... |
994 |
task_unlock(victim); |
5989ad7b5 mm, oom: refactor... |
995 996 |
if (__ratelimit(&oom_rs)) |
bbbe48029 mm, oom: remove '... |
997 |
dump_header(oc, victim); |
5989ad7b5 mm, oom: refactor... |
998 |
|
3d8b38eb8 mm, oom: introduc... |
999 1000 1001 1002 1003 1004 |
/* * 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 '... |
1005 |
__oom_kill_process(victim, message); |
3d8b38eb8 mm, oom: introduc... |
1006 1007 1008 1009 1010 1011 |
/* * If necessary, kill all tasks in the selected memory cgroup. */ if (oom_group) { mem_cgroup_print_oom_group(oom_group); |
bbbe48029 mm, oom: remove '... |
1012 1013 |
mem_cgroup_scan_tasks(oom_group, oom_kill_memcg_member, (void*)message); |
3d8b38eb8 mm, oom: introduc... |
1014 1015 |
mem_cgroup_put(oom_group); } |
5989ad7b5 mm, oom: refactor... |
1016 |
} |
309ed8825 oom: extract pani... |
1017 1018 1019 |
/* * Determines whether the kernel must panic because of the panic_on_oom sysctl. */ |
432b1de0d mm/oom_kill.c: fi... |
1020 |
static void check_panic_on_oom(struct oom_control *oc) |
309ed8825 oom: extract pani... |
1021 1022 1023 1024 1025 1026 1027 1028 1029 |
{ 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... |
1030 |
if (oc->constraint != CONSTRAINT_NONE) |
309ed8825 oom: extract pani... |
1031 1032 |
return; } |
071a4befe mm, oom: do not p... |
1033 |
/* Do not panic for oom kills triggered by sysrq */ |
db2a0dd7a mm/oom_kill.c: in... |
1034 |
if (is_sysrq_oom(oc)) |
071a4befe mm, oom: do not p... |
1035 |
return; |
2a966b77a mm: oom: add memc... |
1036 |
dump_header(oc, NULL); |
309ed8825 oom: extract pani... |
1037 1038 1039 1040 |
panic("Out of memory: %s panic_on_oom is enabled ", sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide"); } |
8bc719d3c [PATCH] out of me... |
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 |
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 |
1054 |
/** |
6e0fc46dc mm, oom: organize... |
1055 1056 |
* 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 |
1057 1058 1059 1060 1061 1062 |
* * 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... |
1063 |
bool out_of_memory(struct oom_control *oc) |
1da177e4c Linux-2.6.12-rc2 |
1064 |
{ |
8bc719d3c [PATCH] out of me... |
1065 |
unsigned long freed = 0; |
dc56401fc mm: oom_kill: sim... |
1066 1067 |
if (oom_killer_disabled) return false; |
7c5f64f84 mm: oom: deduplic... |
1068 1069 1070 1071 1072 1073 |
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 |
1074 |
|
7b98c2e40 oom: give current... |
1075 |
/* |
9ff4868e3 mm, oom: allow ex... |
1076 1077 1078 |
* 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... |
1079 |
*/ |
091f362c5 mm, oom: tighten ... |
1080 |
if (task_will_free_mem(current)) { |
16e951966 mm: oom_kill: cle... |
1081 |
mark_oom_victim(current); |
1af8bb432 mm, oom: fortify ... |
1082 |
wake_oom_reaper(current); |
75e8f8b24 mm, oom: remove u... |
1083 |
return true; |
7b98c2e40 oom: give current... |
1084 |
} |
9b0f8b040 [PATCH] Terminate... |
1085 |
/* |
3da88fb3b mm, oom: move GFP... |
1086 1087 1088 |
* 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... |
1089 1090 |
* ___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... |
1091 |
*/ |
f9c645621 memcg, oom: don't... |
1092 |
if (oc->gfp_mask && !(oc->gfp_mask & __GFP_FS) && !is_memcg_oom(oc)) |
3da88fb3b mm, oom: move GFP... |
1093 1094 1095 |
return true; /* |
9b0f8b040 [PATCH] Terminate... |
1096 |
* Check if there were limitations on the allocation (only relevant for |
7c5f64f84 mm: oom: deduplic... |
1097 |
* NUMA and memcg) that may require different handling. |
9b0f8b040 [PATCH] Terminate... |
1098 |
*/ |
432b1de0d mm/oom_kill.c: fi... |
1099 1100 |
oc->constraint = constrained_alloc(oc); if (oc->constraint != CONSTRAINT_MEMORY_POLICY) |
6e0fc46dc mm, oom: organize... |
1101 |
oc->nodemask = NULL; |
432b1de0d mm/oom_kill.c: fi... |
1102 |
check_panic_on_oom(oc); |
0aad4b312 oom: fold __out_o... |
1103 |
|
7c5f64f84 mm: oom: deduplic... |
1104 |
if (!is_memcg_oom(oc) && sysctl_oom_kill_allocating_task && |
ac311a14c oom: decouple mem... |
1105 1106 |
current->mm && !oom_unkillable_task(current) && oom_cpuset_eligible(current, oc) && |
121d1ba0a mm, oom: fix pote... |
1107 |
current->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) { |
6b0c81b3b mm, oom: reduce d... |
1108 |
get_task_struct(current); |
7c5f64f84 mm: oom: deduplic... |
1109 1110 |
oc->chosen = current; oom_kill_process(oc, "Out of memory (oom_kill_allocating_task)"); |
75e8f8b24 mm, oom: remove u... |
1111 |
return true; |
0aad4b312 oom: fold __out_o... |
1112 |
} |
7c5f64f84 mm: oom: deduplic... |
1113 |
select_bad_process(oc); |
3100dab2a mm: memcontrol: p... |
1114 1115 |
/* Found nothing?!?! */ if (!oc->chosen) { |
2a966b77a mm: oom: add memc... |
1116 |
dump_header(oc, NULL); |
3100dab2a mm: memcontrol: p... |
1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 |
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... |
1127 |
} |
9bfe5ded0 mm, oom: remove s... |
1128 |
if (oc->chosen && oc->chosen != (void *)-1UL) |
7c5f64f84 mm: oom: deduplic... |
1129 1130 |
oom_kill_process(oc, !is_memcg_oom(oc) ? "Out of memory" : "Memory cgroup out of memory"); |
7c5f64f84 mm: oom: deduplic... |
1131 |
return !!oc->chosen; |
c32b3cbe0 oom, PM: make OOM... |
1132 |
} |
e36589323 oom: remove speci... |
1133 1134 |
/* * The pagefault handler calls here because it is out of memory, so kill a |
798fd7569 mm: zap ZONE_OOM_... |
1135 1136 |
* 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... |
1137 1138 1139 |
*/ void pagefault_out_of_memory(void) { |
6e0fc46dc mm, oom: organize... |
1140 1141 1142 |
struct oom_control oc = { .zonelist = NULL, .nodemask = NULL, |
2a966b77a mm: oom: add memc... |
1143 |
.memcg = NULL, |
6e0fc46dc mm, oom: organize... |
1144 1145 |
.gfp_mask = 0, .order = 0, |
6e0fc46dc mm, oom: organize... |
1146 |
}; |
494264208 mm: memcg: handle... |
1147 |
if (mem_cgroup_oom_synchronize(true)) |
dc56401fc mm: oom_kill: sim... |
1148 |
return; |
3812c8c8f mm: memcg: do not... |
1149 |
|
dc56401fc mm: oom_kill: sim... |
1150 1151 |
if (!mutex_trylock(&oom_lock)) return; |
a104808e2 mm: don't emit wa... |
1152 |
out_of_memory(&oc); |
dc56401fc mm: oom_kill: sim... |
1153 |
mutex_unlock(&oom_lock); |
e36589323 oom: remove speci... |
1154 |
} |
a7af91adc ANDROID: mm: oom_... |
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 |
void add_to_oom_reaper(struct task_struct *p) { p = find_lock_task_mm(p); if (!p) return; get_task_struct(p); if (task_will_free_mem(p)) { __mark_oom_victim(p); wake_oom_reaper(p); } task_unlock(p); put_task_struct(p); } |