]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/core/net_namespace.c
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux...
[karo-tx-linux.git] / net / core / net_namespace.c
index e41e5110c65ca2aa1ae57ddfd970caee49a6312f..ea489db1bc2361c20001576a5e909aa22cb689d2 100644 (file)
@@ -128,6 +128,7 @@ static __net_init int setup_net(struct net *net)
        LIST_HEAD(net_exit_list);
 
        atomic_set(&net->count, 1);
+       atomic_set(&net->passive, 1);
 
 #ifdef NETNS_REFCNT_DEBUG
        atomic_set(&net->use_count, 0);
@@ -210,6 +211,13 @@ static void net_free(struct net *net)
        kmem_cache_free(net_cachep, net);
 }
 
+void net_drop_ns(void *p)
+{
+       struct net *ns = p;
+       if (ns && atomic_dec_and_test(&ns->passive))
+               net_free(ns);
+}
+
 struct net *copy_net_ns(unsigned long flags, struct net *old_net)
 {
        struct net *net;
@@ -230,7 +238,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
        }
        mutex_unlock(&net_mutex);
        if (rv < 0) {
-               net_free(net);
+               net_drop_ns(net);
                return ERR_PTR(rv);
        }
        return net;
@@ -286,7 +294,7 @@ static void cleanup_net(struct work_struct *work)
        /* Finally it is safe to free my network namespace structure */
        list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) {
                list_del_init(&net->exit_list);
-               net_free(net);
+               net_drop_ns(net);
        }
 }
 static DECLARE_WORK(net_cleanup_work, cleanup_net);