aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
authorDavid Rientjes <rientjes@google.com>2013-04-29 18:08:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-29 18:54:39 -0400
commit465adcf1ea7b2e49b2e0899366624f5532b64012 (patch)
tree7a72aacfc3a84f23f5c66662c2cf24f710f1853b /mm/memcontrol.c
parent5918d10a4bb1081920a04e2c17197a02ff06e651 (diff)
mm, memcg: give exiting processes access to memory reserves
A memcg may livelock when oom if the process that grabs the hierarchy's oom lock is never the first process with PF_EXITING set in the memcg's task iteration. The oom killer, both global and memcg, will defer if it finds an eligible process that is in the process of exiting and it is not being ptraced. The idea is to allow it to exit without using memory reserves before needlessly killing another process. This normally works fine except in the memcg case with a large number of threads attached to the oom memcg. In this case, the memcg oom killer only gets called for the process that grabs the hierarchy's oom lock; all others end up blocked on the memcg's oom waitqueue. Thus, if the process that grabs the hierarchy's oom lock is never the first PF_EXITING process in the memcg's task iteration, the oom killer is constantly deferred without anything making progress. The fix is to give PF_EXITING processes access to memory reserves so that we've marked them as oom killed without any iteration. This allows __mem_cgroup_try_charge() to succeed so that the process may exit. This makes the memcg oom killer exemption for TIF_MEMDIE tasks, now immediately granted for processes with pending SIGKILLs and those in the exit path, to be equivalent to what is done for the global oom killer. Signed-off-by: David Rientjes <rientjes@google.com> Acked-by: Michal Hocko <mhocko@suse.cz> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r--mm/memcontrol.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index c92bcfc5466e..47b36fea7e1f 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1787,11 +1787,11 @@ static void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
1787 struct task_struct *chosen = NULL; 1787 struct task_struct *chosen = NULL;
1788 1788
1789 /* 1789 /*
1790 * If current has a pending SIGKILL, then automatically select it. The 1790 * If current has a pending SIGKILL or is exiting, then automatically
1791 * goal is to allow it to allocate so that it may quickly exit and free 1791 * select it. The goal is to allow it to allocate so that it may
1792 * its memory. 1792 * quickly exit and free its memory.
1793 */ 1793 */
1794 if (fatal_signal_pending(current)) { 1794 if (fatal_signal_pending(current) || current->flags & PF_EXITING) {
1795 set_thread_flag(TIF_MEMDIE); 1795 set_thread_flag(TIF_MEMDIE);
1796 return; 1796 return;
1797 } 1797 }