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);
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;
}
mutex_unlock(&net_mutex);
if (rv < 0) {
- net_free(net);
+ net_drop_ns(net);
return ERR_PTR(rv);
}
return net;
/* 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);
struct file *file;
struct net *net;
- net = ERR_PTR(-EINVAL);
file = proc_ns_fget(fd);
- if (!file)
- goto out;
+ if (IS_ERR(file))
+ return ERR_CAST(file);
ei = PROC_I(file->f_dentry->d_inode);
- if (ei->ns_ops != &netns_operations)
- goto out;
+ if (ei->ns_ops == &netns_operations)
+ net = get_net(ei->ns);
+ else
+ net = ERR_PTR(-EINVAL);
- net = get_net(ei->ns);
-out:
- if (file)
- fput(file);
+ fput(file);
return net;
}