Loading Documentation/admin-guide/sysctl/vm.rst +17 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,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 Loading Loading @@ -669,6 +670,22 @@ OOM killer actually kills a memory-hogging task. 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 ======================== Loading include/linux/oom.h +4 −0 Original line number Diff line number Diff line Loading @@ -126,4 +126,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 */ kernel/signal.c +5 −1 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ #include <linux/livepatch.h> #include <linux/cgroup.h> #include <linux/audit.h> #include <linux/oom.h> #define CREATE_TRACE_POINTS #include <trace/events/signal.h> Loading Loading @@ -1404,8 +1405,11 @@ 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 (capable(CAP_KILL) && sig == SIGKILL) add_to_oom_reaper(p); } return ret; } Loading kernel/sysctl.c +7 −0 Original line number Diff line number Diff line Loading @@ -1576,6 +1576,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, Loading mm/oom_kill.c +41 −8 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ int sysctl_panic_on_oom; int sysctl_oom_kill_allocating_task; int sysctl_oom_dump_tasks = 1; int sysctl_reap_mem_on_sigkill; /* * Serializes oom killer invocations (out_of_memory()) from all contexts to Loading Loading @@ -661,13 +662,22 @@ static int oom_reaper(void *unused) static void wake_oom_reaper(struct task_struct *tsk) { /* * 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); Loading @@ -687,6 +697,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 Loading @@ -699,18 +719,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 Loading Loading @@ -1140,3 +1155,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); } Loading
Documentation/admin-guide/sysctl/vm.rst +17 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,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 Loading Loading @@ -669,6 +670,22 @@ OOM killer actually kills a memory-hogging task. 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 ======================== Loading
include/linux/oom.h +4 −0 Original line number Diff line number Diff line Loading @@ -126,4 +126,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 */
kernel/signal.c +5 −1 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ #include <linux/livepatch.h> #include <linux/cgroup.h> #include <linux/audit.h> #include <linux/oom.h> #define CREATE_TRACE_POINTS #include <trace/events/signal.h> Loading Loading @@ -1404,8 +1405,11 @@ 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 (capable(CAP_KILL) && sig == SIGKILL) add_to_oom_reaper(p); } return ret; } Loading
kernel/sysctl.c +7 −0 Original line number Diff line number Diff line Loading @@ -1576,6 +1576,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, Loading
mm/oom_kill.c +41 −8 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ int sysctl_panic_on_oom; int sysctl_oom_kill_allocating_task; int sysctl_oom_dump_tasks = 1; int sysctl_reap_mem_on_sigkill; /* * Serializes oom killer invocations (out_of_memory()) from all contexts to Loading Loading @@ -661,13 +662,22 @@ static int oom_reaper(void *unused) static void wake_oom_reaper(struct task_struct *tsk) { /* * 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); Loading @@ -687,6 +697,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 Loading @@ -699,18 +719,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 Loading Loading @@ -1140,3 +1155,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); }