patch-2.2.17 linux/drivers/net/bonding.c
Next file: linux/drivers/net/bsd_comp.c
Previous file: linux/drivers/net/bmac.c
Back to the patch index
Back to the overall index
- Lines: 110
- Date:
Mon Sep 4 18:39:19 2000
- Orig file:
v2.2.16/drivers/net/bonding.c
- Orig date:
Mon Sep 4 18:37:28 2000
diff -u --recursive --new-file v2.2.16/drivers/net/bonding.c linux/drivers/net/bonding.c
@@ -4,7 +4,7 @@
* Copyright 1999, Thomas Davis, tadavis@lbl.gov.
* Licensed under the GPL. Based on dummy.c, and eql.c devices.
*
- * bond.c: a bonding/etherchannel/sun trunking net driver
+ * bonding.c: a bonding/etherchannel/sun trunking net driver
*
* This is useful to talk to a Cisco 5500, running Etherchannel, aka:
* Linux Channel Bonding
@@ -28,6 +28,10 @@
*
* v0.1 - first working version.
* v0.2 - changed stats to be calculated by summing slaves stats.
+ *
+ * Changes:
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * - fix leaks on failure at bond_init
*
*/
@@ -71,8 +75,12 @@
bonding_t *private = (struct bonding *) master->priv;
slave_queue_t *queue = (struct slave_queue *) private->queue;
slave_t *slave, *next;
+ unsigned long flags;
- for( slave=queue->head; slave != NULL; slave=next) {
+ save_flags(flags);
+ cli();
+
+ for( slave=queue->head; slave != NULL; ) {
#ifdef BONDING_DEBUG
printk("freeing = %s\n", slave->dev->name);
#endif
@@ -80,8 +88,12 @@
slave->dev->slave = NULL;
next = slave->next;
kfree(slave);
- queue->num_slaves++;
+ slave=next;
+ queue->num_slaves--;
}
+ queue->head = NULL;
+
+ restore_flags(flags);
MOD_DEC_USE_COUNT;
return 0;
@@ -97,7 +109,7 @@
bonding_t *private = (struct bonding *) master->priv;
slave_queue_t *queue = (struct slave_queue *) private->queue;
slave_t *new_slave;
- int flags;
+ unsigned long flags;
if (master == NULL || slave == NULL)
return -ENODEV;
@@ -121,14 +133,15 @@
return -EBUSY;
}
- slave->slave = master; /* save the master in slave->slave */
- slave->flags |= IFF_SLAVE;
-
if ((new_slave = kmalloc(sizeof(slave_t), GFP_KERNEL)) == NULL) {
+ restore_flags(flags);
return -ENOMEM;
}
memset(new_slave, 0, sizeof(slave_t));
+ slave->slave = master; /* save the master in slave->slave */
+ slave->flags |= IFF_SLAVE;
+
new_slave->dev = slave;
if (queue->head == NULL) {
@@ -202,14 +215,19 @@
bond = (struct bonding *) dev->priv;
bond->queue = kmalloc(sizeof(struct slave_queue), GFP_KERNEL);
- if (bond->queue == NULL)
+ if (bond->queue == NULL) {
+ kfree(dev->priv);
return -ENOMEM;
+ }
memset(bond->queue, 0, sizeof(struct slave_queue));
bond->stats = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
- if (bond->stats == NULL)
+ if (bond->stats == NULL) {
+ kfree(dev->priv);
+ kfree(bond->queue);
return -ENOMEM;
+ }
memset(bond->stats, 0, sizeof(struct enet_statistics));
@@ -240,6 +258,11 @@
struct slave_queue *queue = bond->queue;
int good = 0;
+ if(!queue->num_slaves) {
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
while (good == 0) {
slave = queue->current_slave->dev;
if (slave->flags & (IFF_UP|IFF_RUNNING)) {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)