diff options
author | Keith Packard <keithp@keithp.com> | 2011-06-21 15:02:57 -0400 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2011-06-21 15:02:57 -0400 |
commit | 2cd1176bd9e92924242e779dcc5c8fc922f96659 (patch) | |
tree | e9daa254647af2e7d9f99694e19976df0ea2a14d /net/core/net_namespace.c | |
parent | a18711120764dd96ed2ee6a4d436c448542bad77 (diff) | |
parent | e92d03bff9a0d0bcbb812c9b1290ca96c9338d45 (diff) |
Merge branch 'drm-intel-fixes' into drm-intel-next
Diffstat (limited to 'net/core/net_namespace.c')
-rw-r--r-- | net/core/net_namespace.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 6c6b86d0da15..ea489db1bc23 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); |
@@ -310,19 +318,17 @@ struct net *get_net_ns_by_fd(int fd) | |||
310 | struct file *file; | 318 | struct file *file; |
311 | struct net *net; | 319 | struct net *net; |
312 | 320 | ||
313 | net = ERR_PTR(-EINVAL); | ||
314 | file = proc_ns_fget(fd); | 321 | file = proc_ns_fget(fd); |
315 | if (!file) | 322 | if (IS_ERR(file)) |
316 | goto out; | 323 | return ERR_CAST(file); |
317 | 324 | ||
318 | ei = PROC_I(file->f_dentry->d_inode); | 325 | ei = PROC_I(file->f_dentry->d_inode); |
319 | if (ei->ns_ops != &netns_operations) | 326 | if (ei->ns_ops == &netns_operations) |
320 | goto out; | 327 | net = get_net(ei->ns); |
328 | else | ||
329 | net = ERR_PTR(-EINVAL); | ||
321 | 330 | ||
322 | net = get_net(ei->ns); | 331 | fput(file); |
323 | out: | ||
324 | if (file) | ||
325 | fput(file); | ||
326 | return net; | 332 | return net; |
327 | } | 333 | } |
328 | 334 | ||