Commit 1eda5166 authored by Paul E. McKenney's avatar Paul E. McKenney Committed by Greg Kroah-Hartman

staging: android/lowmemorykiller: Don't unregister notifier from atomic context

The lowmemorykiller registers an atomic notifier for notfication of when
the task is freed.  From this atomic notifier callback, it removes the
atomic notifier via task_free_unregister().  This is incorrect because
atomic_notifier_chain_unregister() calls syncronize_rcu(), which can
sleep, which shouldn't be done from an atomic notifier.

Fix this by registering the notifier during init, and only unregister it
if the lowmemorykiller is unloaded.

Rebased to -next by Paul E. McKenney.
Rebased to -next again by Anton Vorontsov.
Signed-off-by: default avatarRabin Vincent <rabin.vincent@stericsson.com>
Signed-off-by: default avatarChristian Bejram <christian.bejram@stericsson.com>
Signed-off-by: default avatarPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Reported-by: default avatarJohn Stultz <john.stultz@linaro.org>
Signed-off-by: default avatarAnton Vorontsov <anton.vorontsov@linaro.org>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2c52325e
...@@ -75,10 +75,10 @@ static int ...@@ -75,10 +75,10 @@ static int
task_notify_func(struct notifier_block *self, unsigned long val, void *data) task_notify_func(struct notifier_block *self, unsigned long val, void *data)
{ {
struct task_struct *task = data; struct task_struct *task = data;
if (task == lowmem_deathpending) {
if (task == lowmem_deathpending)
lowmem_deathpending = NULL; lowmem_deathpending = NULL;
task_handoff_unregister(&task_nb);
}
return NOTIFY_OK; return NOTIFY_OK;
} }
...@@ -175,14 +175,12 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc) ...@@ -175,14 +175,12 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
selected->pid, selected->comm, selected->pid, selected->comm,
selected_oom_score_adj, selected_tasksize); selected_oom_score_adj, selected_tasksize);
/* /*
* If CONFIG_PROFILING is off, then task_handoff_register() * If CONFIG_PROFILING is off, then we don't want to stall
* is a nop. In that case we don't want to stall the killer * the killer by setting lowmem_deathpending.
* by setting lowmem_deathpending.
*/ */
#ifdef CONFIG_PROFILING #ifdef CONFIG_PROFILING
lowmem_deathpending = selected; lowmem_deathpending = selected;
lowmem_deathpending_timeout = jiffies + HZ; lowmem_deathpending_timeout = jiffies + HZ;
task_handoff_register(&task_nb);
#endif #endif
send_sig(SIGKILL, selected, 0); send_sig(SIGKILL, selected, 0);
rem -= selected_tasksize; rem -= selected_tasksize;
...@@ -200,6 +198,7 @@ static struct shrinker lowmem_shrinker = { ...@@ -200,6 +198,7 @@ static struct shrinker lowmem_shrinker = {
static int __init lowmem_init(void) static int __init lowmem_init(void)
{ {
task_handoff_register(&task_nb);
register_shrinker(&lowmem_shrinker); register_shrinker(&lowmem_shrinker);
return 0; return 0;
} }
...@@ -207,6 +206,7 @@ static int __init lowmem_init(void) ...@@ -207,6 +206,7 @@ static int __init lowmem_init(void)
static void __exit lowmem_exit(void) static void __exit lowmem_exit(void)
{ {
unregister_shrinker(&lowmem_shrinker); unregister_shrinker(&lowmem_shrinker);
task_handoff_unregister(&task_nb);
} }
module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR); module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment