mirror of https://gitee.com/openkylin/linux.git
Merge branch 'bonding_rcu'
Eric Dumazet says: ==================== bonding: rcu cleanups RCU was added to bonding in linux-3.12 but lacked proper sparse annotations. Using __rcu annotation actually helps to spot all accesses to bond->curr_active_slave & cond->current_arp_slave are correctly protected, with full sparse & LOCKDEP support. Lets clean the code. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
c8ad0f298c
|
@ -448,11 +448,13 @@ static struct slave *__rlb_next_rx_slave(struct bonding *bond)
|
||||||
*/
|
*/
|
||||||
static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
|
static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
|
||||||
{
|
{
|
||||||
if (!bond->curr_active_slave)
|
struct slave *curr_active = bond_deref_active_protected(bond);
|
||||||
|
|
||||||
|
if (!curr_active)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!bond->alb_info.primary_is_promisc) {
|
if (!bond->alb_info.primary_is_promisc) {
|
||||||
if (!dev_set_promiscuity(bond->curr_active_slave->dev, 1))
|
if (!dev_set_promiscuity(curr_active->dev, 1))
|
||||||
bond->alb_info.primary_is_promisc = 1;
|
bond->alb_info.primary_is_promisc = 1;
|
||||||
else
|
else
|
||||||
bond->alb_info.primary_is_promisc = 0;
|
bond->alb_info.primary_is_promisc = 0;
|
||||||
|
@ -460,7 +462,7 @@ static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
|
||||||
|
|
||||||
bond->alb_info.rlb_promisc_timeout_counter = 0;
|
bond->alb_info.rlb_promisc_timeout_counter = 0;
|
||||||
|
|
||||||
alb_send_learning_packets(bond->curr_active_slave, addr, true);
|
alb_send_learning_packets(curr_active, addr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* slave being removed should not be active at this point
|
/* slave being removed should not be active at this point
|
||||||
|
@ -509,7 +511,7 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
|
||||||
|
|
||||||
write_lock_bh(&bond->curr_slave_lock);
|
write_lock_bh(&bond->curr_slave_lock);
|
||||||
|
|
||||||
if (slave != bond->curr_active_slave)
|
if (slave != bond_deref_active_protected(bond))
|
||||||
rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr);
|
rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr);
|
||||||
|
|
||||||
write_unlock_bh(&bond->curr_slave_lock);
|
write_unlock_bh(&bond->curr_slave_lock);
|
||||||
|
@ -684,7 +686,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
|
||||||
* move the old client to primary (curr_active_slave) so
|
* move the old client to primary (curr_active_slave) so
|
||||||
* that the new client can be assigned to this entry.
|
* that the new client can be assigned to this entry.
|
||||||
*/
|
*/
|
||||||
if (bond->curr_active_slave &&
|
if (curr_active_slave &&
|
||||||
client_info->slave != curr_active_slave) {
|
client_info->slave != curr_active_slave) {
|
||||||
client_info->slave = curr_active_slave;
|
client_info->slave = curr_active_slave;
|
||||||
rlb_update_client(client_info);
|
rlb_update_client(client_info);
|
||||||
|
@ -1221,7 +1223,7 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla
|
||||||
*/
|
*/
|
||||||
static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
|
static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
|
||||||
{
|
{
|
||||||
struct slave *has_bond_addr = bond->curr_active_slave;
|
struct slave *has_bond_addr = rcu_access_pointer(bond->curr_active_slave);
|
||||||
struct slave *tmp_slave1, *free_mac_slave = NULL;
|
struct slave *tmp_slave1, *free_mac_slave = NULL;
|
||||||
struct list_head *iter;
|
struct list_head *iter;
|
||||||
|
|
||||||
|
@ -1575,7 +1577,7 @@ void bond_alb_monitor(struct work_struct *work)
|
||||||
* use mac of the slave device.
|
* use mac of the slave device.
|
||||||
* In RLB mode, we always use strict matches.
|
* In RLB mode, we always use strict matches.
|
||||||
*/
|
*/
|
||||||
strict_match = (slave != bond->curr_active_slave ||
|
strict_match = (slave != rcu_access_pointer(bond->curr_active_slave) ||
|
||||||
bond_info->rlb_enabled);
|
bond_info->rlb_enabled);
|
||||||
alb_send_learning_packets(slave, slave->dev->dev_addr,
|
alb_send_learning_packets(slave, slave->dev->dev_addr,
|
||||||
strict_match);
|
strict_match);
|
||||||
|
@ -1593,7 +1595,7 @@ void bond_alb_monitor(struct work_struct *work)
|
||||||
|
|
||||||
bond_for_each_slave_rcu(bond, slave, iter) {
|
bond_for_each_slave_rcu(bond, slave, iter) {
|
||||||
tlb_clear_slave(bond, slave, 1);
|
tlb_clear_slave(bond, slave, 1);
|
||||||
if (slave == bond->curr_active_slave) {
|
if (slave == rcu_access_pointer(bond->curr_active_slave)) {
|
||||||
SLAVE_TLB_INFO(slave).load =
|
SLAVE_TLB_INFO(slave).load =
|
||||||
bond_info->unbalanced_load /
|
bond_info->unbalanced_load /
|
||||||
BOND_TLB_REBALANCE_INTERVAL;
|
BOND_TLB_REBALANCE_INTERVAL;
|
||||||
|
@ -1625,7 +1627,8 @@ void bond_alb_monitor(struct work_struct *work)
|
||||||
* because a slave was disabled then
|
* because a slave was disabled then
|
||||||
* it can now leave promiscuous mode.
|
* it can now leave promiscuous mode.
|
||||||
*/
|
*/
|
||||||
dev_set_promiscuity(bond->curr_active_slave->dev, -1);
|
dev_set_promiscuity(rtnl_dereference(bond->curr_active_slave)->dev,
|
||||||
|
-1);
|
||||||
bond_info->primary_is_promisc = 0;
|
bond_info->primary_is_promisc = 0;
|
||||||
|
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
@ -1742,17 +1745,21 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
|
||||||
__acquires(&bond->curr_slave_lock)
|
__acquires(&bond->curr_slave_lock)
|
||||||
{
|
{
|
||||||
struct slave *swap_slave;
|
struct slave *swap_slave;
|
||||||
|
struct slave *curr_active;
|
||||||
|
|
||||||
if (bond->curr_active_slave == new_slave)
|
curr_active = rcu_dereference_protected(bond->curr_active_slave,
|
||||||
|
!new_slave ||
|
||||||
|
lockdep_is_held(&bond->curr_slave_lock));
|
||||||
|
if (curr_active == new_slave)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (bond->curr_active_slave && bond->alb_info.primary_is_promisc) {
|
if (curr_active && bond->alb_info.primary_is_promisc) {
|
||||||
dev_set_promiscuity(bond->curr_active_slave->dev, -1);
|
dev_set_promiscuity(curr_active->dev, -1);
|
||||||
bond->alb_info.primary_is_promisc = 0;
|
bond->alb_info.primary_is_promisc = 0;
|
||||||
bond->alb_info.rlb_promisc_timeout_counter = 0;
|
bond->alb_info.rlb_promisc_timeout_counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
swap_slave = bond->curr_active_slave;
|
swap_slave = curr_active;
|
||||||
rcu_assign_pointer(bond->curr_active_slave, new_slave);
|
rcu_assign_pointer(bond->curr_active_slave, new_slave);
|
||||||
|
|
||||||
if (!new_slave || !bond_has_slaves(bond))
|
if (!new_slave || !bond_has_slaves(bond))
|
||||||
|
@ -1818,6 +1825,7 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
|
||||||
{
|
{
|
||||||
struct bonding *bond = netdev_priv(bond_dev);
|
struct bonding *bond = netdev_priv(bond_dev);
|
||||||
struct sockaddr *sa = addr;
|
struct sockaddr *sa = addr;
|
||||||
|
struct slave *curr_active;
|
||||||
struct slave *swap_slave;
|
struct slave *swap_slave;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
@ -1834,23 +1842,24 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
|
||||||
* Otherwise we'll need to pass the new address to it and handle
|
* Otherwise we'll need to pass the new address to it and handle
|
||||||
* duplications.
|
* duplications.
|
||||||
*/
|
*/
|
||||||
if (!bond->curr_active_slave)
|
curr_active = rtnl_dereference(bond->curr_active_slave);
|
||||||
|
if (!curr_active)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
swap_slave = bond_slave_has_mac(bond, bond_dev->dev_addr);
|
swap_slave = bond_slave_has_mac(bond, bond_dev->dev_addr);
|
||||||
|
|
||||||
if (swap_slave) {
|
if (swap_slave) {
|
||||||
alb_swap_mac_addr(swap_slave, bond->curr_active_slave);
|
alb_swap_mac_addr(swap_slave, curr_active);
|
||||||
alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
|
alb_fasten_mac_swap(bond, swap_slave, curr_active);
|
||||||
} else {
|
} else {
|
||||||
alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr);
|
alb_set_slave_mac_addr(curr_active, bond_dev->dev_addr);
|
||||||
|
|
||||||
read_lock(&bond->lock);
|
read_lock(&bond->lock);
|
||||||
alb_send_learning_packets(bond->curr_active_slave,
|
alb_send_learning_packets(curr_active,
|
||||||
bond_dev->dev_addr, false);
|
bond_dev->dev_addr, false);
|
||||||
if (bond->alb_info.rlb_enabled) {
|
if (bond->alb_info.rlb_enabled) {
|
||||||
/* inform clients mac address has changed */
|
/* inform clients mac address has changed */
|
||||||
rlb_req_update_slave_clients(bond, bond->curr_active_slave);
|
rlb_req_update_slave_clients(bond, curr_active);
|
||||||
}
|
}
|
||||||
read_unlock(&bond->lock);
|
read_unlock(&bond->lock);
|
||||||
}
|
}
|
||||||
|
|
|
@ -498,11 +498,11 @@ static int bond_set_promiscuity(struct bonding *bond, int inc)
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (bond_uses_primary(bond)) {
|
if (bond_uses_primary(bond)) {
|
||||||
|
struct slave *curr_active = bond_deref_active_protected(bond);
|
||||||
|
|
||||||
/* write lock already acquired */
|
/* write lock already acquired */
|
||||||
if (bond->curr_active_slave) {
|
if (curr_active)
|
||||||
err = dev_set_promiscuity(bond->curr_active_slave->dev,
|
err = dev_set_promiscuity(curr_active->dev, inc);
|
||||||
inc);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
struct slave *slave;
|
struct slave *slave;
|
||||||
|
|
||||||
|
@ -524,11 +524,11 @@ static int bond_set_allmulti(struct bonding *bond, int inc)
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (bond_uses_primary(bond)) {
|
if (bond_uses_primary(bond)) {
|
||||||
|
struct slave *curr_active = bond_deref_active_protected(bond);
|
||||||
|
|
||||||
/* write lock already acquired */
|
/* write lock already acquired */
|
||||||
if (bond->curr_active_slave) {
|
if (curr_active)
|
||||||
err = dev_set_allmulti(bond->curr_active_slave->dev,
|
err = dev_set_allmulti(curr_active->dev, inc);
|
||||||
inc);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
struct slave *slave;
|
struct slave *slave;
|
||||||
|
|
||||||
|
@ -713,7 +713,7 @@ static void bond_do_fail_over_mac(struct bonding *bond,
|
||||||
static bool bond_should_change_active(struct bonding *bond)
|
static bool bond_should_change_active(struct bonding *bond)
|
||||||
{
|
{
|
||||||
struct slave *prim = bond->primary_slave;
|
struct slave *prim = bond->primary_slave;
|
||||||
struct slave *curr = bond->curr_active_slave;
|
struct slave *curr = bond_deref_active_protected(bond);
|
||||||
|
|
||||||
if (!prim || !curr || curr->link != BOND_LINK_UP)
|
if (!prim || !curr || curr->link != BOND_LINK_UP)
|
||||||
return true;
|
return true;
|
||||||
|
@ -792,7 +792,11 @@ static bool bond_should_notify_peers(struct bonding *bond)
|
||||||
*/
|
*/
|
||||||
void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
|
void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
|
||||||
{
|
{
|
||||||
struct slave *old_active = bond->curr_active_slave;
|
struct slave *old_active;
|
||||||
|
|
||||||
|
old_active = rcu_dereference_protected(bond->curr_active_slave,
|
||||||
|
!new_active ||
|
||||||
|
lockdep_is_held(&bond->curr_slave_lock));
|
||||||
|
|
||||||
if (old_active == new_active)
|
if (old_active == new_active)
|
||||||
return;
|
return;
|
||||||
|
@ -900,7 +904,7 @@ void bond_select_active_slave(struct bonding *bond)
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
best_slave = bond_find_best_slave(bond);
|
best_slave = bond_find_best_slave(bond);
|
||||||
if (best_slave != bond->curr_active_slave) {
|
if (best_slave != bond_deref_active_protected(bond)) {
|
||||||
bond_change_active_slave(bond, best_slave);
|
bond_change_active_slave(bond, best_slave);
|
||||||
rv = bond_set_carrier(bond);
|
rv = bond_set_carrier(bond);
|
||||||
if (!rv)
|
if (!rv)
|
||||||
|
@ -1531,7 +1535,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
||||||
* anyway (it holds no special properties of the bond device),
|
* anyway (it holds no special properties of the bond device),
|
||||||
* so we can change it without calling change_active_interface()
|
* so we can change it without calling change_active_interface()
|
||||||
*/
|
*/
|
||||||
if (!bond->curr_active_slave && new_slave->link == BOND_LINK_UP)
|
if (!rcu_access_pointer(bond->curr_active_slave) &&
|
||||||
|
new_slave->link == BOND_LINK_UP)
|
||||||
rcu_assign_pointer(bond->curr_active_slave, new_slave);
|
rcu_assign_pointer(bond->curr_active_slave, new_slave);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -1602,7 +1607,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
||||||
vlan_vids_del_by_dev(slave_dev, bond_dev);
|
vlan_vids_del_by_dev(slave_dev, bond_dev);
|
||||||
if (bond->primary_slave == new_slave)
|
if (bond->primary_slave == new_slave)
|
||||||
bond->primary_slave = NULL;
|
bond->primary_slave = NULL;
|
||||||
if (bond->curr_active_slave == new_slave) {
|
if (rcu_access_pointer(bond->curr_active_slave) == new_slave) {
|
||||||
block_netpoll_tx();
|
block_netpoll_tx();
|
||||||
write_lock_bh(&bond->curr_slave_lock);
|
write_lock_bh(&bond->curr_slave_lock);
|
||||||
bond_change_active_slave(bond, NULL);
|
bond_change_active_slave(bond, NULL);
|
||||||
|
@ -1704,9 +1709,9 @@ static int __bond_release_one(struct net_device *bond_dev,
|
||||||
bond_is_active_slave(slave) ? "active" : "backup",
|
bond_is_active_slave(slave) ? "active" : "backup",
|
||||||
slave_dev->name);
|
slave_dev->name);
|
||||||
|
|
||||||
oldcurrent = bond->curr_active_slave;
|
oldcurrent = rcu_access_pointer(bond->curr_active_slave);
|
||||||
|
|
||||||
bond->current_arp_slave = NULL;
|
RCU_INIT_POINTER(bond->current_arp_slave, NULL);
|
||||||
|
|
||||||
if (!all && (!bond->params.fail_over_mac ||
|
if (!all && (!bond->params.fail_over_mac ||
|
||||||
BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP)) {
|
BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP)) {
|
||||||
|
@ -1878,7 +1883,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
|
||||||
|
|
||||||
/*-------------------------------- Monitoring -------------------------------*/
|
/*-------------------------------- Monitoring -------------------------------*/
|
||||||
|
|
||||||
|
/* called with rcu_read_lock() */
|
||||||
static int bond_miimon_inspect(struct bonding *bond)
|
static int bond_miimon_inspect(struct bonding *bond)
|
||||||
{
|
{
|
||||||
int link_state, commit = 0;
|
int link_state, commit = 0;
|
||||||
|
@ -1886,7 +1891,7 @@ static int bond_miimon_inspect(struct bonding *bond)
|
||||||
struct slave *slave;
|
struct slave *slave;
|
||||||
bool ignore_updelay;
|
bool ignore_updelay;
|
||||||
|
|
||||||
ignore_updelay = !bond->curr_active_slave ? true : false;
|
ignore_updelay = !rcu_dereference(bond->curr_active_slave);
|
||||||
|
|
||||||
bond_for_each_slave_rcu(bond, slave, iter) {
|
bond_for_each_slave_rcu(bond, slave, iter) {
|
||||||
slave->new_link = BOND_LINK_NOCHANGE;
|
slave->new_link = BOND_LINK_NOCHANGE;
|
||||||
|
@ -2046,7 +2051,7 @@ static void bond_miimon_commit(struct bonding *bond)
|
||||||
bond_alb_handle_link_change(bond, slave,
|
bond_alb_handle_link_change(bond, slave,
|
||||||
BOND_LINK_DOWN);
|
BOND_LINK_DOWN);
|
||||||
|
|
||||||
if (slave == bond->curr_active_slave)
|
if (slave == rcu_access_pointer(bond->curr_active_slave))
|
||||||
goto do_failover;
|
goto do_failover;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
@ -2416,7 +2421,7 @@ static void bond_loadbalance_arp_mon(struct work_struct *work)
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
|
||||||
oldcurrent = ACCESS_ONCE(bond->curr_active_slave);
|
oldcurrent = rcu_dereference(bond->curr_active_slave);
|
||||||
/* see if any of the previous devices are up now (i.e. they have
|
/* see if any of the previous devices are up now (i.e. they have
|
||||||
* xmt and rcv traffic). the curr_active_slave does not come into
|
* xmt and rcv traffic). the curr_active_slave does not come into
|
||||||
* the picture unless it is null. also, slave->last_link_up is not
|
* the picture unless it is null. also, slave->last_link_up is not
|
||||||
|
@ -2564,7 +2569,7 @@ static int bond_ab_arp_inspect(struct bonding *bond)
|
||||||
* before being taken out
|
* before being taken out
|
||||||
*/
|
*/
|
||||||
if (!bond_is_active_slave(slave) &&
|
if (!bond_is_active_slave(slave) &&
|
||||||
!bond->current_arp_slave &&
|
!rcu_access_pointer(bond->current_arp_slave) &&
|
||||||
!bond_time_in_interval(bond, last_rx, 3)) {
|
!bond_time_in_interval(bond, last_rx, 3)) {
|
||||||
slave->new_link = BOND_LINK_DOWN;
|
slave->new_link = BOND_LINK_DOWN;
|
||||||
commit++;
|
commit++;
|
||||||
|
@ -2607,21 +2612,24 @@ static void bond_ab_arp_commit(struct bonding *bond)
|
||||||
|
|
||||||
case BOND_LINK_UP:
|
case BOND_LINK_UP:
|
||||||
trans_start = dev_trans_start(slave->dev);
|
trans_start = dev_trans_start(slave->dev);
|
||||||
if (bond->curr_active_slave != slave ||
|
if (rtnl_dereference(bond->curr_active_slave) != slave ||
|
||||||
(!bond->curr_active_slave &&
|
(!rtnl_dereference(bond->curr_active_slave) &&
|
||||||
bond_time_in_interval(bond, trans_start, 1))) {
|
bond_time_in_interval(bond, trans_start, 1))) {
|
||||||
|
struct slave *current_arp_slave;
|
||||||
|
|
||||||
|
current_arp_slave = rtnl_dereference(bond->current_arp_slave);
|
||||||
slave->link = BOND_LINK_UP;
|
slave->link = BOND_LINK_UP;
|
||||||
if (bond->current_arp_slave) {
|
if (current_arp_slave) {
|
||||||
bond_set_slave_inactive_flags(
|
bond_set_slave_inactive_flags(
|
||||||
bond->current_arp_slave,
|
current_arp_slave,
|
||||||
BOND_SLAVE_NOTIFY_NOW);
|
BOND_SLAVE_NOTIFY_NOW);
|
||||||
bond->current_arp_slave = NULL;
|
RCU_INIT_POINTER(bond->current_arp_slave, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_info("%s: link status definitely up for interface %s\n",
|
pr_info("%s: link status definitely up for interface %s\n",
|
||||||
bond->dev->name, slave->dev->name);
|
bond->dev->name, slave->dev->name);
|
||||||
|
|
||||||
if (!bond->curr_active_slave ||
|
if (!rtnl_dereference(bond->curr_active_slave) ||
|
||||||
(slave == bond->primary_slave))
|
(slave == bond->primary_slave))
|
||||||
goto do_failover;
|
goto do_failover;
|
||||||
|
|
||||||
|
@ -2640,8 +2648,8 @@ static void bond_ab_arp_commit(struct bonding *bond)
|
||||||
pr_info("%s: link status definitely down for interface %s, disabling it\n",
|
pr_info("%s: link status definitely down for interface %s, disabling it\n",
|
||||||
bond->dev->name, slave->dev->name);
|
bond->dev->name, slave->dev->name);
|
||||||
|
|
||||||
if (slave == bond->curr_active_slave) {
|
if (slave == rtnl_dereference(bond->curr_active_slave)) {
|
||||||
bond->current_arp_slave = NULL;
|
RCU_INIT_POINTER(bond->current_arp_slave, NULL);
|
||||||
goto do_failover;
|
goto do_failover;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3097,8 +3105,8 @@ static int bond_open(struct net_device *bond_dev)
|
||||||
if (bond_has_slaves(bond)) {
|
if (bond_has_slaves(bond)) {
|
||||||
read_lock(&bond->curr_slave_lock);
|
read_lock(&bond->curr_slave_lock);
|
||||||
bond_for_each_slave(bond, slave, iter) {
|
bond_for_each_slave(bond, slave, iter) {
|
||||||
if (bond_uses_primary(bond)
|
if (bond_uses_primary(bond) &&
|
||||||
&& (slave != bond->curr_active_slave)) {
|
slave != rcu_access_pointer(bond->curr_active_slave)) {
|
||||||
bond_set_slave_inactive_flags(slave,
|
bond_set_slave_inactive_flags(slave,
|
||||||
BOND_SLAVE_NOTIFY_NOW);
|
BOND_SLAVE_NOTIFY_NOW);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -398,20 +398,31 @@ static size_t bond_get_size(const struct net_device *bond_dev)
|
||||||
0;
|
0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bond_option_active_slave_get_ifindex(struct bonding *bond)
|
||||||
|
{
|
||||||
|
const struct net_device *slave;
|
||||||
|
int ifindex;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
slave = bond_option_active_slave_get_rcu(bond);
|
||||||
|
ifindex = slave ? slave->ifindex : 0;
|
||||||
|
rcu_read_unlock();
|
||||||
|
return ifindex;
|
||||||
|
}
|
||||||
|
|
||||||
static int bond_fill_info(struct sk_buff *skb,
|
static int bond_fill_info(struct sk_buff *skb,
|
||||||
const struct net_device *bond_dev)
|
const struct net_device *bond_dev)
|
||||||
{
|
{
|
||||||
struct bonding *bond = netdev_priv(bond_dev);
|
struct bonding *bond = netdev_priv(bond_dev);
|
||||||
struct net_device *slave_dev = bond_option_active_slave_get(bond);
|
|
||||||
struct nlattr *targets;
|
|
||||||
unsigned int packets_per_slave;
|
unsigned int packets_per_slave;
|
||||||
int i, targets_added;
|
int ifindex, i, targets_added;
|
||||||
|
struct nlattr *targets;
|
||||||
|
|
||||||
if (nla_put_u8(skb, IFLA_BOND_MODE, BOND_MODE(bond)))
|
if (nla_put_u8(skb, IFLA_BOND_MODE, BOND_MODE(bond)))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
if (slave_dev &&
|
ifindex = bond_option_active_slave_get_ifindex(bond);
|
||||||
nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, slave_dev->ifindex))
|
if (ifindex && nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, ifindex))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
if (nla_put_u32(skb, IFLA_BOND_MIIMON, bond->params.miimon))
|
if (nla_put_u32(skb, IFLA_BOND_MIIMON, bond->params.miimon))
|
||||||
|
|
|
@ -704,11 +704,6 @@ struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond)
|
||||||
return __bond_option_active_slave_get(bond, slave);
|
return __bond_option_active_slave_get(bond, slave);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct net_device *bond_option_active_slave_get(struct bonding *bond)
|
|
||||||
{
|
|
||||||
return __bond_option_active_slave_get(bond, bond->curr_active_slave);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bond_option_active_slave_set(struct bonding *bond,
|
static int bond_option_active_slave_set(struct bonding *bond,
|
||||||
const struct bond_opt_value *newval)
|
const struct bond_opt_value *newval)
|
||||||
{
|
{
|
||||||
|
@ -748,7 +743,7 @@ static int bond_option_active_slave_set(struct bonding *bond,
|
||||||
RCU_INIT_POINTER(bond->curr_active_slave, NULL);
|
RCU_INIT_POINTER(bond->curr_active_slave, NULL);
|
||||||
bond_select_active_slave(bond);
|
bond_select_active_slave(bond);
|
||||||
} else {
|
} else {
|
||||||
struct slave *old_active = bond->curr_active_slave;
|
struct slave *old_active = bond_deref_active_protected(bond);
|
||||||
struct slave *new_active = bond_slave_get_rtnl(slave_dev);
|
struct slave *new_active = bond_slave_get_rtnl(slave_dev);
|
||||||
|
|
||||||
BUG_ON(!new_active);
|
BUG_ON(!new_active);
|
||||||
|
|
|
@ -492,8 +492,9 @@ static ssize_t bonding_show_mii_status(struct device *d,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct bonding *bond = to_bond(d);
|
struct bonding *bond = to_bond(d);
|
||||||
|
bool active = !!rcu_access_pointer(bond->curr_active_slave);
|
||||||
|
|
||||||
return sprintf(buf, "%s\n", bond->curr_active_slave ? "up" : "down");
|
return sprintf(buf, "%s\n", active ? "up" : "down");
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
|
static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
|
||||||
|
|
||||||
|
|
|
@ -194,8 +194,8 @@ struct slave {
|
||||||
*/
|
*/
|
||||||
struct bonding {
|
struct bonding {
|
||||||
struct net_device *dev; /* first - useful for panic debug */
|
struct net_device *dev; /* first - useful for panic debug */
|
||||||
struct slave *curr_active_slave;
|
struct slave __rcu *curr_active_slave;
|
||||||
struct slave *current_arp_slave;
|
struct slave __rcu *current_arp_slave;
|
||||||
struct slave *primary_slave;
|
struct slave *primary_slave;
|
||||||
bool force_primary;
|
bool force_primary;
|
||||||
s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
|
s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
|
||||||
|
@ -232,6 +232,10 @@ struct bonding {
|
||||||
#define bond_slave_get_rtnl(dev) \
|
#define bond_slave_get_rtnl(dev) \
|
||||||
((struct slave *) rtnl_dereference(dev->rx_handler_data))
|
((struct slave *) rtnl_dereference(dev->rx_handler_data))
|
||||||
|
|
||||||
|
#define bond_deref_active_protected(bond) \
|
||||||
|
rcu_dereference_protected(bond->curr_active_slave, \
|
||||||
|
lockdep_is_held(&bond->curr_slave_lock))
|
||||||
|
|
||||||
struct bond_vlan_tag {
|
struct bond_vlan_tag {
|
||||||
__be16 vlan_proto;
|
__be16 vlan_proto;
|
||||||
unsigned short vlan_id;
|
unsigned short vlan_id;
|
||||||
|
@ -514,7 +518,6 @@ unsigned int bond_get_num_tx_queues(void);
|
||||||
int bond_netlink_init(void);
|
int bond_netlink_init(void);
|
||||||
void bond_netlink_fini(void);
|
void bond_netlink_fini(void);
|
||||||
struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond);
|
struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond);
|
||||||
struct net_device *bond_option_active_slave_get(struct bonding *bond);
|
|
||||||
const char *bond_slave_link_status(s8 link);
|
const char *bond_slave_link_status(s8 link);
|
||||||
bool bond_verify_device_path(struct net_device *start_dev,
|
bool bond_verify_device_path(struct net_device *start_dev,
|
||||||
struct net_device *end_dev,
|
struct net_device *end_dev,
|
||||||
|
|
Loading…
Reference in New Issue