dev_set_allmulti(slave_dev, 1);
}
- netif_tx_lock_bh(bond_dev);
/* upload master's mc_list to new slave */
for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
}
- netif_tx_unlock_bh(bond_dev);
}
if (bond->params.mode == BOND_MODE_8023AD) {
* has been cleared (if our_slave == old_current),
* but before a new active slave is selected.
*/
- write_unlock_bh(&bond->lock);
bond_alb_deinit_slave(bond, slave);
- write_lock_bh(&bond->lock);
}
if (oldcurrent == slave) {
}
/* flush master's mc_list from slave */
- netif_tx_lock_bh(bond_dev);
bond_mc_list_flush(bond_dev, slave_dev);
- netif_tx_unlock_bh(bond_dev);
}
netdev_set_master(slave_dev, NULL);
slave_dev = slave->dev;
bond_detach_slave(bond, slave);
- /* now that the slave is detached, unlock and perform
- * all the undo steps that should not be called from
- * within a lock.
- */
- write_unlock_bh(&bond->lock);
-
if ((bond->params.mode == BOND_MODE_TLB) ||
(bond->params.mode == BOND_MODE_ALB)) {
/* must be called only after the slave
bond_compute_features(bond);
+ /* now that the slave is detached, unlock and perform
+ * all the undo steps that should not be called from
+ * within a lock.
+ */
+ write_unlock_bh(&bond->lock);
+
bond_destroy_slave_symlinks(bond_dev, slave_dev);
bond_del_vlans_from_slave(bond, slave_dev);
}
/* flush master's mc_list from slave */
- netif_tx_lock_bh(bond_dev);
bond_mc_list_flush(bond_dev, slave_dev);
- netif_tx_unlock_bh(bond_dev);
}
netdev_set_master(slave_dev, NULL);
rtnl_lock();
read_lock(&bond->lock);
__bond_mii_monitor(bond, 1);
- read_unlock(&bond->lock);
- rtnl_unlock(); /* might sleep, hold no other locks */
- read_lock(&bond->lock);
+ rtnl_unlock();
}
delay = ((bond->params.miimon * HZ) / 1000) ? : 1;
}
if (do_failover) {
+ rtnl_lock();
write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
write_unlock_bh(&bond->curr_slave_lock);
+ rtnl_unlock();
+
}
re_arm:
slave->link = BOND_LINK_UP;
+ rtnl_lock();
+
write_lock_bh(&bond->curr_slave_lock);
if ((!bond->curr_active_slave) &&
}
write_unlock_bh(&bond->curr_slave_lock);
+ rtnl_unlock();
}
} else {
read_lock(&bond->curr_slave_lock);
bond->dev->name,
slave->dev->name);
+ rtnl_lock();
write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
write_unlock_bh(&bond->curr_slave_lock);
+ rtnl_unlock();
+
bond->current_arp_slave = slave;
if (slave) {
bond->primary_slave->dev->name);
/* primary is up so switch to it */
+ rtnl_lock();
write_lock_bh(&bond->curr_slave_lock);
bond_change_active_slave(bond, bond->primary_slave);
write_unlock_bh(&bond->curr_slave_lock);
+ rtnl_unlock();
+
slave = bond->primary_slave;
slave->jiffies = jiffies;
} else {
case NETDEV_CHANGENAME:
return bond_event_changename(event_bond);
case NETDEV_UNREGISTER:
- bond_release_all(event_bond->dev);
+ /*
+ * TODO: remove a bond from the list?
+ */
break;
default:
break;
{
struct bonding *bond = bond_dev->priv;
struct net_device_stats *stats = &(bond->stats), *sstats;
- struct net_device_stats local_stats;
struct slave *slave;
int i;
- memset(&local_stats, 0, sizeof(struct net_device_stats));
+ memset(stats, 0, sizeof(struct net_device_stats));
read_lock_bh(&bond->lock);
if (slave->dev->get_stats) {
sstats = slave->dev->get_stats(slave->dev);
- local_stats.rx_packets += sstats->rx_packets;
- local_stats.rx_bytes += sstats->rx_bytes;
- local_stats.rx_errors += sstats->rx_errors;
- local_stats.rx_dropped += sstats->rx_dropped;
-
- local_stats.tx_packets += sstats->tx_packets;
- local_stats.tx_bytes += sstats->tx_bytes;
- local_stats.tx_errors += sstats->tx_errors;
- local_stats.tx_dropped += sstats->tx_dropped;
-
- local_stats.multicast += sstats->multicast;
- local_stats.collisions += sstats->collisions;
-
- local_stats.rx_length_errors += sstats->rx_length_errors;
- local_stats.rx_over_errors += sstats->rx_over_errors;
- local_stats.rx_crc_errors += sstats->rx_crc_errors;
- local_stats.rx_frame_errors += sstats->rx_frame_errors;
- local_stats.rx_fifo_errors += sstats->rx_fifo_errors;
- local_stats.rx_missed_errors += sstats->rx_missed_errors;
-
- local_stats.tx_aborted_errors += sstats->tx_aborted_errors;
- local_stats.tx_carrier_errors += sstats->tx_carrier_errors;
- local_stats.tx_fifo_errors += sstats->tx_fifo_errors;
- local_stats.tx_heartbeat_errors += sstats->tx_heartbeat_errors;
- local_stats.tx_window_errors += sstats->tx_window_errors;
+ stats->rx_packets += sstats->rx_packets;
+ stats->rx_bytes += sstats->rx_bytes;
+ stats->rx_errors += sstats->rx_errors;
+ stats->rx_dropped += sstats->rx_dropped;
+
+ stats->tx_packets += sstats->tx_packets;
+ stats->tx_bytes += sstats->tx_bytes;
+ stats->tx_errors += sstats->tx_errors;
+ stats->tx_dropped += sstats->tx_dropped;
+
+ stats->multicast += sstats->multicast;
+ stats->collisions += sstats->collisions;
+
+ stats->rx_length_errors += sstats->rx_length_errors;
+ stats->rx_over_errors += sstats->rx_over_errors;
+ stats->rx_crc_errors += sstats->rx_crc_errors;
+ stats->rx_frame_errors += sstats->rx_frame_errors;
+ stats->rx_fifo_errors += sstats->rx_fifo_errors;
+ stats->rx_missed_errors += sstats->rx_missed_errors;
+
+ stats->tx_aborted_errors += sstats->tx_aborted_errors;
+ stats->tx_carrier_errors += sstats->tx_carrier_errors;
+ stats->tx_fifo_errors += sstats->tx_fifo_errors;
+ stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;
+ stats->tx_window_errors += sstats->tx_window_errors;
}
}
- memcpy(stats,&local_stats,sizeof(struct net_device_stats));
-
read_unlock_bh(&bond->lock);
return stats;
struct bonding *bond = bond_dev->priv;
struct dev_mc_list *dmi;
+ write_lock_bh(&bond->lock);
+
/*
* Do promisc before checking multicast_mode
*/
bond_set_allmulti(bond, -1);
}
- read_lock(&bond->lock);
-
bond->flags = bond_dev->flags;
/* looking for addresses to add to slaves' mc list */
bond_mc_list_destroy(bond);
bond_mc_list_copy(bond_dev->mc_list, bond, GFP_ATOMIC);
- read_unlock(&bond->lock);
+ write_unlock_bh(&bond->lock);
}
/*
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);
/*
* Convert string input module parms. Accept either the
- * number of the mode or its string name. A bit complicated because
- * some mode names are substrings of other names, and calls from sysfs
- * may have whitespace in the name (trailing newlines, for example).
+ * number of the mode or its string name.
*/
-int bond_parse_parm(const char *buf, struct bond_parm_tbl *tbl)
+int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
{
- int mode = -1, i, rv;
- char *p, modestr[BOND_MAX_MODENAME_LEN + 1] = { 0, };
-
- for (p = (char *)buf; *p; p++)
- if (!(isdigit(*p) || isspace(*p)))
- break;
-
- if (*p)
- rv = sscanf(buf, "%20s", modestr);
- else
- rv = sscanf(buf, "%d", &mode);
-
- if (!rv)
- return -1;
+ int i;
for (i = 0; tbl[i].modename; i++) {
- if (mode == tbl[i].mode)
- return tbl[i].mode;
- if (strcmp(modestr, tbl[i].modename) == 0)
+ if ((isdigit(*mode_arg) &&
+ tbl[i].mode == simple_strtol(mode_arg, NULL, 0)) ||
+ (strcmp(mode_arg, tbl[i].modename) == 0)) {
return tbl[i].mode;
+ }
}
return -1;
int bond_create(char *name, struct bond_params *params, struct bonding **newbond)
{
struct net_device *bond_dev;
- struct bonding *bond, *nxt;
int res;
rtnl_lock();
- down_write(&bonding_rwsem);
-
- /* Check to see if the bond already exists. */
- if (name) {
- list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list)
- if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) {
- printk(KERN_ERR DRV_NAME
- ": cannot add bond %s; it already exists\n",
- name);
- res = -EPERM;
- goto out_rtnl;
- }
- }
-
bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "",
ether_setup);
if (!bond_dev) {
netif_carrier_off(bond_dev);
- up_write(&bonding_rwsem);
rtnl_unlock(); /* allows sysfs registration of net device */
res = bond_create_sysfs_entry(bond_dev->priv);
if (res < 0) {
rtnl_lock();
- down_write(&bonding_rwsem);
goto out_bond;
}
out_netdev:
free_netdev(bond_dev);
out_rtnl:
- up_write(&bonding_rwsem);
rtnl_unlock();
return res;
}
#ifdef CONFIG_PROC_FS
bond_create_proc_dir();
#endif
-
- init_rwsem(&bonding_rwsem);
-
for (i = 0; i < max_bonds; i++) {
res = bond_create(NULL, &bonding_defaults, NULL);
if (res)
{
char command[IFNAMSIZ + 1] = {0, };
char *ifname;
- int rv, res = count;
+ int res = count;
struct bonding *bond;
struct bonding *nxt;
+ down_write(&(bonding_rwsem));
sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
ifname = command + 1;
if ((strlen(command) <= 1) ||
goto err_no_cmd;
if (command[0] == '+') {
+
+ /* Check to see if the bond already exists. */
+ list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list)
+ if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) {
+ printk(KERN_ERR DRV_NAME
+ ": cannot add bond %s; it already exists\n",
+ ifname);
+ res = -EPERM;
+ goto out;
+ }
+
printk(KERN_INFO DRV_NAME
": %s is being created...\n", ifname);
- rv = bond_create(ifname, &bonding_defaults, &bond);
- if (rv) {
- printk(KERN_INFO DRV_NAME ": Bond creation failed.\n");
- res = rv;
+ if (bond_create(ifname, &bonding_defaults, &bond)) {
+ printk(KERN_INFO DRV_NAME
+ ": %s interface already exists. Bond creation failed.\n",
+ ifname);
+ res = -EPERM;
}
goto out;
}
if (command[0] == '-') {
- rtnl_lock();
- down_write(&bonding_rwsem);
-
list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list)
if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) {
+ rtnl_lock();
/* check the ref count on the bond's kobject.
* If it's > expected, then there's a file open,
* and we have to fail.
*/
if (atomic_read(&bond->dev->class_dev.kobj.kref.refcount)
> expected_refcount){
+ rtnl_unlock();
printk(KERN_INFO DRV_NAME
": Unable remove bond %s due to open references.\n",
ifname);
": %s is being deleted...\n",
bond->dev->name);
bond_destroy(bond);
- up_write(&bonding_rwsem);
rtnl_unlock();
goto out;
}
printk(KERN_ERR DRV_NAME
": unable to delete non-existent bond %s\n", ifname);
res = -ENODEV;
- up_write(&bonding_rwsem);
- rtnl_unlock();
goto out;
}
* get called forever, which is bad.
*/
out:
+ up_write(&(bonding_rwsem));
return res;
}
/* class attribute for bond_masters file. This ends up in /sys/class/net */
/* Note: We can't hold bond->lock here, as bond_create grabs it. */
- rtnl_lock();
- down_write(&(bonding_rwsem));
-
sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
ifname = command + 1;
if ((strlen(command) <= 1) ||
dev->mtu = bond->dev->mtu;
}
}
+ rtnl_lock();
res = bond_enslave(bond->dev, dev);
+ rtnl_unlock();
if (res) {
ret = res;
}
if (dev) {
printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n",
bond->dev->name, dev->name);
+ rtnl_lock();
if (bond->setup_by_slave)
res = bond_release_and_destroy(bond->dev, dev);
else
res = bond_release(bond->dev, dev);
+ rtnl_unlock();
if (res) {
ret = res;
goto out;
ret = -EPERM;
out:
- up_write(&(bonding_rwsem));
- rtnl_unlock();
return ret;
}
goto out;
}
- new_value = bond_parse_parm(buf, bond_mode_tbl);
+ new_value = bond_parse_parm((char *)buf, bond_mode_tbl);
if (new_value < 0) {
printk(KERN_ERR DRV_NAME
": %s: Ignoring invalid mode value %.*s.\n",
goto out;
}
- new_value = bond_parse_parm(buf, xmit_hashtype_tbl);
+ new_value = bond_parse_parm((char *)buf, xmit_hashtype_tbl);
if (new_value < 0) {
printk(KERN_ERR DRV_NAME
": %s: Ignoring invalid xmit hash policy value %.*s.\n",
int new_value;
struct bonding *bond = to_bond(cd);
- new_value = bond_parse_parm(buf, arp_validate_tbl);
+ new_value = bond_parse_parm((char *)buf, arp_validate_tbl);
if (new_value < 0) {
printk(KERN_ERR DRV_NAME
": %s: Ignoring invalid arp_validate value %s\n",
goto out;
}
- new_value = bond_parse_parm(buf, bond_lacp_tbl);
+ new_value = bond_parse_parm((char *)buf, bond_lacp_tbl);
if ((new_value == 1) || (new_value == 0)) {
bond->params.lacp_fast = new_value;
int ret = 0;
struct bonding *firstbond;
+ init_rwsem(&bonding_rwsem);
+
/* get the netdev class pointer */
firstbond = container_of(bond_dev_list.next, struct bonding, bond_list);
if (!firstbond)