Blame view
mm/oom_kill.c
28.6 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 |
/* * 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... |
7 8 |
* Copyright (C) 2010 Google, Inc. * Rewritten by David Rientjes |
1da177e4c Linux-2.6.12-rc2 |
9 10 |
* * The routines in this file are used to kill a process when |
a49335cce [PATCH] cpusets: ... |
11 12 |
* 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 |
13 14 15 16 17 18 |
* * 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... |
19 |
#include <linux/oom.h> |
1da177e4c Linux-2.6.12-rc2 |
20 |
#include <linux/mm.h> |
4e950f6f0 Remove fs.h from ... |
21 |
#include <linux/err.h> |
5a0e3ad6a include cleanup: ... |
22 |
#include <linux/gfp.h> |
1da177e4c Linux-2.6.12-rc2 |
23 24 25 26 |
#include <linux/sched.h> #include <linux/swap.h> #include <linux/timex.h> #include <linux/jiffies.h> |
ef08e3b49 [PATCH] cpusets: ... |
27 |
#include <linux/cpuset.h> |
b95f1b31b mm: Map most file... |
28 |
#include <linux/export.h> |
8bc719d3c [PATCH] out of me... |
29 |
#include <linux/notifier.h> |
c7ba5c9e8 Memory controller... |
30 |
#include <linux/memcontrol.h> |
6f48d0ebd oom: select task ... |
31 |
#include <linux/mempolicy.h> |
5cd9c58fb security: Fix set... |
32 |
#include <linux/security.h> |
edd45544c oom: avoid deferr... |
33 |
#include <linux/ptrace.h> |
f660daac4 oom: thaw threads... |
34 |
#include <linux/freezer.h> |
43d2b1132 tracepoint: add t... |
35 |
#include <linux/ftrace.h> |
dc3f21ead mm, oom: introduc... |
36 |
#include <linux/ratelimit.h> |
aac453635 mm, oom: introduc... |
37 38 39 40 41 |
#include <linux/kthread.h> #include <linux/init.h> #include <asm/tlb.h> #include "internal.h" |
43d2b1132 tracepoint: add t... |
42 43 44 |
#define CREATE_TRACE_POINTS #include <trace/events/oom.h> |
1da177e4c Linux-2.6.12-rc2 |
45 |
|
fadd8fbd1 [PATCH] support f... |
46 |
int sysctl_panic_on_oom; |
fe071d7e8 oom: add oom_kill... |
47 |
int sysctl_oom_kill_allocating_task; |
ad915c432 oom: enable oom t... |
48 |
int sysctl_oom_dump_tasks = 1; |
dc56401fc mm: oom_kill: sim... |
49 50 |
DEFINE_MUTEX(oom_lock); |
1da177e4c Linux-2.6.12-rc2 |
51 |
|
6f48d0ebd oom: select task ... |
52 53 54 |
#ifdef CONFIG_NUMA /** * has_intersects_mems_allowed() - check task eligiblity for kill |
ad9624417 oom_kill: has_int... |
55 |
* @start: task struct of which task to consider |
6f48d0ebd oom: select task ... |
56 57 58 59 60 |
* @mask: nodemask passed to page allocator for mempolicy ooms * * 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. |
495789a51 oom: make oom_sco... |
61 |
*/ |
ad9624417 oom_kill: has_int... |
62 |
static bool has_intersects_mems_allowed(struct task_struct *start, |
6f48d0ebd oom: select task ... |
63 |
const nodemask_t *mask) |
495789a51 oom: make oom_sco... |
64 |
{ |
ad9624417 oom_kill: has_int... |
65 66 |
struct task_struct *tsk; bool ret = false; |
495789a51 oom: make oom_sco... |
67 |
|
ad9624417 oom_kill: has_int... |
68 |
rcu_read_lock(); |
1da4db0cd oom_kill: change ... |
69 |
for_each_thread(start, tsk) { |
6f48d0ebd oom: select task ... |
70 71 72 73 74 75 76 |
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... |
77 |
ret = mempolicy_nodemask_intersects(tsk, mask); |
6f48d0ebd oom: select task ... |
78 79 80 81 82 |
} else { /* * This is not a mempolicy constrained oom, so only * check the mems of tsk's cpuset. */ |
ad9624417 oom_kill: has_int... |
83 |
ret = cpuset_mems_allowed_intersects(current, tsk); |
6f48d0ebd oom: select task ... |
84 |
} |
ad9624417 oom_kill: has_int... |
85 86 |
if (ret) break; |
1da4db0cd oom_kill: change ... |
87 |
} |
ad9624417 oom_kill: has_int... |
88 |
rcu_read_unlock(); |
df1090a8d oom: cleanup has_... |
89 |
|
ad9624417 oom_kill: has_int... |
90 |
return ret; |
6f48d0ebd oom: select task ... |
91 92 93 94 95 96 |
} #else static bool has_intersects_mems_allowed(struct task_struct *tsk, const nodemask_t *mask) { return true; |
495789a51 oom: make oom_sco... |
97 |
} |
6f48d0ebd oom: select task ... |
98 |
#endif /* CONFIG_NUMA */ |
495789a51 oom: make oom_sco... |
99 |
|
6f48d0ebd oom: select task ... |
100 101 102 103 104 105 |
/* * 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... |
106 |
struct task_struct *find_lock_task_mm(struct task_struct *p) |
dd8e8f405 oom: introduce fi... |
107 |
{ |
1da4db0cd oom_kill: change ... |
108 |
struct task_struct *t; |
dd8e8f405 oom: introduce fi... |
109 |
|
4d4048be8 oom_kill: add rcu... |
110 |
rcu_read_lock(); |
1da4db0cd oom_kill: change ... |
111 |
for_each_thread(p, t) { |
dd8e8f405 oom: introduce fi... |
112 113 |
task_lock(t); if (likely(t->mm)) |
4d4048be8 oom_kill: add rcu... |
114 |
goto found; |
dd8e8f405 oom: introduce fi... |
115 |
task_unlock(t); |
1da4db0cd oom_kill: change ... |
116 |
} |
4d4048be8 oom_kill: add rcu... |
117 118 119 |
t = NULL; found: rcu_read_unlock(); |
dd8e8f405 oom: introduce fi... |
120 |
|
4d4048be8 oom_kill: add rcu... |
121 |
return t; |
dd8e8f405 oom: introduce fi... |
122 |
} |
db2a0dd7a mm/oom_kill.c: in... |
123 124 125 126 127 128 129 130 |
/* * 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; } |
7c5f64f84 mm: oom: deduplic... |
131 132 133 134 |
static inline bool is_memcg_oom(struct oom_control *oc) { return oc->memcg != NULL; } |
ab290adba oom: make oom_unk... |
135 |
/* return true if the task is not adequate as candidate victim task. */ |
e85bfd3aa oom: filter unkil... |
136 |
static bool oom_unkillable_task(struct task_struct *p, |
2314b42db mm: memcontrol: d... |
137 |
struct mem_cgroup *memcg, const nodemask_t *nodemask) |
ab290adba oom: make oom_unk... |
138 139 140 141 142 143 144 |
{ if (is_global_init(p)) return true; if (p->flags & PF_KTHREAD) return true; /* When mem_cgroup_out_of_memory() and p is not member of the group */ |
72835c86c mm: unify remaini... |
145 |
if (memcg && !task_in_mem_cgroup(p, memcg)) |
ab290adba oom: make oom_unk... |
146 147 148 149 150 151 152 153 |
return true; /* p may not have freeable memory in nodemask */ if (!has_intersects_mems_allowed(p, nodemask)) return true; return false; } |
1da177e4c Linux-2.6.12-rc2 |
154 |
/** |
a63d83f42 oom: badness heur... |
155 |
* oom_badness - heuristic function to determine which candidate task to kill |
1da177e4c Linux-2.6.12-rc2 |
156 |
* @p: task struct of which task we should calculate |
a63d83f42 oom: badness heur... |
157 |
* @totalpages: total present RAM allowed for page allocation |
1da177e4c Linux-2.6.12-rc2 |
158 |
* |
a63d83f42 oom: badness heur... |
159 160 161 |
* 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 |
162 |
*/ |
a7f638f99 mm, oom: normaliz... |
163 164 |
unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg, const nodemask_t *nodemask, unsigned long totalpages) |
1da177e4c Linux-2.6.12-rc2 |
165 |
{ |
1e11ad8dc mm, oom: fix badn... |
166 |
long points; |
61eafb00d mm, oom: fix and ... |
167 |
long adj; |
28b83c519 oom: move oom_adj... |
168 |
|
72835c86c mm: unify remaini... |
169 |
if (oom_unkillable_task(p, memcg, nodemask)) |
26ebc9849 oom: /proc/<pid>/... |
170 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
171 |
|
dd8e8f405 oom: introduce fi... |
172 173 |
p = find_lock_task_mm(p); if (!p) |
1da177e4c Linux-2.6.12-rc2 |
174 |
return 0; |
bb8a4b7fd mm, oom_reaper: h... |
175 176 |
/* * Do not even consider tasks which are explicitly marked oom |
b18dc5f29 mm, oom: skip vfo... |
177 178 |
* unkillable or have been already oom reaped or the are in * the middle of vfork |
bb8a4b7fd mm, oom_reaper: h... |
179 |
*/ |
a9c58b907 mm, oom: change t... |
180 |
adj = (long)p->signal->oom_score_adj; |
bb8a4b7fd mm, oom_reaper: h... |
181 |
if (adj == OOM_SCORE_ADJ_MIN || |
862e3073b mm, oom: get rid ... |
182 |
test_bit(MMF_OOM_SKIP, &p->mm->flags) || |
b18dc5f29 mm, oom: skip vfo... |
183 |
in_vfork(p)) { |
5aecc85ab oom: do not kill ... |
184 185 186 |
task_unlock(p); return 0; } |
1da177e4c Linux-2.6.12-rc2 |
187 |
/* |
a63d83f42 oom: badness heur... |
188 |
* The baseline for the badness score is the proportion of RAM that each |
f755a042d oom: use pte page... |
189 |
* task's rss, pagetable and swap space use. |
1da177e4c Linux-2.6.12-rc2 |
190 |
*/ |
dc6c9a35b mm: account pmd p... |
191 192 |
points = get_mm_rss(p->mm) + get_mm_counter(p->mm, MM_SWAPENTS) + atomic_long_read(&p->mm->nr_ptes) + mm_nr_pmds(p->mm); |
a63d83f42 oom: badness heur... |
193 |
task_unlock(p); |
1da177e4c Linux-2.6.12-rc2 |
194 195 |
/* |
a63d83f42 oom: badness heur... |
196 197 |
* Root processes get 3% bonus, just like the __vm_enough_memory() * implementation used by LSMs. |
1da177e4c Linux-2.6.12-rc2 |
198 |
*/ |
a63d83f42 oom: badness heur... |
199 |
if (has_capability_noaudit(p, CAP_SYS_ADMIN)) |
778c14aff mm, oom: base roo... |
200 |
points -= (points * 3) / 100; |
1da177e4c Linux-2.6.12-rc2 |
201 |
|
61eafb00d mm, oom: fix and ... |
202 203 204 |
/* Normalize to oom_score_adj units */ adj *= totalpages / 1000; points += adj; |
1da177e4c Linux-2.6.12-rc2 |
205 |
|
f19e8aa11 oom: always retur... |
206 |
/* |
a7f638f99 mm, oom: normaliz... |
207 208 |
* 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... |
209 |
*/ |
1e11ad8dc mm, oom: fix badn... |
210 |
return points > 0 ? points : 1; |
1da177e4c Linux-2.6.12-rc2 |
211 |
} |
7c5f64f84 mm: oom: deduplic... |
212 213 214 215 216 217 |
enum oom_constraint { CONSTRAINT_NONE, CONSTRAINT_CPUSET, CONSTRAINT_MEMORY_POLICY, CONSTRAINT_MEMCG, }; |
1da177e4c Linux-2.6.12-rc2 |
218 |
/* |
9b0f8b040 [PATCH] Terminate... |
219 220 |
* Determine the type of allocation constraint. */ |
7c5f64f84 mm: oom: deduplic... |
221 |
static enum oom_constraint constrained_alloc(struct oom_control *oc) |
4365a5676 oom-kill: fix NUM... |
222 |
{ |
54a6eb5c4 mm: use two zonel... |
223 |
struct zone *zone; |
dd1a239f6 mm: have zonelist... |
224 |
struct zoneref *z; |
6e0fc46dc mm, oom: organize... |
225 |
enum zone_type high_zoneidx = gfp_zone(oc->gfp_mask); |
a63d83f42 oom: badness heur... |
226 227 |
bool cpuset_limited = false; int nid; |
9b0f8b040 [PATCH] Terminate... |
228 |
|
7c5f64f84 mm: oom: deduplic... |
229 230 231 232 |
if (is_memcg_oom(oc)) { oc->totalpages = mem_cgroup_get_limit(oc->memcg) ?: 1; return CONSTRAINT_MEMCG; } |
a63d83f42 oom: badness heur... |
233 |
/* Default to all available memory */ |
7c5f64f84 mm: oom: deduplic... |
234 235 236 237 |
oc->totalpages = totalram_pages + total_swap_pages; if (!IS_ENABLED(CONFIG_NUMA)) return CONSTRAINT_NONE; |
a63d83f42 oom: badness heur... |
238 |
|
6e0fc46dc mm, oom: organize... |
239 |
if (!oc->zonelist) |
a63d83f42 oom: badness heur... |
240 |
return CONSTRAINT_NONE; |
4365a5676 oom-kill: fix NUM... |
241 242 243 244 245 |
/* * 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... |
246 |
if (oc->gfp_mask & __GFP_THISNODE) |
4365a5676 oom-kill: fix NUM... |
247 |
return CONSTRAINT_NONE; |
9b0f8b040 [PATCH] Terminate... |
248 |
|
4365a5676 oom-kill: fix NUM... |
249 |
/* |
a63d83f42 oom: badness heur... |
250 251 252 |
* 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... |
253 |
*/ |
6e0fc46dc mm, oom: organize... |
254 255 |
if (oc->nodemask && !nodes_subset(node_states[N_MEMORY], *oc->nodemask)) { |
7c5f64f84 mm: oom: deduplic... |
256 |
oc->totalpages = total_swap_pages; |
6e0fc46dc mm, oom: organize... |
257 |
for_each_node_mask(nid, *oc->nodemask) |
7c5f64f84 mm: oom: deduplic... |
258 |
oc->totalpages += node_spanned_pages(nid); |
9b0f8b040 [PATCH] Terminate... |
259 |
return CONSTRAINT_MEMORY_POLICY; |
a63d83f42 oom: badness heur... |
260 |
} |
4365a5676 oom-kill: fix NUM... |
261 262 |
/* Check this allocation failure is caused by cpuset's wall function */ |
6e0fc46dc mm, oom: organize... |
263 264 265 |
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... |
266 |
cpuset_limited = true; |
9b0f8b040 [PATCH] Terminate... |
267 |
|
a63d83f42 oom: badness heur... |
268 |
if (cpuset_limited) { |
7c5f64f84 mm: oom: deduplic... |
269 |
oc->totalpages = total_swap_pages; |
a63d83f42 oom: badness heur... |
270 |
for_each_node_mask(nid, cpuset_current_mems_allowed) |
7c5f64f84 mm: oom: deduplic... |
271 |
oc->totalpages += node_spanned_pages(nid); |
a63d83f42 oom: badness heur... |
272 273 |
return CONSTRAINT_CPUSET; } |
9b0f8b040 [PATCH] Terminate... |
274 275 |
return CONSTRAINT_NONE; } |
7c5f64f84 mm: oom: deduplic... |
276 |
static int oom_evaluate_task(struct task_struct *task, void *arg) |
462607ecc mm, oom: introduc... |
277 |
{ |
7c5f64f84 mm: oom: deduplic... |
278 279 |
struct oom_control *oc = arg; unsigned long points; |
6e0fc46dc mm, oom: organize... |
280 |
if (oom_unkillable_task(task, NULL, oc->nodemask)) |
7c5f64f84 mm: oom: deduplic... |
281 |
goto next; |
462607ecc mm, oom: introduc... |
282 283 284 |
/* * This task already has access to memory reserves and is being killed. |
a373966d1 mm, oom: hide mm ... |
285 |
* Don't allow any other task to have access to the reserves unless |
862e3073b mm, oom: get rid ... |
286 |
* the task has MMF_OOM_SKIP because chances that it would release |
a373966d1 mm, oom: hide mm ... |
287 |
* any memory is quite low. |
462607ecc mm, oom: introduc... |
288 |
*/ |
862e3073b mm, oom: get rid ... |
289 290 |
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... |
291 292 |
goto next; goto abort; |
a373966d1 mm, oom: hide mm ... |
293 |
} |
462607ecc mm, oom: introduc... |
294 |
|
e1e12d2f3 mm, oom: fix race... |
295 296 297 298 |
/* * 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... |
299 300 301 302 |
if (oom_task_origin(task)) { points = ULONG_MAX; goto select; } |
e1e12d2f3 mm, oom: fix race... |
303 |
|
7c5f64f84 mm: oom: deduplic... |
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
points = oom_badness(task, NULL, oc->nodemask, oc->totalpages); if (!points || points < oc->chosen_points) goto next; /* Prefer thread group leaders for display purposes */ if (points == oc->chosen_points && thread_group_leader(oc->chosen)) goto next; 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... |
324 |
} |
9b0f8b040 [PATCH] Terminate... |
325 |
/* |
7c5f64f84 mm: oom: deduplic... |
326 327 |
* 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 |
328 |
*/ |
7c5f64f84 mm: oom: deduplic... |
329 |
static void select_bad_process(struct oom_control *oc) |
1da177e4c Linux-2.6.12-rc2 |
330 |
{ |
7c5f64f84 mm: oom: deduplic... |
331 332 333 334 |
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... |
335 |
|
7c5f64f84 mm: oom: deduplic... |
336 337 338 339 340 |
rcu_read_lock(); for_each_process(p) if (oom_evaluate_task(p, oc)) break; rcu_read_unlock(); |
1da4db0cd oom_kill: change ... |
341 |
} |
972c4ea59 [PATCH] select_ba... |
342 |
|
7c5f64f84 mm: oom: deduplic... |
343 |
oc->chosen_points = oc->chosen_points * 1000 / oc->totalpages; |
1da177e4c Linux-2.6.12-rc2 |
344 345 346 |
} /** |
1b578df02 mm/oom_kill: fix ... |
347 |
* dump_tasks - dump current memory state of all system tasks |
dad7557eb mm: fix kernel-do... |
348 |
* @memcg: current's memory controller, if constrained |
e85bfd3aa oom: filter unkil... |
349 |
* @nodemask: nodemask passed to page allocator for mempolicy ooms |
1b578df02 mm/oom_kill: fix ... |
350 |
* |
e85bfd3aa oom: filter unkil... |
351 352 353 |
* 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. |
de34d965a mm, oom: replace ... |
354 355 |
* State information includes task's pid, uid, tgid, vm size, rss, nr_ptes, * swapents, oom_score_adj value, and name. |
fef1bdd68 oom: add sysctl t... |
356 |
*/ |
2314b42db mm: memcontrol: d... |
357 |
static void dump_tasks(struct mem_cgroup *memcg, const nodemask_t *nodemask) |
fef1bdd68 oom: add sysctl t... |
358 |
{ |
c55db9578 oom: dump_tasks u... |
359 360 |
struct task_struct *p; struct task_struct *task; |
fef1bdd68 oom: add sysctl t... |
361 |
|
dc6c9a35b mm: account pmd p... |
362 363 |
pr_info("[ pid ] uid tgid total_vm rss nr_ptes nr_pmds swapents oom_score_adj name "); |
6b0c81b3b mm, oom: reduce d... |
364 |
rcu_read_lock(); |
c55db9578 oom: dump_tasks u... |
365 |
for_each_process(p) { |
72835c86c mm: unify remaini... |
366 |
if (oom_unkillable_task(p, memcg, nodemask)) |
b4416d2be oom: do not dump ... |
367 |
continue; |
fef1bdd68 oom: add sysctl t... |
368 |
|
c55db9578 oom: dump_tasks u... |
369 370 |
task = find_lock_task_mm(p); if (!task) { |
6d2661ede oom: fix possible... |
371 |
/* |
74ab7f1d3 oom: improve comm... |
372 373 |
* This is a kthread or all of p's threads have already * detached their mm's. There's no need to report |
c55db9578 oom: dump_tasks u... |
374 |
* them; they can't be oom killed anyway. |
6d2661ede oom: fix possible... |
375 |
*/ |
6d2661ede oom: fix possible... |
376 377 |
continue; } |
c55db9578 oom: dump_tasks u... |
378 |
|
dc6c9a35b mm: account pmd p... |
379 380 |
pr_info("[%5d] %5d %5d %8lu %8lu %7ld %7ld %8lu %5hd %s ", |
078de5f70 userns: Store uid... |
381 382 |
task->pid, from_kuid(&init_user_ns, task_uid(task)), task->tgid, task->mm->total_vm, get_mm_rss(task->mm), |
e1f56c89b mm: convert mm->n... |
383 |
atomic_long_read(&task->mm->nr_ptes), |
dc6c9a35b mm: account pmd p... |
384 |
mm_nr_pmds(task->mm), |
de34d965a mm, oom: replace ... |
385 |
get_mm_counter(task->mm, MM_SWAPENTS), |
a63d83f42 oom: badness heur... |
386 |
task->signal->oom_score_adj, task->comm); |
c55db9578 oom: dump_tasks u... |
387 388 |
task_unlock(task); } |
6b0c81b3b mm, oom: reduce d... |
389 |
rcu_read_unlock(); |
fef1bdd68 oom: add sysctl t... |
390 |
} |
2a966b77a mm: oom: add memc... |
391 |
static void dump_header(struct oom_control *oc, struct task_struct *p) |
1b604d75b oom: dump stack a... |
392 |
{ |
82e7d3abe oom: print nodema... |
393 394 395 396 397 398 |
nodemask_t *nm = (oc->nodemask) ? oc->nodemask : &cpuset_current_mems_allowed; pr_warn("%s invoked oom-killer: gfp_mask=%#x(%pGg), nodemask=%*pbl, order=%d, oom_score_adj=%hd ", current->comm, oc->gfp_mask, &oc->gfp_mask, nodemask_pr_args(nm), oc->order, |
a63d83f42 oom: badness heur... |
399 |
current->signal->oom_score_adj); |
9254990fb oom: warn if we g... |
400 401 402 |
if (!IS_ENABLED(CONFIG_COMPACTION) && oc->order) pr_warn("COMPACTION is disabled!!! "); |
a0795cd41 mm, oom: print sy... |
403 |
|
da39da3a5 mm, oom: remove t... |
404 |
cpuset_print_current_mems_allowed(); |
1b604d75b oom: dump stack a... |
405 |
dump_stack(); |
2a966b77a mm: oom: add memc... |
406 407 |
if (oc->memcg) mem_cgroup_print_oom_info(oc->memcg, p); |
58cf188ed memcg, oom: provi... |
408 409 |
else show_mem(SHOW_MEM_FILTER_NODES); |
1b604d75b oom: dump stack a... |
410 |
if (sysctl_oom_dump_tasks) |
2a966b77a mm: oom: add memc... |
411 |
dump_tasks(oc->memcg, oc->nodemask); |
1b604d75b oom: dump stack a... |
412 |
} |
5695be142 OOM, PM: OOM kill... |
413 |
/* |
c32b3cbe0 oom, PM: make OOM... |
414 |
* Number of OOM victims in flight |
5695be142 OOM, PM: OOM kill... |
415 |
*/ |
c32b3cbe0 oom, PM: make OOM... |
416 417 |
static atomic_t oom_victims = ATOMIC_INIT(0); static DECLARE_WAIT_QUEUE_HEAD(oom_victims_wait); |
5695be142 OOM, PM: OOM kill... |
418 |
|
7c5f64f84 mm: oom: deduplic... |
419 |
static bool oom_killer_disabled __read_mostly; |
5695be142 OOM, PM: OOM kill... |
420 |
|
bc448e897 mm, oom_reaper: r... |
421 |
#define K(x) ((x) << (PAGE_SHIFT-10)) |
3ef22dfff oom, oom_reaper: ... |
422 423 424 425 426 427 |
/* * 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... |
428 |
bool process_shares_mm(struct task_struct *p, struct mm_struct *mm) |
3ef22dfff oom, oom_reaper: ... |
429 430 431 432 433 434 435 436 437 438 |
{ 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... |
439 440 441 442 443 444 |
#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... |
445 |
static DECLARE_WAIT_QUEUE_HEAD(oom_reaper_wait); |
29c696e1c oom: make oom_rea... |
446 |
static struct task_struct *oom_reaper_list; |
03049269d mm, oom_reaper: i... |
447 |
static DEFINE_SPINLOCK(oom_reaper_lock); |
7ebffa455 mm,oom_reaper: re... |
448 |
static bool __oom_reap_task_mm(struct task_struct *tsk, struct mm_struct *mm) |
aac453635 mm, oom: introduc... |
449 450 451 452 453 454 |
{ struct mmu_gather tlb; struct vm_area_struct *vma; struct zap_details details = {.check_swap_entries = true, .ignore_dirty = true}; bool ret = true; |
36324a990 oom: clear TIF_ME... |
455 |
/* |
e2fe14564 oom_reaper: close... |
456 457 |
* We have to make sure to not race with the victim exit path * and cause premature new oom victim selection: |
7ebffa455 mm,oom_reaper: re... |
458 |
* __oom_reap_task_mm exit_mm |
e5e3f4c4f mm, oom_reaper: m... |
459 |
* mmget_not_zero |
e2fe14564 oom_reaper: close... |
460 461 462 463 464 465 466 467 468 469 |
* mmput * atomic_dec_and_test * exit_oom_victim * [...] * out_of_memory * select_bad_process * # no TIF_MEMDIE task selects new victim * unmap_page_range # frees some memory */ mutex_lock(&oom_lock); |
aac453635 mm, oom: introduc... |
470 471 |
if (!down_read_trylock(&mm->mmap_sem)) { ret = false; |
7ebffa455 mm,oom_reaper: re... |
472 |
goto unlock_oom; |
e5e3f4c4f mm, oom_reaper: m... |
473 474 475 476 477 478 479 480 481 |
} /* * increase mm_users only after we know we will reap something so * that the mmput_async is called only when we have reaped something * and delayed __mmput doesn't matter that much */ if (!mmget_not_zero(mm)) { up_read(&mm->mmap_sem); |
7ebffa455 mm,oom_reaper: re... |
482 |
goto unlock_oom; |
aac453635 mm, oom: introduc... |
483 |
} |
3f70dc38c mm: make sure tha... |
484 485 486 487 488 489 490 |
/* * 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); |
aac453635 mm, oom: introduc... |
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 |
tlb_gather_mmu(&tlb, mm, 0, -1); for (vma = mm->mmap ; vma; vma = vma->vm_next) { if (is_vm_hugetlb_page(vma)) continue; /* * mlocked VMAs require explicit munlocking before unmap. * Let's keep it simple here and skip such VMAs. */ if (vma->vm_flags & VM_LOCKED) 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)) unmap_page_range(&tlb, vma, vma->vm_start, vma->vm_end, &details); } tlb_finish_mmu(&tlb, 0, -1); |
bc448e897 mm, oom_reaper: r... |
518 519 520 521 522 523 |
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))); |
aac453635 mm, oom: introduc... |
524 |
up_read(&mm->mmap_sem); |
36324a990 oom: clear TIF_ME... |
525 526 |
/* |
ec8d7c14e mm, oom_reaper: d... |
527 528 529 530 |
* Drop our reference but make sure the mmput slow path is called from a * different context because we shouldn't risk we get stuck there and * put the oom_reaper out of the way. */ |
e5e3f4c4f mm, oom_reaper: m... |
531 |
mmput_async(mm); |
e5e3f4c4f mm, oom_reaper: m... |
532 533 |
unlock_oom: mutex_unlock(&oom_lock); |
aac453635 mm, oom: introduc... |
534 535 |
return ret; } |
bc448e897 mm, oom_reaper: r... |
536 |
#define MAX_OOM_REAP_RETRIES 10 |
36324a990 oom: clear TIF_ME... |
537 |
static void oom_reap_task(struct task_struct *tsk) |
aac453635 mm, oom: introduc... |
538 539 |
{ int attempts = 0; |
26db62f17 oom: keep mm of t... |
540 |
struct mm_struct *mm = tsk->signal->oom_mm; |
aac453635 mm, oom: introduc... |
541 542 |
/* Retry the down_read_trylock(mmap_sem) a few times */ |
7ebffa455 mm,oom_reaper: re... |
543 |
while (attempts++ < MAX_OOM_REAP_RETRIES && !__oom_reap_task_mm(tsk, mm)) |
aac453635 mm, oom: introduc... |
544 |
schedule_timeout_idle(HZ/10); |
7ebffa455 mm,oom_reaper: re... |
545 546 |
if (attempts <= MAX_OOM_REAP_RETRIES) goto done; |
11a410d51 mm, oom_reaper: d... |
547 |
|
8496afaba mm,oom_reaper: do... |
548 |
|
7ebffa455 mm,oom_reaper: re... |
549 550 551 |
pr_info("oom_reaper: unable to reap pid:%d (%s) ", task_pid_nr(tsk), tsk->comm); |
7ebffa455 mm,oom_reaper: re... |
552 |
debug_show_all_locks(); |
bc448e897 mm, oom_reaper: r... |
553 |
|
7ebffa455 mm,oom_reaper: re... |
554 |
done: |
449d777d7 mm, oom_reaper: c... |
555 |
tsk->oom_reaper_list = NULL; |
449d777d7 mm, oom_reaper: c... |
556 |
|
26db62f17 oom: keep mm of t... |
557 558 559 560 |
/* * 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 ... |
561 |
set_bit(MMF_OOM_SKIP, &mm->flags); |
26db62f17 oom: keep mm of t... |
562 |
|
aac453635 mm, oom: introduc... |
563 |
/* Drop a reference taken by wake_oom_reaper */ |
36324a990 oom: clear TIF_ME... |
564 |
put_task_struct(tsk); |
aac453635 mm, oom: introduc... |
565 566 567 568 569 |
} static int oom_reaper(void *unused) { while (true) { |
03049269d mm, oom_reaper: i... |
570 |
struct task_struct *tsk = NULL; |
aac453635 mm, oom: introduc... |
571 |
|
29c696e1c oom: make oom_rea... |
572 |
wait_event_freezable(oom_reaper_wait, oom_reaper_list != NULL); |
03049269d mm, oom_reaper: i... |
573 |
spin_lock(&oom_reaper_lock); |
29c696e1c oom: make oom_rea... |
574 575 576 |
if (oom_reaper_list != NULL) { tsk = oom_reaper_list; oom_reaper_list = tsk->oom_reaper_list; |
03049269d mm, oom_reaper: i... |
577 578 579 580 581 |
} spin_unlock(&oom_reaper_lock); if (tsk) oom_reap_task(tsk); |
aac453635 mm, oom: introduc... |
582 583 584 585 |
} return 0; } |
7c5f64f84 mm: oom: deduplic... |
586 |
static void wake_oom_reaper(struct task_struct *tsk) |
aac453635 mm, oom: introduc... |
587 |
{ |
af8e15cc8 oom, oom_reaper: ... |
588 589 590 591 592 |
if (!oom_reaper_th) return; /* tsk is already queued? */ if (tsk == oom_reaper_list || tsk->oom_reaper_list) |
aac453635 mm, oom: introduc... |
593 |
return; |
36324a990 oom: clear TIF_ME... |
594 |
get_task_struct(tsk); |
aac453635 mm, oom: introduc... |
595 |
|
03049269d mm, oom_reaper: i... |
596 |
spin_lock(&oom_reaper_lock); |
29c696e1c oom: make oom_rea... |
597 598 |
tsk->oom_reaper_list = oom_reaper_list; oom_reaper_list = tsk; |
03049269d mm, oom_reaper: i... |
599 600 |
spin_unlock(&oom_reaper_lock); wake_up(&oom_reaper_wait); |
aac453635 mm, oom: introduc... |
601 602 603 604 605 606 607 608 609 610 611 612 613 614 |
} static int __init oom_init(void) { oom_reaper_th = kthread_run(oom_reaper, NULL, "oom_reaper"); if (IS_ERR(oom_reaper_th)) { pr_err("Unable to start OOM reaper %ld. Continuing regardless ", PTR_ERR(oom_reaper_th)); oom_reaper_th = NULL; } return 0; } subsys_initcall(oom_init) |
7c5f64f84 mm: oom: deduplic... |
615 616 617 618 619 |
#else static inline void wake_oom_reaper(struct task_struct *tsk) { } #endif /* CONFIG_MMU */ |
aac453635 mm, oom: introduc... |
620 |
|
49550b605 oom: add helpers ... |
621 |
/** |
16e951966 mm: oom_kill: cle... |
622 |
* mark_oom_victim - mark the given task as OOM victim |
49550b605 oom: add helpers ... |
623 |
* @tsk: task to mark |
c32b3cbe0 oom, PM: make OOM... |
624 |
* |
dc56401fc mm: oom_kill: sim... |
625 |
* Has to be called with oom_lock held and never after |
c32b3cbe0 oom, PM: make OOM... |
626 |
* oom has been disabled already. |
26db62f17 oom: keep mm of t... |
627 628 629 |
* * 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 ... |
630 |
*/ |
7c5f64f84 mm: oom: deduplic... |
631 |
static void mark_oom_victim(struct task_struct *tsk) |
49550b605 oom: add helpers ... |
632 |
{ |
26db62f17 oom: keep mm of t... |
633 |
struct mm_struct *mm = tsk->mm; |
c32b3cbe0 oom, PM: make OOM... |
634 635 636 637 |
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... |
638 |
|
26db62f17 oom: keep mm of t... |
639 640 641 |
/* oom_mm is bound to the signal struct life time. */ if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm)) atomic_inc(&tsk->signal->oom_mm->mm_count); |
63a8ca9b2 oom: thaw the OOM... |
642 643 644 645 646 647 648 |
/* * 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... |
649 |
atomic_inc(&oom_victims); |
49550b605 oom: add helpers ... |
650 651 652 |
} /** |
16e951966 mm: oom_kill: cle... |
653 |
* exit_oom_victim - note the exit of an OOM victim |
49550b605 oom: add helpers ... |
654 |
*/ |
38531201c mm, oom: enforce ... |
655 |
void exit_oom_victim(void) |
49550b605 oom: add helpers ... |
656 |
{ |
38531201c mm, oom: enforce ... |
657 |
clear_thread_flag(TIF_MEMDIE); |
c32b3cbe0 oom, PM: make OOM... |
658 |
|
c38f1025f mm: oom_kill: gen... |
659 |
if (!atomic_dec_return(&oom_victims)) |
c32b3cbe0 oom, PM: make OOM... |
660 |
wake_up_all(&oom_victims_wait); |
c32b3cbe0 oom, PM: make OOM... |
661 662 663 |
} /** |
7d2e7a22c oom, suspend: fix... |
664 665 666 667 668 669 670 671 |
* oom_killer_enable - enable OOM killer */ void oom_killer_enable(void) { oom_killer_disabled = false; } /** |
c32b3cbe0 oom, PM: make OOM... |
672 |
* oom_killer_disable - disable OOM killer |
7d2e7a22c oom, suspend: fix... |
673 |
* @timeout: maximum timeout to wait for oom victims in jiffies |
c32b3cbe0 oom, PM: make OOM... |
674 675 |
* * Forces all page allocations to fail rather than trigger OOM killer. |
7d2e7a22c oom, suspend: fix... |
676 677 |
* Will block and wait until all OOM victims are killed or the given * timeout expires. |
c32b3cbe0 oom, PM: make OOM... |
678 679 680 681 682 683 684 685 |
* * 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... |
686 |
bool oom_killer_disable(signed long timeout) |
c32b3cbe0 oom, PM: make OOM... |
687 |
{ |
7d2e7a22c oom, suspend: fix... |
688 |
signed long ret; |
c32b3cbe0 oom, PM: make OOM... |
689 |
/* |
6afcf2895 mm,oom: make oom_... |
690 691 |
* 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... |
692 |
*/ |
6afcf2895 mm,oom: make oom_... |
693 |
if (mutex_lock_killable(&oom_lock)) |
c32b3cbe0 oom, PM: make OOM... |
694 |
return false; |
c32b3cbe0 oom, PM: make OOM... |
695 |
oom_killer_disabled = true; |
dc56401fc mm: oom_kill: sim... |
696 |
mutex_unlock(&oom_lock); |
c32b3cbe0 oom, PM: make OOM... |
697 |
|
7d2e7a22c oom, suspend: fix... |
698 699 700 701 702 703 |
ret = wait_event_interruptible_timeout(oom_victims_wait, !atomic_read(&oom_victims), timeout); if (ret <= 0) { oom_killer_enable(); return false; } |
c32b3cbe0 oom, PM: make OOM... |
704 705 706 |
return true; } |
1af8bb432 mm, oom: fortify ... |
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 |
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 ... |
732 733 |
* Caller has to make sure that task->mm is stable (hold task_lock or * it operates on the current). |
1af8bb432 mm, oom: fortify ... |
734 |
*/ |
7c5f64f84 mm: oom: deduplic... |
735 |
static bool task_will_free_mem(struct task_struct *task) |
1af8bb432 mm, oom: fortify ... |
736 |
{ |
091f362c5 mm, oom: tighten ... |
737 |
struct mm_struct *mm = task->mm; |
1af8bb432 mm, oom: fortify ... |
738 |
struct task_struct *p; |
f33e6f067 mm, oom: fix unin... |
739 |
bool ret = true; |
1af8bb432 mm, oom: fortify ... |
740 |
|
1af8bb432 mm, oom: fortify ... |
741 |
/* |
091f362c5 mm, oom: tighten ... |
742 743 744 |
* 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 ... |
745 |
*/ |
091f362c5 mm, oom: tighten ... |
746 |
if (!mm) |
1af8bb432 mm, oom: fortify ... |
747 |
return false; |
091f362c5 mm, oom: tighten ... |
748 749 |
if (!__task_will_free_mem(task)) return false; |
696453e66 mm, oom: task_wil... |
750 751 752 753 754 |
/* * 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 ... |
755 |
if (test_bit(MMF_OOM_SKIP, &mm->flags)) |
696453e66 mm, oom: task_wil... |
756 |
return false; |
696453e66 mm, oom: task_wil... |
757 |
|
091f362c5 mm, oom: tighten ... |
758 |
if (atomic_read(&mm->mm_users) <= 1) |
1af8bb432 mm, oom: fortify ... |
759 |
return true; |
1af8bb432 mm, oom: fortify ... |
760 761 |
/* |
5870c2e1d mm/oom_kill.c: fi... |
762 763 764 |
* 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 ... |
765 766 767 768 769 770 771 772 773 774 775 776 |
*/ 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 ... |
777 778 779 |
return ret; } |
7c5f64f84 mm: oom: deduplic... |
780 |
static void oom_kill_process(struct oom_control *oc, const char *message) |
1da177e4c Linux-2.6.12-rc2 |
781 |
{ |
7c5f64f84 mm: oom: deduplic... |
782 783 |
struct task_struct *p = oc->chosen; unsigned int points = oc->chosen_points; |
52d3c0367 Revert "oom: oom_... |
784 |
struct task_struct *victim = p; |
5e9d834a0 oom: sacrifice ch... |
785 |
struct task_struct *child; |
1da4db0cd oom_kill: change ... |
786 |
struct task_struct *t; |
647f2bdf4 mm, oom: fold oom... |
787 |
struct mm_struct *mm; |
52d3c0367 Revert "oom: oom_... |
788 |
unsigned int victim_points = 0; |
dc3f21ead mm, oom: introduc... |
789 790 |
static DEFINE_RATELIMIT_STATE(oom_rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); |
bb29902a7 oom, oom_reaper: ... |
791 |
bool can_oom_reap = true; |
1da177e4c Linux-2.6.12-rc2 |
792 |
|
50ec3bbff [PATCH] oom: hand... |
793 794 795 796 |
/* * If the task is already exiting, don't alarm the sysadmin or kill * its children or threads, just set TIF_MEMDIE so it can die quickly */ |
091f362c5 mm, oom: tighten ... |
797 |
task_lock(p); |
1af8bb432 mm, oom: fortify ... |
798 |
if (task_will_free_mem(p)) { |
16e951966 mm: oom_kill: cle... |
799 |
mark_oom_victim(p); |
1af8bb432 mm, oom: fortify ... |
800 |
wake_oom_reaper(p); |
091f362c5 mm, oom: tighten ... |
801 |
task_unlock(p); |
6b0c81b3b mm, oom: reduce d... |
802 |
put_task_struct(p); |
2a1c9b1fc mm, oom: avoid lo... |
803 |
return; |
50ec3bbff [PATCH] oom: hand... |
804 |
} |
091f362c5 mm, oom: tighten ... |
805 |
task_unlock(p); |
50ec3bbff [PATCH] oom: hand... |
806 |
|
dc3f21ead mm, oom: introduc... |
807 |
if (__ratelimit(&oom_rs)) |
2a966b77a mm: oom: add memc... |
808 |
dump_header(oc, p); |
8447d950e mm, oom: do not e... |
809 |
|
f0d6647e8 mm/oom_kill.c: pr... |
810 811 |
pr_err("%s: Kill process %d (%s) score %u or sacrifice child ", |
5e9d834a0 oom: sacrifice ch... |
812 |
message, task_pid_nr(p), p->comm, points); |
f3af38d30 [PATCH] oom: clea... |
813 |
|
5e9d834a0 oom: sacrifice ch... |
814 815 |
/* * If any of p's children has a different mm and is eligible for kill, |
11239836c oom: remove refer... |
816 |
* the one with the highest oom_badness() score is sacrificed for its |
5e9d834a0 oom: sacrifice ch... |
817 818 819 |
* parent. This attempts to lose the minimal amount of work done while * still freeing memory. */ |
6b0c81b3b mm, oom: reduce d... |
820 |
read_lock(&tasklist_lock); |
1da4db0cd oom_kill: change ... |
821 |
for_each_thread(p, t) { |
5e9d834a0 oom: sacrifice ch... |
822 |
list_for_each_entry(child, &t->children, sibling) { |
a63d83f42 oom: badness heur... |
823 |
unsigned int child_points; |
5e9d834a0 oom: sacrifice ch... |
824 |
|
4d7b3394f mm/oom_kill: fix ... |
825 |
if (process_shares_mm(child, p->mm)) |
edd45544c oom: avoid deferr... |
826 |
continue; |
a63d83f42 oom: badness heur... |
827 828 829 |
/* * oom_badness() returns 0 if the thread is unkillable */ |
2a966b77a mm: oom: add memc... |
830 |
child_points = oom_badness(child, |
7c5f64f84 mm: oom: deduplic... |
831 |
oc->memcg, oc->nodemask, oc->totalpages); |
5e9d834a0 oom: sacrifice ch... |
832 |
if (child_points > victim_points) { |
6b0c81b3b mm, oom: reduce d... |
833 |
put_task_struct(victim); |
5e9d834a0 oom: sacrifice ch... |
834 835 |
victim = child; victim_points = child_points; |
6b0c81b3b mm, oom: reduce d... |
836 |
get_task_struct(victim); |
5e9d834a0 oom: sacrifice ch... |
837 |
} |
dd8e8f405 oom: introduce fi... |
838 |
} |
1da4db0cd oom_kill: change ... |
839 |
} |
6b0c81b3b mm, oom: reduce d... |
840 |
read_unlock(&tasklist_lock); |
dd8e8f405 oom: introduce fi... |
841 |
|
6b0c81b3b mm, oom: reduce d... |
842 843 |
p = find_lock_task_mm(victim); if (!p) { |
6b0c81b3b mm, oom: reduce d... |
844 |
put_task_struct(victim); |
647f2bdf4 mm, oom: fold oom... |
845 |
return; |
6b0c81b3b mm, oom: reduce d... |
846 847 848 849 850 |
} else if (victim != p) { get_task_struct(p); put_task_struct(victim); victim = p; } |
647f2bdf4 mm, oom: fold oom... |
851 |
|
880b76893 mm/oom_kill.c: fi... |
852 |
/* Get a reference to safely compare mm after task_unlock(victim) */ |
647f2bdf4 mm, oom: fold oom... |
853 |
mm = victim->mm; |
880b76893 mm/oom_kill.c: fi... |
854 |
atomic_inc(&mm->mm_count); |
426fb5e72 mm/oom_kill.c: re... |
855 856 857 858 859 860 |
/* * We should send SIGKILL before setting TIF_MEMDIE in order to prevent * the OOM victim from depleting the memory reserves from the user * space under its control. */ do_send_sig_info(SIGKILL, SEND_SIG_FORCED, victim, true); |
16e951966 mm: oom_kill: cle... |
861 |
mark_oom_victim(victim); |
eca56ff90 mm, shmem: add in... |
862 863 |
pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB ", |
647f2bdf4 mm, oom: fold oom... |
864 865 |
task_pid_nr(victim), victim->comm, K(victim->mm->total_vm), K(get_mm_counter(victim->mm, MM_ANONPAGES)), |
eca56ff90 mm, shmem: add in... |
866 867 |
K(get_mm_counter(victim->mm, MM_FILEPAGES)), K(get_mm_counter(victim->mm, MM_SHMEMPAGES))); |
647f2bdf4 mm, oom: fold oom... |
868 869 870 871 872 873 874 875 876 877 878 |
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... |
879 |
rcu_read_lock(); |
c319025a6 mm/oom_kill: clea... |
880 |
for_each_process(p) { |
4d7b3394f mm/oom_kill: fix ... |
881 |
if (!process_shares_mm(p, mm)) |
c319025a6 mm/oom_kill: clea... |
882 883 884 |
continue; if (same_thread_group(p, victim)) continue; |
1b51e65ea oom, oom_reaper: ... |
885 |
if (is_global_init(p)) { |
aac453635 mm, oom: introduc... |
886 |
can_oom_reap = false; |
862e3073b mm, oom: get rid ... |
887 |
set_bit(MMF_OOM_SKIP, &mm->flags); |
a373966d1 mm, oom: hide mm ... |
888 889 890 891 |
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... |
892 |
continue; |
aac453635 mm, oom: introduc... |
893 |
} |
1b51e65ea oom, oom_reaper: ... |
894 895 896 897 898 899 |
/* * No use_mm() user needs to read from the userspace so we are * ok to reap it. */ if (unlikely(p->flags & PF_KTHREAD)) continue; |
c319025a6 mm/oom_kill: clea... |
900 901 |
do_send_sig_info(SIGKILL, SEND_SIG_FORCED, p, true); } |
6b0c81b3b mm, oom: reduce d... |
902 |
rcu_read_unlock(); |
647f2bdf4 mm, oom: fold oom... |
903 |
|
aac453635 mm, oom: introduc... |
904 |
if (can_oom_reap) |
36324a990 oom: clear TIF_ME... |
905 |
wake_oom_reaper(victim); |
aac453635 mm, oom: introduc... |
906 |
|
880b76893 mm/oom_kill.c: fi... |
907 |
mmdrop(mm); |
6b0c81b3b mm, oom: reduce d... |
908 |
put_task_struct(victim); |
1da177e4c Linux-2.6.12-rc2 |
909 |
} |
647f2bdf4 mm, oom: fold oom... |
910 |
#undef K |
1da177e4c Linux-2.6.12-rc2 |
911 |
|
309ed8825 oom: extract pani... |
912 913 914 |
/* * Determines whether the kernel must panic because of the panic_on_oom sysctl. */ |
7c5f64f84 mm: oom: deduplic... |
915 916 |
static void check_panic_on_oom(struct oom_control *oc, enum oom_constraint constraint) |
309ed8825 oom: extract pani... |
917 918 919 920 921 922 923 924 925 926 927 928 |
{ 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. */ if (constraint != CONSTRAINT_NONE) return; } |
071a4befe mm, oom: do not p... |
929 |
/* Do not panic for oom kills triggered by sysrq */ |
db2a0dd7a mm/oom_kill.c: in... |
930 |
if (is_sysrq_oom(oc)) |
071a4befe mm, oom: do not p... |
931 |
return; |
2a966b77a mm: oom: add memc... |
932 |
dump_header(oc, NULL); |
309ed8825 oom: extract pani... |
933 934 935 936 |
panic("Out of memory: %s panic_on_oom is enabled ", sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide"); } |
8bc719d3c [PATCH] out of me... |
937 938 939 940 941 942 943 944 945 946 947 948 949 |
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 |
950 |
/** |
6e0fc46dc mm, oom: organize... |
951 952 |
* 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 |
953 954 955 956 957 958 |
* * 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... |
959 |
bool out_of_memory(struct oom_control *oc) |
1da177e4c Linux-2.6.12-rc2 |
960 |
{ |
8bc719d3c [PATCH] out of me... |
961 |
unsigned long freed = 0; |
e36589323 oom: remove speci... |
962 |
enum oom_constraint constraint = CONSTRAINT_NONE; |
8bc719d3c [PATCH] out of me... |
963 |
|
dc56401fc mm: oom_kill: sim... |
964 965 |
if (oom_killer_disabled) return false; |
7c5f64f84 mm: oom: deduplic... |
966 967 968 969 970 971 |
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 |
972 |
|
7b98c2e40 oom: give current... |
973 |
/* |
9ff4868e3 mm, oom: allow ex... |
974 975 976 |
* 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... |
977 |
*/ |
091f362c5 mm, oom: tighten ... |
978 |
if (task_will_free_mem(current)) { |
16e951966 mm: oom_kill: cle... |
979 |
mark_oom_victim(current); |
1af8bb432 mm, oom: fortify ... |
980 |
wake_oom_reaper(current); |
75e8f8b24 mm, oom: remove u... |
981 |
return true; |
7b98c2e40 oom: give current... |
982 |
} |
9b0f8b040 [PATCH] Terminate... |
983 |
/* |
3da88fb3b mm, oom: move GFP... |
984 985 986 987 988 989 990 991 992 |
* 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 * ___GFP_DIRECT_RECLAIM to get here. */ if (oc->gfp_mask && !(oc->gfp_mask & (__GFP_FS|__GFP_NOFAIL))) return true; /* |
9b0f8b040 [PATCH] Terminate... |
993 |
* Check if there were limitations on the allocation (only relevant for |
7c5f64f84 mm: oom: deduplic... |
994 |
* NUMA and memcg) that may require different handling. |
9b0f8b040 [PATCH] Terminate... |
995 |
*/ |
7c5f64f84 mm: oom: deduplic... |
996 |
constraint = constrained_alloc(oc); |
6e0fc46dc mm, oom: organize... |
997 998 |
if (constraint != CONSTRAINT_MEMORY_POLICY) oc->nodemask = NULL; |
2a966b77a mm: oom: add memc... |
999 |
check_panic_on_oom(oc, constraint); |
0aad4b312 oom: fold __out_o... |
1000 |
|
7c5f64f84 mm: oom: deduplic... |
1001 1002 |
if (!is_memcg_oom(oc) && sysctl_oom_kill_allocating_task && current->mm && !oom_unkillable_task(current, NULL, oc->nodemask) && |
121d1ba0a mm, oom: fix pote... |
1003 |
current->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) { |
6b0c81b3b mm, oom: reduce d... |
1004 |
get_task_struct(current); |
7c5f64f84 mm: oom: deduplic... |
1005 1006 |
oc->chosen = current; oom_kill_process(oc, "Out of memory (oom_kill_allocating_task)"); |
75e8f8b24 mm, oom: remove u... |
1007 |
return true; |
0aad4b312 oom: fold __out_o... |
1008 |
} |
7c5f64f84 mm: oom: deduplic... |
1009 |
select_bad_process(oc); |
0aad4b312 oom: fold __out_o... |
1010 |
/* Found nothing?!?! Either we hang forever, or we panic. */ |
7c5f64f84 mm: oom: deduplic... |
1011 |
if (!oc->chosen && !is_sysrq_oom(oc) && !is_memcg_oom(oc)) { |
2a966b77a mm: oom: add memc... |
1012 |
dump_header(oc, NULL); |
0aad4b312 oom: fold __out_o... |
1013 1014 1015 |
panic("Out of memory and no killable processes... "); } |
7c5f64f84 mm: oom: deduplic... |
1016 1017 1018 |
if (oc->chosen && oc->chosen != (void *)-1UL) { oom_kill_process(oc, !is_memcg_oom(oc) ? "Out of memory" : "Memory cgroup out of memory"); |
75e8f8b24 mm, oom: remove u... |
1019 1020 1021 1022 |
/* * Give the killed process a good chance to exit before trying * to allocate memory again. */ |
4f774b912 mm, oom: do not s... |
1023 |
schedule_timeout_killable(1); |
75e8f8b24 mm, oom: remove u... |
1024 |
} |
7c5f64f84 mm: oom: deduplic... |
1025 |
return !!oc->chosen; |
c32b3cbe0 oom, PM: make OOM... |
1026 |
} |
e36589323 oom: remove speci... |
1027 1028 |
/* * The pagefault handler calls here because it is out of memory, so kill a |
798fd7569 mm: zap ZONE_OOM_... |
1029 1030 |
* 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... |
1031 1032 1033 |
*/ void pagefault_out_of_memory(void) { |
6e0fc46dc mm, oom: organize... |
1034 1035 1036 |
struct oom_control oc = { .zonelist = NULL, .nodemask = NULL, |
2a966b77a mm: oom: add memc... |
1037 |
.memcg = NULL, |
6e0fc46dc mm, oom: organize... |
1038 1039 |
.gfp_mask = 0, .order = 0, |
6e0fc46dc mm, oom: organize... |
1040 |
}; |
494264208 mm: memcg: handle... |
1041 |
if (mem_cgroup_oom_synchronize(true)) |
dc56401fc mm: oom_kill: sim... |
1042 |
return; |
3812c8c8f mm: memcg: do not... |
1043 |
|
dc56401fc mm: oom_kill: sim... |
1044 1045 |
if (!mutex_trylock(&oom_lock)) return; |
a104808e2 mm: don't emit wa... |
1046 |
out_of_memory(&oc); |
dc56401fc mm: oom_kill: sim... |
1047 |
mutex_unlock(&oom_lock); |
e36589323 oom: remove speci... |
1048 |
} |