diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-06-08 21:13:01 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-06-12 17:45:41 -0400 |
commit | a685e08987d1edf1995b76511d4c98ea0e905377 (patch) | |
tree | 1d42593e2bc320f8d93b98851b2df0fd432e3859 /include | |
parent | dde194a64bb5c3fd05d965775dc92e8a4920a53a (diff) |
Delay struct net freeing while there's a sysfs instance refering to it
* new refcount in struct net, controlling actual freeing of the memory
* new method in kobj_ns_type_operations (->drop_ns())
* ->current_ns() semantics change - it's supposed to be followed by
corresponding ->drop_ns(). For struct net in case of CONFIG_NET_NS it bumps
the new refcount; net_drop_ns() decrements it and calls net_free() if the
last reference has been dropped. Method renamed to ->grab_current_ns().
* old net_free() callers call net_drop_ns() instead.
* sysfs_exit_ns() is gone, along with a large part of callchain
leading to it; now that the references stored in ->ns[...] stay valid we
do not need to hunt them down and replace them with NULL. That fixes
problems in sysfs_lookup() and sysfs_readdir(), along with getting rid
of sb->s_instances abuse.
Note that struct net *shutdown* logics has not changed - net_cleanup()
is called exactly when it used to be called. The only thing postponed by
having a sysfs instance refering to that struct net is actual freeing of
memory occupied by struct net.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/kobject_ns.h | 10 | ||||
-rw-r--r-- | include/linux/sysfs.h | 7 | ||||
-rw-r--r-- | include/net/net_namespace.h | 10 |
3 files changed, 15 insertions, 12 deletions
diff --git a/include/linux/kobject_ns.h b/include/linux/kobject_ns.h index 82cb5bf461fb..f66b065a8b5f 100644 --- a/include/linux/kobject_ns.h +++ b/include/linux/kobject_ns.h | |||
@@ -32,15 +32,17 @@ enum kobj_ns_type { | |||
32 | 32 | ||
33 | /* | 33 | /* |
34 | * Callbacks so sysfs can determine namespaces | 34 | * Callbacks so sysfs can determine namespaces |
35 | * @current_ns: return calling task's namespace | 35 | * @grab_current_ns: return a new reference to calling task's namespace |
36 | * @netlink_ns: return namespace to which a sock belongs (right?) | 36 | * @netlink_ns: return namespace to which a sock belongs (right?) |
37 | * @initial_ns: return the initial namespace (i.e. init_net_ns) | 37 | * @initial_ns: return the initial namespace (i.e. init_net_ns) |
38 | * @drop_ns: drops a reference to namespace | ||
38 | */ | 39 | */ |
39 | struct kobj_ns_type_operations { | 40 | struct kobj_ns_type_operations { |
40 | enum kobj_ns_type type; | 41 | enum kobj_ns_type type; |
41 | const void *(*current_ns)(void); | 42 | void *(*grab_current_ns)(void); |
42 | const void *(*netlink_ns)(struct sock *sk); | 43 | const void *(*netlink_ns)(struct sock *sk); |
43 | const void *(*initial_ns)(void); | 44 | const void *(*initial_ns)(void); |
45 | void (*drop_ns)(void *); | ||
44 | }; | 46 | }; |
45 | 47 | ||
46 | int kobj_ns_type_register(const struct kobj_ns_type_operations *ops); | 48 | int kobj_ns_type_register(const struct kobj_ns_type_operations *ops); |
@@ -48,9 +50,9 @@ int kobj_ns_type_registered(enum kobj_ns_type type); | |||
48 | const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent); | 50 | const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent); |
49 | const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj); | 51 | const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj); |
50 | 52 | ||
51 | const void *kobj_ns_current(enum kobj_ns_type type); | 53 | void *kobj_ns_grab_current(enum kobj_ns_type type); |
52 | const void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk); | 54 | const void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk); |
53 | const void *kobj_ns_initial(enum kobj_ns_type type); | 55 | const void *kobj_ns_initial(enum kobj_ns_type type); |
54 | void kobj_ns_exit(enum kobj_ns_type type, const void *ns); | 56 | void kobj_ns_drop(enum kobj_ns_type type, void *ns); |
55 | 57 | ||
56 | #endif /* _LINUX_KOBJECT_NS_H */ | 58 | #endif /* _LINUX_KOBJECT_NS_H */ |
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index c3acda60eee0..e2696d76a599 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h | |||
@@ -177,9 +177,6 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, | |||
177 | struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd); | 177 | struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd); |
178 | void sysfs_put(struct sysfs_dirent *sd); | 178 | void sysfs_put(struct sysfs_dirent *sd); |
179 | 179 | ||
180 | /* Called to clear a ns tag when it is no longer valid */ | ||
181 | void sysfs_exit_ns(enum kobj_ns_type type, const void *tag); | ||
182 | |||
183 | int __must_check sysfs_init(void); | 180 | int __must_check sysfs_init(void); |
184 | 181 | ||
185 | #else /* CONFIG_SYSFS */ | 182 | #else /* CONFIG_SYSFS */ |
@@ -338,10 +335,6 @@ static inline void sysfs_put(struct sysfs_dirent *sd) | |||
338 | { | 335 | { |
339 | } | 336 | } |
340 | 337 | ||
341 | static inline void sysfs_exit_ns(int type, const void *tag) | ||
342 | { | ||
343 | } | ||
344 | |||
345 | static inline int __must_check sysfs_init(void) | 338 | static inline int __must_check sysfs_init(void) |
346 | { | 339 | { |
347 | return 0; | 340 | return 0; |
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 2bf9ed9ef26b..aef430d779bd 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h | |||
@@ -35,8 +35,11 @@ struct netns_ipvs; | |||
35 | #define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS) | 35 | #define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS) |
36 | 36 | ||
37 | struct net { | 37 | struct net { |
38 | atomic_t passive; /* To decided when the network | ||
39 | * namespace should be freed. | ||
40 | */ | ||
38 | atomic_t count; /* To decided when the network | 41 | atomic_t count; /* To decided when the network |
39 | * namespace should be freed. | 42 | * namespace should be shut down. |
40 | */ | 43 | */ |
41 | #ifdef NETNS_REFCNT_DEBUG | 44 | #ifdef NETNS_REFCNT_DEBUG |
42 | atomic_t use_count; /* To track references we | 45 | atomic_t use_count; /* To track references we |
@@ -154,6 +157,9 @@ int net_eq(const struct net *net1, const struct net *net2) | |||
154 | { | 157 | { |
155 | return net1 == net2; | 158 | return net1 == net2; |
156 | } | 159 | } |
160 | |||
161 | extern void net_drop_ns(void *); | ||
162 | |||
157 | #else | 163 | #else |
158 | 164 | ||
159 | static inline struct net *get_net(struct net *net) | 165 | static inline struct net *get_net(struct net *net) |
@@ -175,6 +181,8 @@ int net_eq(const struct net *net1, const struct net *net2) | |||
175 | { | 181 | { |
176 | return 1; | 182 | return 1; |
177 | } | 183 | } |
184 | |||
185 | #define net_drop_ns NULL | ||
178 | #endif | 186 | #endif |
179 | 187 | ||
180 | 188 | ||