diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-07-10 05:51:33 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-07-12 17:03:25 -0400 |
commit | 11a28d373ed2539a110d56419457e2e7db221ac7 (patch) | |
tree | d1460cb057299c89ff34b20821e30c8bfc7e589a /net | |
parent | 6c04bb18ddd633b7feac2c8fe2ae0bf61d20ca7a (diff) |
net: make namespace iteration possible under RCU
All we need to take care of is using proper RCU list
add/del primitives and inserting a synchronize_rcu()
at one place to make sure the exit notifiers are run
after everybody has stopped iterating the list.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/net_namespace.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index b7292a2719dc..5cd0b22e649d 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
8 | #include <linux/idr.h> | 8 | #include <linux/idr.h> |
9 | #include <linux/rculist.h> | ||
9 | #include <net/net_namespace.h> | 10 | #include <net/net_namespace.h> |
10 | #include <net/netns/generic.h> | 11 | #include <net/netns/generic.h> |
11 | 12 | ||
@@ -127,7 +128,7 @@ static struct net *net_create(void) | |||
127 | rv = setup_net(net); | 128 | rv = setup_net(net); |
128 | if (rv == 0) { | 129 | if (rv == 0) { |
129 | rtnl_lock(); | 130 | rtnl_lock(); |
130 | list_add_tail(&net->list, &net_namespace_list); | 131 | list_add_tail_rcu(&net->list, &net_namespace_list); |
131 | rtnl_unlock(); | 132 | rtnl_unlock(); |
132 | } | 133 | } |
133 | mutex_unlock(&net_mutex); | 134 | mutex_unlock(&net_mutex); |
@@ -156,9 +157,16 @@ static void cleanup_net(struct work_struct *work) | |||
156 | 157 | ||
157 | /* Don't let anyone else find us. */ | 158 | /* Don't let anyone else find us. */ |
158 | rtnl_lock(); | 159 | rtnl_lock(); |
159 | list_del(&net->list); | 160 | list_del_rcu(&net->list); |
160 | rtnl_unlock(); | 161 | rtnl_unlock(); |
161 | 162 | ||
163 | /* | ||
164 | * Another CPU might be rcu-iterating the list, wait for it. | ||
165 | * This needs to be before calling the exit() notifiers, so | ||
166 | * the rcu_barrier() below isn't sufficient alone. | ||
167 | */ | ||
168 | synchronize_rcu(); | ||
169 | |||
162 | /* Run all of the network namespace exit methods */ | 170 | /* Run all of the network namespace exit methods */ |
163 | list_for_each_entry_reverse(ops, &pernet_list, list) { | 171 | list_for_each_entry_reverse(ops, &pernet_list, list) { |
164 | if (ops->exit) | 172 | if (ops->exit) |
@@ -219,7 +227,7 @@ static int __init net_ns_init(void) | |||
219 | panic("Could not setup the initial network namespace"); | 227 | panic("Could not setup the initial network namespace"); |
220 | 228 | ||
221 | rtnl_lock(); | 229 | rtnl_lock(); |
222 | list_add_tail(&init_net.list, &net_namespace_list); | 230 | list_add_tail_rcu(&init_net.list, &net_namespace_list); |
223 | rtnl_unlock(); | 231 | rtnl_unlock(); |
224 | 232 | ||
225 | mutex_unlock(&net_mutex); | 233 | mutex_unlock(&net_mutex); |