History

[PATCH] Convert cpu hotplug notifiers to use raw_notifier instead of blocking_notifier

The use of blocking notifier by _cpu_up and _cpu_down in cpu.c has two problem. 1/ An interaction with the workqueue notifier causes lockdep to spit a warning. 2/ A notifier could conceivable be added or removed while _cpu_up or _cpu_down are in process. As each notifier is called twice (prepare then commit/abort) this could be unhealthy. To fix to we simply take cpu_add_remove_lock while adding or removing notifiers to/from the list. This makes the 'blocking' usage unnecessary as all accesses to cpu_chain are now protected by cpu_add_remove_lock. So change "blocking" to "raw" in all relevant places. This fixes 1.

Neil Brown committed 20 years ago

Commit bd5349c1 parent bea493a1 file · +15 −9Browse files

Unified · Split

kernel/cpu.c+15−9
@@ -19,7 +19,7 @@ · 18 unmodified lines
19static DEFINE_MUTEX(cpu_add_remove_lock);19static DEFINE_MUTEX(cpu_add_remove_lock);
20static DEFINE_MUTEX(cpu_bitmask_lock);20static DEFINE_MUTEX(cpu_bitmask_lock);
21 21
22static __cpuinitdata BLOCKING_NOTIFIER_HEAD(cpu_chain);22static __cpuinitdata RAW_NOTIFIER_HEAD(cpu_chain);
23 23
24/* If set, cpu_up and cpu_down will return -EBUSY and do nothing.24/* If set, cpu_up and cpu_down will return -EBUSY and do nothing.
25 * Should always be manipulated under cpu_add_remove_lock25 * Should always be manipulated under cpu_add_remove_lock
@@ -68,7 +68,11 @@ EXPORT_SYMBOL_GPL(unlock_cpu_hotplug); · 42 unmodified lines
68/* Need to know about CPUs going up/down? */68/* Need to know about CPUs going up/down? */
69int __cpuinit register_cpu_notifier(struct notifier_block *nb)69int __cpuinit register_cpu_notifier(struct notifier_block *nb)
70{70{
71 return blocking_notifier_chain_register(&cpu_chain, nb);71 int ret;
72 mutex_lock(&cpu_add_remove_lock);
73 ret = raw_notifier_chain_register(&cpu_chain, nb);
74 mutex_unlock(&cpu_add_remove_lock);
75 return ret;
72}76}
73 77
74#ifdef CONFIG_HOTPLUG_CPU78#ifdef CONFIG_HOTPLUG_CPU
@@ -77,7 +81,9 @@ EXPORT_SYMBOL(register_cpu_notifier); · 2 unmodified lines
77 81
78void unregister_cpu_notifier(struct notifier_block *nb)82void unregister_cpu_notifier(struct notifier_block *nb)
79{83{
80 blocking_notifier_chain_unregister(&cpu_chain, nb);84 mutex_lock(&cpu_add_remove_lock);
85 raw_notifier_chain_unregister(&cpu_chain, nb);
86 mutex_unlock(&cpu_add_remove_lock);
81}87}
82EXPORT_SYMBOL(unregister_cpu_notifier);88EXPORT_SYMBOL(unregister_cpu_notifier);
83 89
@@ -126,7 +132,7 @@ static int _cpu_down(unsigned int cpu) · 42 unmodified lines
126 if (!cpu_online(cpu))132 if (!cpu_online(cpu))
127 return -EINVAL;133 return -EINVAL;
128 134
129 err = blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE,135 err = raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE,
130 (void *)(long)cpu);136 (void *)(long)cpu);
131 if (err == NOTIFY_BAD) {137 if (err == NOTIFY_BAD) {
132 printk("%s: attempt to take down CPU %u failed\n",138 printk("%s: attempt to take down CPU %u failed\n",
@@ -146,7 +152,7 @@ static int _cpu_down(unsigned int cpu) · 13 unmodified lines
146 152
147 if (IS_ERR(p)) {153 if (IS_ERR(p)) {
148 /* CPU didn't die: tell everyone. Can't complain. */154 /* CPU didn't die: tell everyone. Can't complain. */
149 if (blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED,155 if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED,
150 (void *)(long)cpu) == NOTIFY_BAD)156 (void *)(long)cpu) == NOTIFY_BAD)
151 BUG();157 BUG();
152 158
@@ -169,7 +175,7 @@ static int _cpu_down(unsigned int cpu) · 16 unmodified lines
169 put_cpu();175 put_cpu();
170 176
171 /* CPU is completely dead: tell everyone. Too late to complain. */177 /* CPU is completely dead: tell everyone. Too late to complain. */
172 if (blocking_notifier_call_chain(&cpu_chain, CPU_DEAD,178 if (raw_notifier_call_chain(&cpu_chain, CPU_DEAD,
173 (void *)(long)cpu) == NOTIFY_BAD)179 (void *)(long)cpu) == NOTIFY_BAD)
174 BUG();180 BUG();
175 181
@@ -206,7 +212,7 @@ static int __devinit _cpu_up(unsigned int cpu) · 30 unmodified lines
206 if (cpu_online(cpu) || !cpu_present(cpu))212 if (cpu_online(cpu) || !cpu_present(cpu))
207 return -EINVAL;213 return -EINVAL;
208 214
209 ret = blocking_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);215 ret = raw_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);
210 if (ret == NOTIFY_BAD) {216 if (ret == NOTIFY_BAD) {
211 printk("%s: attempt to bring up CPU %u failed\n",217 printk("%s: attempt to bring up CPU %u failed\n",
212 __FUNCTION__, cpu);218 __FUNCTION__, cpu);
@@ -223,11 +229,11 @@ static int __devinit _cpu_up(unsigned int cpu) · 10 unmodified lines
223 BUG_ON(!cpu_online(cpu));229 BUG_ON(!cpu_online(cpu));
224 230
225 /* Now call notifier in preparation. */231 /* Now call notifier in preparation. */
226 blocking_notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);232 raw_notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);
227 233
228out_notify:234out_notify:
229 if (ret != 0)235 if (ret != 0)
230 blocking_notifier_call_chain(&cpu_chain,236 raw_notifier_call_chain(&cpu_chain,
231 CPU_UP_CANCELED, hcpu);237 CPU_UP_CANCELED, hcpu);
232 238
233 return ret;239 return ret;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t