aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/dummy.c2
-rw-r--r--drivers/net/ifb.c2
-rw-r--r--net/core/net_namespace.c1
-rw-r--r--net/core/rtnetlink.c6
4 files changed, 8 insertions, 3 deletions
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 30b1c8512049..0d15a12a4560 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -219,6 +219,7 @@ static int __init dummy_init_module(void)
219{ 219{
220 int i, err = 0; 220 int i, err = 0;
221 221
222 down_write(&pernet_ops_rwsem);
222 rtnl_lock(); 223 rtnl_lock();
223 err = __rtnl_link_register(&dummy_link_ops); 224 err = __rtnl_link_register(&dummy_link_ops);
224 if (err < 0) 225 if (err < 0)
@@ -233,6 +234,7 @@ static int __init dummy_init_module(void)
233 234
234out: 235out:
235 rtnl_unlock(); 236 rtnl_unlock();
237 up_write(&pernet_ops_rwsem);
236 238
237 return err; 239 return err;
238} 240}
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 0008da7e9d4c..5f2897ec0edc 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -330,6 +330,7 @@ static int __init ifb_init_module(void)
330{ 330{
331 int i, err; 331 int i, err;
332 332
333 down_write(&pernet_ops_rwsem);
333 rtnl_lock(); 334 rtnl_lock();
334 err = __rtnl_link_register(&ifb_link_ops); 335 err = __rtnl_link_register(&ifb_link_ops);
335 if (err < 0) 336 if (err < 0)
@@ -344,6 +345,7 @@ static int __init ifb_init_module(void)
344 345
345out: 346out:
346 rtnl_unlock(); 347 rtnl_unlock();
348 up_write(&pernet_ops_rwsem);
347 349
348 return err; 350 return err;
349} 351}
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 7fdf321d4997..a11e03f920d3 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -51,6 +51,7 @@ static bool init_net_initialized;
51 * outside. 51 * outside.
52 */ 52 */
53DECLARE_RWSEM(pernet_ops_rwsem); 53DECLARE_RWSEM(pernet_ops_rwsem);
54EXPORT_SYMBOL_GPL(pernet_ops_rwsem);
54 55
55#define MIN_PERNET_OPS_ID \ 56#define MIN_PERNET_OPS_ID \
56 ((sizeof(struct net_generic) + sizeof(void *) - 1) / sizeof(void *)) 57 ((sizeof(struct net_generic) + sizeof(void *) - 1) / sizeof(void *))
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index e86b28482ca7..45936922d7e2 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -412,17 +412,17 @@ static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops)
412 * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. 412 * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
413 * @ops: struct rtnl_link_ops * to unregister 413 * @ops: struct rtnl_link_ops * to unregister
414 * 414 *
415 * The caller must hold the rtnl_mutex. 415 * The caller must hold the rtnl_mutex and guarantee net_namespace_list
416 * integrity (hold pernet_ops_rwsem for writing to close the race
417 * with setup_net() and cleanup_net()).
416 */ 418 */
417void __rtnl_link_unregister(struct rtnl_link_ops *ops) 419void __rtnl_link_unregister(struct rtnl_link_ops *ops)
418{ 420{
419 struct net *net; 421 struct net *net;
420 422
421 down_read(&net_rwsem);
422 for_each_net(net) { 423 for_each_net(net) {
423 __rtnl_kill_links(net, ops); 424 __rtnl_kill_links(net, ops);
424 } 425 }
425 up_read(&net_rwsem);
426 list_del(&ops->list); 426 list_del(&ops->list);
427} 427}
428EXPORT_SYMBOL_GPL(__rtnl_link_unregister); 428EXPORT_SYMBOL_GPL(__rtnl_link_unregister);