From: KOSAKI Motohiro Date: Tue, 10 Aug 2010 00:19:37 +0000 (-0700) Subject: oom: /proc//oom_score treat kernel thread honestly X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=26ebc984913b;p=openwrt%2Fstaging%2Fblogic.git oom: /proc//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//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 Cc: Minchan Kim Cc: David Rientjes Cc: KAMEZAWA Hiroyuki Cc: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- 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 = { #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 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, * 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;