aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/soft-interface.c
diff options
context:
space:
mode:
authorSimon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>2013-01-11 04:19:51 -0500
committerAntonio Quartulli <ordex@autistici.org>2013-01-19 08:18:12 -0500
commit5bc44dc8458cbac08c664f2f337326bf87cc924b (patch)
tree05828c0b6a6f00138a539c0ce39e3ea0b109dbce /net/batman-adv/soft-interface.c
parente76e4320a26ba6301dfd3e9a28a1e3faccd302ab (diff)
batman-adv: postpone sysfs removal when unregistering
When processing the unregister notify for a hard interface, removing the sysfs files may lead to a circular deadlock (rtnl mutex <-> s_active). To overcome this problem, postpone the sysfs removal in a worker. Reported-by: Sasha Levin <sasha.levin@oracle.com> Reported-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> Signed-off-by: Marek Lindner <lindner_marek@yahoo.de> Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Diffstat (limited to 'net/batman-adv/soft-interface.c')
-rw-r--r--net/batman-adv/soft-interface.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 3d6816667bfc..c9962fee44b1 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -449,6 +449,30 @@ static void batadv_interface_setup(struct net_device *dev)
449 memset(priv, 0, sizeof(*priv)); 449 memset(priv, 0, sizeof(*priv));
450} 450}
451 451
452/**
453 * batadv_softif_destroy_finish - cleans up the remains of a softif
454 * @work: work queue item
455 *
456 * Free the parts of the soft interface which can not be removed under
457 * rtnl lock (to prevent deadlock situations).
458 */
459static void batadv_softif_destroy_finish(struct work_struct *work)
460{
461 struct batadv_priv *bat_priv;
462 struct net_device *soft_iface;
463
464 bat_priv = container_of(work, struct batadv_priv,
465 cleanup_work);
466 soft_iface = bat_priv->soft_iface;
467
468 batadv_debugfs_del_meshif(soft_iface);
469 batadv_sysfs_del_meshif(soft_iface);
470
471 rtnl_lock();
472 unregister_netdevice(soft_iface);
473 rtnl_unlock();
474}
475
452struct net_device *batadv_softif_create(const char *name) 476struct net_device *batadv_softif_create(const char *name)
453{ 477{
454 struct net_device *soft_iface; 478 struct net_device *soft_iface;
@@ -463,6 +487,8 @@ struct net_device *batadv_softif_create(const char *name)
463 goto out; 487 goto out;
464 488
465 bat_priv = netdev_priv(soft_iface); 489 bat_priv = netdev_priv(soft_iface);
490 bat_priv->soft_iface = soft_iface;
491 INIT_WORK(&bat_priv->cleanup_work, batadv_softif_destroy_finish);
466 492
467 /* batadv_interface_stats() needs to be available as soon as 493 /* batadv_interface_stats() needs to be available as soon as
468 * register_netdevice() has been called 494 * register_netdevice() has been called
@@ -551,10 +577,10 @@ out:
551 577
552void batadv_softif_destroy(struct net_device *soft_iface) 578void batadv_softif_destroy(struct net_device *soft_iface)
553{ 579{
554 batadv_debugfs_del_meshif(soft_iface); 580 struct batadv_priv *bat_priv = netdev_priv(soft_iface);
555 batadv_sysfs_del_meshif(soft_iface); 581
556 batadv_mesh_free(soft_iface); 582 batadv_mesh_free(soft_iface);
557 unregister_netdevice(soft_iface); 583 queue_work(batadv_event_workqueue, &bat_priv->cleanup_work);
558} 584}
559 585
560int batadv_softif_is_valid(const struct net_device *net_dev) 586int batadv_softif_is_valid(const struct net_device *net_dev)