|
@@ -156,7 +156,7 @@ static const struct file_operations socket_file_ops = {
|
|
*/
|
|
*/
|
|
|
|
|
|
static DEFINE_SPINLOCK(net_family_lock);
|
|
static DEFINE_SPINLOCK(net_family_lock);
|
|
-static const struct net_proto_family *net_families[NPROTO] __read_mostly;
|
|
|
|
|
|
+static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
|
|
|
|
|
|
/*
|
|
/*
|
|
* Statistics counters of the socket lists
|
|
* Statistics counters of the socket lists
|
|
@@ -1200,7 +1200,7 @@ int __sock_create(struct net *net, int family, int type, int protocol,
|
|
* requested real, full-featured networking support upon configuration.
|
|
* requested real, full-featured networking support upon configuration.
|
|
* Otherwise module support will break!
|
|
* Otherwise module support will break!
|
|
*/
|
|
*/
|
|
- if (net_families[family] == NULL)
|
|
|
|
|
|
+ if (rcu_access_pointer(net_families[family]) == NULL)
|
|
request_module("net-pf-%d", family);
|
|
request_module("net-pf-%d", family);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
@@ -2332,10 +2332,11 @@ int sock_register(const struct net_proto_family *ops)
|
|
}
|
|
}
|
|
|
|
|
|
spin_lock(&net_family_lock);
|
|
spin_lock(&net_family_lock);
|
|
- if (net_families[ops->family])
|
|
|
|
|
|
+ if (rcu_dereference_protected(net_families[ops->family],
|
|
|
|
+ lockdep_is_held(&net_family_lock)))
|
|
err = -EEXIST;
|
|
err = -EEXIST;
|
|
else {
|
|
else {
|
|
- net_families[ops->family] = ops;
|
|
|
|
|
|
+ rcu_assign_pointer(net_families[ops->family], ops);
|
|
err = 0;
|
|
err = 0;
|
|
}
|
|
}
|
|
spin_unlock(&net_family_lock);
|
|
spin_unlock(&net_family_lock);
|
|
@@ -2363,7 +2364,7 @@ void sock_unregister(int family)
|
|
BUG_ON(family < 0 || family >= NPROTO);
|
|
BUG_ON(family < 0 || family >= NPROTO);
|
|
|
|
|
|
spin_lock(&net_family_lock);
|
|
spin_lock(&net_family_lock);
|
|
- net_families[family] = NULL;
|
|
|
|
|
|
+ rcu_assign_pointer(net_families[family], NULL);
|
|
spin_unlock(&net_family_lock);
|
|
spin_unlock(&net_family_lock);
|
|
|
|
|
|
synchronize_rcu();
|
|
synchronize_rcu();
|