diff options
| author | Takashi Iwai <tiwai@suse.de> | 2011-08-08 08:30:29 -0400 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2011-08-08 08:30:29 -0400 |
| commit | 0a2d31b62dba9b5b92a38c67c9cc42630513662a (patch) | |
| tree | f755d74ec85248de645e10c45ed1a2ed467530f6 /net/core/net_namespace.c | |
| parent | 8039290a91c5dc4414093c086987a5d7738fe2fd (diff) | |
| parent | df944f66784e6d4f2f50739263a4947885d8b6ae (diff) | |
Merge branch 'fix/kconfig' into for-linus
Diffstat (limited to 'net/core/net_namespace.c')
| -rw-r--r-- | net/core/net_namespace.c | 29 |
1 files changed, 18 insertions, 11 deletions
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 6c6b86d0da15..5bbdbf0d3664 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
| @@ -128,6 +128,8 @@ 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); | ||
| 132 | net->dev_base_seq = 1; | ||
| 131 | 133 | ||
| 132 | #ifdef NETNS_REFCNT_DEBUG | 134 | #ifdef NETNS_REFCNT_DEBUG |
| 133 | atomic_set(&net->use_count, 0); | 135 | atomic_set(&net->use_count, 0); |
| @@ -210,6 +212,13 @@ static void net_free(struct net *net) | |||
| 210 | kmem_cache_free(net_cachep, net); | 212 | kmem_cache_free(net_cachep, net); |
| 211 | } | 213 | } |
| 212 | 214 | ||
| 215 | void net_drop_ns(void *p) | ||
| 216 | { | ||
| 217 | struct net *ns = p; | ||
| 218 | if (ns && atomic_dec_and_test(&ns->passive)) | ||
| 219 | net_free(ns); | ||
| 220 | } | ||
| 221 | |||
| 213 | struct net *copy_net_ns(unsigned long flags, struct net *old_net) | 222 | struct net *copy_net_ns(unsigned long flags, struct net *old_net) |
| 214 | { | 223 | { |
| 215 | struct net *net; | 224 | struct net *net; |
| @@ -230,7 +239,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) | |||
| 230 | } | 239 | } |
| 231 | mutex_unlock(&net_mutex); | 240 | mutex_unlock(&net_mutex); |
| 232 | if (rv < 0) { | 241 | if (rv < 0) { |
| 233 | net_free(net); | 242 | net_drop_ns(net); |
| 234 | return ERR_PTR(rv); | 243 | return ERR_PTR(rv); |
| 235 | } | 244 | } |
| 236 | return net; | 245 | return net; |
| @@ -286,7 +295,7 @@ static void cleanup_net(struct work_struct *work) | |||
| 286 | /* Finally it is safe to free my network namespace structure */ | 295 | /* Finally it is safe to free my network namespace structure */ |
| 287 | list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { | 296 | list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { |
| 288 | list_del_init(&net->exit_list); | 297 | list_del_init(&net->exit_list); |
| 289 | net_free(net); | 298 | net_drop_ns(net); |
| 290 | } | 299 | } |
| 291 | } | 300 | } |
| 292 | static DECLARE_WORK(net_cleanup_work, cleanup_net); | 301 | static DECLARE_WORK(net_cleanup_work, cleanup_net); |
| @@ -310,19 +319,17 @@ struct net *get_net_ns_by_fd(int fd) | |||
| 310 | struct file *file; | 319 | struct file *file; |
| 311 | struct net *net; | 320 | struct net *net; |
| 312 | 321 | ||
| 313 | net = ERR_PTR(-EINVAL); | ||
| 314 | file = proc_ns_fget(fd); | 322 | file = proc_ns_fget(fd); |
| 315 | if (!file) | 323 | if (IS_ERR(file)) |
| 316 | goto out; | 324 | return ERR_CAST(file); |
| 317 | 325 | ||
| 318 | ei = PROC_I(file->f_dentry->d_inode); | 326 | ei = PROC_I(file->f_dentry->d_inode); |
| 319 | if (ei->ns_ops != &netns_operations) | 327 | if (ei->ns_ops == &netns_operations) |
| 320 | goto out; | 328 | net = get_net(ei->ns); |
| 329 | else | ||
| 330 | net = ERR_PTR(-EINVAL); | ||
| 321 | 331 | ||
| 322 | net = get_net(ei->ns); | 332 | fput(file); |
| 323 | out: | ||
| 324 | if (file) | ||
| 325 | fput(file); | ||
| 326 | return net; | 333 | return net; |
| 327 | } | 334 | } |
| 328 | 335 | ||
