diff options
author | Jiri Pirko <jiri@resnulli.us> | 2013-01-03 17:49:01 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-01-04 16:31:50 -0500 |
commit | 471cb5a33dcbd7c529684a2ac7ba4451414ee4a7 (patch) | |
tree | 8bf8fa62166a62acb7737bf257b0eb82da8e1be1 | |
parent | 7f6e7101dfcc228151779354f6cdc5e1d62f576b (diff) |
bonding: remove usage of dev->master
Benefit from new upper dev list and free bonding from dev->master usage.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/bonding/bond_3ad.c | 30 | ||||
-rw-r--r-- | drivers/net/bonding/bond_alb.c | 6 | ||||
-rw-r--r-- | drivers/net/bonding/bond_main.c | 94 | ||||
-rw-r--r-- | drivers/net/bonding/bonding.h | 14 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 1 |
5 files changed, 81 insertions, 64 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index a030e635f001..84fabd69df4c 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c | |||
@@ -1127,7 +1127,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
1127 | // INFO_RECEIVED_LOOPBACK_FRAMES | 1127 | // INFO_RECEIVED_LOOPBACK_FRAMES |
1128 | pr_err("%s: An illegal loopback occurred on adapter (%s).\n" | 1128 | pr_err("%s: An illegal loopback occurred on adapter (%s).\n" |
1129 | "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n", | 1129 | "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n", |
1130 | port->slave->dev->master->name, port->slave->dev->name); | 1130 | port->slave->bond->dev->name, port->slave->dev->name); |
1131 | return; | 1131 | return; |
1132 | } | 1132 | } |
1133 | __update_selected(lacpdu, port); | 1133 | __update_selected(lacpdu, port); |
@@ -1306,7 +1306,7 @@ static void ad_port_selection_logic(struct port *port) | |||
1306 | } | 1306 | } |
1307 | if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list | 1307 | if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list |
1308 | pr_warning("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n", | 1308 | pr_warning("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n", |
1309 | port->slave->dev->master->name, | 1309 | port->slave->bond->dev->name, |
1310 | port->actor_port_number, | 1310 | port->actor_port_number, |
1311 | port->slave->dev->name, | 1311 | port->slave->dev->name, |
1312 | port->aggregator->aggregator_identifier); | 1312 | port->aggregator->aggregator_identifier); |
@@ -1386,7 +1386,7 @@ static void ad_port_selection_logic(struct port *port) | |||
1386 | port->aggregator->aggregator_identifier); | 1386 | port->aggregator->aggregator_identifier); |
1387 | } else { | 1387 | } else { |
1388 | pr_err("%s: Port %d (on %s) did not find a suitable aggregator\n", | 1388 | pr_err("%s: Port %d (on %s) did not find a suitable aggregator\n", |
1389 | port->slave->dev->master->name, | 1389 | port->slave->bond->dev->name, |
1390 | port->actor_port_number, port->slave->dev->name); | 1390 | port->actor_port_number, port->slave->dev->name); |
1391 | } | 1391 | } |
1392 | } | 1392 | } |
@@ -1463,7 +1463,7 @@ static struct aggregator *ad_agg_selection_test(struct aggregator *best, | |||
1463 | 1463 | ||
1464 | default: | 1464 | default: |
1465 | pr_warning("%s: Impossible agg select mode %d\n", | 1465 | pr_warning("%s: Impossible agg select mode %d\n", |
1466 | curr->slave->dev->master->name, | 1466 | curr->slave->bond->dev->name, |
1467 | __get_agg_selection_mode(curr->lag_ports)); | 1467 | __get_agg_selection_mode(curr->lag_ports)); |
1468 | break; | 1468 | break; |
1469 | } | 1469 | } |
@@ -1571,7 +1571,7 @@ static void ad_agg_selection_logic(struct aggregator *agg) | |||
1571 | // check if any partner replys | 1571 | // check if any partner replys |
1572 | if (best->is_individual) { | 1572 | if (best->is_individual) { |
1573 | pr_warning("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n", | 1573 | pr_warning("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n", |
1574 | best->slave ? best->slave->dev->master->name : "NULL"); | 1574 | best->slave ? best->slave->bond->dev->name : "NULL"); |
1575 | } | 1575 | } |
1576 | 1576 | ||
1577 | best->is_active = 1; | 1577 | best->is_active = 1; |
@@ -1898,7 +1898,7 @@ int bond_3ad_bind_slave(struct slave *slave) | |||
1898 | 1898 | ||
1899 | if (bond == NULL) { | 1899 | if (bond == NULL) { |
1900 | pr_err("%s: The slave %s is not attached to its bond\n", | 1900 | pr_err("%s: The slave %s is not attached to its bond\n", |
1901 | slave->dev->master->name, slave->dev->name); | 1901 | slave->bond->dev->name, slave->dev->name); |
1902 | return -1; | 1902 | return -1; |
1903 | } | 1903 | } |
1904 | 1904 | ||
@@ -1973,7 +1973,7 @@ void bond_3ad_unbind_slave(struct slave *slave) | |||
1973 | // if slave is null, the whole port is not initialized | 1973 | // if slave is null, the whole port is not initialized |
1974 | if (!port->slave) { | 1974 | if (!port->slave) { |
1975 | pr_warning("Warning: %s: Trying to unbind an uninitialized port on %s\n", | 1975 | pr_warning("Warning: %s: Trying to unbind an uninitialized port on %s\n", |
1976 | slave->dev->master->name, slave->dev->name); | 1976 | slave->bond->dev->name, slave->dev->name); |
1977 | return; | 1977 | return; |
1978 | } | 1978 | } |
1979 | 1979 | ||
@@ -2009,7 +2009,7 @@ void bond_3ad_unbind_slave(struct slave *slave) | |||
2009 | 2009 | ||
2010 | if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) { | 2010 | if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) { |
2011 | pr_info("%s: Removing an active aggregator\n", | 2011 | pr_info("%s: Removing an active aggregator\n", |
2012 | aggregator->slave->dev->master->name); | 2012 | aggregator->slave->bond->dev->name); |
2013 | // select new active aggregator | 2013 | // select new active aggregator |
2014 | select_new_active_agg = 1; | 2014 | select_new_active_agg = 1; |
2015 | } | 2015 | } |
@@ -2040,7 +2040,7 @@ void bond_3ad_unbind_slave(struct slave *slave) | |||
2040 | ad_agg_selection_logic(__get_first_agg(port)); | 2040 | ad_agg_selection_logic(__get_first_agg(port)); |
2041 | } else { | 2041 | } else { |
2042 | pr_warning("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n", | 2042 | pr_warning("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n", |
2043 | slave->dev->master->name); | 2043 | slave->bond->dev->name); |
2044 | } | 2044 | } |
2045 | } else { // in case that the only port related to this aggregator is the one we want to remove | 2045 | } else { // in case that the only port related to this aggregator is the one we want to remove |
2046 | select_new_active_agg = aggregator->is_active; | 2046 | select_new_active_agg = aggregator->is_active; |
@@ -2048,7 +2048,7 @@ void bond_3ad_unbind_slave(struct slave *slave) | |||
2048 | ad_clear_agg(aggregator); | 2048 | ad_clear_agg(aggregator); |
2049 | if (select_new_active_agg) { | 2049 | if (select_new_active_agg) { |
2050 | pr_info("%s: Removing an active aggregator\n", | 2050 | pr_info("%s: Removing an active aggregator\n", |
2051 | slave->dev->master->name); | 2051 | slave->bond->dev->name); |
2052 | // select new active aggregator | 2052 | // select new active aggregator |
2053 | ad_agg_selection_logic(__get_first_agg(port)); | 2053 | ad_agg_selection_logic(__get_first_agg(port)); |
2054 | } | 2054 | } |
@@ -2076,7 +2076,7 @@ void bond_3ad_unbind_slave(struct slave *slave) | |||
2076 | ad_clear_agg(temp_aggregator); | 2076 | ad_clear_agg(temp_aggregator); |
2077 | if (select_new_active_agg) { | 2077 | if (select_new_active_agg) { |
2078 | pr_info("%s: Removing an active aggregator\n", | 2078 | pr_info("%s: Removing an active aggregator\n", |
2079 | slave->dev->master->name); | 2079 | slave->bond->dev->name); |
2080 | // select new active aggregator | 2080 | // select new active aggregator |
2081 | ad_agg_selection_logic(__get_first_agg(port)); | 2081 | ad_agg_selection_logic(__get_first_agg(port)); |
2082 | } | 2082 | } |
@@ -2184,7 +2184,7 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u1 | |||
2184 | 2184 | ||
2185 | if (!port->slave) { | 2185 | if (!port->slave) { |
2186 | pr_warning("%s: Warning: port of slave %s is uninitialized\n", | 2186 | pr_warning("%s: Warning: port of slave %s is uninitialized\n", |
2187 | slave->dev->name, slave->dev->master->name); | 2187 | slave->dev->name, slave->bond->dev->name); |
2188 | return ret; | 2188 | return ret; |
2189 | } | 2189 | } |
2190 | 2190 | ||
@@ -2240,7 +2240,7 @@ void bond_3ad_adapter_speed_changed(struct slave *slave) | |||
2240 | // if slave is null, the whole port is not initialized | 2240 | // if slave is null, the whole port is not initialized |
2241 | if (!port->slave) { | 2241 | if (!port->slave) { |
2242 | pr_warning("Warning: %s: speed changed for uninitialized port on %s\n", | 2242 | pr_warning("Warning: %s: speed changed for uninitialized port on %s\n", |
2243 | slave->dev->master->name, slave->dev->name); | 2243 | slave->bond->dev->name, slave->dev->name); |
2244 | return; | 2244 | return; |
2245 | } | 2245 | } |
2246 | 2246 | ||
@@ -2268,7 +2268,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave) | |||
2268 | // if slave is null, the whole port is not initialized | 2268 | // if slave is null, the whole port is not initialized |
2269 | if (!port->slave) { | 2269 | if (!port->slave) { |
2270 | pr_warning("%s: Warning: duplex changed for uninitialized port on %s\n", | 2270 | pr_warning("%s: Warning: duplex changed for uninitialized port on %s\n", |
2271 | slave->dev->master->name, slave->dev->name); | 2271 | slave->bond->dev->name, slave->dev->name); |
2272 | return; | 2272 | return; |
2273 | } | 2273 | } |
2274 | 2274 | ||
@@ -2297,7 +2297,7 @@ void bond_3ad_handle_link_change(struct slave *slave, char link) | |||
2297 | // if slave is null, the whole port is not initialized | 2297 | // if slave is null, the whole port is not initialized |
2298 | if (!port->slave) { | 2298 | if (!port->slave) { |
2299 | pr_warning("Warning: %s: link status changed for uninitialized port on %s\n", | 2299 | pr_warning("Warning: %s: link status changed for uninitialized port on %s\n", |
2300 | slave->dev->master->name, slave->dev->name); | 2300 | slave->bond->dev->name, slave->dev->name); |
2301 | return; | 2301 | return; |
2302 | } | 2302 | } |
2303 | 2303 | ||
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 7c9d136e74be..f5e052723029 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c | |||
@@ -507,7 +507,7 @@ static void rlb_update_client(struct rlb_client_info *client_info) | |||
507 | client_info->mac_dst); | 507 | client_info->mac_dst); |
508 | if (!skb) { | 508 | if (!skb) { |
509 | pr_err("%s: Error: failed to create an ARP packet\n", | 509 | pr_err("%s: Error: failed to create an ARP packet\n", |
510 | client_info->slave->dev->master->name); | 510 | client_info->slave->bond->dev->name); |
511 | continue; | 511 | continue; |
512 | } | 512 | } |
513 | 513 | ||
@@ -517,7 +517,7 @@ static void rlb_update_client(struct rlb_client_info *client_info) | |||
517 | skb = vlan_put_tag(skb, client_info->vlan_id); | 517 | skb = vlan_put_tag(skb, client_info->vlan_id); |
518 | if (!skb) { | 518 | if (!skb) { |
519 | pr_err("%s: Error: failed to insert VLAN tag\n", | 519 | pr_err("%s: Error: failed to insert VLAN tag\n", |
520 | client_info->slave->dev->master->name); | 520 | client_info->slave->bond->dev->name); |
521 | continue; | 521 | continue; |
522 | } | 522 | } |
523 | } | 523 | } |
@@ -1043,7 +1043,7 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[]) | |||
1043 | if (dev_set_mac_address(dev, &s_addr)) { | 1043 | if (dev_set_mac_address(dev, &s_addr)) { |
1044 | pr_err("%s: Error: dev_set_mac_address of dev %s failed!\n" | 1044 | pr_err("%s: Error: dev_set_mac_address of dev %s failed!\n" |
1045 | "ALB mode requires that the base driver support setting the hw address also when the network device's interface is open\n", | 1045 | "ALB mode requires that the base driver support setting the hw address also when the network device's interface is open\n", |
1046 | dev->master->name, dev->name); | 1046 | slave->bond->dev->name, dev->name); |
1047 | return -EOPNOTSUPP; | 1047 | return -EOPNOTSUPP; |
1048 | } | 1048 | } |
1049 | return 0; | 1049 | return 0; |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b7d45f367d4a..c4952985c084 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -746,11 +746,9 @@ static void __bond_resend_igmp_join_requests(struct net_device *dev) | |||
746 | { | 746 | { |
747 | struct in_device *in_dev; | 747 | struct in_device *in_dev; |
748 | 748 | ||
749 | rcu_read_lock(); | ||
750 | in_dev = __in_dev_get_rcu(dev); | 749 | in_dev = __in_dev_get_rcu(dev); |
751 | if (in_dev) | 750 | if (in_dev) |
752 | ip_mc_rejoin_groups(in_dev); | 751 | ip_mc_rejoin_groups(in_dev); |
753 | rcu_read_unlock(); | ||
754 | } | 752 | } |
755 | 753 | ||
756 | /* | 754 | /* |
@@ -760,9 +758,10 @@ static void __bond_resend_igmp_join_requests(struct net_device *dev) | |||
760 | */ | 758 | */ |
761 | static void bond_resend_igmp_join_requests(struct bonding *bond) | 759 | static void bond_resend_igmp_join_requests(struct bonding *bond) |
762 | { | 760 | { |
763 | struct net_device *bond_dev, *vlan_dev, *master_dev; | 761 | struct net_device *bond_dev, *vlan_dev, *upper_dev; |
764 | struct vlan_entry *vlan; | 762 | struct vlan_entry *vlan; |
765 | 763 | ||
764 | rcu_read_lock(); | ||
766 | read_lock(&bond->lock); | 765 | read_lock(&bond->lock); |
767 | 766 | ||
768 | bond_dev = bond->dev; | 767 | bond_dev = bond->dev; |
@@ -774,18 +773,14 @@ static void bond_resend_igmp_join_requests(struct bonding *bond) | |||
774 | * if bond is enslaved to a bridge, | 773 | * if bond is enslaved to a bridge, |
775 | * then rejoin all groups on its master | 774 | * then rejoin all groups on its master |
776 | */ | 775 | */ |
777 | master_dev = bond_dev->master; | 776 | upper_dev = netdev_master_upper_dev_get_rcu(bond_dev); |
778 | if (master_dev) | 777 | if (upper_dev && upper_dev->priv_flags & IFF_EBRIDGE) |
779 | if ((master_dev->priv_flags & IFF_EBRIDGE) | 778 | __bond_resend_igmp_join_requests(upper_dev); |
780 | && (bond_dev->priv_flags & IFF_BRIDGE_PORT)) | ||
781 | __bond_resend_igmp_join_requests(master_dev); | ||
782 | 779 | ||
783 | /* rejoin all groups on vlan devices */ | 780 | /* rejoin all groups on vlan devices */ |
784 | list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { | 781 | list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { |
785 | rcu_read_lock(); | ||
786 | vlan_dev = __vlan_find_dev_deep(bond_dev, | 782 | vlan_dev = __vlan_find_dev_deep(bond_dev, |
787 | vlan->vlan_id); | 783 | vlan->vlan_id); |
788 | rcu_read_unlock(); | ||
789 | if (vlan_dev) | 784 | if (vlan_dev) |
790 | __bond_resend_igmp_join_requests(vlan_dev); | 785 | __bond_resend_igmp_join_requests(vlan_dev); |
791 | } | 786 | } |
@@ -794,13 +789,16 @@ static void bond_resend_igmp_join_requests(struct bonding *bond) | |||
794 | queue_delayed_work(bond->wq, &bond->mcast_work, HZ/5); | 789 | queue_delayed_work(bond->wq, &bond->mcast_work, HZ/5); |
795 | 790 | ||
796 | read_unlock(&bond->lock); | 791 | read_unlock(&bond->lock); |
792 | rcu_read_unlock(); | ||
797 | } | 793 | } |
798 | 794 | ||
799 | static void bond_resend_igmp_join_requests_delayed(struct work_struct *work) | 795 | static void bond_resend_igmp_join_requests_delayed(struct work_struct *work) |
800 | { | 796 | { |
801 | struct bonding *bond = container_of(work, struct bonding, | 797 | struct bonding *bond = container_of(work, struct bonding, |
802 | mcast_work.work); | 798 | mcast_work.work); |
799 | rcu_read_lock(); | ||
803 | bond_resend_igmp_join_requests(bond); | 800 | bond_resend_igmp_join_requests(bond); |
801 | rcu_read_unlock(); | ||
804 | } | 802 | } |
805 | 803 | ||
806 | /* | 804 | /* |
@@ -1493,6 +1491,27 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb) | |||
1493 | return ret; | 1491 | return ret; |
1494 | } | 1492 | } |
1495 | 1493 | ||
1494 | static int bond_master_upper_dev_link(struct net_device *bond_dev, | ||
1495 | struct net_device *slave_dev) | ||
1496 | { | ||
1497 | int err; | ||
1498 | |||
1499 | err = netdev_master_upper_dev_link(slave_dev, bond_dev); | ||
1500 | if (err) | ||
1501 | return err; | ||
1502 | slave_dev->flags |= IFF_SLAVE; | ||
1503 | rtmsg_ifinfo(RTM_NEWLINK, slave_dev, IFF_SLAVE); | ||
1504 | return 0; | ||
1505 | } | ||
1506 | |||
1507 | static void bond_upper_dev_unlink(struct net_device *bond_dev, | ||
1508 | struct net_device *slave_dev) | ||
1509 | { | ||
1510 | netdev_upper_dev_unlink(slave_dev, bond_dev); | ||
1511 | slave_dev->flags &= ~IFF_SLAVE; | ||
1512 | rtmsg_ifinfo(RTM_NEWLINK, slave_dev, IFF_SLAVE); | ||
1513 | } | ||
1514 | |||
1496 | /* enslave device <slave> to bond device <master> */ | 1515 | /* enslave device <slave> to bond device <master> */ |
1497 | int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | 1516 | int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) |
1498 | { | 1517 | { |
@@ -1655,9 +1674,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1655 | } | 1674 | } |
1656 | } | 1675 | } |
1657 | 1676 | ||
1658 | res = netdev_set_bond_master(slave_dev, bond_dev); | 1677 | res = bond_master_upper_dev_link(bond_dev, slave_dev); |
1659 | if (res) { | 1678 | if (res) { |
1660 | pr_debug("Error %d calling netdev_set_bond_master\n", res); | 1679 | pr_debug("Error %d calling bond_master_upper_dev_link\n", res); |
1661 | goto err_restore_mac; | 1680 | goto err_restore_mac; |
1662 | } | 1681 | } |
1663 | 1682 | ||
@@ -1891,7 +1910,7 @@ err_close: | |||
1891 | dev_close(slave_dev); | 1910 | dev_close(slave_dev); |
1892 | 1911 | ||
1893 | err_unset_master: | 1912 | err_unset_master: |
1894 | netdev_set_bond_master(slave_dev, NULL); | 1913 | bond_upper_dev_unlink(bond_dev, slave_dev); |
1895 | 1914 | ||
1896 | err_restore_mac: | 1915 | err_restore_mac: |
1897 | if (!bond->params.fail_over_mac) { | 1916 | if (!bond->params.fail_over_mac) { |
@@ -1936,7 +1955,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1936 | 1955 | ||
1937 | /* slave is not a slave or master is not master of this slave */ | 1956 | /* slave is not a slave or master is not master of this slave */ |
1938 | if (!(slave_dev->flags & IFF_SLAVE) || | 1957 | if (!(slave_dev->flags & IFF_SLAVE) || |
1939 | (slave_dev->master != bond_dev)) { | 1958 | !netdev_has_upper_dev(slave_dev, bond_dev)) { |
1940 | pr_err("%s: Error: cannot release %s.\n", | 1959 | pr_err("%s: Error: cannot release %s.\n", |
1941 | bond_dev->name, slave_dev->name); | 1960 | bond_dev->name, slave_dev->name); |
1942 | return -EINVAL; | 1961 | return -EINVAL; |
@@ -2080,7 +2099,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) | |||
2080 | netif_addr_unlock_bh(bond_dev); | 2099 | netif_addr_unlock_bh(bond_dev); |
2081 | } | 2100 | } |
2082 | 2101 | ||
2083 | netdev_set_bond_master(slave_dev, NULL); | 2102 | bond_upper_dev_unlink(bond_dev, slave_dev); |
2084 | 2103 | ||
2085 | slave_disable_netpoll(slave); | 2104 | slave_disable_netpoll(slave); |
2086 | 2105 | ||
@@ -2195,7 +2214,7 @@ static int bond_release_all(struct net_device *bond_dev) | |||
2195 | netif_addr_unlock_bh(bond_dev); | 2214 | netif_addr_unlock_bh(bond_dev); |
2196 | } | 2215 | } |
2197 | 2216 | ||
2198 | netdev_set_bond_master(slave_dev, NULL); | 2217 | bond_upper_dev_unlink(bond_dev, slave_dev); |
2199 | 2218 | ||
2200 | slave_disable_netpoll(slave); | 2219 | slave_disable_netpoll(slave); |
2201 | 2220 | ||
@@ -2259,8 +2278,9 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi | |||
2259 | if (!USES_PRIMARY(bond->params.mode)) | 2278 | if (!USES_PRIMARY(bond->params.mode)) |
2260 | return -EINVAL; | 2279 | return -EINVAL; |
2261 | 2280 | ||
2262 | /* Verify that master_dev is indeed the master of slave_dev */ | 2281 | /* Verify that bond_dev is indeed the master of slave_dev */ |
2263 | if (!(slave_dev->flags & IFF_SLAVE) || (slave_dev->master != bond_dev)) | 2282 | if (!(slave_dev->flags & IFF_SLAVE) || |
2283 | !netdev_has_upper_dev(slave_dev, bond_dev)) | ||
2264 | return -EINVAL; | 2284 | return -EINVAL; |
2265 | 2285 | ||
2266 | read_lock(&bond->lock); | 2286 | read_lock(&bond->lock); |
@@ -3258,36 +3278,32 @@ static int bond_master_netdev_event(unsigned long event, | |||
3258 | static int bond_slave_netdev_event(unsigned long event, | 3278 | static int bond_slave_netdev_event(unsigned long event, |
3259 | struct net_device *slave_dev) | 3279 | struct net_device *slave_dev) |
3260 | { | 3280 | { |
3261 | struct net_device *bond_dev = slave_dev->master; | 3281 | struct slave *slave = bond_slave_get_rtnl(slave_dev); |
3262 | struct bonding *bond = netdev_priv(bond_dev); | 3282 | struct bonding *bond = slave->bond; |
3263 | struct slave *slave = NULL; | 3283 | struct net_device *bond_dev = slave->bond->dev; |
3284 | u32 old_speed; | ||
3285 | u8 old_duplex; | ||
3264 | 3286 | ||
3265 | switch (event) { | 3287 | switch (event) { |
3266 | case NETDEV_UNREGISTER: | 3288 | case NETDEV_UNREGISTER: |
3267 | if (bond_dev) { | 3289 | if (bond->setup_by_slave) |
3268 | if (bond->setup_by_slave) | 3290 | bond_release_and_destroy(bond_dev, slave_dev); |
3269 | bond_release_and_destroy(bond_dev, slave_dev); | 3291 | else |
3270 | else | 3292 | bond_release(bond_dev, slave_dev); |
3271 | bond_release(bond_dev, slave_dev); | ||
3272 | } | ||
3273 | break; | 3293 | break; |
3274 | case NETDEV_UP: | 3294 | case NETDEV_UP: |
3275 | case NETDEV_CHANGE: | 3295 | case NETDEV_CHANGE: |
3276 | slave = bond_get_slave_by_dev(bond, slave_dev); | 3296 | old_speed = slave->speed; |
3277 | if (slave) { | 3297 | old_duplex = slave->duplex; |
3278 | u32 old_speed = slave->speed; | ||
3279 | u8 old_duplex = slave->duplex; | ||
3280 | 3298 | ||
3281 | bond_update_speed_duplex(slave); | 3299 | bond_update_speed_duplex(slave); |
3282 | 3300 | ||
3283 | if (bond->params.mode == BOND_MODE_8023AD) { | 3301 | if (bond->params.mode == BOND_MODE_8023AD) { |
3284 | if (old_speed != slave->speed) | 3302 | if (old_speed != slave->speed) |
3285 | bond_3ad_adapter_speed_changed(slave); | 3303 | bond_3ad_adapter_speed_changed(slave); |
3286 | if (old_duplex != slave->duplex) | 3304 | if (old_duplex != slave->duplex) |
3287 | bond_3ad_adapter_duplex_changed(slave); | 3305 | bond_3ad_adapter_duplex_changed(slave); |
3288 | } | ||
3289 | } | 3306 | } |
3290 | |||
3291 | break; | 3307 | break; |
3292 | case NETDEV_DOWN: | 3308 | case NETDEV_DOWN: |
3293 | /* | 3309 | /* |
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 21b68e5c14fd..0d282d20b5a8 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h | |||
@@ -258,6 +258,9 @@ static inline bool bond_vlan_used(struct bonding *bond) | |||
258 | #define bond_slave_get_rcu(dev) \ | 258 | #define bond_slave_get_rcu(dev) \ |
259 | ((struct slave *) rcu_dereference(dev->rx_handler_data)) | 259 | ((struct slave *) rcu_dereference(dev->rx_handler_data)) |
260 | 260 | ||
261 | #define bond_slave_get_rtnl(dev) \ | ||
262 | ((struct slave *) rtnl_dereference(dev->rx_handler_data)) | ||
263 | |||
261 | /** | 264 | /** |
262 | * Returns NULL if the net_device does not belong to any of the bond's slaves | 265 | * Returns NULL if the net_device does not belong to any of the bond's slaves |
263 | * | 266 | * |
@@ -280,11 +283,9 @@ static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, | |||
280 | 283 | ||
281 | static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) | 284 | static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) |
282 | { | 285 | { |
283 | if (!slave || !slave->dev->master) { | 286 | if (!slave || !slave->bond) |
284 | return NULL; | 287 | return NULL; |
285 | } | 288 | return slave->bond; |
286 | |||
287 | return netdev_priv(slave->dev->master); | ||
288 | } | 289 | } |
289 | 290 | ||
290 | static inline bool bond_is_lb(const struct bonding *bond) | 291 | static inline bool bond_is_lb(const struct bonding *bond) |
@@ -360,10 +361,9 @@ static inline void bond_netpoll_send_skb(const struct slave *slave, | |||
360 | 361 | ||
361 | static inline void bond_set_slave_inactive_flags(struct slave *slave) | 362 | static inline void bond_set_slave_inactive_flags(struct slave *slave) |
362 | { | 363 | { |
363 | struct bonding *bond = netdev_priv(slave->dev->master); | 364 | if (!bond_is_lb(slave->bond)) |
364 | if (!bond_is_lb(bond)) | ||
365 | bond_set_backup_slave(slave); | 365 | bond_set_backup_slave(slave); |
366 | if (!bond->params.all_slaves_active) | 366 | if (!slave->bond->params.all_slaves_active) |
367 | slave->inactive = 1; | 367 | slave->inactive = 1; |
368 | } | 368 | } |
369 | 369 | ||
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index d26becbcddc4..9969afb82271 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -1987,6 +1987,7 @@ errout: | |||
1987 | if (err < 0) | 1987 | if (err < 0) |
1988 | rtnl_set_sk_err(net, RTNLGRP_LINK, err); | 1988 | rtnl_set_sk_err(net, RTNLGRP_LINK, err); |
1989 | } | 1989 | } |
1990 | EXPORT_SYMBOL(rtmsg_ifinfo); | ||
1990 | 1991 | ||
1991 | static int nlmsg_populate_fdb_fill(struct sk_buff *skb, | 1992 | static int nlmsg_populate_fdb_fill(struct sk_buff *skb, |
1992 | struct net_device *dev, | 1993 | struct net_device *dev, |