Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2476

kernel-2.6.18-238.el5.src.rpm

From: Masahiro Matsuya <mmatsuya@redhat.com>
Date: Tue, 14 Apr 2009 13:51:49 +0900
Subject: [net] bonding: clean up resources upon removing a bond
Message-id: 49E41665.2090206@redhat.com
O-Subject: [RHEL5.4 PATCH] BZ463244 bonding: clean up the resources upon removing a bond - REPOST
Bugzilla: 463244
RH-Acked-by: Jiri Pirko <jpirko@redhat.com>
RH-Acked-by: Neil Horman <nhorman@redhat.com>

BZ#463244
https://bugzilla.redhat.com/show_bug.cgi?id=463244
[PATCH] Removing bond interfaces causes workqueue thread leak

Description:
The workqueue thread for the bond remained, after a bond was removed.
Some customer have already seen this issues. This is a patch to clean up
the workqueue thread and multicast lists when a bond is removed.

Upstream patch
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=a434e43f3d844192bc23bd7b408bac979c40efe7

Test Status
A simple reproducer is provided in the bugzilla. The attachment is a
patch which was backported for -138. I tested this patch with the
reproducer and the fix was confirmed.

Thanks,

Masahiro Matsuya

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 8fa2ebb..4426166 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1865,6 +1865,20 @@ void bond_destroy(struct bonding *bond)
 	unregister_netdevice(bond->dev);
 }
 
+static void bond_destructor(struct net_device *bond_dev)
+{
+	struct bonding *bond = netdev_priv(bond_dev);
+
+	if (bond->wq)
+	destroy_workqueue(bond->wq);
+
+	netif_tx_lock_bh(bond_dev);
+	bond_mc_list_destroy(bond);
+	netif_tx_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.
@@ -4449,7 +4463,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;
@@ -4488,20 +4502,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);
@@ -4523,6 +4523,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.
  */
@@ -4534,9 +4550,6 @@ static void bond_free_all(void)
 		struct net_device *bond_dev = bond->dev;
 
 		bond_work_cancel_all(bond);
-		netif_tx_lock_bh(bond_dev);
-		bond_mc_list_destroy(bond);
-		netif_tx_unlock_bh(bond_dev);
 		/* Release the bonded slaves */
 		bond_release_all(bond_dev);
 		bond_deinit(bond_dev);