psi:kernel:oom reaper porting into samsung platform
authorwangwang <wangwang1@lenovo.com>
Wed, 13 Nov 2019 06:04:33 +0000 (14:04 +0800)
committerwangwang <wangwang1@lenovo.com>
Wed, 13 Nov 2019 06:04:33 +0000 (14:04 +0800)
reaper can help to reclaim the memory in time, the knob will be set to true
when init parses the init.rc conf file.

Change-Id: I59f1173c0e46202904da6eeacb2fecc32c53232c

Documentation/sysctl/vm.txt
include/linux/oom.h
kernel/signal.c
kernel/sysctl.c
mm/oom_kill.c

index 1d1f2cb5abc85f9055261470e8e28b8cd482ed95..b60e950d3a6a07509fe6015c9235cb3270bd5bb0 100644 (file)
@@ -50,6 +50,7 @@ Currently, these files are in /proc/sys/vm:
 - nr_trim_pages         (only if CONFIG_MMU=n)
 - numa_zonelist_order
 - oom_dump_tasks
+- reap_mem_on_sigkill
 - oom_kill_allocating_task
 - overcommit_kbytes
 - overcommit_memory
@@ -656,6 +657,24 @@ The default value is 1 (enabled).
 
 ==============================================================
 
+reap_mem_on_sigkill
+
+This enables or disables the memory reaping for a SIGKILL received
+process and that the sending process must have the CAP_KILL capabilities.
+
+If this is set to 1, when a process receives SIGKILL from a process
+that has the capability, CAP_KILL, the process is added into the oom_reaper
+queue which can be picked up by the oom_reaper thread to reap the memory of
+that process. This reaps for the process which received SIGKILL through
+either sys_kill from user or kill_pid from kernel.
+
+If this is set to 0, we are not reaping memory of a SIGKILL, sent through
+either sys_kill from user or kill_pid from kernel, received process.
+
+The default value is 0 (disabled).
+
+==============================================================
+
 oom_kill_allocating_task
 
 This enables or disables killing the OOM-triggering task in
index 6adac113e96d29b5059ed65ac0522237c9b94388..1aa1b5133da0562be4bdb7cf92b16638c845f3e6 100644 (file)
@@ -117,4 +117,8 @@ 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;
+extern int sysctl_reap_mem_on_sigkill;
+
+/* calls for LMK reaper */
+extern void add_to_oom_reaper(struct task_struct *p);
 #endif /* _INCLUDE_LINUX_OOM_H */
index 619c6160f64f6bbc395a4fcb68407006c217455b..5da5b95e006a3d5107bd4496e60b1dd200d7cde6 100644 (file)
@@ -40,6 +40,8 @@
 #include <linux/cn_proc.h>
 #include <linux/compiler.h>
 #include <linux/posix-timers.h>
+#include <linux/oom.h>
+#include <linux/capability.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/signal.h>
@@ -1326,8 +1328,11 @@ int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
        ret = check_kill_permission(sig, info, p);
        rcu_read_unlock();
 
-       if (!ret && sig)
+       if (!ret && sig) {
                ret = do_send_sig_info(sig, info, p, true);
+               if (capable(CAP_KILL) && sig == SIGKILL)
+                       add_to_oom_reaper(p);
+       }
 
        return ret;
 }
index 12d8cdce48c0fd2e55ed28d4ce2fcacc9e708d84..d3d2d466b5285f03691bf582d431aa48c752ab4a 100644 (file)
@@ -1298,6 +1298,13 @@ static struct ctl_table vm_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
+       {
+               .procname       = "reap_mem_on_sigkill",
+               .data           = &sysctl_reap_mem_on_sigkill,
+               .maxlen         = sizeof(sysctl_reap_mem_on_sigkill),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
        {
                .procname       = "overcommit_ratio",
                .data           = &sysctl_overcommit_ratio,
index fe0aac2348e52ea8a661a8c7f03a689e93dae117..da605357f99ba36d8b4490f79ecfe92a435079dc 100644 (file)
@@ -51,6 +51,7 @@
 int sysctl_panic_on_oom;
 int sysctl_oom_kill_allocating_task;
 int sysctl_oom_dump_tasks = 1;
+int sysctl_reap_mem_on_sigkill;
 
 DEFINE_MUTEX(oom_lock);
 
@@ -627,14 +628,22 @@ static void wake_oom_reaper(struct task_struct *tsk)
 {
        if (!oom_reaper_th)
                return;
+    /*
+     * Move the lock here to avoid scenario of queuing
+     * the same task by both OOM killer and any other SIGKILL
+     * path.
+     */        
+
+    spin_lock(&oom_reaper_lock);
 
        /* mm is already queued? */
-       if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags))
+       if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags)) {
+        spin_unlock(&oom_reaper_lock);
                return;
+    }
 
        get_task_struct(tsk);
 
-       spin_lock(&oom_reaper_lock);
        tsk->oom_reaper_list = oom_reaper_list;
        oom_reaper_list = tsk;
        spin_unlock(&oom_reaper_lock);
@@ -659,6 +668,16 @@ static inline void wake_oom_reaper(struct task_struct *tsk)
 }
 #endif /* CONFIG_MMU */
 
+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
@@ -671,18 +690,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
@@ -1114,3 +1128,21 @@ void pagefault_out_of_memory(void)
        out_of_memory(&oc);
        mutex_unlock(&oom_lock);
 }
+
+void add_to_oom_reaper(struct task_struct *p)
+{
+       if (!sysctl_reap_mem_on_sigkill)
+               return;
+
+       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);
+}