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 |