Merge branch 'master' into 85xx
[linux-drm-fsl-dcu.git] / kernel / sys.c
index c7675c1bfdf24e8c9d45b22e67da5c5679ba662b..6e2101dec0fcfc9e95c52a1ac53bc6898b976edf 100644 (file)
@@ -323,11 +323,18 @@ EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
 int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
                unsigned long val, void *v)
 {
-       int ret;
+       int ret = NOTIFY_DONE;
 
-       down_read(&nh->rwsem);
-       ret = notifier_call_chain(&nh->head, val, v);
-       up_read(&nh->rwsem);
+       /*
+        * We check the head outside the lock, but if this access is
+        * racy then it does not matter what the result of the test
+        * is, we re-check the list after having taken the lock anyway:
+        */
+       if (rcu_dereference(nh->head)) {
+               down_read(&nh->rwsem);
+               ret = notifier_call_chain(&nh->head, val, v);
+               up_read(&nh->rwsem);
+       }
        return ret;
 }