- 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
==============================================================
+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
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 */
#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>
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;
}
.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,
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);
/* Serializes oom_score_adj and oom_score_adj_min updates */
{
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);
}
#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
*/
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
if (__ratelimit(&pfoom_rs))
pr_warn("Huh VM_FAULT_OOM leaked out to the #PF handler. Retrying PF\n");
}
+
+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);
+}