There is no destroy_workqueue() in bond device destroying process, therefore
worker thread will remain even if bond device is destroyed. So add
destroy_workqueue(), and also, ensure all works are canceled before
destroy_workqueue() is called.

Signed-off-by: Makito SHIOKAWA <[EMAIL PROTECTED]>
---

 drivers/net/bonding/bond_main.c  |   72 +++++++++++++++++++-------------------
 drivers/net/bonding/bond_sysfs.c |    9 ++++
 drivers/net/bonding/bonding.h    |    5 ++
 3 files changed, 48 insertions(+), 38 deletions(-)

--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -190,7 +190,6 @@ struct bond_parm_tbl arp_validate_tbl[] 
 /*-------------------------- Forward declarations ---------------------------*/
 
 static void bond_send_gratuitous_arp(struct bonding *bond);
-static void bond_deinit(struct net_device *bond_dev);
 
 /*---------------------------- General routines -----------------------------*/
 
@@ -862,7 +861,7 @@ static void bond_resend_igmp_join_reques
 /*
  * Totally destroys the mc_list in bond
  */
-static void bond_mc_list_destroy(struct bonding *bond)
+void bond_mc_list_destroy(struct bonding *bond)
 {
        struct dev_mc_list *dmi;
 
@@ -1875,7 +1874,7 @@ int  bond_release_and_destroy(struct net
 /*
  * This function releases all slaves.
  */
-static int bond_release_all(struct net_device *bond_dev)
+int bond_release_all(struct net_device *bond_dev)
 {
        struct bonding *bond = bond_dev->priv;
        struct slave *slave;
@@ -4392,6 +4391,25 @@ static const struct ethtool_ops bond_eth
        .get_drvinfo            = bond_ethtool_get_drvinfo,
 };
 
+/* Caller must not hold rtnl_lock */
+void bond_work_cancel_all(struct bonding *bond)
+{
+       /* ensure all works are stopped */
+       cancel_delayed_work_sync(&bond->alb_work);
+       cancel_delayed_work_sync(&bond->mii_work);
+       cancel_delayed_work_sync(&bond->ab_arp_work);
+       cancel_delayed_work_sync(&bond->lb_arp_work);
+       cancel_delayed_work_sync(&bond->ad_work);
+}
+
+static void bond_free_netdev(struct net_device *dev)
+{
+       struct bonding *bond = netdev_priv(dev);
+
+       destroy_workqueue(bond->wq);
+       free_netdev(dev);
+}
+
 /*
  * Does not allocate but creates a /proc entry.
  * Allowed to fail.
@@ -4441,7 +4459,7 @@ static int bond_init(struct net_device *
 
        bond_set_mode_ops(bond, bond->params.mode);
 
-       bond_dev->destructor = free_netdev;
+       bond_dev->destructor = bond_free_netdev;
 
        /* Initialize the device options */
        bond_dev->tx_queue_len = 0;
@@ -4483,7 +4501,7 @@ static int bond_init(struct net_device *
 /* De-initialize device specific data.
  * Caller must hold rtnl_lock.
  */
-static void bond_deinit(struct net_device *bond_dev)
+void bond_deinit(struct net_device *bond_dev)
 {
        struct bonding *bond = bond_dev->priv;
 
@@ -4494,29 +4512,6 @@ static void bond_deinit(struct net_devic
 #endif
 }
 
-static void bond_work_cancel_all(struct bonding *bond)
-{
-       write_lock_bh(&bond->lock);
-       bond->kill_timers = 1;
-       write_unlock_bh(&bond->lock);
-
-       if (bond->params.miimon)
-               cancel_delayed_work(&bond->mii_work);
-
-       if (bond->params.arp_interval) {
-               if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
-                       cancel_delayed_work(&bond->ab_arp_work);
-               else
-                       cancel_delayed_work(&bond->lb_arp_work);
-       }
-
-       if (bond->params.mode == BOND_MODE_ALB)
-               cancel_delayed_work(&bond->alb_work);
-
-       if (bond->params.mode == BOND_MODE_8023AD)
-               cancel_delayed_work(&bond->ad_work);
-}
-
 /* Unregister and free all bond devices.
  * Caller must hold rtnl_lock.
  */
@@ -4527,11 +4522,14 @@ static void bond_free_all(void)
        list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
                struct net_device *bond_dev = bond->dev;
 
+               bond_deinit(bond_dev);
+               rtnl_unlock();
                bond_work_cancel_all(bond);
+               rtnl_lock();
                bond_mc_list_destroy(bond);
                /* Release the bonded slaves */
                bond_release_all(bond_dev);
-               bond_deinit(bond_dev);
+               bond_destroy_sysfs_entry(bond);
                unregister_netdevice(bond_dev);
        }
 
@@ -4921,8 +4919,16 @@ int bond_create(char *name, struct bond_
 
 out_bond:
        bond_deinit(bond_dev);
+       if (*newbond)
+               unregister_netdevice(bond_dev);
+       else {
+               rtnl_unlock();
+               bond_work_cancel_all(netdev_priv(bond_dev));
+               rtnl_lock();
+               destroy_workqueue(((struct bonding 
*)netdev_priv(bond_dev))->wq);
 out_netdev:
-       free_netdev(bond_dev);
+               free_netdev(bond_dev);
+       }
 out_rtnl:
        rtnl_unlock();
        return res;
@@ -4932,7 +4938,6 @@ static int __init bonding_init(void)
 {
        int i;
        int res;
-       struct bonding *bond, *nxt;
 
        printk(KERN_INFO "%s", version);
 
@@ -4959,11 +4964,6 @@ static int __init bonding_init(void)
 
        goto out;
 err:
-       list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
-               bond_work_cancel_all(bond);
-               destroy_workqueue(bond->wq);
-       }
-
        rtnl_lock();
        bond_free_all();
        bond_destroy_sysfs();
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -163,7 +163,14 @@ static ssize_t bonding_store_bonds(struc
                                printk(KERN_INFO DRV_NAME
                                        ": %s is being deleted...\n",
                                        bond->dev->name);
-                               bond_destroy(bond);
+                               bond_deinit(bond->dev);
+                               rtnl_unlock();
+                               bond_work_cancel_all(bond);
+                               rtnl_lock();
+                               bond_mc_list_destroy(bond);
+                               bond_release_all(bond->dev);
+                               bond_destroy_sysfs_entry(bond);
+                               unregister_netdevice(bond->dev);
                                rtnl_unlock();
                                goto out;
                        }
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -301,7 +301,10 @@ static inline void bond_unset_master_alb
 struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry 
*curr);
 int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct 
net_device *slave_dev);
 int bond_create(char *name, struct bond_params *params, struct bonding 
**newbond);
-void bond_destroy(struct bonding *bond);
+void bond_deinit(struct net_device *bond_dev);
+void bond_work_cancel_all(struct bonding *bond);
+void bond_mc_list_destroy(struct bonding *bond);
+int bond_release_all(struct net_device *bond_dev);
 int  bond_release_and_destroy(struct net_device *bond_dev, struct net_device 
*slave_dev);
 int bond_create_sysfs(void);
 void bond_destroy_sysfs(void);

-- 
Makito SHIOKAWA
MIRACLE LINUX CORPORATION 
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to