diff options
-rw-r--r-- | drivers/net/dummy.c | 2 | ||||
-rw-r--r-- | drivers/net/ifb.c | 2 | ||||
-rw-r--r-- | net/core/net_namespace.c | 1 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 6 |
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 | ||
234 | out: | 235 | out: |
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 | ||
345 | out: | 346 | out: |
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 | */ |
53 | DECLARE_RWSEM(pernet_ops_rwsem); | 53 | DECLARE_RWSEM(pernet_ops_rwsem); |
54 | EXPORT_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 | */ |
417 | void __rtnl_link_unregister(struct rtnl_link_ops *ops) | 419 | void __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 | } |
428 | EXPORT_SYMBOL_GPL(__rtnl_link_unregister); | 428 | EXPORT_SYMBOL_GPL(__rtnl_link_unregister); |