staging: android/lowmemorykiller: Don't unregister notifier from atomic context
PATCH 1/1 staging: android/lowmemorykiller: Don't unregister notifier from atomic context
From: "Paul E. McKenney" <[email protected]>
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.
---
This is respin of http://lkml.org/lkml/2012/1/3/265, which does not apply cleanly nowadays.
drivers/staging/android/lowmemorykiller.c | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-)
drivers/staging/android/lowmemorykiller.c +7 -7
@@ -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 ; }
@@ -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;
@@ -200,6 +198,7 @@ static struct shrinker lowmem_shrinker = {static int __init lowmem_init (void ) { +task_handoff_register (&task_nb);register_shrinker (&lowmem_shrinker);return 0 ; }
@@ -207,6 +206,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 );
Signature · 1 line
1.7.7.6