aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-07-10 05:51:33 -0400
committerDavid S. Miller <davem@davemloft.net>2009-07-12 17:03:25 -0400
commit11a28d373ed2539a110d56419457e2e7db221ac7 (patch)
treed1460cb057299c89ff34b20821e30c8bfc7e589a /net
parent6c04bb18ddd633b7feac2c8fe2ae0bf61d20ca7a (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.c14
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);