Skip to content

Commit

Permalink
bonding: Clean up resource leaks
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jay Vosburgh authored and Jeff Garzik committed Oct 31, 2008
1 parent fba4acd commit a434e43
Showing 1 changed file with 31 additions and 18 deletions.
49 changes: 31 additions & 18 deletions drivers/net/bonding/bond_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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.
*/
Expand All @@ -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);
Expand Down

0 comments on commit a434e43

Please sign in to comment.