diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-16 13:21:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-16 13:21:59 -0400 |
commit | 8dac6bee32425dd5145b40fa2307648cb7fb4d4a (patch) | |
tree | b7165517729b755686f336b3066ebc982c8793ea /net/core | |
parent | f8f44f09eaa2bfb40651e7fc6054d65c8091499a (diff) | |
parent | d6e43f751f252c68ca69fa6d18665d88d69ef8b7 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
AFS: Use i_generation not i_version for the vnode uniquifier
AFS: Set s_id in the superblock to the volume name
vfs: Fix data corruption after failed write in __block_write_begin()
afs: afs_fill_page reads too much, or wrong data
VFS: Fix vfsmount overput on simultaneous automount
fix wrong iput on d_inode introduced by e6bc45d65d
Delay struct net freeing while there's a sysfs instance refering to it
afs: fix sget() races, close leak on umount
ubifs: fix sget races
ubifs: split allocation of ubifs_info into a separate function
fix leak in proc_set_super()
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/net-sysfs.c | 23 | ||||
-rw-r--r-- | net/core/net_namespace.c | 12 |
2 files changed, 19 insertions, 16 deletions
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 11b98bc2aa8f..33d2a1fba131 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -1179,9 +1179,14 @@ static void remove_queue_kobjects(struct net_device *net) | |||
1179 | #endif | 1179 | #endif |
1180 | } | 1180 | } |
1181 | 1181 | ||
1182 | static const void *net_current_ns(void) | 1182 | static void *net_grab_current_ns(void) |
1183 | { | 1183 | { |
1184 | return current->nsproxy->net_ns; | 1184 | struct net *ns = current->nsproxy->net_ns; |
1185 | #ifdef CONFIG_NET_NS | ||
1186 | if (ns) | ||
1187 | atomic_inc(&ns->passive); | ||
1188 | #endif | ||
1189 | return ns; | ||
1185 | } | 1190 | } |
1186 | 1191 | ||
1187 | static const void *net_initial_ns(void) | 1192 | static const void *net_initial_ns(void) |
@@ -1196,22 +1201,13 @@ static const void *net_netlink_ns(struct sock *sk) | |||
1196 | 1201 | ||
1197 | struct kobj_ns_type_operations net_ns_type_operations = { | 1202 | struct kobj_ns_type_operations net_ns_type_operations = { |
1198 | .type = KOBJ_NS_TYPE_NET, | 1203 | .type = KOBJ_NS_TYPE_NET, |
1199 | .current_ns = net_current_ns, | 1204 | .grab_current_ns = net_grab_current_ns, |
1200 | .netlink_ns = net_netlink_ns, | 1205 | .netlink_ns = net_netlink_ns, |
1201 | .initial_ns = net_initial_ns, | 1206 | .initial_ns = net_initial_ns, |
1207 | .drop_ns = net_drop_ns, | ||
1202 | }; | 1208 | }; |
1203 | EXPORT_SYMBOL_GPL(net_ns_type_operations); | 1209 | EXPORT_SYMBOL_GPL(net_ns_type_operations); |
1204 | 1210 | ||
1205 | static void net_kobj_ns_exit(struct net *net) | ||
1206 | { | ||
1207 | kobj_ns_exit(KOBJ_NS_TYPE_NET, net); | ||
1208 | } | ||
1209 | |||
1210 | static struct pernet_operations kobj_net_ops = { | ||
1211 | .exit = net_kobj_ns_exit, | ||
1212 | }; | ||
1213 | |||
1214 | |||
1215 | #ifdef CONFIG_HOTPLUG | 1211 | #ifdef CONFIG_HOTPLUG |
1216 | static int netdev_uevent(struct device *d, struct kobj_uevent_env *env) | 1212 | static int netdev_uevent(struct device *d, struct kobj_uevent_env *env) |
1217 | { | 1213 | { |
@@ -1339,6 +1335,5 @@ EXPORT_SYMBOL(netdev_class_remove_file); | |||
1339 | int netdev_kobject_init(void) | 1335 | int netdev_kobject_init(void) |
1340 | { | 1336 | { |
1341 | kobj_ns_type_register(&net_ns_type_operations); | 1337 | kobj_ns_type_register(&net_ns_type_operations); |
1342 | register_pernet_subsys(&kobj_net_ops); | ||
1343 | return class_register(&net_class); | 1338 | return class_register(&net_class); |
1344 | } | 1339 | } |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index e41e5110c65c..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); |