Skip to contentSkip to conversation

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

PATCH New Anton Vorontsov 1 participant 1 message Mar 7, 2012 Staging

lore
Share & tools
lore
#0 lore raw

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
index cf4c6f7..03d1de2 100644
@@ -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