android,lowmemorykiller: Don't abuse TIF_MEMDIE.
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Tue, 8 Mar 2016 11:01:32 +0000 (20:01 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 Apr 2016 19:41:24 +0000 (12:41 -0700)
Currently, lowmemorykiller (LMK) is using TIF_MEMDIE for two purposes.
One is to remember processes killed by LMK, and the other is to
accelerate termination of processes killed by LMK.

But since LMK is invoked as a memory shrinker function, there still
should be some memory available. It is very likely that memory
allocations by processes killed by LMK will succeed without using
ALLOC_NO_WATERMARKS via TIF_MEMDIE. Even if their allocations cannot
escape from memory allocation loop unless they use ALLOC_NO_WATERMARKS,
lowmem_deathpending_timeout can guarantee forward progress by choosing
next victim process.

On the other hand, mark_oom_victim() assumes that it must be called with
oom_lock held and it must not be called after oom_killer_disable() was
called. But LMK is calling it without holding oom_lock and checking
oom_killer_disabled. It is possible that LMK calls mark_oom_victim()
due to allocation requests by kernel threads after current thread
returned from oom_killer_disabled(). This will break synchronization
for PM/suspend.

This patch introduces per a task_struct flag for remembering processes
killed by LMK, and replaces TIF_MEMDIE with that flag. By applying this
patch, assumption by mark_oom_victim() becomes true.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Acked-by: Michal Hocko <mhocko@suse.com>
Cc: Arve Hjonnevag <arve@android.com>
Cc: Riley Andrews <riandrews@android.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/android/lowmemorykiller.c
include/linux/sched.h

index 2509e5df7244a16d6b926d6e5d6a881f9f5bb792..c79f22425fa877904b06941c13745da9ea62fb8a 100644 (file)
@@ -131,7 +131,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
                if (!p)
                        continue;
 
-               if (test_tsk_thread_flag(p, TIF_MEMDIE) &&
+               if (task_lmk_waiting(p) && p->mm &&
                    time_before_eq(jiffies, lowmem_deathpending_timeout)) {
                        task_unlock(p);
                        rcu_read_unlock();
@@ -162,13 +162,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
        if (selected) {
                task_lock(selected);
                send_sig(SIGKILL, selected, 0);
-               /*
-                * FIXME: lowmemorykiller shouldn't abuse global OOM killer
-                * infrastructure. There is no real reason why the selected
-                * task should have access to the memory reserves.
-                */
                if (selected->mm)
-                       mark_oom_victim(selected);
+                       task_set_lmk_waiting(selected);
                task_unlock(selected);
                lowmem_print(1, "Killing '%s' (%d), adj %hd,\n"
                                 "   to free %ldkB on behalf of '%s' (%d) because\n"
index 60bba7e032dc33c57156751c6a5270e1f72a0feb..9dff190e6a0a923f88642589aa3f7879b4a7c281 100644 (file)
@@ -2184,6 +2184,7 @@ static inline void memalloc_noio_restore(unsigned int flags)
 #define PFA_NO_NEW_PRIVS 0     /* May not gain new privileges. */
 #define PFA_SPREAD_PAGE  1      /* Spread page cache over cpuset */
 #define PFA_SPREAD_SLAB  2      /* Spread some slab caches over cpuset */
+#define PFA_LMK_WAITING  3      /* Lowmemorykiller is waiting */
 
 
 #define TASK_PFA_TEST(name, func)                                      \
@@ -2207,6 +2208,9 @@ TASK_PFA_TEST(SPREAD_SLAB, spread_slab)
 TASK_PFA_SET(SPREAD_SLAB, spread_slab)
 TASK_PFA_CLEAR(SPREAD_SLAB, spread_slab)
 
+TASK_PFA_TEST(LMK_WAITING, lmk_waiting)
+TASK_PFA_SET(LMK_WAITING, lmk_waiting)
+
 /*
  * task->jobctl flags
  */