aboutsummaryrefslogtreecommitdiff
path: root/net/core/net_namespace.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2011-06-24 17:16:40 +0900
committerPaul Mundt <lethal@linux-sh.org>2011-06-24 17:16:40 +0900
commit20733d59d5763ecd96276f868c1f39e677b3b4e2 (patch)
tree89177676a2a45afa97595ce1827630aa131c51e2 /net/core/net_namespace.c
parent75e1b6a84f7e2186e843da94751b6d175caf9209 (diff)
parent17e8c4e1ebf139743e3830439fa65fd906af4a43 (diff)
Merge branch 'fbdev/stable-updates'
Diffstat (limited to 'net/core/net_namespace.c')
-rw-r--r--net/core/net_namespace.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index e41e5110c65..ea489db1bc2 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -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);