3.3-stable review patch. If anyone has any objections, please let me know.
------------------ From: "Paul E. McKenney" <[email protected]> commit 1eda5166c7640092f512138be6899d050c3d62ed upstream. 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 <[email protected]> Signed-off-by: Christian Bejram <[email protected]> Signed-off-by: Paul E. McKenney <[email protected]> Reported-by: John Stultz <[email protected]> Signed-off-by: Anton Vorontsov <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> --- drivers/staging/android/lowmemorykiller.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -73,10 +73,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; } @@ -174,14 +174,12 @@ static int lowmem_shrink(struct shrinker selected->pid, selected->comm, selected_oom_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 force_sig(SIGKILL, selected); rem -= selected_tasksize; @@ -199,6 +197,7 @@ static struct shrinker lowmem_shrinker = static int __init lowmem_init(void) { + task_handoff_register(&task_nb); register_shrinker(&lowmem_shrinker); return 0; } @@ -206,6 +205,7 @@ static int __init lowmem_init(void) 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); -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
