From: Jay Vosburgh Date: Fri, 7 Dec 2007 07:40:35 +0000 (-0800) Subject: bonding: Fix race at module unload X-Git-Tag: v2.6.24-rc5~41 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fdaea7a93d097b066e76c7db6091228a84f87ec2;p=linux-2.6 bonding: Fix race at module unload Fixes a race condition in module unload. Without this change, workqueue events may fire while bonding data structures are partially freed but before bond_close() is invoked by unregister_netdevice(). Update version to 3.2.3. Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 08879d552a..b0b2603626 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4492,6 +4492,27 @@ static void bond_deinit(struct net_device *bond_dev) #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 && delayed_work_pending(&bond->mii_work)) + cancel_delayed_work(&bond->mii_work); + + if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work)) + cancel_delayed_work(&bond->arp_work); + + if (bond->params.mode == BOND_MODE_ALB && + delayed_work_pending(&bond->alb_work)) + cancel_delayed_work(&bond->alb_work); + + if (bond->params.mode == BOND_MODE_8023AD && + delayed_work_pending(&bond->ad_work)) + cancel_delayed_work(&bond->ad_work); +} + /* Unregister and free all bond devices. * Caller must hold rtnl_lock. */ @@ -4502,6 +4523,7 @@ 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_work_cancel_all(bond); bond_mc_list_destroy(bond); /* Release the bonded slaves */ bond_release_all(bond_dev); @@ -4902,27 +4924,6 @@ out_rtnl: return res; } -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 && delayed_work_pending(&bond->mii_work)) - cancel_delayed_work(&bond->mii_work); - - if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work)) - cancel_delayed_work(&bond->arp_work); - - if (bond->params.mode == BOND_MODE_ALB && - delayed_work_pending(&bond->alb_work)) - cancel_delayed_work(&bond->alb_work); - - if (bond->params.mode == BOND_MODE_8023AD && - delayed_work_pending(&bond->ad_work)) - cancel_delayed_work(&bond->ad_work); -} - static int __init bonding_init(void) { int i; diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index ccafc74c5a..e1e4734e23 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -22,7 +22,7 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.2.2" +#define DRV_VERSION "3.2.3" #define DRV_RELDATE "December 6, 2007" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"