diff options
author | David S. Miller <davem@davemloft.net> | 2014-05-24 00:32:30 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-05-24 00:32:30 -0400 |
commit | 54e5c4def0614ab540fbdf68e45342a4af141702 (patch) | |
tree | 95a2f61c72336932e83d9e4180cd9739106d624b /net/core/rtnetlink.c | |
parent | be65de7174123e02477bd488db1a657caf0f9947 (diff) | |
parent | 1ee1ceafb572f1a925809168267a7962a4289de8 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts:
drivers/net/bonding/bond_alb.c
drivers/net/ethernet/altera/altera_msgdma.c
drivers/net/ethernet/altera/altera_sgdma.c
net/ipv6/xfrm6_output.c
Several cases of overlapping changes.
The xfrm6_output.c has a bug fix which overlaps the renaming
of skb->local_df to skb->ignore_df.
In the Altera TSE driver cases, the register access cleanups
in net-next overlapped with bug fixes done in net.
Similarly a bug fix to send ALB packets in the bonding driver using
the right source address overlaps with cleanups in net-next.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r-- | net/core/rtnetlink.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index d6417464dc66..f31268dbc0d1 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -353,15 +353,46 @@ void __rtnl_link_unregister(struct rtnl_link_ops *ops) | |||
353 | } | 353 | } |
354 | EXPORT_SYMBOL_GPL(__rtnl_link_unregister); | 354 | EXPORT_SYMBOL_GPL(__rtnl_link_unregister); |
355 | 355 | ||
356 | /* Return with the rtnl_lock held when there are no network | ||
357 | * devices unregistering in any network namespace. | ||
358 | */ | ||
359 | static void rtnl_lock_unregistering_all(void) | ||
360 | { | ||
361 | struct net *net; | ||
362 | bool unregistering; | ||
363 | DEFINE_WAIT(wait); | ||
364 | |||
365 | for (;;) { | ||
366 | prepare_to_wait(&netdev_unregistering_wq, &wait, | ||
367 | TASK_UNINTERRUPTIBLE); | ||
368 | unregistering = false; | ||
369 | rtnl_lock(); | ||
370 | for_each_net(net) { | ||
371 | if (net->dev_unreg_count > 0) { | ||
372 | unregistering = true; | ||
373 | break; | ||
374 | } | ||
375 | } | ||
376 | if (!unregistering) | ||
377 | break; | ||
378 | __rtnl_unlock(); | ||
379 | schedule(); | ||
380 | } | ||
381 | finish_wait(&netdev_unregistering_wq, &wait); | ||
382 | } | ||
383 | |||
356 | /** | 384 | /** |
357 | * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. | 385 | * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. |
358 | * @ops: struct rtnl_link_ops * to unregister | 386 | * @ops: struct rtnl_link_ops * to unregister |
359 | */ | 387 | */ |
360 | void rtnl_link_unregister(struct rtnl_link_ops *ops) | 388 | void rtnl_link_unregister(struct rtnl_link_ops *ops) |
361 | { | 389 | { |
362 | rtnl_lock(); | 390 | /* Close the race with cleanup_net() */ |
391 | mutex_lock(&net_mutex); | ||
392 | rtnl_lock_unregistering_all(); | ||
363 | __rtnl_link_unregister(ops); | 393 | __rtnl_link_unregister(ops); |
364 | rtnl_unlock(); | 394 | rtnl_unlock(); |
395 | mutex_unlock(&net_mutex); | ||
365 | } | 396 | } |
366 | EXPORT_SYMBOL_GPL(rtnl_link_unregister); | 397 | EXPORT_SYMBOL_GPL(rtnl_link_unregister); |
367 | 398 | ||