aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c124
1 files changed, 123 insertions, 1 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index 2314867ae34f..fd5c71006775 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -153,7 +153,7 @@ static int __kprobes notifier_call_chain(struct notifier_block **nl,
153 153
154/* 154/*
155 * Atomic notifier chain routines. Registration and unregistration 155 * Atomic notifier chain routines. Registration and unregistration
156 * use a mutex, and call_chain is synchronized by RCU (no locks). 156 * use a spinlock, and call_chain is synchronized by RCU (no locks).
157 */ 157 */
158 158
159/** 159/**
@@ -401,6 +401,128 @@ int raw_notifier_call_chain(struct raw_notifier_head *nh,
401 401
402EXPORT_SYMBOL_GPL(raw_notifier_call_chain); 402EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
403 403
404/*
405 * SRCU notifier chain routines. Registration and unregistration
406 * use a mutex, and call_chain is synchronized by SRCU (no locks).
407 */
408
409/**
410 * srcu_notifier_chain_register - Add notifier to an SRCU notifier chain
411 * @nh: Pointer to head of the SRCU notifier chain
412 * @n: New entry in notifier chain
413 *
414 * Adds a notifier to an SRCU notifier chain.
415 * Must be called in process context.
416 *
417 * Currently always returns zero.
418 */
419
420int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
421 struct notifier_block *n)
422{
423 int ret;
424
425 /*
426 * This code gets used during boot-up, when task switching is
427 * not yet working and interrupts must remain disabled. At
428 * such times we must not call mutex_lock().
429 */
430 if (unlikely(system_state == SYSTEM_BOOTING))
431 return notifier_chain_register(&nh->head, n);
432
433 mutex_lock(&nh->mutex);
434 ret = notifier_chain_register(&nh->head, n);
435 mutex_unlock(&nh->mutex);
436 return ret;
437}
438
439EXPORT_SYMBOL_GPL(srcu_notifier_chain_register);
440
441/**
442 * srcu_notifier_chain_unregister - Remove notifier from an SRCU notifier chain
443 * @nh: Pointer to head of the SRCU notifier chain
444 * @n: Entry to remove from notifier chain
445 *
446 * Removes a notifier from an SRCU notifier chain.
447 * Must be called from process context.
448 *
449 * Returns zero on success or %-ENOENT on failure.
450 */
451int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
452 struct notifier_block *n)
453{
454 int ret;
455
456 /*
457 * This code gets used during boot-up, when task switching is
458 * not yet working and interrupts must remain disabled. At
459 * such times we must not call mutex_lock().
460 */
461 if (unlikely(system_state == SYSTEM_BOOTING))
462 return notifier_chain_unregister(&nh->head, n);
463
464 mutex_lock(&nh->mutex);
465 ret = notifier_chain_unregister(&nh->head, n);
466 mutex_unlock(&nh->mutex);
467 synchronize_srcu(&nh->srcu);
468 return ret;
469}
470
471EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
472
473/**
474 * srcu_notifier_call_chain - Call functions in an SRCU notifier chain
475 * @nh: Pointer to head of the SRCU notifier chain
476 * @val: Value passed unmodified to notifier function
477 * @v: Pointer passed unmodified to notifier function
478 *
479 * Calls each function in a notifier chain in turn. The functions
480 * run in a process context, so they are allowed to block.
481 *
482 * If the return value of the notifier can be and'ed
483 * with %NOTIFY_STOP_MASK then srcu_notifier_call_chain
484 * will return immediately, with the return value of
485 * the notifier function which halted execution.
486 * Otherwise the return value is the return value
487 * of the last notifier function called.
488 */
489
490int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
491 unsigned long val, void *v)
492{
493 int ret;
494 int idx;
495
496 idx = srcu_read_lock(&nh->srcu);
497 ret = notifier_call_chain(&nh->head, val, v);
498 srcu_read_unlock(&nh->srcu, idx);
499 return ret;
500}
501
502EXPORT_SYMBOL_GPL(srcu_notifier_call_chain);
503
504/**
505 * srcu_init_notifier_head - Initialize an SRCU notifier head
506 * @nh: Pointer to head of the srcu notifier chain
507 *
508 * Unlike other sorts of notifier heads, SRCU notifier heads require
509 * dynamic initialization. Be sure to call this routine before
510 * calling any of the other SRCU notifier routines for this head.
511 *
512 * If an SRCU notifier head is deallocated, it must first be cleaned
513 * up by calling srcu_cleanup_notifier_head(). Otherwise the head's
514 * per-cpu data (used by the SRCU mechanism) will leak.
515 */
516
517void srcu_init_notifier_head(struct srcu_notifier_head *nh)
518{
519 mutex_init(&nh->mutex);
520 init_srcu_struct(&nh->srcu);
521 nh->head = NULL;
522}
523
524EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
525
404/** 526/**
405 * register_reboot_notifier - Register function to be called at reboot time 527 * register_reboot_notifier - Register function to be called at reboot time
406 * @nb: Info about notifier function to be called 528 * @nb: Info about notifier function to be called