[Devel] [PATCH RHEL7 COMMIT] ms/oom: make sure that TIF_MEMDIE is set under task_lock

Konstantin Khorenko khorenko at virtuozzo.com
Thu Oct 15 06:47:34 PDT 2015


The commit is pushed to "branch-rh7-3.10.0-229.7.2.vz7.8.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-229.7.2.vz7.8.6
------>
commit 82d2c87b0e1ecd58487d26f479142a3517cffc44
Author: Vladimir Davydov <vdavydov at parallels.com>
Date:   Thu Oct 15 17:47:34 2015 +0400

    ms/oom: make sure that TIF_MEMDIE is set under task_lock
    
    Patchset description: oom enhancements - part 1
    
    Pull mainstream patches that clean up TIF_MEMDIE handling. They will
    come in handy for the upcoming oom rework.
    
    https://jira.sw.ru/browse/PSBM-26973
    
    David Rientjes (1):
      mm, oom: remove unnecessary exit_state check
    
    Johannes Weiner (1):
      mm: oom_kill: clean up victim marking and exiting interfaces
    
    Michal Hocko (3):
      oom: make sure that TIF_MEMDIE is set under task_lock
      oom: add helpers for setting and clearing TIF_MEMDIE
      oom: thaw the OOM victim if it is frozen
    
    Tetsuo Handa (1):
      oom: don't count on mm-less current process
    
    ===============================================
    This patch desciption:
    
    From: Michal Hocko <mhocko at suse.cz>
    
    OOM killer tries to exclude tasks which do not have mm_struct associated
    because killing such a task wouldn't help much.  The OOM victim gets
    TIF_MEMDIE set to disable OOM killer while the current victim releases the
    memory and then enables the OOM killer again by dropping the flag.
    
    oom_kill_process is currently prone to a race condition when the OOM
    victim is already exiting and TIF_MEMDIE is set after the task releases
    its address space.  This might theoretically lead to OOM livelock if the
    OOM victim blocks on an allocation later during exiting because it
    wouldn't kill any other process and the exiting one won't be able to exit.
     The situation is highly unlikely because the OOM victim is expected to
    release some memory which should help to sort out OOM situation.
    
    Fix this by checking task->mm and setting TIF_MEMDIE flag under task_lock
    which will serialize the OOM killer with exit_mm which sets task->mm to
    NULL.  Setting the flag for current is not necessary because check and set
    is not racy.
    
    Reported-by: Tetsuo Handa <penguin-kernel at I-love.SAKURA.ne.jp>
    Signed-off-by: Michal Hocko <mhocko at suse.cz>
    Cc: David Rientjes <rientjes at google.com>
    Cc: Oleg Nesterov <oleg at redhat.com>
    Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
    (cherry picked from commit 83363b917a2982dd509a5e2125e905b6873505a3)
    Signed-off-by: Vladimir Davydov <vdavydov at parallels.com>
    
    Reviewed-by: Kirill Tkhai <ktkhai at odin.com>
    
    Conflicts:
    	mm/oom_kill.c
---
 mm/oom_kill.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index fd9e13d..5ac5d96 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -432,11 +432,14 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 	 * 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
 	 */
-	if (p->flags & PF_EXITING) {
+	task_lock(p);
+	if (p->mm && p->flags & PF_EXITING) {
 		set_tsk_thread_flag(p, TIF_MEMDIE);
+		task_unlock(p);
 		put_task_struct(p);
 		return;
 	}
+	task_unlock(p);
 
 	if (__ratelimit(&oom_rs))
 		dump_header(p, gfp_mask, order, memcg, nodemask);
@@ -486,6 +489,7 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 
 	/* mm cannot safely be dereferenced after task_unlock(victim) */
 	mm = victim->mm;
+	set_tsk_thread_flag(victim, TIF_MEMDIE);
 	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)),
@@ -517,7 +521,6 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 		}
 	rcu_read_unlock();
 
-	set_tsk_thread_flag(victim, TIF_MEMDIE);
 	do_send_sig_info(SIGKILL, SEND_SIG_FORCED, victim, true);
 	mem_cgroup_note_oom_kill(memcg, victim);
 	put_task_struct(victim);



More information about the Devel mailing list