diff options
author | KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> | 2010-08-09 20:19:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-09 23:45:01 -0400 |
commit | 26ebc984913b6a8d86d724b3a79d2ed4ed574612 (patch) | |
tree | 9d293c6f8b1bc5120beaa173590dcd83cd0e2eb0 | |
parent | f88ccad5886d5a864b8b0d48c666ee9998dec53f (diff) |
oom: /proc/<pid>/oom_score treat kernel thread honestly
If a kernel thread is using use_mm(), badness() returns a positive value.
This is not a big issue because caller take care of it correctly. But
there is one exception, /proc/<pid>/oom_score calls badness() directly and
doesn't care that the task is a regular process.
Another example, /proc/1/oom_score return !0 value. But it's unkillable.
This incorrectness makes administration a little confusing.
This patch fixes it.
Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Minchan Kim <minchan.kim@gmail.com>
Cc: David Rientjes <rientjes@google.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/proc/base.c | 5 | ||||
-rw-r--r-- | mm/oom_kill.c | 13 |
2 files changed, 10 insertions, 8 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index acb7ef80ea4f..fc23f62bb0b8 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -428,7 +428,8 @@ static const struct file_operations proc_lstats_operations = { | |||
428 | #endif | 428 | #endif |
429 | 429 | ||
430 | /* The badness from the OOM killer */ | 430 | /* The badness from the OOM killer */ |
431 | unsigned long badness(struct task_struct *p, unsigned long uptime); | 431 | unsigned long badness(struct task_struct *p, struct mem_cgroup *mem, |
432 | nodemask_t *nodemask, unsigned long uptime); | ||
432 | static int proc_oom_score(struct task_struct *task, char *buffer) | 433 | static int proc_oom_score(struct task_struct *task, char *buffer) |
433 | { | 434 | { |
434 | unsigned long points = 0; | 435 | unsigned long points = 0; |
@@ -437,7 +438,7 @@ static int proc_oom_score(struct task_struct *task, char *buffer) | |||
437 | do_posix_clock_monotonic_gettime(&uptime); | 438 | do_posix_clock_monotonic_gettime(&uptime); |
438 | read_lock(&tasklist_lock); | 439 | read_lock(&tasklist_lock); |
439 | if (pid_alive(task)) | 440 | if (pid_alive(task)) |
440 | points = badness(task, uptime.tv_sec); | 441 | points = badness(task, NULL, NULL, uptime.tv_sec); |
441 | read_unlock(&tasklist_lock); | 442 | read_unlock(&tasklist_lock); |
442 | return sprintf(buffer, "%lu\n", points); | 443 | return sprintf(buffer, "%lu\n", points); |
443 | } | 444 | } |
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 3999747aef48..867bd26274b4 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -139,8 +139,8 @@ static bool oom_unkillable_task(struct task_struct *p, struct mem_cgroup *mem, | |||
139 | * algorithm has been meticulously tuned to meet the principle | 139 | * algorithm has been meticulously tuned to meet the principle |
140 | * of least surprise ... (be careful when you change it) | 140 | * of least surprise ... (be careful when you change it) |
141 | */ | 141 | */ |
142 | 142 | unsigned long badness(struct task_struct *p, struct mem_cgroup *mem, | |
143 | unsigned long badness(struct task_struct *p, unsigned long uptime) | 143 | const nodemask_t *nodemask, unsigned long uptime) |
144 | { | 144 | { |
145 | unsigned long points, cpu_time, run_time; | 145 | unsigned long points, cpu_time, run_time; |
146 | struct task_struct *child; | 146 | struct task_struct *child; |
@@ -150,6 +150,8 @@ unsigned long badness(struct task_struct *p, unsigned long uptime) | |||
150 | unsigned long utime; | 150 | unsigned long utime; |
151 | unsigned long stime; | 151 | unsigned long stime; |
152 | 152 | ||
153 | if (oom_unkillable_task(p, mem, nodemask)) | ||
154 | return 0; | ||
153 | if (oom_adj == OOM_DISABLE) | 155 | if (oom_adj == OOM_DISABLE) |
154 | return 0; | 156 | return 0; |
155 | 157 | ||
@@ -351,7 +353,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints, | |||
351 | if (p->signal->oom_adj == OOM_DISABLE) | 353 | if (p->signal->oom_adj == OOM_DISABLE) |
352 | continue; | 354 | continue; |
353 | 355 | ||
354 | points = badness(p, uptime.tv_sec); | 356 | points = badness(p, mem, nodemask, uptime.tv_sec); |
355 | if (points > *ppoints || !chosen) { | 357 | if (points > *ppoints || !chosen) { |
356 | chosen = p; | 358 | chosen = p; |
357 | *ppoints = points; | 359 | *ppoints = points; |
@@ -482,11 +484,10 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, | |||
482 | 484 | ||
483 | if (child->mm == p->mm) | 485 | if (child->mm == p->mm) |
484 | continue; | 486 | continue; |
485 | if (oom_unkillable_task(p, mem, nodemask)) | ||
486 | continue; | ||
487 | 487 | ||
488 | /* badness() returns 0 if the thread is unkillable */ | 488 | /* badness() returns 0 if the thread is unkillable */ |
489 | child_points = badness(child, uptime.tv_sec); | 489 | child_points = badness(child, mem, nodemask, |
490 | uptime.tv_sec); | ||
490 | if (child_points > victim_points) { | 491 | if (child_points > victim_points) { |
491 | victim = child; | 492 | victim = child; |
492 | victim_points = child_points; | 493 | victim_points = child_points; |