linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [patch 1/3] mm, oom: avoid looping when chosen thread detaches its mm
@ 2012-01-12  3:24 David Rientjes
  2012-01-12  3:24 ` [patch 2/3] mm, oom: fold oom_kill_task into oom_kill_process David Rientjes
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: David Rientjes @ 2012-01-12  3:24 UTC (permalink / raw)
  To: Andrew Morton; +Cc: KAMEZAWA Hiroyuki, KOSAKI Motohiro, linux-mm

oom_kill_task() returns non-zero iff the chosen process does not have any
threads with an attached ->mm.

In such a case, it's better to just return to the page allocator and
retry the allocation because memory could have been freed in the interim
and the oom condition may no longer exist.  It's unnecessary to loop in
the oom killer and find another thread to kill.

This allows both oom_kill_task() and oom_kill_process() to be converted
to void functions.  If the oom condition persists, the oom killer will be
recalled.

Signed-off-by: David Rientjes <rientjes@google.com>
---
 mm/oom_kill.c |   56 ++++++++++++++++++++------------------------------------
 1 files changed, 20 insertions(+), 36 deletions(-)

diff --git a/mm/oom_kill.c b/mm/oom_kill.c
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -434,14 +434,14 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
 }
 
 #define K(x) ((x) << (PAGE_SHIFT-10))
-static int oom_kill_task(struct task_struct *p, struct mem_cgroup *mem)
+static void oom_kill_task(struct task_struct *p, struct mem_cgroup *mem)
 {
 	struct task_struct *q;
 	struct mm_struct *mm;
 
 	p = find_lock_task_mm(p);
 	if (!p)
-		return 1;
+		return;
 
 	/* mm cannot be safely dereferenced after task_unlock(p) */
 	mm = p->mm;
@@ -477,15 +477,13 @@ static int oom_kill_task(struct task_struct *p, struct mem_cgroup *mem)
 
 	set_tsk_thread_flag(p, TIF_MEMDIE);
 	force_sig(SIGKILL, p);
-
-	return 0;
 }
 #undef K
 
-static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
-			    unsigned int points, unsigned long totalpages,
-			    struct mem_cgroup *mem, nodemask_t *nodemask,
-			    const char *message)
+static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
+			     unsigned int points, unsigned long totalpages,
+			     struct mem_cgroup *mem, nodemask_t *nodemask,
+			     const char *message)
 {
 	struct task_struct *victim = p;
 	struct task_struct *child;
@@ -501,7 +499,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 	 */
 	if (p->flags & PF_EXITING) {
 		set_tsk_thread_flag(p, TIF_MEMDIE);
-		return 0;
+		return;
 	}
 
 	task_lock(p);
@@ -533,7 +531,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 		}
 	} while_each_thread(p, t);
 
-	return oom_kill_task(victim, mem);
+	oom_kill_task(victim, mem);
 }
 
 /*
@@ -580,15 +578,10 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask)
 	check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, 0, NULL);
 	limit = mem_cgroup_get_limit(mem) >> PAGE_SHIFT;
 	read_lock(&tasklist_lock);
-retry:
 	p = select_bad_process(&points, limit, mem, NULL);
-	if (!p || PTR_ERR(p) == -1UL)
-		goto out;
-
-	if (oom_kill_process(p, gfp_mask, 0, points, limit, mem, NULL,
-				"Memory cgroup out of memory"))
-		goto retry;
-out:
+	if (p && PTR_ERR(p) != -1UL)
+		oom_kill_process(p, gfp_mask, 0, points, limit, mem, NULL,
+				 "Memory cgroup out of memory");
 	read_unlock(&tasklist_lock);
 }
 #endif
@@ -745,33 +738,24 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
 	if (sysctl_oom_kill_allocating_task &&
 	    !oom_unkillable_task(current, NULL, nodemask) &&
 	    current->mm) {
-		/*
-		 * oom_kill_process() needs tasklist_lock held.  If it returns
-		 * non-zero, current could not be killed so we must fallback to
-		 * the tasklist scan.
-		 */
-		if (!oom_kill_process(current, gfp_mask, order, 0, totalpages,
-				NULL, nodemask,
-				"Out of memory (oom_kill_allocating_task)"))
-			goto out;
+		oom_kill_process(current, gfp_mask, order, 0, totalpages, NULL,
+				 nodemask,
+				 "Out of memory (oom_kill_allocating_task)");
+		goto out;
 	}
 
-retry:
 	p = select_bad_process(&points, totalpages, NULL, mpol_mask);
-	if (PTR_ERR(p) == -1UL)
-		goto out;
-
 	/* Found nothing?!?! Either we hang forever, or we panic. */
 	if (!p) {
 		dump_header(NULL, gfp_mask, order, NULL, mpol_mask);
 		read_unlock(&tasklist_lock);
 		panic("Out of memory and no killable processes...\n");
 	}
-
-	if (oom_kill_process(p, gfp_mask, order, points, totalpages, NULL,
-				nodemask, "Out of memory"))
-		goto retry;
-	killed = 1;
+	if (PTR_ERR(p) != -1UL) {
+		oom_kill_process(p, gfp_mask, order, points, totalpages, NULL,
+				 nodemask, "Out of memory");
+		killed = 1;
+	}
 out:
 	read_unlock(&tasklist_lock);
 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch 2/3] mm, oom: fold oom_kill_task into oom_kill_process
  2012-01-12  3:24 [patch 1/3] mm, oom: avoid looping when chosen thread detaches its mm David Rientjes
@ 2012-01-12  3:24 ` David Rientjes
  2012-01-12  3:48   ` KOSAKI Motohiro
  2012-01-12  4:48   ` KAMEZAWA Hiroyuki
  2012-01-12  3:24 ` [patch 3/3] mm, oom: do not emit oom killer warning if chosen thread is already exiting David Rientjes
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 13+ messages in thread
From: David Rientjes @ 2012-01-12  3:24 UTC (permalink / raw)
  To: Andrew Morton; +Cc: KAMEZAWA Hiroyuki, KOSAKI Motohiro, linux-mm

oom_kill_task() has a single caller, so fold it into its parent function,
oom_kill_process().  Slightly reduces the number of lines in the oom
killer.

Signed-off-by: David Rientjes <rientjes@google.com>
---
 mm/oom_kill.c |   87 ++++++++++++++++++++++++++------------------------------
 1 files changed, 40 insertions(+), 47 deletions(-)

diff --git a/mm/oom_kill.c b/mm/oom_kill.c
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -434,52 +434,6 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
 }
 
 #define K(x) ((x) << (PAGE_SHIFT-10))
-static void oom_kill_task(struct task_struct *p, struct mem_cgroup *mem)
-{
-	struct task_struct *q;
-	struct mm_struct *mm;
-
-	p = find_lock_task_mm(p);
-	if (!p)
-		return;
-
-	/* mm cannot be safely dereferenced after task_unlock(p) */
-	mm = p->mm;
-
-	pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
-		task_pid_nr(p), p->comm, K(p->mm->total_vm),
-		K(get_mm_counter(p->mm, MM_ANONPAGES)),
-		K(get_mm_counter(p->mm, MM_FILEPAGES)));
-	task_unlock(p);
-
-	/*
-	 * Kill all user processes sharing p->mm in other thread groups, if any.
-	 * They don't get access to memory reserves or a higher scheduler
-	 * priority, though, to avoid depletion of all memory or task
-	 * starvation.  This prevents mm->mmap_sem livelock when an oom killed
-	 * task 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.
-	 */
-	for_each_process(q)
-		if (q->mm == mm && !same_thread_group(q, p) &&
-		    !(q->flags & PF_KTHREAD)) {
-			if (q->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
-				continue;
-
-			task_lock(q);	/* Protect ->comm from prctl() */
-			pr_err("Kill process %d (%s) sharing same memory\n",
-				task_pid_nr(q), q->comm);
-			task_unlock(q);
-			force_sig(SIGKILL, q);
-		}
-
-	set_tsk_thread_flag(p, TIF_MEMDIE);
-	force_sig(SIGKILL, p);
-}
-#undef K
-
 static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 			     unsigned int points, unsigned long totalpages,
 			     struct mem_cgroup *mem, nodemask_t *nodemask,
@@ -488,6 +442,7 @@ static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 	struct task_struct *victim = p;
 	struct task_struct *child;
 	struct task_struct *t = p;
+	struct mm_struct *mm;
 	unsigned int victim_points = 0;
 
 	if (printk_ratelimit())
@@ -531,8 +486,46 @@ static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 		}
 	} while_each_thread(p, t);
 
-	oom_kill_task(victim, mem);
+	victim = find_lock_task_mm(victim);
+	if (!victim)
+		return;
+
+	/* mm cannot be safely dereferenced after task_unlock(p) */
+	mm = victim->mm;
+
+	pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
+		task_pid_nr(victim), victim->comm, K(victim->mm->total_vm),
+		K(get_mm_counter(victim->mm, MM_ANONPAGES)),
+		K(get_mm_counter(victim->mm, MM_FILEPAGES)));
+	task_unlock(victim);
+
+	/*
+	 * Kill all user processes sharing victim->mm in other thread groups, if 
+	 * any.  They don't get access to memory reserves or a higher scheduler
+	 * priority, though, to avoid depletion of all memory or task
+	 * starvation.  This prevents mm->mmap_sem livelock when an oom killed
+	 * task 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.
+	 */
+	for_each_process(p)
+		if (p->mm == mm && !same_thread_group(p, victim) &&
+		    !(p->flags & PF_KTHREAD)) {
+			if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
+				continue;
+
+			task_lock(p);	/* Protect ->comm from prctl() */
+			pr_err("Kill process %d (%s) sharing same memory\n",
+				task_pid_nr(p), p->comm);
+			task_unlock(p);
+			force_sig(SIGKILL, p);
+		}
+
+	set_tsk_thread_flag(victim, TIF_MEMDIE);
+	force_sig(SIGKILL, victim);
 }
+#undef K
 
 /*
  * Determines whether the kernel must panic because of the panic_on_oom sysctl.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch 3/3] mm, oom: do not emit oom killer warning if chosen thread is already exiting
  2012-01-12  3:24 [patch 1/3] mm, oom: avoid looping when chosen thread detaches its mm David Rientjes
  2012-01-12  3:24 ` [patch 2/3] mm, oom: fold oom_kill_task into oom_kill_process David Rientjes
@ 2012-01-12  3:24 ` David Rientjes
  2012-01-12  3:48   ` KOSAKI Motohiro
                     ` (2 more replies)
  2012-01-12  4:47 ` [patch 1/3] mm, oom: avoid looping when chosen thread detaches its mm KAMEZAWA Hiroyuki
                   ` (2 subsequent siblings)
  4 siblings, 3 replies; 13+ messages in thread
From: David Rientjes @ 2012-01-12  3:24 UTC (permalink / raw)
  To: Andrew Morton; +Cc: KAMEZAWA Hiroyuki, KOSAKI Motohiro, linux-mm

If a thread is chosen for oom kill and is already PF_EXITING, then the
oom killer simply sets TIF_MEMDIE and returns.  This allows the thread to
have access to memory reserves so that it may quickly exit.  This logic
is preceeded with a comment saying there's no need to alarm the sysadmin.
This patch adds truth to that statement.

There's no need to emit any warning about the oom condition if the thread
is already exiting since it will not be killed.  In this condition, just
silently return the oom killer since its only giving access to memory
reserves and is otherwise a no-op.

Signed-off-by: David Rientjes <rientjes@google.com>
---
 mm/oom_kill.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/mm/oom_kill.c b/mm/oom_kill.c
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -445,9 +445,6 @@ static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 	struct mm_struct *mm;
 	unsigned int victim_points = 0;
 
-	if (printk_ratelimit())
-		dump_header(p, gfp_mask, order, mem, nodemask);
-
 	/*
 	 * 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
@@ -457,6 +454,9 @@ static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 		return;
 	}
 
+	if (printk_ratelimit())
+		dump_header(p, gfp_mask, order, mem, nodemask);
+
 	task_lock(p);
 	pr_err("%s: Kill process %d (%s) score %d or sacrifice child\n",
 		message, task_pid_nr(p), p->comm, points);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch 2/3] mm, oom: fold oom_kill_task into oom_kill_process
  2012-01-12  3:24 ` [patch 2/3] mm, oom: fold oom_kill_task into oom_kill_process David Rientjes
@ 2012-01-12  3:48   ` KOSAKI Motohiro
  2012-01-12  4:48   ` KAMEZAWA Hiroyuki
  1 sibling, 0 replies; 13+ messages in thread
From: KOSAKI Motohiro @ 2012-01-12  3:48 UTC (permalink / raw)
  To: David Rientjes
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, KOSAKI Motohiro, linux-mm

(1/11/12 10:24 PM), David Rientjes wrote:
> oom_kill_task() has a single caller, so fold it into its parent function,
> oom_kill_process().  Slightly reduces the number of lines in the oom
> killer.
>
> Signed-off-by: David Rientjes<rientjes@google.com>

Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch 3/3] mm, oom: do not emit oom killer warning if chosen thread is already exiting
  2012-01-12  3:24 ` [patch 3/3] mm, oom: do not emit oom killer warning if chosen thread is already exiting David Rientjes
@ 2012-01-12  3:48   ` KOSAKI Motohiro
  2012-01-12  4:49   ` KAMEZAWA Hiroyuki
  2012-01-12 14:44   ` Michal Hocko
  2 siblings, 0 replies; 13+ messages in thread
From: KOSAKI Motohiro @ 2012-01-12  3:48 UTC (permalink / raw)
  To: David Rientjes
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, KOSAKI Motohiro, linux-mm

(1/11/12 10:24 PM), David Rientjes wrote:
> If a thread is chosen for oom kill and is already PF_EXITING, then the
> oom killer simply sets TIF_MEMDIE and returns.  This allows the thread to
> have access to memory reserves so that it may quickly exit.  This logic
> is preceeded with a comment saying there's no need to alarm the sysadmin.
> This patch adds truth to that statement.
>
> There's no need to emit any warning about the oom condition if the thread
> is already exiting since it will not be killed.  In this condition, just
> silently return the oom killer since its only giving access to memory
> reserves and is otherwise a no-op.
>
> Signed-off-by: David Rientjes<rientjes@google.com>
> ---


Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch 1/3] mm, oom: avoid looping when chosen thread detaches its mm
  2012-01-12  3:24 [patch 1/3] mm, oom: avoid looping when chosen thread detaches its mm David Rientjes
  2012-01-12  3:24 ` [patch 2/3] mm, oom: fold oom_kill_task into oom_kill_process David Rientjes
  2012-01-12  3:24 ` [patch 3/3] mm, oom: do not emit oom killer warning if chosen thread is already exiting David Rientjes
@ 2012-01-12  4:47 ` KAMEZAWA Hiroyuki
  2012-01-12 14:26 ` Michal Hocko
  2012-01-14  0:39 ` [patch -mm " David Rientjes
  4 siblings, 0 replies; 13+ messages in thread
From: KAMEZAWA Hiroyuki @ 2012-01-12  4:47 UTC (permalink / raw)
  To: David Rientjes; +Cc: Andrew Morton, KOSAKI Motohiro, linux-mm

On Wed, 11 Jan 2012 19:24:20 -0800 (PST)
David Rientjes <rientjes@google.com> wrote:

> oom_kill_task() returns non-zero iff the chosen process does not have any
> threads with an attached ->mm.
> 
> In such a case, it's better to just return to the page allocator and
> retry the allocation because memory could have been freed in the interim
> and the oom condition may no longer exist.  It's unnecessary to loop in
> the oom killer and find another thread to kill.
> 
> This allows both oom_kill_task() and oom_kill_process() to be converted
> to void functions.  If the oom condition persists, the oom killer will be
> recalled.
> 
> Signed-off-by: David Rientjes <rientjes@google.com>

I think this is reasonable.
Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>


> ---
>  mm/oom_kill.c |   56 ++++++++++++++++++++------------------------------------
>  1 files changed, 20 insertions(+), 36 deletions(-)
> 
> diff --git a/mm/oom_kill.c b/mm/oom_kill.c
> --- a/mm/oom_kill.c
> +++ b/mm/oom_kill.c
> @@ -434,14 +434,14 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
>  }
>  
>  #define K(x) ((x) << (PAGE_SHIFT-10))
> -static int oom_kill_task(struct task_struct *p, struct mem_cgroup *mem)
> +static void oom_kill_task(struct task_struct *p, struct mem_cgroup *mem)
>  {
>  	struct task_struct *q;
>  	struct mm_struct *mm;
>  
>  	p = find_lock_task_mm(p);
>  	if (!p)
> -		return 1;
> +		return;
>  
>  	/* mm cannot be safely dereferenced after task_unlock(p) */
>  	mm = p->mm;
> @@ -477,15 +477,13 @@ static int oom_kill_task(struct task_struct *p, struct mem_cgroup *mem)
>  
>  	set_tsk_thread_flag(p, TIF_MEMDIE);
>  	force_sig(SIGKILL, p);
> -
> -	return 0;
>  }
>  #undef K
>  
> -static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
> -			    unsigned int points, unsigned long totalpages,
> -			    struct mem_cgroup *mem, nodemask_t *nodemask,
> -			    const char *message)
> +static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
> +			     unsigned int points, unsigned long totalpages,
> +			     struct mem_cgroup *mem, nodemask_t *nodemask,
> +			     const char *message)
>  {
>  	struct task_struct *victim = p;
>  	struct task_struct *child;
> @@ -501,7 +499,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
>  	 */
>  	if (p->flags & PF_EXITING) {
>  		set_tsk_thread_flag(p, TIF_MEMDIE);
> -		return 0;
> +		return;
>  	}
>  
>  	task_lock(p);
> @@ -533,7 +531,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
>  		}
>  	} while_each_thread(p, t);
>  
> -	return oom_kill_task(victim, mem);
> +	oom_kill_task(victim, mem);
>  }
>  
>  /*
> @@ -580,15 +578,10 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask)
>  	check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, 0, NULL);
>  	limit = mem_cgroup_get_limit(mem) >> PAGE_SHIFT;
>  	read_lock(&tasklist_lock);
> -retry:
>  	p = select_bad_process(&points, limit, mem, NULL);
> -	if (!p || PTR_ERR(p) == -1UL)
> -		goto out;
> -
> -	if (oom_kill_process(p, gfp_mask, 0, points, limit, mem, NULL,
> -				"Memory cgroup out of memory"))
> -		goto retry;
> -out:
> +	if (p && PTR_ERR(p) != -1UL)
> +		oom_kill_process(p, gfp_mask, 0, points, limit, mem, NULL,
> +				 "Memory cgroup out of memory");
>  	read_unlock(&tasklist_lock);
>  }
>  #endif
> @@ -745,33 +738,24 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
>  	if (sysctl_oom_kill_allocating_task &&
>  	    !oom_unkillable_task(current, NULL, nodemask) &&
>  	    current->mm) {
> -		/*
> -		 * oom_kill_process() needs tasklist_lock held.  If it returns
> -		 * non-zero, current could not be killed so we must fallback to
> -		 * the tasklist scan.
> -		 */
> -		if (!oom_kill_process(current, gfp_mask, order, 0, totalpages,
> -				NULL, nodemask,
> -				"Out of memory (oom_kill_allocating_task)"))
> -			goto out;
> +		oom_kill_process(current, gfp_mask, order, 0, totalpages, NULL,
> +				 nodemask,
> +				 "Out of memory (oom_kill_allocating_task)");
> +		goto out;
>  	}
>  
> -retry:
>  	p = select_bad_process(&points, totalpages, NULL, mpol_mask);
> -	if (PTR_ERR(p) == -1UL)
> -		goto out;
> -
>  	/* Found nothing?!?! Either we hang forever, or we panic. */
>  	if (!p) {
>  		dump_header(NULL, gfp_mask, order, NULL, mpol_mask);
>  		read_unlock(&tasklist_lock);
>  		panic("Out of memory and no killable processes...\n");
>  	}
> -
> -	if (oom_kill_process(p, gfp_mask, order, points, totalpages, NULL,
> -				nodemask, "Out of memory"))
> -		goto retry;
> -	killed = 1;
> +	if (PTR_ERR(p) != -1UL) {
> +		oom_kill_process(p, gfp_mask, order, points, totalpages, NULL,
> +				 nodemask, "Out of memory");
> +		killed = 1;
> +	}
>  out:
>  	read_unlock(&tasklist_lock);
>  
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch 2/3] mm, oom: fold oom_kill_task into oom_kill_process
  2012-01-12  3:24 ` [patch 2/3] mm, oom: fold oom_kill_task into oom_kill_process David Rientjes
  2012-01-12  3:48   ` KOSAKI Motohiro
@ 2012-01-12  4:48   ` KAMEZAWA Hiroyuki
  1 sibling, 0 replies; 13+ messages in thread
From: KAMEZAWA Hiroyuki @ 2012-01-12  4:48 UTC (permalink / raw)
  To: David Rientjes; +Cc: Andrew Morton, KOSAKI Motohiro, linux-mm

On Wed, 11 Jan 2012 19:24:24 -0800 (PST)
David Rientjes <rientjes@google.com> wrote:

> oom_kill_task() has a single caller, so fold it into its parent function,
> oom_kill_process().  Slightly reduces the number of lines in the oom
> killer.
> 
> Signed-off-by: David Rientjes <rientjes@google.com>

Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>


> ---
>  mm/oom_kill.c |   87 ++++++++++++++++++++++++++------------------------------
>  1 files changed, 40 insertions(+), 47 deletions(-)
> 
> diff --git a/mm/oom_kill.c b/mm/oom_kill.c
> --- a/mm/oom_kill.c
> +++ b/mm/oom_kill.c
> @@ -434,52 +434,6 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
>  }
>  
>  #define K(x) ((x) << (PAGE_SHIFT-10))
> -static void oom_kill_task(struct task_struct *p, struct mem_cgroup *mem)
> -{
> -	struct task_struct *q;
> -	struct mm_struct *mm;
> -
> -	p = find_lock_task_mm(p);
> -	if (!p)
> -		return;
> -
> -	/* mm cannot be safely dereferenced after task_unlock(p) */
> -	mm = p->mm;
> -
> -	pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
> -		task_pid_nr(p), p->comm, K(p->mm->total_vm),
> -		K(get_mm_counter(p->mm, MM_ANONPAGES)),
> -		K(get_mm_counter(p->mm, MM_FILEPAGES)));
> -	task_unlock(p);
> -
> -	/*
> -	 * Kill all user processes sharing p->mm in other thread groups, if any.
> -	 * They don't get access to memory reserves or a higher scheduler
> -	 * priority, though, to avoid depletion of all memory or task
> -	 * starvation.  This prevents mm->mmap_sem livelock when an oom killed
> -	 * task 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.
> -	 */
> -	for_each_process(q)
> -		if (q->mm == mm && !same_thread_group(q, p) &&
> -		    !(q->flags & PF_KTHREAD)) {
> -			if (q->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
> -				continue;
> -
> -			task_lock(q);	/* Protect ->comm from prctl() */
> -			pr_err("Kill process %d (%s) sharing same memory\n",
> -				task_pid_nr(q), q->comm);
> -			task_unlock(q);
> -			force_sig(SIGKILL, q);
> -		}
> -
> -	set_tsk_thread_flag(p, TIF_MEMDIE);
> -	force_sig(SIGKILL, p);
> -}
> -#undef K
> -
>  static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
>  			     unsigned int points, unsigned long totalpages,
>  			     struct mem_cgroup *mem, nodemask_t *nodemask,
> @@ -488,6 +442,7 @@ static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
>  	struct task_struct *victim = p;
>  	struct task_struct *child;
>  	struct task_struct *t = p;
> +	struct mm_struct *mm;
>  	unsigned int victim_points = 0;
>  
>  	if (printk_ratelimit())
> @@ -531,8 +486,46 @@ static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
>  		}
>  	} while_each_thread(p, t);
>  
> -	oom_kill_task(victim, mem);
> +	victim = find_lock_task_mm(victim);
> +	if (!victim)
> +		return;
> +
> +	/* mm cannot be safely dereferenced after task_unlock(p) */
> +	mm = victim->mm;
> +
> +	pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
> +		task_pid_nr(victim), victim->comm, K(victim->mm->total_vm),
> +		K(get_mm_counter(victim->mm, MM_ANONPAGES)),
> +		K(get_mm_counter(victim->mm, MM_FILEPAGES)));
> +	task_unlock(victim);
> +
> +	/*
> +	 * Kill all user processes sharing victim->mm in other thread groups, if 
> +	 * any.  They don't get access to memory reserves or a higher scheduler
> +	 * priority, though, to avoid depletion of all memory or task
> +	 * starvation.  This prevents mm->mmap_sem livelock when an oom killed
> +	 * task 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.
> +	 */
> +	for_each_process(p)
> +		if (p->mm == mm && !same_thread_group(p, victim) &&
> +		    !(p->flags & PF_KTHREAD)) {
> +			if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
> +				continue;
> +
> +			task_lock(p);	/* Protect ->comm from prctl() */
> +			pr_err("Kill process %d (%s) sharing same memory\n",
> +				task_pid_nr(p), p->comm);
> +			task_unlock(p);
> +			force_sig(SIGKILL, p);
> +		}
> +
> +	set_tsk_thread_flag(victim, TIF_MEMDIE);
> +	force_sig(SIGKILL, victim);
>  }
> +#undef K
>  
>  /*
>   * Determines whether the kernel must panic because of the panic_on_oom sysctl.
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch 3/3] mm, oom: do not emit oom killer warning if chosen thread is already exiting
  2012-01-12  3:24 ` [patch 3/3] mm, oom: do not emit oom killer warning if chosen thread is already exiting David Rientjes
  2012-01-12  3:48   ` KOSAKI Motohiro
@ 2012-01-12  4:49   ` KAMEZAWA Hiroyuki
  2012-01-12 14:44   ` Michal Hocko
  2 siblings, 0 replies; 13+ messages in thread
From: KAMEZAWA Hiroyuki @ 2012-01-12  4:49 UTC (permalink / raw)
  To: David Rientjes; +Cc: Andrew Morton, KOSAKI Motohiro, linux-mm

On Wed, 11 Jan 2012 19:24:28 -0800 (PST)
David Rientjes <rientjes@google.com> wrote:

> If a thread is chosen for oom kill and is already PF_EXITING, then the
> oom killer simply sets TIF_MEMDIE and returns.  This allows the thread to
> have access to memory reserves so that it may quickly exit.  This logic
> is preceeded with a comment saying there's no need to alarm the sysadmin.
> This patch adds truth to that statement.
> 
> There's no need to emit any warning about the oom condition if the thread
> is already exiting since it will not be killed.  In this condition, just
> silently return the oom killer since its only giving access to memory
> reserves and is otherwise a no-op.
> 
> Signed-off-by: David Rientjes <rientjes@google.com>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch 1/3] mm, oom: avoid looping when chosen thread detaches its mm
  2012-01-12  3:24 [patch 1/3] mm, oom: avoid looping when chosen thread detaches its mm David Rientjes
                   ` (2 preceding siblings ...)
  2012-01-12  4:47 ` [patch 1/3] mm, oom: avoid looping when chosen thread detaches its mm KAMEZAWA Hiroyuki
@ 2012-01-12 14:26 ` Michal Hocko
  2012-01-14  0:39 ` [patch -mm " David Rientjes
  4 siblings, 0 replies; 13+ messages in thread
From: Michal Hocko @ 2012-01-12 14:26 UTC (permalink / raw)
  To: David Rientjes
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, KOSAKI Motohiro, linux-mm

On Wed 11-01-12 19:24:20, David Rientjes wrote:
> oom_kill_task() returns non-zero iff the chosen process does not have any
> threads with an attached ->mm.
> 
> In such a case, it's better to just return to the page allocator and
> retry the allocation because memory could have been freed in the interim
> and the oom condition may no longer exist.  It's unnecessary to loop in
> the oom killer and find another thread to kill.
> 
> This allows both oom_kill_task() and oom_kill_process() to be converted
> to void functions.  If the oom condition persists, the oom killer will be
> recalled.
> 
> Signed-off-by: David Rientjes <rientjes@google.com>

Makes sense and the code is easier to read
Reviewed-by: Michal Hocko <mhocko@suse.cz>

Thanks
> ---
>  mm/oom_kill.c |   56 ++++++++++++++++++++------------------------------------
>  1 files changed, 20 insertions(+), 36 deletions(-)
> 
> diff --git a/mm/oom_kill.c b/mm/oom_kill.c
> --- a/mm/oom_kill.c
> +++ b/mm/oom_kill.c
> @@ -434,14 +434,14 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
>  }
>  
>  #define K(x) ((x) << (PAGE_SHIFT-10))
> -static int oom_kill_task(struct task_struct *p, struct mem_cgroup *mem)
> +static void oom_kill_task(struct task_struct *p, struct mem_cgroup *mem)
>  {
>  	struct task_struct *q;
>  	struct mm_struct *mm;
>  
>  	p = find_lock_task_mm(p);
>  	if (!p)
> -		return 1;
> +		return;
>  
>  	/* mm cannot be safely dereferenced after task_unlock(p) */
>  	mm = p->mm;
> @@ -477,15 +477,13 @@ static int oom_kill_task(struct task_struct *p, struct mem_cgroup *mem)
>  
>  	set_tsk_thread_flag(p, TIF_MEMDIE);
>  	force_sig(SIGKILL, p);
> -
> -	return 0;
>  }
>  #undef K
>  
> -static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
> -			    unsigned int points, unsigned long totalpages,
> -			    struct mem_cgroup *mem, nodemask_t *nodemask,
> -			    const char *message)
> +static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
> +			     unsigned int points, unsigned long totalpages,
> +			     struct mem_cgroup *mem, nodemask_t *nodemask,
> +			     const char *message)
>  {
>  	struct task_struct *victim = p;
>  	struct task_struct *child;
> @@ -501,7 +499,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
>  	 */
>  	if (p->flags & PF_EXITING) {
>  		set_tsk_thread_flag(p, TIF_MEMDIE);
> -		return 0;
> +		return;
>  	}
>  
>  	task_lock(p);
> @@ -533,7 +531,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
>  		}
>  	} while_each_thread(p, t);
>  
> -	return oom_kill_task(victim, mem);
> +	oom_kill_task(victim, mem);
>  }
>  
>  /*
> @@ -580,15 +578,10 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask)
>  	check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, 0, NULL);
>  	limit = mem_cgroup_get_limit(mem) >> PAGE_SHIFT;
>  	read_lock(&tasklist_lock);
> -retry:
>  	p = select_bad_process(&points, limit, mem, NULL);
> -	if (!p || PTR_ERR(p) == -1UL)
> -		goto out;
> -
> -	if (oom_kill_process(p, gfp_mask, 0, points, limit, mem, NULL,
> -				"Memory cgroup out of memory"))
> -		goto retry;
> -out:
> +	if (p && PTR_ERR(p) != -1UL)
> +		oom_kill_process(p, gfp_mask, 0, points, limit, mem, NULL,
> +				 "Memory cgroup out of memory");
>  	read_unlock(&tasklist_lock);
>  }
>  #endif
> @@ -745,33 +738,24 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
>  	if (sysctl_oom_kill_allocating_task &&
>  	    !oom_unkillable_task(current, NULL, nodemask) &&
>  	    current->mm) {
> -		/*
> -		 * oom_kill_process() needs tasklist_lock held.  If it returns
> -		 * non-zero, current could not be killed so we must fallback to
> -		 * the tasklist scan.
> -		 */
> -		if (!oom_kill_process(current, gfp_mask, order, 0, totalpages,
> -				NULL, nodemask,
> -				"Out of memory (oom_kill_allocating_task)"))
> -			goto out;
> +		oom_kill_process(current, gfp_mask, order, 0, totalpages, NULL,
> +				 nodemask,
> +				 "Out of memory (oom_kill_allocating_task)");
> +		goto out;
>  	}
>  
> -retry:
>  	p = select_bad_process(&points, totalpages, NULL, mpol_mask);
> -	if (PTR_ERR(p) == -1UL)
> -		goto out;
> -
>  	/* Found nothing?!?! Either we hang forever, or we panic. */
>  	if (!p) {
>  		dump_header(NULL, gfp_mask, order, NULL, mpol_mask);
>  		read_unlock(&tasklist_lock);
>  		panic("Out of memory and no killable processes...\n");
>  	}
> -
> -	if (oom_kill_process(p, gfp_mask, order, points, totalpages, NULL,
> -				nodemask, "Out of memory"))
> -		goto retry;
> -	killed = 1;
> +	if (PTR_ERR(p) != -1UL) {
> +		oom_kill_process(p, gfp_mask, order, points, totalpages, NULL,
> +				 nodemask, "Out of memory");
> +		killed = 1;
> +	}
>  out:
>  	read_unlock(&tasklist_lock);
>  
> 
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo@kvack.org.  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
> Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

-- 
Michal Hocko
SUSE Labs
SUSE LINUX s.r.o.
Lihovarska 1060/12
190 00 Praha 9    
Czech Republic

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch 3/3] mm, oom: do not emit oom killer warning if chosen thread is already exiting
  2012-01-12  3:24 ` [patch 3/3] mm, oom: do not emit oom killer warning if chosen thread is already exiting David Rientjes
  2012-01-12  3:48   ` KOSAKI Motohiro
  2012-01-12  4:49   ` KAMEZAWA Hiroyuki
@ 2012-01-12 14:44   ` Michal Hocko
  2 siblings, 0 replies; 13+ messages in thread
From: Michal Hocko @ 2012-01-12 14:44 UTC (permalink / raw)
  To: David Rientjes
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, KOSAKI Motohiro, linux-mm

On Wed 11-01-12 19:24:28, David Rientjes wrote:
> If a thread is chosen for oom kill and is already PF_EXITING, then the
> oom killer simply sets TIF_MEMDIE and returns.  This allows the thread to
> have access to memory reserves so that it may quickly exit.  This logic
> is preceeded with a comment saying there's no need to alarm the sysadmin.
> This patch adds truth to that statement.
> 
> There's no need to emit any warning about the oom condition if the thread
> is already exiting since it will not be killed.  In this condition, just
> silently return the oom killer since its only giving access to memory
> reserves and is otherwise a no-op.

Definitely

Reviewed-by: Michal Hocko <mhocko@suse.cz>

> 
> Signed-off-by: David Rientjes <rientjes@google.com>
> ---
>  mm/oom_kill.c |    6 +++---
>  1 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/mm/oom_kill.c b/mm/oom_kill.c
> --- a/mm/oom_kill.c
> +++ b/mm/oom_kill.c
> @@ -445,9 +445,6 @@ static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
>  	struct mm_struct *mm;
>  	unsigned int victim_points = 0;
>  
> -	if (printk_ratelimit())
> -		dump_header(p, gfp_mask, order, mem, nodemask);
> -
>  	/*
>  	 * 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
> @@ -457,6 +454,9 @@ static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
>  		return;
>  	}
>  
> +	if (printk_ratelimit())
> +		dump_header(p, gfp_mask, order, mem, nodemask);
> +
>  	task_lock(p);
>  	pr_err("%s: Kill process %d (%s) score %d or sacrifice child\n",
>  		message, task_pid_nr(p), p->comm, points);
> 
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo@kvack.org.  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
> Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

-- 
Michal Hocko
SUSE Labs
SUSE LINUX s.r.o.
Lihovarska 1060/12
190 00 Praha 9    
Czech Republic

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch -mm 1/3] mm, oom: avoid looping when chosen thread detaches its mm
  2012-01-12  3:24 [patch 1/3] mm, oom: avoid looping when chosen thread detaches its mm David Rientjes
                   ` (3 preceding siblings ...)
  2012-01-12 14:26 ` Michal Hocko
@ 2012-01-14  0:39 ` David Rientjes
  2012-01-14  0:39   ` [patch -mm 2/3] mm, oom: fold oom_kill_task into oom_kill_process David Rientjes
  2012-01-14  0:39   ` [patch -mm 3/3] mm, oom: do not emit oom killer warning if chosen thread is already exiting David Rientjes
  4 siblings, 2 replies; 13+ messages in thread
From: David Rientjes @ 2012-01-14  0:39 UTC (permalink / raw)
  To: Andrew Morton; +Cc: KAMEZAWA Hiroyuki, KOSAKI Motohiro, linux-mm

oom_kill_task() returns non-zero iff the chosen process does not have any
threads with an attached ->mm.

In such a case, it's better to just return to the page allocator and
retry the allocation because memory could have been freed in the interim
and the oom condition may no longer exist.  It's unnecessary to loop in
the oom killer and find another thread to kill.

This allows both oom_kill_task() and oom_kill_process() to be converted
to void functions.  If the oom condition persists, the oom killer will be
recalled.

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: David Rientjes <rientjes@google.com>
---
 rebased to next-20120113

 mm/oom_kill.c |   56 ++++++++++++++++++++------------------------------------
 1 files changed, 20 insertions(+), 36 deletions(-)

diff --git a/mm/oom_kill.c b/mm/oom_kill.c
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -434,14 +434,14 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
 }
 
 #define K(x) ((x) << (PAGE_SHIFT-10))
-static int oom_kill_task(struct task_struct *p)
+static void oom_kill_task(struct task_struct *p)
 {
 	struct task_struct *q;
 	struct mm_struct *mm;
 
 	p = find_lock_task_mm(p);
 	if (!p)
-		return 1;
+		return;
 
 	/* mm cannot be safely dereferenced after task_unlock(p) */
 	mm = p->mm;
@@ -477,15 +477,13 @@ static int oom_kill_task(struct task_struct *p)
 
 	set_tsk_thread_flag(p, TIF_MEMDIE);
 	force_sig(SIGKILL, p);
-
-	return 0;
 }
 #undef K
 
-static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
-			    unsigned int points, unsigned long totalpages,
-			    struct mem_cgroup *memcg, nodemask_t *nodemask,
-			    const char *message)
+static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
+			     unsigned int points, unsigned long totalpages,
+			     struct mem_cgroup *memcg, nodemask_t *nodemask,
+			     const char *message)
 {
 	struct task_struct *victim = p;
 	struct task_struct *child;
@@ -501,7 +499,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 	 */
 	if (p->flags & PF_EXITING) {
 		set_tsk_thread_flag(p, TIF_MEMDIE);
-		return 0;
+		return;
 	}
 
 	task_lock(p);
@@ -533,7 +531,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 		}
 	} while_each_thread(p, t);
 
-	return oom_kill_task(victim);
+	oom_kill_task(victim);
 }
 
 /*
@@ -580,15 +578,10 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask)
 	check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, 0, NULL);
 	limit = mem_cgroup_get_limit(memcg) >> PAGE_SHIFT;
 	read_lock(&tasklist_lock);
-retry:
 	p = select_bad_process(&points, limit, memcg, NULL);
-	if (!p || PTR_ERR(p) == -1UL)
-		goto out;
-
-	if (oom_kill_process(p, gfp_mask, 0, points, limit, memcg, NULL,
-				"Memory cgroup out of memory"))
-		goto retry;
-out:
+	if (p && PTR_ERR(p) != -1UL)
+		oom_kill_process(p, gfp_mask, 0, points, limit, memcg, NULL,
+				 "Memory cgroup out of memory");
 	read_unlock(&tasklist_lock);
 }
 #endif
@@ -745,33 +738,24 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
 	if (sysctl_oom_kill_allocating_task &&
 	    !oom_unkillable_task(current, NULL, nodemask) &&
 	    current->mm) {
-		/*
-		 * oom_kill_process() needs tasklist_lock held.  If it returns
-		 * non-zero, current could not be killed so we must fallback to
-		 * the tasklist scan.
-		 */
-		if (!oom_kill_process(current, gfp_mask, order, 0, totalpages,
-				NULL, nodemask,
-				"Out of memory (oom_kill_allocating_task)"))
-			goto out;
+		oom_kill_process(current, gfp_mask, order, 0, totalpages, NULL,
+				 nodemask,
+				 "Out of memory (oom_kill_allocating_task)");
+		goto out;
 	}
 
-retry:
 	p = select_bad_process(&points, totalpages, NULL, mpol_mask);
-	if (PTR_ERR(p) == -1UL)
-		goto out;
-
 	/* Found nothing?!?! Either we hang forever, or we panic. */
 	if (!p) {
 		dump_header(NULL, gfp_mask, order, NULL, mpol_mask);
 		read_unlock(&tasklist_lock);
 		panic("Out of memory and no killable processes...\n");
 	}
-
-	if (oom_kill_process(p, gfp_mask, order, points, totalpages, NULL,
-				nodemask, "Out of memory"))
-		goto retry;
-	killed = 1;
+	if (PTR_ERR(p) != -1UL) {
+		oom_kill_process(p, gfp_mask, order, points, totalpages, NULL,
+				 nodemask, "Out of memory");
+		killed = 1;
+	}
 out:
 	read_unlock(&tasklist_lock);
 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch -mm 2/3] mm, oom: fold oom_kill_task into oom_kill_process
  2012-01-14  0:39 ` [patch -mm " David Rientjes
@ 2012-01-14  0:39   ` David Rientjes
  2012-01-14  0:39   ` [patch -mm 3/3] mm, oom: do not emit oom killer warning if chosen thread is already exiting David Rientjes
  1 sibling, 0 replies; 13+ messages in thread
From: David Rientjes @ 2012-01-14  0:39 UTC (permalink / raw)
  To: Andrew Morton; +Cc: KAMEZAWA Hiroyuki, KOSAKI Motohiro, linux-mm

oom_kill_task() has a single caller, so fold it into its parent function,
oom_kill_process().  Slightly reduces the number of lines in the oom
killer.

Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: David Rientjes <rientjes@google.com>
---
 mm/oom_kill.c |   85 +++++++++++++++++++++++++-------------------------------
 1 files changed, 38 insertions(+), 47 deletions(-)

diff --git a/mm/oom_kill.c b/mm/oom_kill.c
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -434,52 +434,6 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
 }
 
 #define K(x) ((x) << (PAGE_SHIFT-10))
-static void oom_kill_task(struct task_struct *p)
-{
-	struct task_struct *q;
-	struct mm_struct *mm;
-
-	p = find_lock_task_mm(p);
-	if (!p)
-		return;
-
-	/* mm cannot be safely dereferenced after task_unlock(p) */
-	mm = p->mm;
-
-	pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
-		task_pid_nr(p), p->comm, K(p->mm->total_vm),
-		K(get_mm_counter(p->mm, MM_ANONPAGES)),
-		K(get_mm_counter(p->mm, MM_FILEPAGES)));
-	task_unlock(p);
-
-	/*
-	 * Kill all user processes sharing p->mm in other thread groups, if any.
-	 * They don't get access to memory reserves or a higher scheduler
-	 * priority, though, to avoid depletion of all memory or task
-	 * starvation.  This prevents mm->mmap_sem livelock when an oom killed
-	 * task 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.
-	 */
-	for_each_process(q)
-		if (q->mm == mm && !same_thread_group(q, p) &&
-		    !(q->flags & PF_KTHREAD)) {
-			if (q->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
-				continue;
-
-			task_lock(q);	/* Protect ->comm from prctl() */
-			pr_err("Kill process %d (%s) sharing same memory\n",
-				task_pid_nr(q), q->comm);
-			task_unlock(q);
-			force_sig(SIGKILL, q);
-		}
-
-	set_tsk_thread_flag(p, TIF_MEMDIE);
-	force_sig(SIGKILL, p);
-}
-#undef K
-
 static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 			     unsigned int points, unsigned long totalpages,
 			     struct mem_cgroup *memcg, nodemask_t *nodemask,
@@ -488,6 +442,7 @@ static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 	struct task_struct *victim = p;
 	struct task_struct *child;
 	struct task_struct *t = p;
+	struct mm_struct *mm;
 	unsigned int victim_points = 0;
 
 	if (printk_ratelimit())
@@ -531,8 +486,44 @@ static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 		}
 	} while_each_thread(p, t);
 
-	oom_kill_task(victim);
+	victim = find_lock_task_mm(victim);
+	if (!victim)
+		return;
+
+	/* mm cannot safely be dereferenced after task_unlock(victim) */
+	mm = victim->mm;
+	pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
+		task_pid_nr(victim), victim->comm, K(victim->mm->total_vm),
+		K(get_mm_counter(victim->mm, MM_ANONPAGES)),
+		K(get_mm_counter(victim->mm, MM_FILEPAGES)));
+	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.
+	 */
+	for_each_process(p)
+		if (p->mm == mm && !same_thread_group(p, victim) &&
+		    !(p->flags & PF_KTHREAD)) {
+			if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
+				continue;
+
+			task_lock(p);	/* Protect ->comm from prctl() */
+			pr_err("Kill process %d (%s) sharing same memory\n",
+				task_pid_nr(p), p->comm);
+			task_unlock(p);
+			force_sig(SIGKILL, p);
+		}
+
+	set_tsk_thread_flag(victim, TIF_MEMDIE);
+	force_sig(SIGKILL, victim);
 }
+#undef K
 
 /*
  * Determines whether the kernel must panic because of the panic_on_oom sysctl.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch -mm 3/3] mm, oom: do not emit oom killer warning if chosen thread is already exiting
  2012-01-14  0:39 ` [patch -mm " David Rientjes
  2012-01-14  0:39   ` [patch -mm 2/3] mm, oom: fold oom_kill_task into oom_kill_process David Rientjes
@ 2012-01-14  0:39   ` David Rientjes
  1 sibling, 0 replies; 13+ messages in thread
From: David Rientjes @ 2012-01-14  0:39 UTC (permalink / raw)
  To: Andrew Morton; +Cc: KAMEZAWA Hiroyuki, KOSAKI Motohiro, linux-mm

If a thread is chosen for oom kill and is already PF_EXITING, then the
oom killer simply sets TIF_MEMDIE and returns.  This allows the thread to
have access to memory reserves so that it may quickly exit.  This logic
is preceeded with a comment saying there's no need to alarm the sysadmin.
This patch adds truth to that statement.

There's no need to emit any warning about the oom condition if the thread
is already exiting since it will not be killed.  In this condition, just
silently return the oom killer since its only giving access to memory
reserves and is otherwise a no-op.

Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: David Rientjes <rientjes@google.com>
---
 mm/oom_kill.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/mm/oom_kill.c b/mm/oom_kill.c
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -445,9 +445,6 @@ static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 	struct mm_struct *mm;
 	unsigned int victim_points = 0;
 
-	if (printk_ratelimit())
-		dump_header(p, gfp_mask, order, memcg, nodemask);
-
 	/*
 	 * 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
@@ -457,6 +454,9 @@ static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 		return;
 	}
 
+	if (printk_ratelimit())
+		dump_header(p, gfp_mask, order, memcg, nodemask);
+
 	task_lock(p);
 	pr_err("%s: Kill process %d (%s) score %d or sacrifice child\n",
 		message, task_pid_nr(p), p->comm, points);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2012-01-14  0:39 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-12  3:24 [patch 1/3] mm, oom: avoid looping when chosen thread detaches its mm David Rientjes
2012-01-12  3:24 ` [patch 2/3] mm, oom: fold oom_kill_task into oom_kill_process David Rientjes
2012-01-12  3:48   ` KOSAKI Motohiro
2012-01-12  4:48   ` KAMEZAWA Hiroyuki
2012-01-12  3:24 ` [patch 3/3] mm, oom: do not emit oom killer warning if chosen thread is already exiting David Rientjes
2012-01-12  3:48   ` KOSAKI Motohiro
2012-01-12  4:49   ` KAMEZAWA Hiroyuki
2012-01-12 14:44   ` Michal Hocko
2012-01-12  4:47 ` [patch 1/3] mm, oom: avoid looping when chosen thread detaches its mm KAMEZAWA Hiroyuki
2012-01-12 14:26 ` Michal Hocko
2012-01-14  0:39 ` [patch -mm " David Rientjes
2012-01-14  0:39   ` [patch -mm 2/3] mm, oom: fold oom_kill_task into oom_kill_process David Rientjes
2012-01-14  0:39   ` [patch -mm 3/3] mm, oom: do not emit oom killer warning if chosen thread is already exiting David Rientjes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).