This source file includes following definitions.
- notifier_chain_register
- notifier_chain_cond_register
- notifier_chain_unregister
- notifier_call_chain
- atomic_notifier_chain_register
- atomic_notifier_chain_unregister
- __atomic_notifier_call_chain
- atomic_notifier_call_chain
- blocking_notifier_chain_register
- blocking_notifier_chain_cond_register
- blocking_notifier_chain_unregister
- __blocking_notifier_call_chain
- blocking_notifier_call_chain
- raw_notifier_chain_register
- raw_notifier_chain_unregister
- __raw_notifier_call_chain
- raw_notifier_call_chain
- srcu_notifier_chain_register
- srcu_notifier_chain_unregister
- __srcu_notifier_call_chain
- srcu_notifier_call_chain
- srcu_init_notifier_head
- notify_die
- register_die_notifier
- unregister_die_notifier
1
2 #include <linux/kdebug.h>
3 #include <linux/kprobes.h>
4 #include <linux/export.h>
5 #include <linux/notifier.h>
6 #include <linux/rcupdate.h>
7 #include <linux/vmalloc.h>
8 #include <linux/reboot.h>
9
10
11
12
13
14
15 BLOCKING_NOTIFIER_HEAD(reboot_notifier_list);
16
17
18
19
20
21
22 static int notifier_chain_register(struct notifier_block **nl,
23 struct notifier_block *n)
24 {
25 while ((*nl) != NULL) {
26 WARN_ONCE(((*nl) == n), "double register detected");
27 if (n->priority > (*nl)->priority)
28 break;
29 nl = &((*nl)->next);
30 }
31 n->next = *nl;
32 rcu_assign_pointer(*nl, n);
33 return 0;
34 }
35
36 static int notifier_chain_cond_register(struct notifier_block **nl,
37 struct notifier_block *n)
38 {
39 while ((*nl) != NULL) {
40 if ((*nl) == n)
41 return 0;
42 if (n->priority > (*nl)->priority)
43 break;
44 nl = &((*nl)->next);
45 }
46 n->next = *nl;
47 rcu_assign_pointer(*nl, n);
48 return 0;
49 }
50
51 static int notifier_chain_unregister(struct notifier_block **nl,
52 struct notifier_block *n)
53 {
54 while ((*nl) != NULL) {
55 if ((*nl) == n) {
56 rcu_assign_pointer(*nl, n->next);
57 return 0;
58 }
59 nl = &((*nl)->next);
60 }
61 return -ENOENT;
62 }
63
64
65
66
67
68
69
70
71
72
73
74
75
76 static int notifier_call_chain(struct notifier_block **nl,
77 unsigned long val, void *v,
78 int nr_to_call, int *nr_calls)
79 {
80 int ret = NOTIFY_DONE;
81 struct notifier_block *nb, *next_nb;
82
83 nb = rcu_dereference_raw(*nl);
84
85 while (nb && nr_to_call) {
86 next_nb = rcu_dereference_raw(nb->next);
87
88 #ifdef CONFIG_DEBUG_NOTIFIERS
89 if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) {
90 WARN(1, "Invalid notifier called!");
91 nb = next_nb;
92 continue;
93 }
94 #endif
95 ret = nb->notifier_call(nb, val, v);
96
97 if (nr_calls)
98 (*nr_calls)++;
99
100 if (ret & NOTIFY_STOP_MASK)
101 break;
102 nb = next_nb;
103 nr_to_call--;
104 }
105 return ret;
106 }
107 NOKPROBE_SYMBOL(notifier_call_chain);
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
124 struct notifier_block *n)
125 {
126 unsigned long flags;
127 int ret;
128
129 spin_lock_irqsave(&nh->lock, flags);
130 ret = notifier_chain_register(&nh->head, n);
131 spin_unlock_irqrestore(&nh->lock, flags);
132 return ret;
133 }
134 EXPORT_SYMBOL_GPL(atomic_notifier_chain_register);
135
136
137
138
139
140
141
142
143
144
145 int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
146 struct notifier_block *n)
147 {
148 unsigned long flags;
149 int ret;
150
151 spin_lock_irqsave(&nh->lock, flags);
152 ret = notifier_chain_unregister(&nh->head, n);
153 spin_unlock_irqrestore(&nh->lock, flags);
154 synchronize_rcu();
155 return ret;
156 }
157 EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178 int __atomic_notifier_call_chain(struct atomic_notifier_head *nh,
179 unsigned long val, void *v,
180 int nr_to_call, int *nr_calls)
181 {
182 int ret;
183
184 rcu_read_lock();
185 ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
186 rcu_read_unlock();
187 return ret;
188 }
189 EXPORT_SYMBOL_GPL(__atomic_notifier_call_chain);
190 NOKPROBE_SYMBOL(__atomic_notifier_call_chain);
191
192 int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
193 unsigned long val, void *v)
194 {
195 return __atomic_notifier_call_chain(nh, val, v, -1, NULL);
196 }
197 EXPORT_SYMBOL_GPL(atomic_notifier_call_chain);
198 NOKPROBE_SYMBOL(atomic_notifier_call_chain);
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215 int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
216 struct notifier_block *n)
217 {
218 int ret;
219
220
221
222
223
224
225 if (unlikely(system_state == SYSTEM_BOOTING))
226 return notifier_chain_register(&nh->head, n);
227
228 down_write(&nh->rwsem);
229 ret = notifier_chain_register(&nh->head, n);
230 up_write(&nh->rwsem);
231 return ret;
232 }
233 EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
234
235
236
237
238
239
240
241
242
243
244
245
246 int blocking_notifier_chain_cond_register(struct blocking_notifier_head *nh,
247 struct notifier_block *n)
248 {
249 int ret;
250
251 down_write(&nh->rwsem);
252 ret = notifier_chain_cond_register(&nh->head, n);
253 up_write(&nh->rwsem);
254 return ret;
255 }
256 EXPORT_SYMBOL_GPL(blocking_notifier_chain_cond_register);
257
258
259
260
261
262
263
264
265
266
267
268 int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
269 struct notifier_block *n)
270 {
271 int ret;
272
273
274
275
276
277
278 if (unlikely(system_state == SYSTEM_BOOTING))
279 return notifier_chain_unregister(&nh->head, n);
280
281 down_write(&nh->rwsem);
282 ret = notifier_chain_unregister(&nh->head, n);
283 up_write(&nh->rwsem);
284 return ret;
285 }
286 EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306 int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
307 unsigned long val, void *v,
308 int nr_to_call, int *nr_calls)
309 {
310 int ret = NOTIFY_DONE;
311
312
313
314
315
316
317 if (rcu_access_pointer(nh->head)) {
318 down_read(&nh->rwsem);
319 ret = notifier_call_chain(&nh->head, val, v, nr_to_call,
320 nr_calls);
321 up_read(&nh->rwsem);
322 }
323 return ret;
324 }
325 EXPORT_SYMBOL_GPL(__blocking_notifier_call_chain);
326
327 int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
328 unsigned long val, void *v)
329 {
330 return __blocking_notifier_call_chain(nh, val, v, -1, NULL);
331 }
332 EXPORT_SYMBOL_GPL(blocking_notifier_call_chain);
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349 int raw_notifier_chain_register(struct raw_notifier_head *nh,
350 struct notifier_block *n)
351 {
352 return notifier_chain_register(&nh->head, n);
353 }
354 EXPORT_SYMBOL_GPL(raw_notifier_chain_register);
355
356
357
358
359
360
361
362
363
364
365
366 int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
367 struct notifier_block *n)
368 {
369 return notifier_chain_unregister(&nh->head, n);
370 }
371 EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392 int __raw_notifier_call_chain(struct raw_notifier_head *nh,
393 unsigned long val, void *v,
394 int nr_to_call, int *nr_calls)
395 {
396 return notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
397 }
398 EXPORT_SYMBOL_GPL(__raw_notifier_call_chain);
399
400 int raw_notifier_call_chain(struct raw_notifier_head *nh,
401 unsigned long val, void *v)
402 {
403 return __raw_notifier_call_chain(nh, val, v, -1, NULL);
404 }
405 EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
406
407 #ifdef CONFIG_SRCU
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423 int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
424 struct notifier_block *n)
425 {
426 int ret;
427
428
429
430
431
432
433 if (unlikely(system_state == SYSTEM_BOOTING))
434 return notifier_chain_register(&nh->head, n);
435
436 mutex_lock(&nh->mutex);
437 ret = notifier_chain_register(&nh->head, n);
438 mutex_unlock(&nh->mutex);
439 return ret;
440 }
441 EXPORT_SYMBOL_GPL(srcu_notifier_chain_register);
442
443
444
445
446
447
448
449
450
451
452
453 int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
454 struct notifier_block *n)
455 {
456 int ret;
457
458
459
460
461
462
463 if (unlikely(system_state == SYSTEM_BOOTING))
464 return notifier_chain_unregister(&nh->head, n);
465
466 mutex_lock(&nh->mutex);
467 ret = notifier_chain_unregister(&nh->head, n);
468 mutex_unlock(&nh->mutex);
469 synchronize_srcu(&nh->srcu);
470 return ret;
471 }
472 EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492 int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
493 unsigned long val, void *v,
494 int nr_to_call, int *nr_calls)
495 {
496 int ret;
497 int idx;
498
499 idx = srcu_read_lock(&nh->srcu);
500 ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
501 srcu_read_unlock(&nh->srcu, idx);
502 return ret;
503 }
504 EXPORT_SYMBOL_GPL(__srcu_notifier_call_chain);
505
506 int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
507 unsigned long val, void *v)
508 {
509 return __srcu_notifier_call_chain(nh, val, v, -1, NULL);
510 }
511 EXPORT_SYMBOL_GPL(srcu_notifier_call_chain);
512
513
514
515
516
517
518
519
520
521
522
523
524
525 void srcu_init_notifier_head(struct srcu_notifier_head *nh)
526 {
527 mutex_init(&nh->mutex);
528 if (init_srcu_struct(&nh->srcu) < 0)
529 BUG();
530 nh->head = NULL;
531 }
532 EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
533
534 #endif
535
536 static ATOMIC_NOTIFIER_HEAD(die_chain);
537
538 int notrace notify_die(enum die_val val, const char *str,
539 struct pt_regs *regs, long err, int trap, int sig)
540 {
541 struct die_args args = {
542 .regs = regs,
543 .str = str,
544 .err = err,
545 .trapnr = trap,
546 .signr = sig,
547
548 };
549 RCU_LOCKDEP_WARN(!rcu_is_watching(),
550 "notify_die called but RCU thinks we're quiescent");
551 return atomic_notifier_call_chain(&die_chain, val, &args);
552 }
553 NOKPROBE_SYMBOL(notify_die);
554
555 int register_die_notifier(struct notifier_block *nb)
556 {
557 vmalloc_sync_mappings();
558 return atomic_notifier_chain_register(&die_chain, nb);
559 }
560 EXPORT_SYMBOL_GPL(register_die_notifier);
561
562 int unregister_die_notifier(struct notifier_block *nb)
563 {
564 return atomic_notifier_chain_unregister(&die_chain, nb);
565 }
566 EXPORT_SYMBOL_GPL(unregister_die_notifier);