The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kernel/notifier.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include <linux/kdebug.h>
    2 #include <linux/kprobes.h>
    3 #include <linux/export.h>
    4 #include <linux/notifier.h>
    5 #include <linux/rcupdate.h>
    6 #include <linux/vmalloc.h>
    7 #include <linux/reboot.h>
    8 
    9 /*
   10  *      Notifier list for kernel code which wants to be called
   11  *      at shutdown. This is used to stop any idling DMA operations
   12  *      and the like.
   13  */
   14 BLOCKING_NOTIFIER_HEAD(reboot_notifier_list);
   15 
   16 /*
   17  *      Notifier chain core routines.  The exported routines below
   18  *      are layered on top of these, with appropriate locking added.
   19  */
   20 
   21 static int notifier_chain_register(struct notifier_block **nl,
   22                 struct notifier_block *n)
   23 {
   24         while ((*nl) != NULL) {
   25                 if (n->priority > (*nl)->priority)
   26                         break;
   27                 nl = &((*nl)->next);
   28         }
   29         n->next = *nl;
   30         rcu_assign_pointer(*nl, n);
   31         return 0;
   32 }
   33 
   34 static int notifier_chain_cond_register(struct notifier_block **nl,
   35                 struct notifier_block *n)
   36 {
   37         while ((*nl) != NULL) {
   38                 if ((*nl) == n)
   39                         return 0;
   40                 if (n->priority > (*nl)->priority)
   41                         break;
   42                 nl = &((*nl)->next);
   43         }
   44         n->next = *nl;
   45         rcu_assign_pointer(*nl, n);
   46         return 0;
   47 }
   48 
   49 static int notifier_chain_unregister(struct notifier_block **nl,
   50                 struct notifier_block *n)
   51 {
   52         while ((*nl) != NULL) {
   53                 if ((*nl) == n) {
   54                         rcu_assign_pointer(*nl, n->next);
   55                         return 0;
   56                 }
   57                 nl = &((*nl)->next);
   58         }
   59         return -ENOENT;
   60 }
   61 
   62 /**
   63  * notifier_call_chain - Informs the registered notifiers about an event.
   64  *      @nl:            Pointer to head of the blocking notifier chain
   65  *      @val:           Value passed unmodified to notifier function
   66  *      @v:             Pointer passed unmodified to notifier function
   67  *      @nr_to_call:    Number of notifier functions to be called. Don't care
   68  *                      value of this parameter is -1.
   69  *      @nr_calls:      Records the number of notifications sent. Don't care
   70  *                      value of this field is NULL.
   71  *      @returns:       notifier_call_chain returns the value returned by the
   72  *                      last notifier function called.
   73  */
   74 static int __kprobes notifier_call_chain(struct notifier_block **nl,
   75                                         unsigned long val, void *v,
   76                                         int nr_to_call, int *nr_calls)
   77 {
   78         int ret = NOTIFY_DONE;
   79         struct notifier_block *nb, *next_nb;
   80 
   81         nb = rcu_dereference_raw(*nl);
   82 
   83         while (nb && nr_to_call) {
   84                 next_nb = rcu_dereference_raw(nb->next);
   85 
   86 #ifdef CONFIG_DEBUG_NOTIFIERS
   87                 if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) {
   88                         WARN(1, "Invalid notifier called!");
   89                         nb = next_nb;
   90                         continue;
   91                 }
   92 #endif
   93                 ret = nb->notifier_call(nb, val, v);
   94 
   95                 if (nr_calls)
   96                         (*nr_calls)++;
   97 
   98                 if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
   99                         break;
  100                 nb = next_nb;
  101                 nr_to_call--;
  102         }
  103         return ret;
  104 }
  105 
  106 /*
  107  *      Atomic notifier chain routines.  Registration and unregistration
  108  *      use a spinlock, and call_chain is synchronized by RCU (no locks).
  109  */
  110 
  111 /**
  112  *      atomic_notifier_chain_register - Add notifier to an atomic notifier chain
  113  *      @nh: Pointer to head of the atomic notifier chain
  114  *      @n: New entry in notifier chain
  115  *
  116  *      Adds a notifier to an atomic notifier chain.
  117  *
  118  *      Currently always returns zero.
  119  */
  120 int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
  121                 struct notifier_block *n)
  122 {
  123         unsigned long flags;
  124         int ret;
  125 
  126         spin_lock_irqsave(&nh->lock, flags);
  127         ret = notifier_chain_register(&nh->head, n);
  128         spin_unlock_irqrestore(&nh->lock, flags);
  129         return ret;
  130 }
  131 EXPORT_SYMBOL_GPL(atomic_notifier_chain_register);
  132 
  133 /**
  134  *      atomic_notifier_chain_unregister - Remove notifier from an atomic notifier chain
  135  *      @nh: Pointer to head of the atomic notifier chain
  136  *      @n: Entry to remove from notifier chain
  137  *
  138  *      Removes a notifier from an atomic notifier chain.
  139  *
  140  *      Returns zero on success or %-ENOENT on failure.
  141  */
  142 int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
  143                 struct notifier_block *n)
  144 {
  145         unsigned long flags;
  146         int ret;
  147 
  148         spin_lock_irqsave(&nh->lock, flags);
  149         ret = notifier_chain_unregister(&nh->head, n);
  150         spin_unlock_irqrestore(&nh->lock, flags);
  151         synchronize_rcu();
  152         return ret;
  153 }
  154 EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
  155 
  156 /**
  157  *      __atomic_notifier_call_chain - Call functions in an atomic notifier chain
  158  *      @nh: Pointer to head of the atomic notifier chain
  159  *      @val: Value passed unmodified to notifier function
  160  *      @v: Pointer passed unmodified to notifier function
  161  *      @nr_to_call: See the comment for notifier_call_chain.
  162  *      @nr_calls: See the comment for notifier_call_chain.
  163  *
  164  *      Calls each function in a notifier chain in turn.  The functions
  165  *      run in an atomic context, so they must not block.
  166  *      This routine uses RCU to synchronize with changes to the chain.
  167  *
  168  *      If the return value of the notifier can be and'ed
  169  *      with %NOTIFY_STOP_MASK then atomic_notifier_call_chain()
  170  *      will return immediately, with the return value of
  171  *      the notifier function which halted execution.
  172  *      Otherwise the return value is the return value
  173  *      of the last notifier function called.
  174  */
  175 int __kprobes __atomic_notifier_call_chain(struct atomic_notifier_head *nh,
  176                                         unsigned long val, void *v,
  177                                         int nr_to_call, int *nr_calls)
  178 {
  179         int ret;
  180 
  181         rcu_read_lock();
  182         ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
  183         rcu_read_unlock();
  184         return ret;
  185 }
  186 EXPORT_SYMBOL_GPL(__atomic_notifier_call_chain);
  187 
  188 int __kprobes atomic_notifier_call_chain(struct atomic_notifier_head *nh,
  189                 unsigned long val, void *v)
  190 {
  191         return __atomic_notifier_call_chain(nh, val, v, -1, NULL);
  192 }
  193 EXPORT_SYMBOL_GPL(atomic_notifier_call_chain);
  194 
  195 /*
  196  *      Blocking notifier chain routines.  All access to the chain is
  197  *      synchronized by an rwsem.
  198  */
  199 
  200 /**
  201  *      blocking_notifier_chain_register - Add notifier to a blocking notifier chain
  202  *      @nh: Pointer to head of the blocking notifier chain
  203  *      @n: New entry in notifier chain
  204  *
  205  *      Adds a notifier to a blocking notifier chain.
  206  *      Must be called in process context.
  207  *
  208  *      Currently always returns zero.
  209  */
  210 int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
  211                 struct notifier_block *n)
  212 {
  213         int ret;
  214 
  215         /*
  216          * This code gets used during boot-up, when task switching is
  217          * not yet working and interrupts must remain disabled.  At
  218          * such times we must not call down_write().
  219          */
  220         if (unlikely(system_state == SYSTEM_BOOTING))
  221                 return notifier_chain_register(&nh->head, n);
  222 
  223         down_write(&nh->rwsem);
  224         ret = notifier_chain_register(&nh->head, n);
  225         up_write(&nh->rwsem);
  226         return ret;
  227 }
  228 EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
  229 
  230 /**
  231  *      blocking_notifier_chain_cond_register - Cond add notifier to a blocking notifier chain
  232  *      @nh: Pointer to head of the blocking notifier chain
  233  *      @n: New entry in notifier chain
  234  *
  235  *      Adds a notifier to a blocking notifier chain, only if not already
  236  *      present in the chain.
  237  *      Must be called in process context.
  238  *
  239  *      Currently always returns zero.
  240  */
  241 int blocking_notifier_chain_cond_register(struct blocking_notifier_head *nh,
  242                 struct notifier_block *n)
  243 {
  244         int ret;
  245 
  246         down_write(&nh->rwsem);
  247         ret = notifier_chain_cond_register(&nh->head, n);
  248         up_write(&nh->rwsem);
  249         return ret;
  250 }
  251 EXPORT_SYMBOL_GPL(blocking_notifier_chain_cond_register);
  252 
  253 /**
  254  *      blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain
  255  *      @nh: Pointer to head of the blocking notifier chain
  256  *      @n: Entry to remove from notifier chain
  257  *
  258  *      Removes a notifier from a blocking notifier chain.
  259  *      Must be called from process context.
  260  *
  261  *      Returns zero on success or %-ENOENT on failure.
  262  */
  263 int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
  264                 struct notifier_block *n)
  265 {
  266         int ret;
  267 
  268         /*
  269          * This code gets used during boot-up, when task switching is
  270          * not yet working and interrupts must remain disabled.  At
  271          * such times we must not call down_write().
  272          */
  273         if (unlikely(system_state == SYSTEM_BOOTING))
  274                 return notifier_chain_unregister(&nh->head, n);
  275 
  276         down_write(&nh->rwsem);
  277         ret = notifier_chain_unregister(&nh->head, n);
  278         up_write(&nh->rwsem);
  279         return ret;
  280 }
  281 EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
  282 
  283 /**
  284  *      __blocking_notifier_call_chain - Call functions in a blocking notifier chain
  285  *      @nh: Pointer to head of the blocking notifier chain
  286  *      @val: Value passed unmodified to notifier function
  287  *      @v: Pointer passed unmodified to notifier function
  288  *      @nr_to_call: See comment for notifier_call_chain.
  289  *      @nr_calls: See comment for notifier_call_chain.
  290  *
  291  *      Calls each function in a notifier chain in turn.  The functions
  292  *      run in a process context, so they are allowed to block.
  293  *
  294  *      If the return value of the notifier can be and'ed
  295  *      with %NOTIFY_STOP_MASK then blocking_notifier_call_chain()
  296  *      will return immediately, with the return value of
  297  *      the notifier function which halted execution.
  298  *      Otherwise the return value is the return value
  299  *      of the last notifier function called.
  300  */
  301 int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
  302                                    unsigned long val, void *v,
  303                                    int nr_to_call, int *nr_calls)
  304 {
  305         int ret = NOTIFY_DONE;
  306 
  307         /*
  308          * We check the head outside the lock, but if this access is
  309          * racy then it does not matter what the result of the test
  310          * is, we re-check the list after having taken the lock anyway:
  311          */
  312         if (rcu_dereference_raw(nh->head)) {
  313                 down_read(&nh->rwsem);
  314                 ret = notifier_call_chain(&nh->head, val, v, nr_to_call,
  315                                         nr_calls);
  316                 up_read(&nh->rwsem);
  317         }
  318         return ret;
  319 }
  320 EXPORT_SYMBOL_GPL(__blocking_notifier_call_chain);
  321 
  322 int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
  323                 unsigned long val, void *v)
  324 {
  325         return __blocking_notifier_call_chain(nh, val, v, -1, NULL);
  326 }
  327 EXPORT_SYMBOL_GPL(blocking_notifier_call_chain);
  328 
  329 /*
  330  *      Raw notifier chain routines.  There is no protection;
  331  *      the caller must provide it.  Use at your own risk!
  332  */
  333 
  334 /**
  335  *      raw_notifier_chain_register - Add notifier to a raw notifier chain
  336  *      @nh: Pointer to head of the raw notifier chain
  337  *      @n: New entry in notifier chain
  338  *
  339  *      Adds a notifier to a raw notifier chain.
  340  *      All locking must be provided by the caller.
  341  *
  342  *      Currently always returns zero.
  343  */
  344 int raw_notifier_chain_register(struct raw_notifier_head *nh,
  345                 struct notifier_block *n)
  346 {
  347         return notifier_chain_register(&nh->head, n);
  348 }
  349 EXPORT_SYMBOL_GPL(raw_notifier_chain_register);
  350 
  351 /**
  352  *      raw_notifier_chain_unregister - Remove notifier from a raw notifier chain
  353  *      @nh: Pointer to head of the raw notifier chain
  354  *      @n: Entry to remove from notifier chain
  355  *
  356  *      Removes a notifier from a raw notifier chain.
  357  *      All locking must be provided by the caller.
  358  *
  359  *      Returns zero on success or %-ENOENT on failure.
  360  */
  361 int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
  362                 struct notifier_block *n)
  363 {
  364         return notifier_chain_unregister(&nh->head, n);
  365 }
  366 EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
  367 
  368 /**
  369  *      __raw_notifier_call_chain - Call functions in a raw notifier chain
  370  *      @nh: Pointer to head of the raw notifier chain
  371  *      @val: Value passed unmodified to notifier function
  372  *      @v: Pointer passed unmodified to notifier function
  373  *      @nr_to_call: See comment for notifier_call_chain.
  374  *      @nr_calls: See comment for notifier_call_chain
  375  *
  376  *      Calls each function in a notifier chain in turn.  The functions
  377  *      run in an undefined context.
  378  *      All locking must be provided by the caller.
  379  *
  380  *      If the return value of the notifier can be and'ed
  381  *      with %NOTIFY_STOP_MASK then raw_notifier_call_chain()
  382  *      will return immediately, with the return value of
  383  *      the notifier function which halted execution.
  384  *      Otherwise the return value is the return value
  385  *      of the last notifier function called.
  386  */
  387 int __raw_notifier_call_chain(struct raw_notifier_head *nh,
  388                               unsigned long val, void *v,
  389                               int nr_to_call, int *nr_calls)
  390 {
  391         return notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
  392 }
  393 EXPORT_SYMBOL_GPL(__raw_notifier_call_chain);
  394 
  395 int raw_notifier_call_chain(struct raw_notifier_head *nh,
  396                 unsigned long val, void *v)
  397 {
  398         return __raw_notifier_call_chain(nh, val, v, -1, NULL);
  399 }
  400 EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
  401 
  402 /*
  403  *      SRCU notifier chain routines.    Registration and unregistration
  404  *      use a mutex, and call_chain is synchronized by SRCU (no locks).
  405  */
  406 
  407 /**
  408  *      srcu_notifier_chain_register - Add notifier to an SRCU notifier chain
  409  *      @nh: Pointer to head of the SRCU notifier chain
  410  *      @n: New entry in notifier chain
  411  *
  412  *      Adds a notifier to an SRCU notifier chain.
  413  *      Must be called in process context.
  414  *
  415  *      Currently always returns zero.
  416  */
  417 int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
  418                 struct notifier_block *n)
  419 {
  420         int ret;
  421 
  422         /*
  423          * This code gets used during boot-up, when task switching is
  424          * not yet working and interrupts must remain disabled.  At
  425          * such times we must not call mutex_lock().
  426          */
  427         if (unlikely(system_state == SYSTEM_BOOTING))
  428                 return notifier_chain_register(&nh->head, n);
  429 
  430         mutex_lock(&nh->mutex);
  431         ret = notifier_chain_register(&nh->head, n);
  432         mutex_unlock(&nh->mutex);
  433         return ret;
  434 }
  435 EXPORT_SYMBOL_GPL(srcu_notifier_chain_register);
  436 
  437 /**
  438  *      srcu_notifier_chain_unregister - Remove notifier from an SRCU notifier chain
  439  *      @nh: Pointer to head of the SRCU notifier chain
  440  *      @n: Entry to remove from notifier chain
  441  *
  442  *      Removes a notifier from an SRCU notifier chain.
  443  *      Must be called from process context.
  444  *
  445  *      Returns zero on success or %-ENOENT on failure.
  446  */
  447 int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
  448                 struct notifier_block *n)
  449 {
  450         int ret;
  451 
  452         /*
  453          * This code gets used during boot-up, when task switching is
  454          * not yet working and interrupts must remain disabled.  At
  455          * such times we must not call mutex_lock().
  456          */
  457         if (unlikely(system_state == SYSTEM_BOOTING))
  458                 return notifier_chain_unregister(&nh->head, n);
  459 
  460         mutex_lock(&nh->mutex);
  461         ret = notifier_chain_unregister(&nh->head, n);
  462         mutex_unlock(&nh->mutex);
  463         synchronize_srcu(&nh->srcu);
  464         return ret;
  465 }
  466 EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
  467 
  468 /**
  469  *      __srcu_notifier_call_chain - Call functions in an SRCU notifier chain
  470  *      @nh: Pointer to head of the SRCU notifier chain
  471  *      @val: Value passed unmodified to notifier function
  472  *      @v: Pointer passed unmodified to notifier function
  473  *      @nr_to_call: See comment for notifier_call_chain.
  474  *      @nr_calls: See comment for notifier_call_chain
  475  *
  476  *      Calls each function in a notifier chain in turn.  The functions
  477  *      run in a process context, so they are allowed to block.
  478  *
  479  *      If the return value of the notifier can be and'ed
  480  *      with %NOTIFY_STOP_MASK then srcu_notifier_call_chain()
  481  *      will return immediately, with the return value of
  482  *      the notifier function which halted execution.
  483  *      Otherwise the return value is the return value
  484  *      of the last notifier function called.
  485  */
  486 int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
  487                                unsigned long val, void *v,
  488                                int nr_to_call, int *nr_calls)
  489 {
  490         int ret;
  491         int idx;
  492 
  493         idx = srcu_read_lock(&nh->srcu);
  494         ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
  495         srcu_read_unlock(&nh->srcu, idx);
  496         return ret;
  497 }
  498 EXPORT_SYMBOL_GPL(__srcu_notifier_call_chain);
  499 
  500 int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
  501                 unsigned long val, void *v)
  502 {
  503         return __srcu_notifier_call_chain(nh, val, v, -1, NULL);
  504 }
  505 EXPORT_SYMBOL_GPL(srcu_notifier_call_chain);
  506 
  507 /**
  508  *      srcu_init_notifier_head - Initialize an SRCU notifier head
  509  *      @nh: Pointer to head of the srcu notifier chain
  510  *
  511  *      Unlike other sorts of notifier heads, SRCU notifier heads require
  512  *      dynamic initialization.  Be sure to call this routine before
  513  *      calling any of the other SRCU notifier routines for this head.
  514  *
  515  *      If an SRCU notifier head is deallocated, it must first be cleaned
  516  *      up by calling srcu_cleanup_notifier_head().  Otherwise the head's
  517  *      per-cpu data (used by the SRCU mechanism) will leak.
  518  */
  519 void srcu_init_notifier_head(struct srcu_notifier_head *nh)
  520 {
  521         mutex_init(&nh->mutex);
  522         if (init_srcu_struct(&nh->srcu) < 0)
  523                 BUG();
  524         nh->head = NULL;
  525 }
  526 EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
  527 
  528 static ATOMIC_NOTIFIER_HEAD(die_chain);
  529 
  530 int notrace __kprobes notify_die(enum die_val val, const char *str,
  531                struct pt_regs *regs, long err, int trap, int sig)
  532 {
  533         struct die_args args = {
  534                 .regs   = regs,
  535                 .str    = str,
  536                 .err    = err,
  537                 .trapnr = trap,
  538                 .signr  = sig,
  539 
  540         };
  541         return atomic_notifier_call_chain(&die_chain, val, &args);
  542 }
  543 
  544 int register_die_notifier(struct notifier_block *nb)
  545 {
  546         vmalloc_sync_all();
  547         return atomic_notifier_chain_register(&die_chain, nb);
  548 }
  549 EXPORT_SYMBOL_GPL(register_die_notifier);
  550 
  551 int unregister_die_notifier(struct notifier_block *nb)
  552 {
  553         return atomic_notifier_chain_unregister(&die_chain, nb);
  554 }
  555 EXPORT_SYMBOL_GPL(unregister_die_notifier);

Cache object: 7edf44d3d02bf519914c8449c54d3c55


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.