Merge "lowmemorykiller: use oom reaper to free pages of task killed by lmk "
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 616375a..8d67f76 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -48,6 +48,7 @@
#include <linux/fs.h>
#include <linux/cpuset.h>
#include <linux/vmpressure.h>
+#include <linux/freezer.h>
#define CREATE_TRACE_POINTS
#include <trace/events/almk.h>
@@ -116,6 +117,10 @@
static int vmpressure_file_min;
module_param_named(vmpressure_file_min, vmpressure_file_min, int, 0644);
+/* User knob to enable/disable oom reaping feature */
+static int oom_reaper;
+module_param_named(oom_reaper, oom_reaper, int, 0644);
+
enum {
VMPRESSURE_NO_ADJUST = 0,
VMPRESSURE_ADJUST_ENCROACH,
@@ -406,6 +411,14 @@
}
}
+static void mark_lmk_victim(struct task_struct *tsk)
+{
+ struct mm_struct *mm = tsk->mm;
+
+ if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm))
+ atomic_inc(&tsk->signal->oom_mm->mm_count);
+}
+
static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
{
struct task_struct *tsk;
@@ -524,7 +537,11 @@
send_sig(SIGKILL, selected, 0);
if (selected->mm)
task_set_lmk_waiting(selected);
+ if (oom_reaper)
+ mark_lmk_victim(selected);
task_unlock(selected);
+ if (oom_reaper)
+ wake_oom_reaper(selected);
trace_lowmemory_kill(selected, cache_size, cache_limit, free);
lowmem_print(1, "Killing '%s' (%d) (tgid %d), adj %hd,\n"
"to free %ldkB on behalf of '%s' (%d) because\n"
diff --git a/include/linux/oom.h b/include/linux/oom.h
index b986840..5b5d4c7 100644
--- a/include/linux/oom.h
+++ b/include/linux/oom.h
@@ -82,6 +82,8 @@
extern void dump_tasks(struct mem_cgroup *memcg,
const nodemask_t *nodemask);
+extern void wake_oom_reaper(struct task_struct *tsk);
+
/* sysctls */
extern int sysctl_oom_dump_tasks;
extern int sysctl_oom_kill_allocating_task;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 3a22b14..af783a6 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -608,18 +608,23 @@
return 0;
}
-static void wake_oom_reaper(struct task_struct *tsk)
+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 LMK.
+ */
+ spin_lock(&oom_reaper_lock);
/* tsk is already queued? */
- if (tsk == oom_reaper_list || tsk->oom_reaper_list)
+ if (tsk == oom_reaper_list || tsk->oom_reaper_list) {
+ 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);