The notifier chain facility is a general mechanism provided by the kernel. It is designed to provide a way for kernel elements to express interest in being informed about the occurrence of general asynchronous
events.
The basic building block of the mechanism is the struct notifier_block which is defined in include/linux/notifier.h.
The block contains a pointer to the function to be called when the event occurs. The parameters passed to the notifier function include:
? a pointer to the notifier block itself,
? an event code such as NETDEV_REGISTER or NETDEV_UNREGISTER,
? and a pointer to an unspecified private data type which in the case of the network chain points to the associated struct netdevice.
The kernel function notifier_chain_register() assembles related notifier blocks into notifier chains. Modules within the networking subsystem
use the register_netdevice_notifier() function defined in net/core/dev.c to add their own notifier blocks to the netdev_chain which is statically initialized as NULL in dev.c.
int register_netdevice_notifier(struct notifier_block *nb) { return notifier_chain_register(&netdev_chain, nb); }
Adding the notifier_block to the chain.
The kernel routine notifier_chain_register() links the notifier block into the specified chain in priority order.
/*
* Notifier chain core routines. The exported routines below
* are layered on top of these, with appropriate locking added.
*/
/**
* notifier_call_chain - Informs the registered notifiers about an event.
* @nl: Pointer to head of the blocking notifier chain
* @val: Value passed unmodified to notifier function
* @v: Pointer passed unmodified to notifier function
* @nr_to_call: Number of notifier functions to be called. Don't care
* value of this parameter is -1.
* @nr_calls: Records the number of notifications sent. Don't care
* value of this field is NULL.
* @returns: notifier_call_chain returns the value returned by the
* last notifier function called.
*/ staticint __kprobes notifier_call_chain(struct notifier_block **nl, unsignedlong val,void*v, int nr_to_call,int*nr_calls) { int ret = NOTIFY_DONE; struct notifier_block *nb,*next_nb;
/*
* Notifier chains are of four types:
* * Atomic notifier chains: Chain callbacks run in interrupt/atomic context. Callouts are not allowed to block.
* Blocking notifier chains: Chain callbacks run in process context. Callouts are allowed to block.
* Raw notifier chains: There are no restrictions on callbacks, registration, or unregistration. All locking and protection must be provided by the caller.
* SRCU notifier chains: A variant of blocking notifier chains, with the same restrictions. * * atomic_notifier_chain_register() may be called from an atomic context, but blocking_notifier_chain_register() and srcu_notifier_chain_register() must be called from a process context. Ditto for the corresponding _unregister()
routines.
*
* atomic_notifier_chain_unregister(), blocking_notifier_chain_unregister(),and srcu_notifier_chain_unregister() _must not_ be called from within the call chain.
*
* SRCU notifier chains are an alternative form of blocking notifier chains. They use SRCU (Sleepable Read-Copy Update) instead of rw-semaphores for protection of the chain links. This means there is _very_ low overheadin srcu_notifier_call_chain(): no cache
bounces and no memory barriers. As compensation, srcu_notifier_chain_unregister() is rather expensive. SRCU notifier chains should be used when the chain will be called very often but notifier_blocks will seldom be removed. Also, SRCU notifier chains are slightly
more difficult to use because they require special runtime initialization. */