diff options
Diffstat (limited to 'mm/oom_kill.c')
-rw-r--r-- | mm/oom_kill.c | 86 |
1 files changed, 45 insertions, 41 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index a7b2460e922b..ea2147dabba6 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -34,6 +34,23 @@ int sysctl_oom_dump_tasks; | |||
34 | static DEFINE_SPINLOCK(zone_scan_lock); | 34 | static DEFINE_SPINLOCK(zone_scan_lock); |
35 | /* #define DEBUG */ | 35 | /* #define DEBUG */ |
36 | 36 | ||
37 | /* | ||
38 | * Is all threads of the target process nodes overlap ours? | ||
39 | */ | ||
40 | static int has_intersects_mems_allowed(struct task_struct *tsk) | ||
41 | { | ||
42 | struct task_struct *t; | ||
43 | |||
44 | t = tsk; | ||
45 | do { | ||
46 | if (cpuset_mems_allowed_intersects(current, t)) | ||
47 | return 1; | ||
48 | t = next_thread(t); | ||
49 | } while (t != tsk); | ||
50 | |||
51 | return 0; | ||
52 | } | ||
53 | |||
37 | /** | 54 | /** |
38 | * badness - calculate a numeric value for how bad this task has been | 55 | * badness - calculate a numeric value for how bad this task has been |
39 | * @p: task struct of which task we should calculate | 56 | * @p: task struct of which task we should calculate |
@@ -58,6 +75,13 @@ unsigned long badness(struct task_struct *p, unsigned long uptime) | |||
58 | unsigned long points, cpu_time, run_time; | 75 | unsigned long points, cpu_time, run_time; |
59 | struct mm_struct *mm; | 76 | struct mm_struct *mm; |
60 | struct task_struct *child; | 77 | struct task_struct *child; |
78 | int oom_adj = p->signal->oom_adj; | ||
79 | struct task_cputime task_time; | ||
80 | unsigned long utime; | ||
81 | unsigned long stime; | ||
82 | |||
83 | if (oom_adj == OOM_DISABLE) | ||
84 | return 0; | ||
61 | 85 | ||
62 | task_lock(p); | 86 | task_lock(p); |
63 | mm = p->mm; | 87 | mm = p->mm; |
@@ -79,7 +103,7 @@ unsigned long badness(struct task_struct *p, unsigned long uptime) | |||
79 | /* | 103 | /* |
80 | * swapoff can easily use up all memory, so kill those first. | 104 | * swapoff can easily use up all memory, so kill those first. |
81 | */ | 105 | */ |
82 | if (p->flags & PF_SWAPOFF) | 106 | if (p->flags & PF_OOM_ORIGIN) |
83 | return ULONG_MAX; | 107 | return ULONG_MAX; |
84 | 108 | ||
85 | /* | 109 | /* |
@@ -102,8 +126,11 @@ unsigned long badness(struct task_struct *p, unsigned long uptime) | |||
102 | * of seconds. There is no particular reason for this other than | 126 | * of seconds. There is no particular reason for this other than |
103 | * that it turned out to work very well in practice. | 127 | * that it turned out to work very well in practice. |
104 | */ | 128 | */ |
105 | cpu_time = (cputime_to_jiffies(p->utime) + cputime_to_jiffies(p->stime)) | 129 | thread_group_cputime(p, &task_time); |
106 | >> (SHIFT_HZ + 3); | 130 | utime = cputime_to_jiffies(task_time.utime); |
131 | stime = cputime_to_jiffies(task_time.stime); | ||
132 | cpu_time = (utime + stime) >> (SHIFT_HZ + 3); | ||
133 | |||
107 | 134 | ||
108 | if (uptime >= p->start_time.tv_sec) | 135 | if (uptime >= p->start_time.tv_sec) |
109 | run_time = (uptime - p->start_time.tv_sec) >> 10; | 136 | run_time = (uptime - p->start_time.tv_sec) >> 10; |
@@ -144,19 +171,19 @@ unsigned long badness(struct task_struct *p, unsigned long uptime) | |||
144 | * because p may have allocated or otherwise mapped memory on | 171 | * because p may have allocated or otherwise mapped memory on |
145 | * this node before. However it will be less likely. | 172 | * this node before. However it will be less likely. |
146 | */ | 173 | */ |
147 | if (!cpuset_mems_allowed_intersects(current, p)) | 174 | if (!has_intersects_mems_allowed(p)) |
148 | points /= 8; | 175 | points /= 8; |
149 | 176 | ||
150 | /* | 177 | /* |
151 | * Adjust the score by oomkilladj. | 178 | * Adjust the score by oom_adj. |
152 | */ | 179 | */ |
153 | if (p->oomkilladj) { | 180 | if (oom_adj) { |
154 | if (p->oomkilladj > 0) { | 181 | if (oom_adj > 0) { |
155 | if (!points) | 182 | if (!points) |
156 | points = 1; | 183 | points = 1; |
157 | points <<= p->oomkilladj; | 184 | points <<= oom_adj; |
158 | } else | 185 | } else |
159 | points >>= -(p->oomkilladj); | 186 | points >>= -(oom_adj); |
160 | } | 187 | } |
161 | 188 | ||
162 | #ifdef DEBUG | 189 | #ifdef DEBUG |
@@ -200,13 +227,13 @@ static inline enum oom_constraint constrained_alloc(struct zonelist *zonelist, | |||
200 | static struct task_struct *select_bad_process(unsigned long *ppoints, | 227 | static struct task_struct *select_bad_process(unsigned long *ppoints, |
201 | struct mem_cgroup *mem) | 228 | struct mem_cgroup *mem) |
202 | { | 229 | { |
203 | struct task_struct *g, *p; | 230 | struct task_struct *p; |
204 | struct task_struct *chosen = NULL; | 231 | struct task_struct *chosen = NULL; |
205 | struct timespec uptime; | 232 | struct timespec uptime; |
206 | *ppoints = 0; | 233 | *ppoints = 0; |
207 | 234 | ||
208 | do_posix_clock_monotonic_gettime(&uptime); | 235 | do_posix_clock_monotonic_gettime(&uptime); |
209 | do_each_thread(g, p) { | 236 | for_each_process(p) { |
210 | unsigned long points; | 237 | unsigned long points; |
211 | 238 | ||
212 | /* | 239 | /* |
@@ -251,7 +278,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints, | |||
251 | *ppoints = ULONG_MAX; | 278 | *ppoints = ULONG_MAX; |
252 | } | 279 | } |
253 | 280 | ||
254 | if (p->oomkilladj == OOM_DISABLE) | 281 | if (p->signal->oom_adj == OOM_DISABLE) |
255 | continue; | 282 | continue; |
256 | 283 | ||
257 | points = badness(p, uptime.tv_sec); | 284 | points = badness(p, uptime.tv_sec); |
@@ -259,7 +286,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints, | |||
259 | chosen = p; | 286 | chosen = p; |
260 | *ppoints = points; | 287 | *ppoints = points; |
261 | } | 288 | } |
262 | } while_each_thread(g, p); | 289 | } |
263 | 290 | ||
264 | return chosen; | 291 | return chosen; |
265 | } | 292 | } |
@@ -304,7 +331,7 @@ static void dump_tasks(const struct mem_cgroup *mem) | |||
304 | } | 331 | } |
305 | printk(KERN_INFO "[%5d] %5d %5d %8lu %8lu %3d %3d %s\n", | 332 | printk(KERN_INFO "[%5d] %5d %5d %8lu %8lu %3d %3d %s\n", |
306 | p->pid, __task_cred(p)->uid, p->tgid, mm->total_vm, | 333 | p->pid, __task_cred(p)->uid, p->tgid, mm->total_vm, |
307 | get_mm_rss(mm), (int)task_cpu(p), p->oomkilladj, | 334 | get_mm_rss(mm), (int)task_cpu(p), p->signal->oom_adj, |
308 | p->comm); | 335 | p->comm); |
309 | task_unlock(p); | 336 | task_unlock(p); |
310 | } while_each_thread(g, p); | 337 | } while_each_thread(g, p); |
@@ -346,11 +373,6 @@ static void __oom_kill_task(struct task_struct *p, int verbose) | |||
346 | 373 | ||
347 | static int oom_kill_task(struct task_struct *p) | 374 | static int oom_kill_task(struct task_struct *p) |
348 | { | 375 | { |
349 | struct mm_struct *mm; | ||
350 | struct task_struct *g, *q; | ||
351 | |||
352 | mm = p->mm; | ||
353 | |||
354 | /* WARNING: mm may not be dereferenced since we did not obtain its | 376 | /* WARNING: mm may not be dereferenced since we did not obtain its |
355 | * value from get_task_mm(p). This is OK since all we need to do is | 377 | * value from get_task_mm(p). This is OK since all we need to do is |
356 | * compare mm to q->mm below. | 378 | * compare mm to q->mm below. |
@@ -359,30 +381,11 @@ static int oom_kill_task(struct task_struct *p) | |||
359 | * change to NULL at any time since we do not hold task_lock(p). | 381 | * change to NULL at any time since we do not hold task_lock(p). |
360 | * However, this is of no concern to us. | 382 | * However, this is of no concern to us. |
361 | */ | 383 | */ |
362 | 384 | if (!p->mm || p->signal->oom_adj == OOM_DISABLE) | |
363 | if (mm == NULL) | ||
364 | return 1; | 385 | return 1; |
365 | 386 | ||
366 | /* | ||
367 | * Don't kill the process if any threads are set to OOM_DISABLE | ||
368 | */ | ||
369 | do_each_thread(g, q) { | ||
370 | if (q->mm == mm && q->oomkilladj == OOM_DISABLE) | ||
371 | return 1; | ||
372 | } while_each_thread(g, q); | ||
373 | |||
374 | __oom_kill_task(p, 1); | 387 | __oom_kill_task(p, 1); |
375 | 388 | ||
376 | /* | ||
377 | * kill all processes that share the ->mm (i.e. all threads), | ||
378 | * but are in a different thread group. Don't let them have access | ||
379 | * to memory reserves though, otherwise we might deplete all memory. | ||
380 | */ | ||
381 | do_each_thread(g, q) { | ||
382 | if (q->mm == mm && !same_thread_group(q, p)) | ||
383 | force_sig(SIGKILL, q); | ||
384 | } while_each_thread(g, q); | ||
385 | |||
386 | return 0; | 389 | return 0; |
387 | } | 390 | } |
388 | 391 | ||
@@ -394,8 +397,9 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, | |||
394 | 397 | ||
395 | if (printk_ratelimit()) { | 398 | if (printk_ratelimit()) { |
396 | printk(KERN_WARNING "%s invoked oom-killer: " | 399 | printk(KERN_WARNING "%s invoked oom-killer: " |
397 | "gfp_mask=0x%x, order=%d, oomkilladj=%d\n", | 400 | "gfp_mask=0x%x, order=%d, oom_adj=%d\n", |
398 | current->comm, gfp_mask, order, current->oomkilladj); | 401 | current->comm, gfp_mask, order, |
402 | current->signal->oom_adj); | ||
399 | task_lock(current); | 403 | task_lock(current); |
400 | cpuset_print_task_mems_allowed(current); | 404 | cpuset_print_task_mems_allowed(current); |
401 | task_unlock(current); | 405 | task_unlock(current); |