aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
diff options
context:
space:
mode:
authorMoni Shoua <monis@voltaire.com>2007-10-09 22:43:43 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-15 14:20:46 -0400
commitd90a162a4ee280201e84944a84f86d6728dc0c27 (patch)
treeeff59bda3c6fcec2556b7d80838979e6fe705a43 /drivers/net/bonding
parent1053f62c24faa6d4ee6f5bfddeca847b84f67a95 (diff)
net/bonding: Destroy bonding master when last slave is gone
When bonding enslaves non Ethernet devices it takes pointers to functions in the module that owns the slaves. In this case it becomes unsafe to keep the bonding master registered after last slave was unenslaved because we don't know if the pointers are still valid. Destroying the bond when slave_cnt is zero ensures that these functions be used anymore. Signed-off-by: Moni Shoua <monis at voltaire.com> Acked-by: Jay Vosburgh <fubar@us.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r--drivers/net/bonding/bond_main.c38
-rw-r--r--drivers/net/bonding/bond_sysfs.c9
-rw-r--r--drivers/net/bonding/bonding.h3
3 files changed, 46 insertions, 4 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 19fd35175a77..0e198dd87c20 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1257,6 +1257,8 @@ static int bond_compute_features(struct bonding *bond)
1257static void bond_setup_by_slave(struct net_device *bond_dev, 1257static void bond_setup_by_slave(struct net_device *bond_dev,
1258 struct net_device *slave_dev) 1258 struct net_device *slave_dev)
1259{ 1259{
1260 struct bonding *bond = bond_dev->priv;
1261
1260 bond_dev->neigh_setup = slave_dev->neigh_setup; 1262 bond_dev->neigh_setup = slave_dev->neigh_setup;
1261 1263
1262 bond_dev->type = slave_dev->type; 1264 bond_dev->type = slave_dev->type;
@@ -1265,6 +1267,7 @@ static void bond_setup_by_slave(struct net_device *bond_dev,
1265 1267
1266 memcpy(bond_dev->broadcast, slave_dev->broadcast, 1268 memcpy(bond_dev->broadcast, slave_dev->broadcast,
1267 slave_dev->addr_len); 1269 slave_dev->addr_len);
1270 bond->setup_by_slave = 1;
1268} 1271}
1269 1272
1270/* enslave device <slave> to bond device <master> */ 1273/* enslave device <slave> to bond device <master> */
@@ -1828,6 +1831,35 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
1828} 1831}
1829 1832
1830/* 1833/*
1834* Destroy a bonding device.
1835* Must be under rtnl_lock when this function is called.
1836*/
1837void bond_destroy(struct bonding *bond)
1838{
1839 bond_deinit(bond->dev);
1840 bond_destroy_sysfs_entry(bond);
1841 unregister_netdevice(bond->dev);
1842}
1843
1844/*
1845* First release a slave and than destroy the bond if no more slaves iare left.
1846* Must be under rtnl_lock when this function is called.
1847*/
1848int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev)
1849{
1850 struct bonding *bond = bond_dev->priv;
1851 int ret;
1852
1853 ret = bond_release(bond_dev, slave_dev);
1854 if ((ret == 0) && (bond->slave_cnt == 0)) {
1855 printk(KERN_INFO DRV_NAME ": %s: destroying bond %s.\n",
1856 bond_dev->name, bond_dev->name);
1857 bond_destroy(bond);
1858 }
1859 return ret;
1860}
1861
1862/*
1831 * This function releases all slaves. 1863 * This function releases all slaves.
1832 */ 1864 */
1833static int bond_release_all(struct net_device *bond_dev) 1865static int bond_release_all(struct net_device *bond_dev)
@@ -3325,6 +3357,11 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave
3325 * ... Or is it this? 3357 * ... Or is it this?
3326 */ 3358 */
3327 break; 3359 break;
3360 case NETDEV_GOING_DOWN:
3361 dprintk("slave %s is going down\n", slave_dev->name);
3362 if (bond->setup_by_slave)
3363 bond_release_and_destroy(bond_dev, slave_dev);
3364 break;
3328 case NETDEV_CHANGEMTU: 3365 case NETDEV_CHANGEMTU:
3329 /* 3366 /*
3330 * TODO: Should slaves be allowed to 3367 * TODO: Should slaves be allowed to
@@ -4298,6 +4335,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
4298 bond->primary_slave = NULL; 4335 bond->primary_slave = NULL;
4299 bond->dev = bond_dev; 4336 bond->dev = bond_dev;
4300 bond->send_grat_arp = 0; 4337 bond->send_grat_arp = 0;
4338 bond->setup_by_slave = 0;
4301 INIT_LIST_HEAD(&bond->vlan_list); 4339 INIT_LIST_HEAD(&bond->vlan_list);
4302 4340
4303 /* Initialize the device entry points */ 4341 /* Initialize the device entry points */
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 583c568e1764..b5d2a13fe627 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -164,9 +164,7 @@ static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t
164 printk(KERN_INFO DRV_NAME 164 printk(KERN_INFO DRV_NAME
165 ": %s is being deleted...\n", 165 ": %s is being deleted...\n",
166 bond->dev->name); 166 bond->dev->name);
167 bond_deinit(bond->dev); 167 bond_destroy(bond);
168 bond_destroy_sysfs_entry(bond);
169 unregister_netdevice(bond->dev);
170 rtnl_unlock(); 168 rtnl_unlock();
171 goto out; 169 goto out;
172 } 170 }
@@ -363,7 +361,10 @@ static ssize_t bonding_store_slaves(struct device *d,
363 printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n", 361 printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n",
364 bond->dev->name, dev->name); 362 bond->dev->name, dev->name);
365 rtnl_lock(); 363 rtnl_lock();
366 res = bond_release(bond->dev, dev); 364 if (bond->setup_by_slave)
365 res = bond_release_and_destroy(bond->dev, dev);
366 else
367 res = bond_release(bond->dev, dev);
367 rtnl_unlock(); 368 rtnl_unlock();
368 if (res) { 369 if (res) {
369 ret = res; 370 ret = res;
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index e0e06a84b5b9..85e579b0d6f4 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -188,6 +188,7 @@ struct bonding {
188 s8 kill_timers; 188 s8 kill_timers;
189 s8 do_set_mac_addr; 189 s8 do_set_mac_addr;
190 s8 send_grat_arp; 190 s8 send_grat_arp;
191 s8 setup_by_slave;
191 struct net_device_stats stats; 192 struct net_device_stats stats;
192#ifdef CONFIG_PROC_FS 193#ifdef CONFIG_PROC_FS
193 struct proc_dir_entry *proc_entry; 194 struct proc_dir_entry *proc_entry;
@@ -295,6 +296,8 @@ static inline void bond_unset_master_alb_flags(struct bonding *bond)
295struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); 296struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
296int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); 297int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
297int bond_create(char *name, struct bond_params *params, struct bonding **newbond); 298int bond_create(char *name, struct bond_params *params, struct bonding **newbond);
299void bond_destroy(struct bonding *bond);
300int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev);
298void bond_deinit(struct net_device *bond_dev); 301void bond_deinit(struct net_device *bond_dev);
299int bond_create_sysfs(void); 302int bond_create_sysfs(void);
300void bond_destroy_sysfs(void); 303void bond_destroy_sysfs(void);