From a7af91adc7c6fc3240b2de0dac04d8a37b6d1a16 Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Tue, 1 May 2018 20:20:20 +0530 Subject: [PATCH] ANDROID: mm: oom_kill: reap memory of a task that receives SIGKILL Free the pages parallely for a task that receives SIGKILL, from ULMK process, using the oom_reaper. This freeing of pages will help to give the pages to buddy system well advance. Add the boot param, reap_mem_when_killed_by=, that configures the process name, the kill signal to a process from which makes its memory reaped by oom reaper. As an example, when reap_mem_when_killed_by=lmkd, then all the processes that receives the kill signal from lmkd is added to oom reaper. Not initializing this param makes this feature disabled. Change-Id: I21adb95de5e380a80d7eb0b87d9b5b553f52e28a Bug: 171763461 Signed-off-by: Charan Teja Reddy Signed-off-by: Isaac J. Manjarres --- .../admin-guide/kernel-parameters.txt | 4 +++ include/linux/oom.h | 3 ++ kernel/signal.c | 19 +++++++++- mm/oom_kill.c | 36 +++++++++++++++---- 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index b885bbf9c8fd..b8fa20236da0 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -4604,6 +4604,10 @@ (that will set all pages holding image data during restoration read-only). + reap_mem_when_killed_by= + The name of a process, the kill signal from which to a process + make its memory reaped with oom reaper. + retain_initrd [RAM] Keep initrd memory after extraction rfkill.default_state= diff --git a/include/linux/oom.h b/include/linux/oom.h index 2db9a1432511..b52ce6cfd687 100644 --- a/include/linux/oom.h +++ b/include/linux/oom.h @@ -127,4 +127,7 @@ extern struct task_struct *find_lock_task_mm(struct task_struct *p); extern int sysctl_oom_dump_tasks; extern int sysctl_oom_kill_allocating_task; extern int sysctl_panic_on_oom; + +/* calls for LMK reaper */ +extern void add_to_oom_reaper(struct task_struct *p); #endif /* _INCLUDE_LINUX_OOM_H */ diff --git a/kernel/signal.c b/kernel/signal.c index dd83edcfaf0a..5a4d060270ec 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -46,6 +46,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -64,6 +65,18 @@ static struct kmem_cache *sigqueue_cachep; int print_fatal_signals __read_mostly; +static char reaper_comm[TASK_COMM_LEN]; + +static __init int setup_mem_reap(char *str) +{ + if (!str) + return 0; + strlcpy(reaper_comm, str, TASK_COMM_LEN); + + return 1; +} +__setup("reap_mem_when_killed_by=", setup_mem_reap); + static void __user *sig_handler(struct task_struct *t, int sig) { return t->sighand->action[sig - 1].sa.sa_handler; @@ -1411,8 +1424,12 @@ int group_send_sig_info(int sig, struct kernel_siginfo *info, ret = check_kill_permission(sig, info, p); rcu_read_unlock(); - if (!ret && sig) + if (!ret && sig) { ret = do_send_sig_info(sig, info, p, type); + if (!ret && sig == SIGKILL && + !strcmp(current->comm, reaper_comm)) + add_to_oom_reaper(p); + } return ret; } diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 8b84661a6410..32e25247f846 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -685,6 +685,20 @@ static inline void wake_oom_reaper(struct task_struct *tsk) } #endif /* CONFIG_MMU */ +/** + * tsk->mm has to be non NULL and caller has to guarantee it is stable (either + * under task_lock or operate on the current). + */ +static void __mark_oom_victim(struct task_struct *tsk) +{ + struct mm_struct *mm = tsk->mm; + + if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm)) { + mmgrab(tsk->signal->oom_mm); + set_bit(MMF_OOM_VICTIM, &mm->flags); + } +} + /** * mark_oom_victim - mark the given task as OOM victim * @tsk: task to mark @@ -697,18 +711,13 @@ static inline void wake_oom_reaper(struct task_struct *tsk) */ static void mark_oom_victim(struct task_struct *tsk) { - struct mm_struct *mm = tsk->mm; - WARN_ON(oom_killer_disabled); /* OOM killer might race with memcg OOM */ if (test_and_set_tsk_thread_flag(tsk, TIF_MEMDIE)) return; /* oom_mm is bound to the signal struct life time. */ - if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm)) { - mmgrab(tsk->signal->oom_mm); - set_bit(MMF_OOM_VICTIM, &mm->flags); - } + __mark_oom_victim(tsk); /* * Make sure that the task is woken up from uninterruptible sleep @@ -1140,3 +1149,18 @@ void pagefault_out_of_memory(void) out_of_memory(&oc); mutex_unlock(&oom_lock); } + +void add_to_oom_reaper(struct task_struct *p) +{ + p = find_lock_task_mm(p); + if (!p) + return; + + get_task_struct(p); + if (task_will_free_mem(p)) { + __mark_oom_victim(p); + wake_oom_reaper(p); + } + task_unlock(p); + put_task_struct(p); +}