diff options
Diffstat (limited to 'net/core/net_namespace.c')
-rw-r--r-- | net/core/net_namespace.c | 12 |
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) | |||
128 | LIST_HEAD(net_exit_list); | 128 | LIST_HEAD(net_exit_list); |
129 | 129 | ||
130 | atomic_set(&net->count, 1); | 130 | atomic_set(&net->count, 1); |
131 | atomic_set(&net->passive, 1); | ||
131 | 132 | ||
132 | #ifdef NETNS_REFCNT_DEBUG | 133 | #ifdef NETNS_REFCNT_DEBUG |
133 | atomic_set(&net->use_count, 0); | 134 | atomic_set(&net->use_count, 0); |
@@ -210,6 +211,13 @@ static void net_free(struct net *net) | |||
210 | kmem_cache_free(net_cachep, net); | 211 | kmem_cache_free(net_cachep, net); |
211 | } | 212 | } |
212 | 213 | ||
214 | void net_drop_ns(void *p) | ||
215 | { | ||
216 | struct net *ns = p; | ||
217 | if (ns && atomic_dec_and_test(&ns->passive)) | ||
218 | net_free(ns); | ||
219 | } | ||
220 | |||
213 | struct net *copy_net_ns(unsigned long flags, struct net *old_net) | 221 | struct net *copy_net_ns(unsigned long flags, struct net *old_net) |
214 | { | 222 | { |
215 | struct net *net; | 223 | struct net *net; |
@@ -230,7 +238,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) | |||
230 | } | 238 | } |
231 | mutex_unlock(&net_mutex); | 239 | mutex_unlock(&net_mutex); |
232 | if (rv < 0) { | 240 | if (rv < 0) { |
233 | net_free(net); | 241 | net_drop_ns(net); |
234 | return ERR_PTR(rv); | 242 | return ERR_PTR(rv); |
235 | } | 243 | } |
236 | return net; | 244 | return net; |
@@ -286,7 +294,7 @@ static void cleanup_net(struct work_struct *work) | |||
286 | /* Finally it is safe to free my network namespace structure */ | 294 | /* Finally it is safe to free my network namespace structure */ |
287 | list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { | 295 | list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { |
288 | list_del_init(&net->exit_list); | 296 | list_del_init(&net->exit_list); |
289 | net_free(net); | 297 | net_drop_ns(net); |
290 | } | 298 | } |
291 | } | 299 | } |
292 | static DECLARE_WORK(net_cleanup_work, cleanup_net); | 300 | static DECLARE_WORK(net_cleanup_work, cleanup_net); |