summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2010-09-09 10:48:21 +0530
committerNiket Sirsi <nsirsi@nvidia.com>2010-12-28 10:35:56 -0800
commit8b31719041662bae54d9acbef4e8c907756cdb6c (patch)
treeaf539e4962930291446de1c0900a24d6c182943f
parent1508f7aa5850b1ac02d9876eb5dac34356c86244 (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. Change-Id: Ie9cf2f23d31c78e1fe1b9dd2e11af5267832ee94 Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> Signed-off-by: Christian Bejram <christian.bejram@stericsson.com> Reviewed-on: http://git-master/r/13943 Reviewed-by: Ching Kuang (Roger) Hsieh <rhsieh@nvidia.com> Tested-by: Ching Kuang (Roger) Hsieh <rhsieh@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
-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 39d5e6502b21..37ed0f8c432c 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(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);