@@ -94,6 +94,34 @@ static int notifier_call_chain(struct notifier_block **nl,
9494}
9595NOKPROBE_SYMBOL (notifier_call_chain );
9696
97+ /**
98+ * notifier_call_chain_robust - Inform the registered notifiers about an event
99+ * and rollback on error.
100+ * @nl: Pointer to head of the blocking notifier chain
101+ * @val_up: Value passed unmodified to the notifier function
102+ * @val_down: Value passed unmodified to the notifier function when recovering
103+ * from an error on @val_up
104+ * @v Pointer passed unmodified to the notifier function
105+ *
106+ * NOTE: It is important the @nl chain doesn't change between the two
107+ * invocations of notifier_call_chain() such that we visit the
108+ * exact same notifier callbacks; this rules out any RCU usage.
109+ *
110+ * Returns: the return value of the @val_up call.
111+ */
112+ static int notifier_call_chain_robust (struct notifier_block * * nl ,
113+ unsigned long val_up , unsigned long val_down ,
114+ void * v )
115+ {
116+ int ret , nr = 0 ;
117+
118+ ret = notifier_call_chain (nl , val_up , v , -1 , & nr );
119+ if (ret & NOTIFY_STOP_MASK )
120+ notifier_call_chain (nl , val_down , v , nr - 1 , NULL );
121+
122+ return ret ;
123+ }
124+
97125/*
98126 * Atomic notifier chain routines. Registration and unregistration
99127 * use a spinlock, and call_chain is synchronized by RCU (no locks).
@@ -144,13 +172,30 @@ int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
144172}
145173EXPORT_SYMBOL_GPL (atomic_notifier_chain_unregister );
146174
175+ int atomic_notifier_call_chain_robust (struct atomic_notifier_head * nh ,
176+ unsigned long val_up , unsigned long val_down , void * v )
177+ {
178+ unsigned long flags ;
179+ int ret ;
180+
181+ /*
182+ * Musn't use RCU; because then the notifier list can
183+ * change between the up and down traversal.
184+ */
185+ spin_lock_irqsave (& nh -> lock , flags );
186+ ret = notifier_call_chain_robust (& nh -> head , val_up , val_down , v );
187+ spin_unlock_irqrestore (& nh -> lock , flags );
188+
189+ return ret ;
190+ }
191+ EXPORT_SYMBOL_GPL (atomic_notifier_call_chain_robust );
192+ NOKPROBE_SYMBOL (atomic_notifier_call_chain_robust );
193+
147194/**
148- * __atomic_notifier_call_chain - Call functions in an atomic notifier chain
195+ * atomic_notifier_call_chain - Call functions in an atomic notifier chain
149196 * @nh: Pointer to head of the atomic notifier chain
150197 * @val: Value passed unmodified to notifier function
151198 * @v: Pointer passed unmodified to notifier function
152- * @nr_to_call: See the comment for notifier_call_chain.
153- * @nr_calls: See the comment for notifier_call_chain.
154199 *
155200 * Calls each function in a notifier chain in turn. The functions
156201 * run in an atomic context, so they must not block.
@@ -163,24 +208,16 @@ EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
163208 * Otherwise the return value is the return value
164209 * of the last notifier function called.
165210 */
166- int __atomic_notifier_call_chain (struct atomic_notifier_head * nh ,
167- unsigned long val , void * v ,
168- int nr_to_call , int * nr_calls )
211+ int atomic_notifier_call_chain (struct atomic_notifier_head * nh ,
212+ unsigned long val , void * v )
169213{
170214 int ret ;
171215
172216 rcu_read_lock ();
173- ret = notifier_call_chain (& nh -> head , val , v , nr_to_call , nr_calls );
217+ ret = notifier_call_chain (& nh -> head , val , v , -1 , NULL );
174218 rcu_read_unlock ();
175- return ret ;
176- }
177- EXPORT_SYMBOL_GPL (__atomic_notifier_call_chain );
178- NOKPROBE_SYMBOL (__atomic_notifier_call_chain );
179219
180- int atomic_notifier_call_chain (struct atomic_notifier_head * nh ,
181- unsigned long val , void * v )
182- {
183- return __atomic_notifier_call_chain (nh , val , v , -1 , NULL );
220+ return ret ;
184221}
185222EXPORT_SYMBOL_GPL (atomic_notifier_call_chain );
186223NOKPROBE_SYMBOL (atomic_notifier_call_chain );
@@ -250,13 +287,30 @@ int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
250287}
251288EXPORT_SYMBOL_GPL (blocking_notifier_chain_unregister );
252289
290+ int blocking_notifier_call_chain_robust (struct blocking_notifier_head * nh ,
291+ unsigned long val_up , unsigned long val_down , void * v )
292+ {
293+ int ret = NOTIFY_DONE ;
294+
295+ /*
296+ * We check the head outside the lock, but if this access is
297+ * racy then it does not matter what the result of the test
298+ * is, we re-check the list after having taken the lock anyway:
299+ */
300+ if (rcu_access_pointer (nh -> head )) {
301+ down_read (& nh -> rwsem );
302+ ret = notifier_call_chain_robust (& nh -> head , val_up , val_down , v );
303+ up_read (& nh -> rwsem );
304+ }
305+ return ret ;
306+ }
307+ EXPORT_SYMBOL_GPL (blocking_notifier_call_chain_robust );
308+
253309/**
254- * __blocking_notifier_call_chain - Call functions in a blocking notifier chain
310+ * blocking_notifier_call_chain - Call functions in a blocking notifier chain
255311 * @nh: Pointer to head of the blocking notifier chain
256312 * @val: Value passed unmodified to notifier function
257313 * @v: Pointer passed unmodified to notifier function
258- * @nr_to_call: See comment for notifier_call_chain.
259- * @nr_calls: See comment for notifier_call_chain.
260314 *
261315 * Calls each function in a notifier chain in turn. The functions
262316 * run in a process context, so they are allowed to block.
@@ -268,9 +322,8 @@ EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
268322 * Otherwise the return value is the return value
269323 * of the last notifier function called.
270324 */
271- int __blocking_notifier_call_chain (struct blocking_notifier_head * nh ,
272- unsigned long val , void * v ,
273- int nr_to_call , int * nr_calls )
325+ int blocking_notifier_call_chain (struct blocking_notifier_head * nh ,
326+ unsigned long val , void * v )
274327{
275328 int ret = NOTIFY_DONE ;
276329
@@ -281,19 +334,11 @@ int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
281334 */
282335 if (rcu_access_pointer (nh -> head )) {
283336 down_read (& nh -> rwsem );
284- ret = notifier_call_chain (& nh -> head , val , v , nr_to_call ,
285- nr_calls );
337+ ret = notifier_call_chain (& nh -> head , val , v , -1 , NULL );
286338 up_read (& nh -> rwsem );
287339 }
288340 return ret ;
289341}
290- EXPORT_SYMBOL_GPL (__blocking_notifier_call_chain );
291-
292- int blocking_notifier_call_chain (struct blocking_notifier_head * nh ,
293- unsigned long val , void * v )
294- {
295- return __blocking_notifier_call_chain (nh , val , v , -1 , NULL );
296- }
297342EXPORT_SYMBOL_GPL (blocking_notifier_call_chain );
298343
299344/*
@@ -335,13 +380,18 @@ int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
335380}
336381EXPORT_SYMBOL_GPL (raw_notifier_chain_unregister );
337382
383+ int raw_notifier_call_chain_robust (struct raw_notifier_head * nh ,
384+ unsigned long val_up , unsigned long val_down , void * v )
385+ {
386+ return notifier_call_chain_robust (& nh -> head , val_up , val_down , v );
387+ }
388+ EXPORT_SYMBOL_GPL (raw_notifier_call_chain_robust );
389+
338390/**
339- * __raw_notifier_call_chain - Call functions in a raw notifier chain
391+ * raw_notifier_call_chain - Call functions in a raw notifier chain
340392 * @nh: Pointer to head of the raw notifier chain
341393 * @val: Value passed unmodified to notifier function
342394 * @v: Pointer passed unmodified to notifier function
343- * @nr_to_call: See comment for notifier_call_chain.
344- * @nr_calls: See comment for notifier_call_chain
345395 *
346396 * Calls each function in a notifier chain in turn. The functions
347397 * run in an undefined context.
@@ -354,18 +404,10 @@ EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
354404 * Otherwise the return value is the return value
355405 * of the last notifier function called.
356406 */
357- int __raw_notifier_call_chain (struct raw_notifier_head * nh ,
358- unsigned long val , void * v ,
359- int nr_to_call , int * nr_calls )
360- {
361- return notifier_call_chain (& nh -> head , val , v , nr_to_call , nr_calls );
362- }
363- EXPORT_SYMBOL_GPL (__raw_notifier_call_chain );
364-
365407int raw_notifier_call_chain (struct raw_notifier_head * nh ,
366408 unsigned long val , void * v )
367409{
368- return __raw_notifier_call_chain ( nh , val , v , -1 , NULL );
410+ return notifier_call_chain ( & nh -> head , val , v , -1 , NULL );
369411}
370412EXPORT_SYMBOL_GPL (raw_notifier_call_chain );
371413
@@ -437,12 +479,10 @@ int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
437479EXPORT_SYMBOL_GPL (srcu_notifier_chain_unregister );
438480
439481/**
440- * __srcu_notifier_call_chain - Call functions in an SRCU notifier chain
482+ * srcu_notifier_call_chain - Call functions in an SRCU notifier chain
441483 * @nh: Pointer to head of the SRCU notifier chain
442484 * @val: Value passed unmodified to notifier function
443485 * @v: Pointer passed unmodified to notifier function
444- * @nr_to_call: See comment for notifier_call_chain.
445- * @nr_calls: See comment for notifier_call_chain
446486 *
447487 * Calls each function in a notifier chain in turn. The functions
448488 * run in a process context, so they are allowed to block.
@@ -454,25 +494,17 @@ EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
454494 * Otherwise the return value is the return value
455495 * of the last notifier function called.
456496 */
457- int __srcu_notifier_call_chain (struct srcu_notifier_head * nh ,
458- unsigned long val , void * v ,
459- int nr_to_call , int * nr_calls )
497+ int srcu_notifier_call_chain (struct srcu_notifier_head * nh ,
498+ unsigned long val , void * v )
460499{
461500 int ret ;
462501 int idx ;
463502
464503 idx = srcu_read_lock (& nh -> srcu );
465- ret = notifier_call_chain (& nh -> head , val , v , nr_to_call , nr_calls );
504+ ret = notifier_call_chain (& nh -> head , val , v , -1 , NULL );
466505 srcu_read_unlock (& nh -> srcu , idx );
467506 return ret ;
468507}
469- EXPORT_SYMBOL_GPL (__srcu_notifier_call_chain );
470-
471- int srcu_notifier_call_chain (struct srcu_notifier_head * nh ,
472- unsigned long val , void * v )
473- {
474- return __srcu_notifier_call_chain (nh , val , v , -1 , NULL );
475- }
476508EXPORT_SYMBOL_GPL (srcu_notifier_call_chain );
477509
478510/**
0 commit comments