Revert "netns: don't clear nsid too early on removal"
authorNicolas Dichtel <nicolas.dichtel@6wind.com>
Fri, 3 Apr 2015 10:02:36 +0000 (12:02 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 3 Apr 2015 16:36:31 +0000 (12:36 -0400)
This reverts
commit 4217291e592d ("netns: don't clear nsid too early on removal").

This is not the right fix, it introduces races.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/net_namespace.c

index 5221f975a4cc313bd622ecbe9bba263a4faff4a1..cb5290b8c428c5c348b25d842ab9cf3797b70eba 100644 (file)
@@ -349,7 +349,7 @@ static LIST_HEAD(cleanup_list);  /* Must hold cleanup_list_lock to touch */
 static void cleanup_net(struct work_struct *work)
 {
        const struct pernet_operations *ops;
-       struct net *net, *tmp, *peer;
+       struct net *net, *tmp;
        struct list_head net_kill_list;
        LIST_HEAD(net_exit_list);
 
@@ -365,6 +365,14 @@ static void cleanup_net(struct work_struct *work)
        list_for_each_entry(net, &net_kill_list, cleanup_list) {
                list_del_rcu(&net->list);
                list_add_tail(&net->exit_list, &net_exit_list);
+               for_each_net(tmp) {
+                       int id = __peernet2id(tmp, net, false);
+
+                       if (id >= 0)
+                               idr_remove(&tmp->netns_ids, id);
+               }
+               idr_destroy(&net->netns_ids);
+
        }
        rtnl_unlock();
 
@@ -390,26 +398,12 @@ static void cleanup_net(struct work_struct *work)
         */
        rcu_barrier();
 
-       rtnl_lock();
        /* Finally it is safe to free my network namespace structure */
        list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) {
-               /* Unreference net from all peers (no need to loop over
-                * net_exit_list because idr_destroy() will be called for each
-                * element of this list.
-                */
-               for_each_net(peer) {
-                       int id = __peernet2id(peer, net, false);
-
-                       if (id >= 0)
-                               idr_remove(&peer->netns_ids, id);
-               }
-               idr_destroy(&net->netns_ids);
-
                list_del_init(&net->exit_list);
                put_user_ns(net->user_ns);
                net_drop_ns(net);
        }
-       rtnl_unlock();
 }
 static DECLARE_WORK(net_cleanup_work, cleanup_net);