diff options
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 106 |
1 files changed, 56 insertions, 50 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2039f7838f2d..0942d82f7cbf 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -1464,10 +1464,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1464 | dev_set_allmulti(slave_dev, 1); | 1464 | dev_set_allmulti(slave_dev, 1); |
1465 | } | 1465 | } |
1466 | 1466 | ||
1467 | netif_tx_lock_bh(bond_dev); | ||
1467 | /* upload master's mc_list to new slave */ | 1468 | /* upload master's mc_list to new slave */ |
1468 | for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) { | 1469 | for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) { |
1469 | dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | 1470 | dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); |
1470 | } | 1471 | } |
1472 | netif_tx_unlock_bh(bond_dev); | ||
1471 | } | 1473 | } |
1472 | 1474 | ||
1473 | if (bond->params.mode == BOND_MODE_8023AD) { | 1475 | if (bond->params.mode == BOND_MODE_8023AD) { |
@@ -1821,7 +1823,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1821 | } | 1823 | } |
1822 | 1824 | ||
1823 | /* flush master's mc_list from slave */ | 1825 | /* flush master's mc_list from slave */ |
1826 | netif_tx_lock_bh(bond_dev); | ||
1824 | bond_mc_list_flush(bond_dev, slave_dev); | 1827 | bond_mc_list_flush(bond_dev, slave_dev); |
1828 | netif_tx_unlock_bh(bond_dev); | ||
1825 | } | 1829 | } |
1826 | 1830 | ||
1827 | netdev_set_master(slave_dev, NULL); | 1831 | netdev_set_master(slave_dev, NULL); |
@@ -1942,7 +1946,9 @@ static int bond_release_all(struct net_device *bond_dev) | |||
1942 | } | 1946 | } |
1943 | 1947 | ||
1944 | /* flush master's mc_list from slave */ | 1948 | /* flush master's mc_list from slave */ |
1949 | netif_tx_lock_bh(bond_dev); | ||
1945 | bond_mc_list_flush(bond_dev, slave_dev); | 1950 | bond_mc_list_flush(bond_dev, slave_dev); |
1951 | netif_tx_unlock_bh(bond_dev); | ||
1946 | } | 1952 | } |
1947 | 1953 | ||
1948 | netdev_set_master(slave_dev, NULL); | 1954 | netdev_set_master(slave_dev, NULL); |
@@ -2795,14 +2801,11 @@ void bond_loadbalance_arp_mon(struct work_struct *work) | |||
2795 | } | 2801 | } |
2796 | 2802 | ||
2797 | if (do_failover) { | 2803 | if (do_failover) { |
2798 | rtnl_lock(); | ||
2799 | write_lock_bh(&bond->curr_slave_lock); | 2804 | write_lock_bh(&bond->curr_slave_lock); |
2800 | 2805 | ||
2801 | bond_select_active_slave(bond); | 2806 | bond_select_active_slave(bond); |
2802 | 2807 | ||
2803 | write_unlock_bh(&bond->curr_slave_lock); | 2808 | write_unlock_bh(&bond->curr_slave_lock); |
2804 | rtnl_unlock(); | ||
2805 | |||
2806 | } | 2809 | } |
2807 | 2810 | ||
2808 | re_arm: | 2811 | re_arm: |
@@ -2859,8 +2862,6 @@ void bond_activebackup_arp_mon(struct work_struct *work) | |||
2859 | 2862 | ||
2860 | slave->link = BOND_LINK_UP; | 2863 | slave->link = BOND_LINK_UP; |
2861 | 2864 | ||
2862 | rtnl_lock(); | ||
2863 | |||
2864 | write_lock_bh(&bond->curr_slave_lock); | 2865 | write_lock_bh(&bond->curr_slave_lock); |
2865 | 2866 | ||
2866 | if ((!bond->curr_active_slave) && | 2867 | if ((!bond->curr_active_slave) && |
@@ -2896,7 +2897,6 @@ void bond_activebackup_arp_mon(struct work_struct *work) | |||
2896 | } | 2897 | } |
2897 | 2898 | ||
2898 | write_unlock_bh(&bond->curr_slave_lock); | 2899 | write_unlock_bh(&bond->curr_slave_lock); |
2899 | rtnl_unlock(); | ||
2900 | } | 2900 | } |
2901 | } else { | 2901 | } else { |
2902 | read_lock(&bond->curr_slave_lock); | 2902 | read_lock(&bond->curr_slave_lock); |
@@ -2966,7 +2966,6 @@ void bond_activebackup_arp_mon(struct work_struct *work) | |||
2966 | bond->dev->name, | 2966 | bond->dev->name, |
2967 | slave->dev->name); | 2967 | slave->dev->name); |
2968 | 2968 | ||
2969 | rtnl_lock(); | ||
2970 | write_lock_bh(&bond->curr_slave_lock); | 2969 | write_lock_bh(&bond->curr_slave_lock); |
2971 | 2970 | ||
2972 | bond_select_active_slave(bond); | 2971 | bond_select_active_slave(bond); |
@@ -2974,8 +2973,6 @@ void bond_activebackup_arp_mon(struct work_struct *work) | |||
2974 | 2973 | ||
2975 | write_unlock_bh(&bond->curr_slave_lock); | 2974 | write_unlock_bh(&bond->curr_slave_lock); |
2976 | 2975 | ||
2977 | rtnl_unlock(); | ||
2978 | |||
2979 | bond->current_arp_slave = slave; | 2976 | bond->current_arp_slave = slave; |
2980 | 2977 | ||
2981 | if (slave) { | 2978 | if (slave) { |
@@ -2993,13 +2990,10 @@ void bond_activebackup_arp_mon(struct work_struct *work) | |||
2993 | bond->primary_slave->dev->name); | 2990 | bond->primary_slave->dev->name); |
2994 | 2991 | ||
2995 | /* primary is up so switch to it */ | 2992 | /* primary is up so switch to it */ |
2996 | rtnl_lock(); | ||
2997 | write_lock_bh(&bond->curr_slave_lock); | 2993 | write_lock_bh(&bond->curr_slave_lock); |
2998 | bond_change_active_slave(bond, bond->primary_slave); | 2994 | bond_change_active_slave(bond, bond->primary_slave); |
2999 | write_unlock_bh(&bond->curr_slave_lock); | 2995 | write_unlock_bh(&bond->curr_slave_lock); |
3000 | 2996 | ||
3001 | rtnl_unlock(); | ||
3002 | |||
3003 | slave = bond->primary_slave; | 2997 | slave = bond->primary_slave; |
3004 | slave->jiffies = jiffies; | 2998 | slave->jiffies = jiffies; |
3005 | } else { | 2999 | } else { |
@@ -3769,42 +3763,45 @@ static struct net_device_stats *bond_get_stats(struct net_device *bond_dev) | |||
3769 | { | 3763 | { |
3770 | struct bonding *bond = bond_dev->priv; | 3764 | struct bonding *bond = bond_dev->priv; |
3771 | struct net_device_stats *stats = &(bond->stats), *sstats; | 3765 | struct net_device_stats *stats = &(bond->stats), *sstats; |
3766 | struct net_device_stats local_stats; | ||
3772 | struct slave *slave; | 3767 | struct slave *slave; |
3773 | int i; | 3768 | int i; |
3774 | 3769 | ||
3775 | memset(stats, 0, sizeof(struct net_device_stats)); | 3770 | memset(&local_stats, 0, sizeof(struct net_device_stats)); |
3776 | 3771 | ||
3777 | read_lock_bh(&bond->lock); | 3772 | read_lock_bh(&bond->lock); |
3778 | 3773 | ||
3779 | bond_for_each_slave(bond, slave, i) { | 3774 | bond_for_each_slave(bond, slave, i) { |
3780 | sstats = slave->dev->get_stats(slave->dev); | 3775 | sstats = slave->dev->get_stats(slave->dev); |
3781 | stats->rx_packets += sstats->rx_packets; | 3776 | local_stats.rx_packets += sstats->rx_packets; |
3782 | stats->rx_bytes += sstats->rx_bytes; | 3777 | local_stats.rx_bytes += sstats->rx_bytes; |
3783 | stats->rx_errors += sstats->rx_errors; | 3778 | local_stats.rx_errors += sstats->rx_errors; |
3784 | stats->rx_dropped += sstats->rx_dropped; | 3779 | local_stats.rx_dropped += sstats->rx_dropped; |
3785 | 3780 | ||
3786 | stats->tx_packets += sstats->tx_packets; | 3781 | local_stats.tx_packets += sstats->tx_packets; |
3787 | stats->tx_bytes += sstats->tx_bytes; | 3782 | local_stats.tx_bytes += sstats->tx_bytes; |
3788 | stats->tx_errors += sstats->tx_errors; | 3783 | local_stats.tx_errors += sstats->tx_errors; |
3789 | stats->tx_dropped += sstats->tx_dropped; | 3784 | local_stats.tx_dropped += sstats->tx_dropped; |
3790 | 3785 | ||
3791 | stats->multicast += sstats->multicast; | 3786 | local_stats.multicast += sstats->multicast; |
3792 | stats->collisions += sstats->collisions; | 3787 | local_stats.collisions += sstats->collisions; |
3793 | 3788 | ||
3794 | stats->rx_length_errors += sstats->rx_length_errors; | 3789 | local_stats.rx_length_errors += sstats->rx_length_errors; |
3795 | stats->rx_over_errors += sstats->rx_over_errors; | 3790 | local_stats.rx_over_errors += sstats->rx_over_errors; |
3796 | stats->rx_crc_errors += sstats->rx_crc_errors; | 3791 | local_stats.rx_crc_errors += sstats->rx_crc_errors; |
3797 | stats->rx_frame_errors += sstats->rx_frame_errors; | 3792 | local_stats.rx_frame_errors += sstats->rx_frame_errors; |
3798 | stats->rx_fifo_errors += sstats->rx_fifo_errors; | 3793 | local_stats.rx_fifo_errors += sstats->rx_fifo_errors; |
3799 | stats->rx_missed_errors += sstats->rx_missed_errors; | 3794 | local_stats.rx_missed_errors += sstats->rx_missed_errors; |
3800 | 3795 | ||
3801 | stats->tx_aborted_errors += sstats->tx_aborted_errors; | 3796 | local_stats.tx_aborted_errors += sstats->tx_aborted_errors; |
3802 | stats->tx_carrier_errors += sstats->tx_carrier_errors; | 3797 | local_stats.tx_carrier_errors += sstats->tx_carrier_errors; |
3803 | stats->tx_fifo_errors += sstats->tx_fifo_errors; | 3798 | local_stats.tx_fifo_errors += sstats->tx_fifo_errors; |
3804 | stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors; | 3799 | local_stats.tx_heartbeat_errors += sstats->tx_heartbeat_errors; |
3805 | stats->tx_window_errors += sstats->tx_window_errors; | 3800 | local_stats.tx_window_errors += sstats->tx_window_errors; |
3806 | } | 3801 | } |
3807 | 3802 | ||
3803 | memcpy(stats, &local_stats, sizeof(struct net_device_stats)); | ||
3804 | |||
3808 | read_unlock_bh(&bond->lock); | 3805 | read_unlock_bh(&bond->lock); |
3809 | 3806 | ||
3810 | return stats; | 3807 | return stats; |
@@ -3937,8 +3934,6 @@ static void bond_set_multicast_list(struct net_device *bond_dev) | |||
3937 | struct bonding *bond = bond_dev->priv; | 3934 | struct bonding *bond = bond_dev->priv; |
3938 | struct dev_mc_list *dmi; | 3935 | struct dev_mc_list *dmi; |
3939 | 3936 | ||
3940 | write_lock_bh(&bond->lock); | ||
3941 | |||
3942 | /* | 3937 | /* |
3943 | * Do promisc before checking multicast_mode | 3938 | * Do promisc before checking multicast_mode |
3944 | */ | 3939 | */ |
@@ -3959,6 +3954,8 @@ static void bond_set_multicast_list(struct net_device *bond_dev) | |||
3959 | bond_set_allmulti(bond, -1); | 3954 | bond_set_allmulti(bond, -1); |
3960 | } | 3955 | } |
3961 | 3956 | ||
3957 | read_lock(&bond->lock); | ||
3958 | |||
3962 | bond->flags = bond_dev->flags; | 3959 | bond->flags = bond_dev->flags; |
3963 | 3960 | ||
3964 | /* looking for addresses to add to slaves' mc list */ | 3961 | /* looking for addresses to add to slaves' mc list */ |
@@ -3979,7 +3976,7 @@ static void bond_set_multicast_list(struct net_device *bond_dev) | |||
3979 | bond_mc_list_destroy(bond); | 3976 | bond_mc_list_destroy(bond); |
3980 | bond_mc_list_copy(bond_dev->mc_list, bond, GFP_ATOMIC); | 3977 | bond_mc_list_copy(bond_dev->mc_list, bond, GFP_ATOMIC); |
3981 | 3978 | ||
3982 | write_unlock_bh(&bond->lock); | 3979 | read_unlock(&bond->lock); |
3983 | } | 3980 | } |
3984 | 3981 | ||
3985 | /* | 3982 | /* |
@@ -4526,7 +4523,9 @@ static void bond_free_all(void) | |||
4526 | struct net_device *bond_dev = bond->dev; | 4523 | struct net_device *bond_dev = bond->dev; |
4527 | 4524 | ||
4528 | bond_work_cancel_all(bond); | 4525 | bond_work_cancel_all(bond); |
4526 | netif_tx_lock_bh(bond_dev); | ||
4529 | bond_mc_list_destroy(bond); | 4527 | bond_mc_list_destroy(bond); |
4528 | netif_tx_unlock_bh(bond_dev); | ||
4530 | /* Release the bonded slaves */ | 4529 | /* Release the bonded slaves */ |
4531 | bond_release_all(bond_dev); | 4530 | bond_release_all(bond_dev); |
4532 | bond_deinit(bond_dev); | 4531 | bond_deinit(bond_dev); |
@@ -4549,14 +4548,19 @@ static void bond_free_all(void) | |||
4549 | int bond_parse_parm(const char *buf, struct bond_parm_tbl *tbl) | 4548 | int bond_parse_parm(const char *buf, struct bond_parm_tbl *tbl) |
4550 | { | 4549 | { |
4551 | int mode = -1, i, rv; | 4550 | int mode = -1, i, rv; |
4552 | char modestr[BOND_MAX_MODENAME_LEN + 1] = { 0, }; | 4551 | char *p, modestr[BOND_MAX_MODENAME_LEN + 1] = { 0, }; |
4553 | 4552 | ||
4554 | rv = sscanf(buf, "%d", &mode); | 4553 | for (p = (char *)buf; *p; p++) |
4555 | if (!rv) { | 4554 | if (!(isdigit(*p) || isspace(*p))) |
4555 | break; | ||
4556 | |||
4557 | if (*p) | ||
4556 | rv = sscanf(buf, "%20s", modestr); | 4558 | rv = sscanf(buf, "%20s", modestr); |
4557 | if (!rv) | 4559 | else |
4558 | return -1; | 4560 | rv = sscanf(buf, "%d", &mode); |
4559 | } | 4561 | |
4562 | if (!rv) | ||
4563 | return -1; | ||
4560 | 4564 | ||
4561 | for (i = 0; tbl[i].modename; i++) { | 4565 | for (i = 0; tbl[i].modename; i++) { |
4562 | if (mode == tbl[i].mode) | 4566 | if (mode == tbl[i].mode) |
@@ -4883,14 +4887,16 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond | |||
4883 | down_write(&bonding_rwsem); | 4887 | down_write(&bonding_rwsem); |
4884 | 4888 | ||
4885 | /* Check to see if the bond already exists. */ | 4889 | /* Check to see if the bond already exists. */ |
4886 | list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) | 4890 | if (name) { |
4887 | if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) { | 4891 | list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) |
4888 | printk(KERN_ERR DRV_NAME | 4892 | if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) { |
4893 | printk(KERN_ERR DRV_NAME | ||
4889 | ": cannot add bond %s; it already exists\n", | 4894 | ": cannot add bond %s; it already exists\n", |
4890 | name); | 4895 | name); |
4891 | res = -EPERM; | 4896 | res = -EPERM; |
4892 | goto out_rtnl; | 4897 | goto out_rtnl; |
4893 | } | 4898 | } |
4899 | } | ||
4894 | 4900 | ||
4895 | bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "", | 4901 | bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "", |
4896 | ether_setup); | 4902 | ether_setup); |