diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/socket.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/net/socket.c b/net/socket.c index 3ca2fd9e3720..c898df76e924 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -156,7 +156,7 @@ static const struct file_operations socket_file_ops = { | |||
156 | */ | 156 | */ |
157 | 157 | ||
158 | static DEFINE_SPINLOCK(net_family_lock); | 158 | static DEFINE_SPINLOCK(net_family_lock); |
159 | static const struct net_proto_family *net_families[NPROTO] __read_mostly; | 159 | static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly; |
160 | 160 | ||
161 | /* | 161 | /* |
162 | * Statistics counters of the socket lists | 162 | * Statistics counters of the socket lists |
@@ -1200,7 +1200,7 @@ int __sock_create(struct net *net, int family, int type, int protocol, | |||
1200 | * requested real, full-featured networking support upon configuration. | 1200 | * requested real, full-featured networking support upon configuration. |
1201 | * Otherwise module support will break! | 1201 | * Otherwise module support will break! |
1202 | */ | 1202 | */ |
1203 | if (net_families[family] == NULL) | 1203 | if (rcu_access_pointer(net_families[family]) == NULL) |
1204 | request_module("net-pf-%d", family); | 1204 | request_module("net-pf-%d", family); |
1205 | #endif | 1205 | #endif |
1206 | 1206 | ||
@@ -2332,10 +2332,11 @@ int sock_register(const struct net_proto_family *ops) | |||
2332 | } | 2332 | } |
2333 | 2333 | ||
2334 | spin_lock(&net_family_lock); | 2334 | spin_lock(&net_family_lock); |
2335 | if (net_families[ops->family]) | 2335 | if (rcu_dereference_protected(net_families[ops->family], |
2336 | lockdep_is_held(&net_family_lock))) | ||
2336 | err = -EEXIST; | 2337 | err = -EEXIST; |
2337 | else { | 2338 | else { |
2338 | net_families[ops->family] = ops; | 2339 | rcu_assign_pointer(net_families[ops->family], ops); |
2339 | err = 0; | 2340 | err = 0; |
2340 | } | 2341 | } |
2341 | spin_unlock(&net_family_lock); | 2342 | spin_unlock(&net_family_lock); |
@@ -2363,7 +2364,7 @@ void sock_unregister(int family) | |||
2363 | BUG_ON(family < 0 || family >= NPROTO); | 2364 | BUG_ON(family < 0 || family >= NPROTO); |
2364 | 2365 | ||
2365 | spin_lock(&net_family_lock); | 2366 | spin_lock(&net_family_lock); |
2366 | net_families[family] = NULL; | 2367 | rcu_assign_pointer(net_families[family], NULL); |
2367 | spin_unlock(&net_family_lock); | 2368 | spin_unlock(&net_family_lock); |
2368 | 2369 | ||
2369 | synchronize_rcu(); | 2370 | synchronize_rcu(); |