Merge tag 'mailbox-v4.17' of git://git.linaro.org/landing-teams/working/fujitsu/integ...
[linux-2.6-microblaze.git] / net / core / rtnetlink.c
index bc29041..4593692 100644 (file)
@@ -75,6 +75,12 @@ void rtnl_lock(void)
 }
 EXPORT_SYMBOL(rtnl_lock);
 
+int rtnl_lock_killable(void)
+{
+       return mutex_lock_killable(&rtnl_mutex);
+}
+EXPORT_SYMBOL(rtnl_lock_killable);
+
 static struct sk_buff *defer_kfree_skb_list;
 void rtnl_kfree_skbs(struct sk_buff *head, struct sk_buff *tail)
 {
@@ -406,7 +412,9 @@ static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops)
  * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
  * @ops: struct rtnl_link_ops * to unregister
  *
- * The caller must hold the rtnl_mutex.
+ * The caller must hold the rtnl_mutex and guarantee net_namespace_list
+ * integrity (hold pernet_ops_rwsem for writing to close the race
+ * with setup_net() and cleanup_net()).
  */
 void __rtnl_link_unregister(struct rtnl_link_ops *ops)
 {
@@ -432,6 +440,9 @@ static void rtnl_lock_unregistering_all(void)
        for (;;) {
                unregistering = false;
                rtnl_lock();
+               /* We held write locked pernet_ops_rwsem, and parallel
+                * setup_net() and cleanup_net() are not possible.
+                */
                for_each_net(net) {
                        if (net->dev_unreg_count > 0) {
                                unregistering = true;
@@ -453,12 +464,12 @@ static void rtnl_lock_unregistering_all(void)
  */
 void rtnl_link_unregister(struct rtnl_link_ops *ops)
 {
-       /* Close the race with cleanup_net() */
-       mutex_lock(&net_mutex);
+       /* Close the race with setup_net() and cleanup_net() */
+       down_write(&pernet_ops_rwsem);
        rtnl_lock_unregistering_all();
        __rtnl_link_unregister(ops);
        rtnl_unlock();
-       mutex_unlock(&net_mutex);
+       up_write(&pernet_ops_rwsem);
 }
 EXPORT_SYMBOL_GPL(rtnl_link_unregister);