diff options
author | Liam Mark <lmark@codeaurora.org> | 2013-02-07 14:31:36 -0800 |
---|---|---|
committer | Jeevan Shriram <jshriram@codeaurora.org> | 2016-04-13 11:09:29 -0700 |
commit | 21f86651a66abefcfce33f4611c2de7863a8642b (patch) | |
tree | b79f37d019d368bdbd61922de7d00add87cfbaad | |
parent | d40b7c124fec2b1c0163a531e778b9974346e37b (diff) |
android/lowmemorykiller: Ignore tasks with freed mm
A killed task can stay in the task list long after its
memory has been returned to the system, therefore
ignore any tasks whose mm struct has been freed.
Change-Id: I76394b203b4ab2312437c839976f0ecb7b6dde4e
CRs-fixed: 450383
Signed-off-by: Liam Mark <lmark@codeaurora.org>
-rw-r--r-- | arch/arm/include/asm/thread_info.h | 1 | ||||
-rw-r--r-- | drivers/staging/android/lowmemorykiller.c | 9 | ||||
-rw-r--r-- | include/linux/sched.h | 2 | ||||
-rw-r--r-- | kernel/exit.c | 6 | ||||
-rw-r--r-- | kernel/fork.c | 5 |
5 files changed, 18 insertions, 5 deletions
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index 776757d1604a..f23454db246f 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -148,6 +148,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, #define TIF_USING_IWMMXT 17 #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ #define TIF_RESTORE_SIGMASK 20 +#define TIF_MM_RELEASED 21 /* task MM has been released */ #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index b9be6d9a52ef..976453cc834f 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -155,6 +155,10 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (tsk->flags & PF_KTHREAD) continue; + /* if task no longer has any memory ignore it */ + if (test_task_flag(tsk, TIF_MM_RELEASED)) + continue; + if (time_before_eq(jiffies, lowmem_deathpending_timeout)) { if (test_task_flag(tsk, TIF_MEMDIE)) { rcu_read_unlock(); @@ -220,13 +224,14 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) free); lowmem_deathpending_timeout = jiffies + HZ; rem += selected_tasksize; + rcu_read_unlock(); /* give the system time to free up the memory */ msleep_interruptible(20); - } + } else + rcu_read_unlock(); lowmem_print(4, "lowmem_scan %lu, %x, return %lu\n", sc->nr_to_scan, sc->gfp_mask, rem); - rcu_read_unlock(); mutex_unlock(&scan_mutex); return rem; } diff --git a/include/linux/sched.h b/include/linux/sched.h index e963ff30a7f6..7ece18efd02b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2740,7 +2740,7 @@ static inline void mmdrop(struct mm_struct * mm) } /* mmput gets rid of the mappings and all user-space */ -extern void mmput(struct mm_struct *); +extern int mmput(struct mm_struct *); /* Grab a reference to a task's mm, if it is not already going away */ extern struct mm_struct *get_task_mm(struct task_struct *task); /* diff --git a/kernel/exit.c b/kernel/exit.c index 77d54139672b..a32e83d567b9 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -388,6 +388,7 @@ static void exit_mm(struct task_struct *tsk) { struct mm_struct *mm = tsk->mm; struct core_state *core_state; + int mm_released; mm_release(tsk, mm); if (!mm) @@ -434,9 +435,12 @@ static void exit_mm(struct task_struct *tsk) enter_lazy_tlb(mm, current); task_unlock(tsk); mm_update_next_owner(mm); - mmput(mm); + + mm_released = mmput(mm); if (test_thread_flag(TIF_MEMDIE)) exit_oom_victim(); + if (mm_released) + set_tsk_thread_flag(tsk, TIF_MM_RELEASED); } static struct task_struct *find_alive_thread(struct task_struct *p) diff --git a/kernel/fork.c b/kernel/fork.c index 859b949d106f..c9eb86b646ab 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -694,8 +694,9 @@ EXPORT_SYMBOL_GPL(__mmdrop); /* * Decrement the use count and release all resources for an mm. */ -void mmput(struct mm_struct *mm) +int mmput(struct mm_struct *mm) { + int mm_freed = 0; might_sleep(); if (atomic_dec_and_test(&mm->mm_users)) { @@ -713,7 +714,9 @@ void mmput(struct mm_struct *mm) if (mm->binfmt) module_put(mm->binfmt->module); mmdrop(mm); + mm_freed = 1; } + return mm_freed; } EXPORT_SYMBOL_GPL(mmput); |