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: Jay Vosburgh <fubar@us.ibm.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
Jay Vosburgh 2008-10-30 17:41:15 -07:00 committed by Jeff Garzik
parent fba4acda35
commit a434e43f3d

View File

@ -1979,6 +1979,20 @@ void bond_destroy(struct bonding *bond)
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.
* 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)
bond_set_mode_ops(bond, bond->params.mode);
bond_dev->destructor = free_netdev;
bond_dev->destructor = bond_destructor;
/* Initialize the device options */
bond_dev->tx_queue_len = 0;
@ -4592,20 +4606,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
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)
{
write_lock_bh(&bond->lock);
@ -4627,6 +4627,22 @@ static void bond_work_cancel_all(struct bonding *bond)
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.
* Caller must hold rtnl_lock.
*/
@ -4638,9 +4654,6 @@ static void bond_free_all(void)
struct net_device *bond_dev = bond->dev;
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 */
bond_release_all(bond_dev);
bond_destroy(bond);