Commit a434e43f authored by Jay Vosburgh's avatar Jay Vosburgh Committed by Jeff Garzik

bonding: Clean up resource leaks

This patch reworks the resource free logic performed at the time
a bonding device is released.  This (a) closes two resource leaks, one
for workqueues and one for multicast lists, and (b) improves commonality
of code between the "destroy one" and "destroy all" paths by performing
final free activity via destructor instead of explicitly (and differently)
in each path.

"Sean E. Millichamp" <sean@bruenor.org> reported the workqueue
leak, and included a different patch.
Signed-off-by: default avatarJay Vosburgh <fubar@us.ibm.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent fba4acda
...@@ -1979,6 +1979,20 @@ void bond_destroy(struct bonding *bond) ...@@ -1979,6 +1979,20 @@ void bond_destroy(struct bonding *bond)
unregister_netdevice(bond->dev); unregister_netdevice(bond->dev);
} }
static void bond_destructor(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
if (bond->wq)
destroy_workqueue(bond->wq);
netif_addr_lock_bh(bond_dev);
bond_mc_list_destroy(bond);
netif_addr_unlock_bh(bond_dev);
free_netdev(bond_dev);
}
/* /*
* First release a slave and than destroy the bond if no more slaves iare left. * First release a slave and than destroy the bond if no more slaves iare left.
* Must be under rtnl_lock when this function is called. * Must be under rtnl_lock when this function is called.
...@@ -4553,7 +4567,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) ...@@ -4553,7 +4567,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
bond_set_mode_ops(bond, bond->params.mode); bond_set_mode_ops(bond, bond->params.mode);
bond_dev->destructor = free_netdev; bond_dev->destructor = bond_destructor;
/* Initialize the device options */ /* Initialize the device options */
bond_dev->tx_queue_len = 0; bond_dev->tx_queue_len = 0;
...@@ -4592,20 +4606,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) ...@@ -4592,20 +4606,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
return 0; return 0;
} }
/* De-initialize device specific data.
* Caller must hold rtnl_lock.
*/
static void bond_deinit(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
list_del(&bond->bond_list);
#ifdef CONFIG_PROC_FS
bond_remove_proc_entry(bond);
#endif
}
static void bond_work_cancel_all(struct bonding *bond) static void bond_work_cancel_all(struct bonding *bond)
{ {
write_lock_bh(&bond->lock); write_lock_bh(&bond->lock);
...@@ -4627,6 +4627,22 @@ static void bond_work_cancel_all(struct bonding *bond) ...@@ -4627,6 +4627,22 @@ static void bond_work_cancel_all(struct bonding *bond)
cancel_delayed_work(&bond->ad_work); cancel_delayed_work(&bond->ad_work);
} }
/* De-initialize device specific data.
* Caller must hold rtnl_lock.
*/
static void bond_deinit(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
list_del(&bond->bond_list);
bond_work_cancel_all(bond);
#ifdef CONFIG_PROC_FS
bond_remove_proc_entry(bond);
#endif
}
/* Unregister and free all bond devices. /* Unregister and free all bond devices.
* Caller must hold rtnl_lock. * Caller must hold rtnl_lock.
*/ */
...@@ -4638,9 +4654,6 @@ static void bond_free_all(void) ...@@ -4638,9 +4654,6 @@ static void bond_free_all(void)
struct net_device *bond_dev = bond->dev; struct net_device *bond_dev = bond->dev;
bond_work_cancel_all(bond); bond_work_cancel_all(bond);
netif_addr_lock_bh(bond_dev);
bond_mc_list_destroy(bond);
netif_addr_unlock_bh(bond_dev);
/* Release the bonded slaves */ /* Release the bonded slaves */
bond_release_all(bond_dev); bond_release_all(bond_dev);
bond_destroy(bond); bond_destroy(bond);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment