Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d397061 authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller
Browse files

bonding: allow notifications for bond_set_slave_link_state



Similar to state notifications.

We allow caller to indicate if the notification should happen now or later,
depending on if he holds rtnl mutex or not. Introduce bond_slave_link_notify
function (similar to bond_slave_state_notify) which is later on called
with rtnl mutex and goes over slaves and executes delayed notification.

Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3a0d6c5a
Loading
Loading
Loading
Loading
+36 −18
Original line number Original line Diff line number Diff line
@@ -830,7 +830,8 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
			}
			}


			new_active->delay = 0;
			new_active->delay = 0;
			bond_set_slave_link_state(new_active, BOND_LINK_UP);
			bond_set_slave_link_state(new_active, BOND_LINK_UP,
						  BOND_SLAVE_NOTIFY_NOW);


			if (BOND_MODE(bond) == BOND_MODE_8023AD)
			if (BOND_MODE(bond) == BOND_MODE_8023AD)
				bond_3ad_handle_link_change(new_active, BOND_LINK_UP);
				bond_3ad_handle_link_change(new_active, BOND_LINK_UP);
@@ -1580,21 +1581,26 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
		if (bond_check_dev_link(bond, slave_dev, 0) == BMSR_LSTATUS) {
		if (bond_check_dev_link(bond, slave_dev, 0) == BMSR_LSTATUS) {
			if (bond->params.updelay) {
			if (bond->params.updelay) {
				bond_set_slave_link_state(new_slave,
				bond_set_slave_link_state(new_slave,
							  BOND_LINK_BACK);
							  BOND_LINK_BACK,
							  BOND_SLAVE_NOTIFY_NOW);
				new_slave->delay = bond->params.updelay;
				new_slave->delay = bond->params.updelay;
			} else {
			} else {
				bond_set_slave_link_state(new_slave,
				bond_set_slave_link_state(new_slave,
							  BOND_LINK_UP);
							  BOND_LINK_UP,
							  BOND_SLAVE_NOTIFY_NOW);
			}
			}
		} else {
		} else {
			bond_set_slave_link_state(new_slave, BOND_LINK_DOWN);
			bond_set_slave_link_state(new_slave, BOND_LINK_DOWN,
						  BOND_SLAVE_NOTIFY_NOW);
		}
		}
	} else if (bond->params.arp_interval) {
	} else if (bond->params.arp_interval) {
		bond_set_slave_link_state(new_slave,
		bond_set_slave_link_state(new_slave,
					  (netif_carrier_ok(slave_dev) ?
					  (netif_carrier_ok(slave_dev) ?
					  BOND_LINK_UP : BOND_LINK_DOWN));
					  BOND_LINK_UP : BOND_LINK_DOWN),
					  BOND_SLAVE_NOTIFY_NOW);
	} else {
	} else {
		bond_set_slave_link_state(new_slave, BOND_LINK_UP);
		bond_set_slave_link_state(new_slave, BOND_LINK_UP,
					  BOND_SLAVE_NOTIFY_NOW);
	}
	}


	if (new_slave->link != BOND_LINK_DOWN)
	if (new_slave->link != BOND_LINK_DOWN)
@@ -2013,7 +2019,8 @@ static int bond_miimon_inspect(struct bonding *bond)
			if (link_state)
			if (link_state)
				continue;
				continue;


			bond_set_slave_link_state(slave, BOND_LINK_FAIL);
			bond_set_slave_link_state(slave, BOND_LINK_FAIL,
						  BOND_SLAVE_NOTIFY_LATER);
			slave->delay = bond->params.downdelay;
			slave->delay = bond->params.downdelay;
			if (slave->delay) {
			if (slave->delay) {
				netdev_info(bond->dev, "link status down for %sinterface %s, disabling it in %d ms\n",
				netdev_info(bond->dev, "link status down for %sinterface %s, disabling it in %d ms\n",
@@ -2028,7 +2035,8 @@ static int bond_miimon_inspect(struct bonding *bond)
		case BOND_LINK_FAIL:
		case BOND_LINK_FAIL:
			if (link_state) {
			if (link_state) {
				/* recovered before downdelay expired */
				/* recovered before downdelay expired */
				bond_set_slave_link_state(slave, BOND_LINK_UP);
				bond_set_slave_link_state(slave, BOND_LINK_UP,
							  BOND_SLAVE_NOTIFY_LATER);
				slave->last_link_up = jiffies;
				slave->last_link_up = jiffies;
				netdev_info(bond->dev, "link status up again after %d ms for interface %s\n",
				netdev_info(bond->dev, "link status up again after %d ms for interface %s\n",
					    (bond->params.downdelay - slave->delay) *
					    (bond->params.downdelay - slave->delay) *
@@ -2050,7 +2058,8 @@ static int bond_miimon_inspect(struct bonding *bond)
			if (!link_state)
			if (!link_state)
				continue;
				continue;


			bond_set_slave_link_state(slave, BOND_LINK_BACK);
			bond_set_slave_link_state(slave, BOND_LINK_BACK,
						  BOND_SLAVE_NOTIFY_LATER);
			slave->delay = bond->params.updelay;
			slave->delay = bond->params.updelay;


			if (slave->delay) {
			if (slave->delay) {
@@ -2064,7 +2073,8 @@ static int bond_miimon_inspect(struct bonding *bond)
		case BOND_LINK_BACK:
		case BOND_LINK_BACK:
			if (!link_state) {
			if (!link_state) {
				bond_set_slave_link_state(slave,
				bond_set_slave_link_state(slave,
							  BOND_LINK_DOWN);
							  BOND_LINK_DOWN,
							  BOND_SLAVE_NOTIFY_LATER);
				netdev_info(bond->dev, "link status down again after %d ms for interface %s\n",
				netdev_info(bond->dev, "link status down again after %d ms for interface %s\n",
					    (bond->params.updelay - slave->delay) *
					    (bond->params.updelay - slave->delay) *
					    bond->params.miimon,
					    bond->params.miimon,
@@ -2102,7 +2112,8 @@ static void bond_miimon_commit(struct bonding *bond)
			continue;
			continue;


		case BOND_LINK_UP:
		case BOND_LINK_UP:
			bond_set_slave_link_state(slave, BOND_LINK_UP);
			bond_set_slave_link_state(slave, BOND_LINK_UP,
						  BOND_SLAVE_NOTIFY_NOW);
			slave->last_link_up = jiffies;
			slave->last_link_up = jiffies;


			primary = rtnl_dereference(bond->primary_slave);
			primary = rtnl_dereference(bond->primary_slave);
@@ -2142,7 +2153,8 @@ static void bond_miimon_commit(struct bonding *bond)
			if (slave->link_failure_count < UINT_MAX)
			if (slave->link_failure_count < UINT_MAX)
				slave->link_failure_count++;
				slave->link_failure_count++;


			bond_set_slave_link_state(slave, BOND_LINK_DOWN);
			bond_set_slave_link_state(slave, BOND_LINK_DOWN,
						  BOND_SLAVE_NOTIFY_NOW);


			if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP ||
			if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP ||
			    BOND_MODE(bond) == BOND_MODE_8023AD)
			    BOND_MODE(bond) == BOND_MODE_8023AD)
@@ -2725,7 +2737,8 @@ static void bond_ab_arp_commit(struct bonding *bond)
				struct slave *current_arp_slave;
				struct slave *current_arp_slave;


				current_arp_slave = rtnl_dereference(bond->current_arp_slave);
				current_arp_slave = rtnl_dereference(bond->current_arp_slave);
				bond_set_slave_link_state(slave, BOND_LINK_UP);
				bond_set_slave_link_state(slave, BOND_LINK_UP,
							  BOND_SLAVE_NOTIFY_NOW);
				if (current_arp_slave) {
				if (current_arp_slave) {
					bond_set_slave_inactive_flags(
					bond_set_slave_inactive_flags(
						current_arp_slave,
						current_arp_slave,
@@ -2748,7 +2761,8 @@ static void bond_ab_arp_commit(struct bonding *bond)
			if (slave->link_failure_count < UINT_MAX)
			if (slave->link_failure_count < UINT_MAX)
				slave->link_failure_count++;
				slave->link_failure_count++;


			bond_set_slave_link_state(slave, BOND_LINK_DOWN);
			bond_set_slave_link_state(slave, BOND_LINK_DOWN,
						  BOND_SLAVE_NOTIFY_NOW);
			bond_set_slave_inactive_flags(slave,
			bond_set_slave_inactive_flags(slave,
						      BOND_SLAVE_NOTIFY_NOW);
						      BOND_SLAVE_NOTIFY_NOW);


@@ -2827,7 +2841,8 @@ static bool bond_ab_arp_probe(struct bonding *bond)
		 * up when it is actually down
		 * up when it is actually down
		 */
		 */
		if (!bond_slave_is_up(slave) && slave->link == BOND_LINK_UP) {
		if (!bond_slave_is_up(slave) && slave->link == BOND_LINK_UP) {
			bond_set_slave_link_state(slave, BOND_LINK_DOWN);
			bond_set_slave_link_state(slave, BOND_LINK_DOWN,
						  BOND_SLAVE_NOTIFY_LATER);
			if (slave->link_failure_count < UINT_MAX)
			if (slave->link_failure_count < UINT_MAX)
				slave->link_failure_count++;
				slave->link_failure_count++;


@@ -2847,7 +2862,8 @@ static bool bond_ab_arp_probe(struct bonding *bond)
	if (!new_slave)
	if (!new_slave)
		goto check_state;
		goto check_state;


	bond_set_slave_link_state(new_slave, BOND_LINK_BACK);
	bond_set_slave_link_state(new_slave, BOND_LINK_BACK,
				  BOND_SLAVE_NOTIFY_LATER);
	bond_set_slave_active_flags(new_slave, BOND_SLAVE_NOTIFY_LATER);
	bond_set_slave_active_flags(new_slave, BOND_SLAVE_NOTIFY_LATER);
	bond_arp_send_all(bond, new_slave);
	bond_arp_send_all(bond, new_slave);
	new_slave->last_link_up = jiffies;
	new_slave->last_link_up = jiffies;
@@ -2855,7 +2871,7 @@ static bool bond_ab_arp_probe(struct bonding *bond)


check_state:
check_state:
	bond_for_each_slave_rcu(bond, slave, iter) {
	bond_for_each_slave_rcu(bond, slave, iter) {
		if (slave->should_notify) {
		if (slave->should_notify || slave->should_notify_link) {
			should_notify_rtnl = BOND_SLAVE_NOTIFY_NOW;
			should_notify_rtnl = BOND_SLAVE_NOTIFY_NOW;
			break;
			break;
		}
		}
@@ -2910,8 +2926,10 @@ static void bond_activebackup_arp_mon(struct work_struct *work)
		if (should_notify_peers)
		if (should_notify_peers)
			call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
			call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
						 bond->dev);
						 bond->dev);
		if (should_notify_rtnl)
		if (should_notify_rtnl) {
			bond_slave_state_notify(bond);
			bond_slave_state_notify(bond);
			bond_slave_link_notify(bond);
		}


		rtnl_unlock();
		rtnl_unlock();
	}
	}
+29 −3
Original line number Original line Diff line number Diff line
@@ -165,7 +165,8 @@ struct slave {
	u8     backup:1,   /* indicates backup slave. Value corresponds with
	u8     backup:1,   /* indicates backup slave. Value corresponds with
			      BOND_STATE_ACTIVE and BOND_STATE_BACKUP */
			      BOND_STATE_ACTIVE and BOND_STATE_BACKUP */
	       inactive:1, /* indicates inactive slave */
	       inactive:1, /* indicates inactive slave */
	       should_notify:1; /* indicateds whether the state changed */
	       should_notify:1, /* indicates whether the state changed */
	       should_notify_link:1; /* indicates whether the link changed */
	u8     duplex;
	u8     duplex;
	u32    original_mtu;
	u32    original_mtu;
	u32    link_failure_count;
	u32    link_failure_count;
@@ -504,10 +505,35 @@ static inline bool bond_is_slave_inactive(struct slave *slave)
	return slave->inactive;
	return slave->inactive;
}
}


static inline void bond_set_slave_link_state(struct slave *slave, int state)
static inline void bond_set_slave_link_state(struct slave *slave, int state,
					     bool notify)
{
{
	if (slave->link == state)
		return;

	slave->link = state;
	slave->link = state;
	if (notify) {
		bond_queue_slave_event(slave);
		bond_queue_slave_event(slave);
		slave->should_notify_link = 0;
	} else {
		if (slave->should_notify_link)
			slave->should_notify_link = 0;
		else
			slave->should_notify_link = 1;
	}
}

static inline void bond_slave_link_notify(struct bonding *bond)
{
	struct list_head *iter;
	struct slave *tmp;

	bond_for_each_slave(bond, tmp, iter) {
		if (tmp->should_notify_link) {
			bond_queue_slave_event(tmp);
			tmp->should_notify_link = 0;
		}
	}
}
}


static inline __be32 bond_confirm_addr(struct net_device *dev, __be32 dst, __be32 local)
static inline __be32 bond_confirm_addr(struct net_device *dev, __be32 dst, __be32 local)