1 From: Gerald Schaefer <geraldsc@de.ibm.com>
2 Subject: kernel: use mutex for appldata_ops instead of spin_lock.
3 References: bnc#487755,LTC#52788
5 Symptom: Possible deadlock when appldata_mem is active
6 Problem: The appldata_ops callbacks are called with a spin_lock held.
7 But the appldata_mem callback then calls all_vm_events(), which
8 calls get_online_cpus(), which might sleep.
9 Solution: Use a mutex instead of a spin_lock.
11 Acked-by: John Jolly <jjolly@suse.de>
13 arch/s390/appldata/appldata_base.c | 32 ++++++++++++++++----------------
14 arch/s390/appldata/appldata_mem.c | 4 +---
15 2 files changed, 17 insertions(+), 19 deletions(-)
17 Index: linux-sles11/arch/s390/appldata/appldata_base.c
18 ===================================================================
19 --- linux-sles11.orig/arch/s390/appldata/appldata_base.c
20 +++ linux-sles11/arch/s390/appldata/appldata_base.c
21 @@ -97,7 +97,7 @@ static DECLARE_WORK(appldata_work, appld
25 -static DEFINE_SPINLOCK(appldata_ops_lock);
26 +static DEFINE_MUTEX(appldata_ops_mutex);
27 static LIST_HEAD(appldata_ops_list);
30 @@ -128,14 +128,14 @@ static void appldata_work_fn(struct work
34 - spin_lock(&appldata_ops_lock);
35 + mutex_lock(&appldata_ops_mutex);
36 list_for_each(lh, &appldata_ops_list) {
37 ops = list_entry(lh, struct appldata_ops, list);
38 if (ops->active == 1) {
39 ops->callback(ops->data);
42 - spin_unlock(&appldata_ops_lock);
43 + mutex_unlock(&appldata_ops_mutex);
47 @@ -337,7 +337,7 @@ appldata_generic_handler(ctl_table *ctl,
51 - spin_lock(&appldata_ops_lock);
52 + mutex_lock(&appldata_ops_mutex);
53 list_for_each(lh, &appldata_ops_list) {
54 tmp_ops = list_entry(lh, struct appldata_ops, list);
55 if (&tmp_ops->ctl_table[2] == ctl) {
56 @@ -345,15 +345,15 @@ appldata_generic_handler(ctl_table *ctl,
60 - spin_unlock(&appldata_ops_lock);
61 + mutex_unlock(&appldata_ops_mutex);
65 if (!try_module_get(ops->owner)) { // protect this function
66 - spin_unlock(&appldata_ops_lock);
67 + mutex_unlock(&appldata_ops_mutex);
70 - spin_unlock(&appldata_ops_lock);
71 + mutex_unlock(&appldata_ops_mutex);
73 if (!*lenp || *ppos) {
75 @@ -377,11 +377,11 @@ appldata_generic_handler(ctl_table *ctl,
79 - spin_lock(&appldata_ops_lock);
80 + mutex_lock(&appldata_ops_mutex);
81 if ((buf[0] == '1') && (ops->active == 0)) {
82 // protect work queue callback
83 if (!try_module_get(ops->owner)) {
84 - spin_unlock(&appldata_ops_lock);
85 + mutex_unlock(&appldata_ops_mutex);
86 module_put(ops->owner);
89 @@ -406,7 +406,7 @@ appldata_generic_handler(ctl_table *ctl,
90 "failed with rc=%d\n", ops->name, rc);
91 module_put(ops->owner);
93 - spin_unlock(&appldata_ops_lock);
94 + mutex_unlock(&appldata_ops_mutex);
98 @@ -432,9 +432,9 @@ int appldata_register_ops(struct appldat
102 - spin_lock(&appldata_ops_lock);
103 + mutex_lock(&appldata_ops_mutex);
104 list_add(&ops->list, &appldata_ops_list);
105 - spin_unlock(&appldata_ops_lock);
106 + mutex_unlock(&appldata_ops_mutex);
108 ops->ctl_table[0].procname = appldata_proc_name;
109 ops->ctl_table[0].maxlen = 0;
110 @@ -451,9 +451,9 @@ int appldata_register_ops(struct appldat
114 - spin_lock(&appldata_ops_lock);
115 + mutex_lock(&appldata_ops_mutex);
116 list_del(&ops->list);
117 - spin_unlock(&appldata_ops_lock);
118 + mutex_unlock(&appldata_ops_mutex);
119 kfree(ops->ctl_table);
122 @@ -465,9 +465,9 @@ out:
124 void appldata_unregister_ops(struct appldata_ops *ops)
126 - spin_lock(&appldata_ops_lock);
127 + mutex_lock(&appldata_ops_mutex);
128 list_del(&ops->list);
129 - spin_unlock(&appldata_ops_lock);
130 + mutex_unlock(&appldata_ops_mutex);
131 unregister_sysctl_table(ops->sysctl_header);
132 kfree(ops->ctl_table);
134 Index: linux-sles11/arch/s390/appldata/appldata_mem.c
135 ===================================================================
136 --- linux-sles11.orig/arch/s390/appldata/appldata_mem.c
137 +++ linux-sles11/arch/s390/appldata/appldata_mem.c
138 @@ -78,7 +78,7 @@ static void appldata_get_mem_data(void *
141 * don't put large structures on the stack, we are
142 - * serialized through the appldata_ops_lock and can use static
143 + * serialized through the appldata_ops_mutex and can use static
145 static struct sysinfo val;
146 unsigned long ev[NR_VM_EVENT_ITEMS];