Skip to content

Commit

Permalink
staging: android/lowmemorykiller: Don't unregister notifier from atom…
Browse files Browse the repository at this point in the history
…ic 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: Rabin Vincent <rabin.vincent@stericsson.com>
Signed-off-by: Christian Bejram <christian.bejram@stericsson.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Reported-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Paul E. McKenney authored and Greg Kroah-Hartman committed Mar 7, 2012
1 parent 2c52325 commit 1eda516
Showing 1 changed file with 7 additions and 7 deletions.
14 changes: 7 additions & 7 deletions drivers/staging/android/lowmemorykiller.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ static int
task_notify_func(struct notifier_block *self, unsigned long val, void *data)
{
struct task_struct *task = data;
if (task == lowmem_deathpending) {

if (task == lowmem_deathpending)
lowmem_deathpending = NULL;
task_handoff_unregister(&task_nb);
}

return NOTIFY_OK;
}

Expand Down Expand Up @@ -175,14 +175,12 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
selected->pid, selected->comm,
selected_oom_score_adj, selected_tasksize);
/*
* If CONFIG_PROFILING is off, then task_handoff_register()
* is a nop. In that case we don't want to stall the killer
* by setting lowmem_deathpending.
* If CONFIG_PROFILING is off, then we don't want to stall
* the killer by setting lowmem_deathpending.
*/
#ifdef CONFIG_PROFILING
lowmem_deathpending = selected;
lowmem_deathpending_timeout = jiffies + HZ;
task_handoff_register(&task_nb);
#endif
send_sig(SIGKILL, selected, 0);
rem -= selected_tasksize;
Expand All @@ -200,13 +198,15 @@ static struct shrinker lowmem_shrinker = {

static int __init lowmem_init(void)
{
task_handoff_register(&task_nb);
register_shrinker(&lowmem_shrinker);
return 0;
}

static void __exit lowmem_exit(void)
{
unregister_shrinker(&lowmem_shrinker);
task_handoff_unregister(&task_nb);
}

module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
Expand Down

0 comments on commit 1eda516

Please sign in to comment.