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 11b98bc2aa8..33d2a1fba13 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 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); |
