diff options
Diffstat (limited to 'kernel/notifier.c')
| -rw-r--r-- | kernel/notifier.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/kernel/notifier.c b/kernel/notifier.c index 643360d1bb14..823be11584ef 100644 --- a/kernel/notifier.c +++ b/kernel/notifier.c | |||
| @@ -31,6 +31,21 @@ static int notifier_chain_register(struct notifier_block **nl, | |||
| 31 | return 0; | 31 | return 0; |
| 32 | } | 32 | } |
| 33 | 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 | |||
| 34 | static int notifier_chain_unregister(struct notifier_block **nl, | 49 | static int notifier_chain_unregister(struct notifier_block **nl, |
| 35 | struct notifier_block *n) | 50 | struct notifier_block *n) |
| 36 | { | 51 | { |
| @@ -205,6 +220,29 @@ int blocking_notifier_chain_register(struct blocking_notifier_head *nh, | |||
| 205 | EXPORT_SYMBOL_GPL(blocking_notifier_chain_register); | 220 | EXPORT_SYMBOL_GPL(blocking_notifier_chain_register); |
| 206 | 221 | ||
| 207 | /** | 222 | /** |
| 223 | * blocking_notifier_chain_cond_register - Cond add notifier to a blocking notifier chain | ||
| 224 | * @nh: Pointer to head of the blocking notifier chain | ||
| 225 | * @n: New entry in notifier chain | ||
| 226 | * | ||
| 227 | * Adds a notifier to a blocking notifier chain, only if not already | ||
| 228 | * present in the chain. | ||
| 229 | * Must be called in process context. | ||
| 230 | * | ||
| 231 | * Currently always returns zero. | ||
| 232 | */ | ||
| 233 | int blocking_notifier_chain_cond_register(struct blocking_notifier_head *nh, | ||
| 234 | struct notifier_block *n) | ||
| 235 | { | ||
| 236 | int ret; | ||
| 237 | |||
| 238 | down_write(&nh->rwsem); | ||
| 239 | ret = notifier_chain_cond_register(&nh->head, n); | ||
| 240 | up_write(&nh->rwsem); | ||
| 241 | return ret; | ||
| 242 | } | ||
| 243 | EXPORT_SYMBOL_GPL(blocking_notifier_chain_cond_register); | ||
| 244 | |||
| 245 | /** | ||
| 208 | * blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain | 246 | * blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain |
| 209 | * @nh: Pointer to head of the blocking notifier chain | 247 | * @nh: Pointer to head of the blocking notifier chain |
| 210 | * @n: Entry to remove from notifier chain | 248 | * @n: Entry to remove from notifier chain |
