diff options
author | KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> | 2010-08-09 17:19:37 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-09 20:45:01 -0700 |
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 acb7ef80ea4..fc23f62bb0b 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -428,7 +428,8 @@ static const struct file_operations proc_lstats_operations = { #endif /* The badness from the OOM killer */ -unsigned long badness(struct task_struct *p, unsigned long uptime); +unsigned long badness(struct task_struct *p, struct mem_cgroup *mem, + nodemask_t *nodemask, unsigned long uptime); static int proc_oom_score(struct task_struct *task, char *buffer) { unsigned long points = 0; @@ -437,7 +438,7 @@ static int proc_oom_score(struct task_struct *task, char *buffer) do_posix_clock_monotonic_gettime(&uptime); read_lock(&tasklist_lock); if (pid_alive(task)) - points = badness(task, uptime.tv_sec); + points = badness(task, NULL, NULL, uptime.tv_sec); read_unlock(&tasklist_lock); return sprintf(buffer, "%lu\n", points); } diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 3999747aef4..867bd26274b 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, * algorithm has been meticulously tuned to meet the principle * of least surprise ... (be careful when you change it) */ - -unsigned long badness(struct task_struct *p, unsigned long uptime) +unsigned long badness(struct task_struct *p, struct mem_cgroup *mem, + const nodemask_t *nodemask, unsigned long uptime) { unsigned long points, cpu_time, run_time; struct task_struct *child; @@ -150,6 +150,8 @@ unsigned long badness(struct task_struct *p, unsigned long uptime) unsigned long utime; unsigned long stime; + if (oom_unkillable_task(p, mem, nodemask)) + return 0; if (oom_adj == OOM_DISABLE) return 0; @@ -351,7 +353,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints, if (p->signal->oom_adj == OOM_DISABLE) continue; - points = badness(p, uptime.tv_sec); + points = badness(p, mem, nodemask, uptime.tv_sec); if (points > *ppoints || !chosen) { chosen = p; *ppoints = points; @@ -482,11 +484,10 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, if (child->mm == p->mm) continue; - if (oom_unkillable_task(p, mem, nodemask)) - continue; /* badness() returns 0 if the thread is unkillable */ - child_points = badness(child, uptime.tv_sec); + child_points = badness(child, mem, nodemask, + uptime.tv_sec); if (child_points > victim_points) { victim = child; victim_points = child_points; |