aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2010-09-09 10:48:21 +0530
committersrinidhi kasagar <srinidhi.kasagar@stericsson.com>2010-10-27 15:22:52 +0530
commit8ad6a42c427e9ee7040b702a09b245dfa5753a50 (patch)
tree1ef86d5bcb39083c9b24aadfff27d5541857a5e2 /drivers/staging
parent5c1c7a5ba7dd74dc9a7a2827d02df3495eb8f418 (diff)
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. ST-Ericsson ID: ER270430 Change-Id: I81fa09b1cad7675813d290714dc91c6f1e8b7be2 Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/4866 Reviewed-by: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com> Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com> Reviewed-by: Linus WALLEIJ <linus.walleij@stericsson.com> Signed-off-by: srinidhi kasagar <srinidhi.kasagar@stericsson.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/android/lowmemorykiller.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 8b67ac06e4b..efbe556ba86 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -71,10 +71,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_free_unregister(&task_nb);
- }
+
return NOTIFY_OK;
}
@@ -168,7 +168,6 @@ static int lowmem_shrink(struct shrinker *s, int nr_to_scan, gfp_t gfp_mask)
selected->pid, selected->comm,
selected_oom_adj, selected_tasksize);
lowmem_deathpending = selected;
- task_free_register(&task_nb);
force_sig(SIGKILL, selected);
rem -= selected_tasksize;
}
@@ -185,6 +184,7 @@ static struct shrinker lowmem_shrinker = {
static int __init lowmem_init(void)
{
+ task_free_register(&task_nb);
register_shrinker(&lowmem_shrinker);
return 0;
}
@@ -192,6 +192,7 @@ static int __init lowmem_init(void)
static void __exit lowmem_exit(void)
{
unregister_shrinker(&lowmem_shrinker);
+ task_free_unregister(&task_nb);
}
module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);