mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 20:14:06 +02:00
t Merge branch 'a-series-of-minor-optimizations-of-the-bonding-module'
Tonghao Zhang says: ==================== A series of minor optimizations of the bonding module These patches mainly target the peer notify mechanism of the bonding module. Including updates of peer notify, lock races, etc. For more information, please refer to the patch. Cc: Jay Vosburgh <jv@jvosburgh.net> Cc: "David S. Miller" <davem@davemloft.net> Cc: Eric Dumazet <edumazet@google.com> Cc: Jakub Kicinski <kuba@kernel.org> Cc: Paolo Abeni <pabeni@redhat.com> Cc: Simon Horman <horms@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Andrew Lunn <andrew+netdev@lunn.ch> Cc: Nikolay Aleksandrov <razor@blackwall.org> Cc: Hangbin Liu <liuhangbin@gmail.com> Cc: Jason Xing <kerneljasonxing@gmail.com> ==================== Link: https://patch.msgid.link/cover.1768709239.git.tonghao@bamaicloud.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
b6d5a62231
|
|
@ -1017,11 +1017,8 @@ static void ad_cond_set_peer_notif(struct port *port)
|
|||
{
|
||||
struct bonding *bond = port->slave->bond;
|
||||
|
||||
if (bond->params.broadcast_neighbor && rtnl_trylock()) {
|
||||
bond->send_peer_notif = bond->params.num_peer_notif *
|
||||
max(1, bond->params.peer_notif_delay);
|
||||
rtnl_unlock();
|
||||
}
|
||||
if (bond->params.broadcast_neighbor)
|
||||
bond_peer_notify_work_rearm(bond, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1195,6 +1195,49 @@ static bool bond_should_notify_peers(struct bonding *bond)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Use this to update send_peer_notif when RTNL may be held in other places. */
|
||||
void bond_peer_notify_work_rearm(struct bonding *bond, unsigned long delay)
|
||||
{
|
||||
queue_delayed_work(bond->wq, &bond->peer_notify_work, delay);
|
||||
}
|
||||
|
||||
/* Peer notify update handler. Holds only RTNL */
|
||||
static void bond_peer_notify_reset(struct bonding *bond)
|
||||
{
|
||||
WRITE_ONCE(bond->send_peer_notif,
|
||||
bond->params.num_peer_notif *
|
||||
max(1, bond->params.peer_notif_delay));
|
||||
}
|
||||
|
||||
static void bond_peer_notify_handler(struct work_struct *work)
|
||||
{
|
||||
struct bonding *bond = container_of(work, struct bonding,
|
||||
peer_notify_work.work);
|
||||
|
||||
if (!rtnl_trylock()) {
|
||||
bond_peer_notify_work_rearm(bond, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
bond_peer_notify_reset(bond);
|
||||
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
/* Peer notify events post. Holds only RTNL */
|
||||
static void bond_peer_notify_may_events(struct bonding *bond, bool force)
|
||||
{
|
||||
bool notified = false;
|
||||
|
||||
if (bond_should_notify_peers(bond)) {
|
||||
notified = true;
|
||||
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, bond->dev);
|
||||
}
|
||||
|
||||
if (notified || force)
|
||||
bond->send_peer_notif--;
|
||||
}
|
||||
|
||||
/**
|
||||
* bond_change_active_slave - change the active slave into the specified one
|
||||
* @bond: our bonding struct
|
||||
|
|
@ -1270,8 +1313,6 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
|
|||
BOND_SLAVE_NOTIFY_NOW);
|
||||
|
||||
if (new_active) {
|
||||
bool should_notify_peers = false;
|
||||
|
||||
bond_set_slave_active_flags(new_active,
|
||||
BOND_SLAVE_NOTIFY_NOW);
|
||||
|
||||
|
|
@ -1279,19 +1320,11 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
|
|||
bond_do_fail_over_mac(bond, new_active,
|
||||
old_active);
|
||||
|
||||
if (netif_running(bond->dev)) {
|
||||
bond->send_peer_notif =
|
||||
bond->params.num_peer_notif *
|
||||
max(1, bond->params.peer_notif_delay);
|
||||
should_notify_peers =
|
||||
bond_should_notify_peers(bond);
|
||||
}
|
||||
|
||||
call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, bond->dev);
|
||||
if (should_notify_peers) {
|
||||
bond->send_peer_notif--;
|
||||
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
|
||||
bond->dev);
|
||||
|
||||
if (netif_running(bond->dev)) {
|
||||
bond_peer_notify_reset(bond);
|
||||
bond_peer_notify_may_events(bond, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2784,11 +2817,10 @@ static void bond_mii_monitor(struct work_struct *work)
|
|||
{
|
||||
struct bonding *bond = container_of(work, struct bonding,
|
||||
mii_work.work);
|
||||
bool should_notify_peers;
|
||||
bool commit;
|
||||
unsigned long delay;
|
||||
struct slave *slave;
|
||||
struct list_head *iter;
|
||||
struct slave *slave;
|
||||
unsigned long delay;
|
||||
bool commit;
|
||||
|
||||
delay = msecs_to_jiffies(bond->params.miimon);
|
||||
|
||||
|
|
@ -2797,12 +2829,11 @@ static void bond_mii_monitor(struct work_struct *work)
|
|||
|
||||
rcu_read_lock();
|
||||
|
||||
should_notify_peers = bond_should_notify_peers(bond);
|
||||
commit = !!bond_miimon_inspect(bond);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
if (commit || bond->send_peer_notif) {
|
||||
if (commit || READ_ONCE(bond->send_peer_notif)) {
|
||||
/* Race avoidance with bond_close cancel of workqueue */
|
||||
if (!rtnl_trylock()) {
|
||||
delay = 1;
|
||||
|
|
@ -2817,12 +2848,8 @@ static void bond_mii_monitor(struct work_struct *work)
|
|||
bond_miimon_commit(bond);
|
||||
}
|
||||
|
||||
if (bond->send_peer_notif) {
|
||||
bond->send_peer_notif--;
|
||||
if (should_notify_peers)
|
||||
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
|
||||
bond->dev);
|
||||
}
|
||||
if (bond->send_peer_notif)
|
||||
bond_peer_notify_may_events(bond, true);
|
||||
|
||||
rtnl_unlock(); /* might sleep, hold no other locks */
|
||||
}
|
||||
|
|
@ -3733,8 +3760,7 @@ static bool bond_ab_arp_probe(struct bonding *bond)
|
|||
|
||||
static void bond_activebackup_arp_mon(struct bonding *bond)
|
||||
{
|
||||
bool should_notify_peers = false;
|
||||
bool should_notify_rtnl = false;
|
||||
bool should_notify_rtnl;
|
||||
int delta_in_ticks;
|
||||
|
||||
delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
|
||||
|
|
@ -3744,15 +3770,12 @@ static void bond_activebackup_arp_mon(struct bonding *bond)
|
|||
|
||||
rcu_read_lock();
|
||||
|
||||
should_notify_peers = bond_should_notify_peers(bond);
|
||||
|
||||
if (bond_ab_arp_inspect(bond)) {
|
||||
rcu_read_unlock();
|
||||
|
||||
/* Race avoidance with bond_close flush of workqueue */
|
||||
if (!rtnl_trylock()) {
|
||||
delta_in_ticks = 1;
|
||||
should_notify_peers = false;
|
||||
goto re_arm;
|
||||
}
|
||||
|
||||
|
|
@ -3765,19 +3788,15 @@ static void bond_activebackup_arp_mon(struct bonding *bond)
|
|||
should_notify_rtnl = bond_ab_arp_probe(bond);
|
||||
rcu_read_unlock();
|
||||
|
||||
re_arm:
|
||||
if (bond->params.arp_interval)
|
||||
queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
|
||||
|
||||
if (should_notify_peers || should_notify_rtnl) {
|
||||
if (!rtnl_trylock())
|
||||
return;
|
||||
|
||||
if (should_notify_peers) {
|
||||
bond->send_peer_notif--;
|
||||
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
|
||||
bond->dev);
|
||||
if (READ_ONCE(bond->send_peer_notif) || should_notify_rtnl) {
|
||||
if (!rtnl_trylock()) {
|
||||
delta_in_ticks = 1;
|
||||
goto re_arm;
|
||||
}
|
||||
|
||||
if (bond->send_peer_notif)
|
||||
bond_peer_notify_may_events(bond, true);
|
||||
|
||||
if (should_notify_rtnl) {
|
||||
bond_slave_state_notify(bond);
|
||||
bond_slave_link_notify(bond);
|
||||
|
|
@ -3785,6 +3804,10 @@ static void bond_activebackup_arp_mon(struct bonding *bond)
|
|||
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
re_arm:
|
||||
if (bond->params.arp_interval)
|
||||
queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
|
||||
}
|
||||
|
||||
static void bond_arp_monitor(struct work_struct *work)
|
||||
|
|
@ -4213,6 +4236,10 @@ static u32 bond_xmit_hash_xdp(struct bonding *bond, struct xdp_buff *xdp)
|
|||
|
||||
void bond_work_init_all(struct bonding *bond)
|
||||
{
|
||||
/* ndo_stop, bond_close() will try to flush the work under
|
||||
* the rtnl lock. The workqueue must not block on rtnl lock
|
||||
* to avoid deadlock.
|
||||
*/
|
||||
INIT_DELAYED_WORK(&bond->mcast_work,
|
||||
bond_resend_igmp_join_requests_delayed);
|
||||
INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor);
|
||||
|
|
@ -4220,6 +4247,7 @@ void bond_work_init_all(struct bonding *bond)
|
|||
INIT_DELAYED_WORK(&bond->arp_work, bond_arp_monitor);
|
||||
INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler);
|
||||
INIT_DELAYED_WORK(&bond->slave_arr_work, bond_slave_arr_handler);
|
||||
INIT_DELAYED_WORK(&bond->peer_notify_work, bond_peer_notify_handler);
|
||||
}
|
||||
|
||||
void bond_work_cancel_all(struct bonding *bond)
|
||||
|
|
@ -4230,6 +4258,7 @@ void bond_work_cancel_all(struct bonding *bond)
|
|||
cancel_delayed_work_sync(&bond->ad_work);
|
||||
cancel_delayed_work_sync(&bond->mcast_work);
|
||||
cancel_delayed_work_sync(&bond->slave_arr_work);
|
||||
cancel_delayed_work_sync(&bond->peer_notify_work);
|
||||
}
|
||||
|
||||
static int bond_open(struct net_device *bond_dev)
|
||||
|
|
|
|||
|
|
@ -254,6 +254,7 @@ struct bonding {
|
|||
struct delayed_work ad_work;
|
||||
struct delayed_work mcast_work;
|
||||
struct delayed_work slave_arr_work;
|
||||
struct delayed_work peer_notify_work;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
/* debugging support via debugfs */
|
||||
struct dentry *debug_dir;
|
||||
|
|
@ -709,6 +710,7 @@ struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
|
|||
int level);
|
||||
int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave);
|
||||
void bond_slave_arr_work_rearm(struct bonding *bond, unsigned long delay);
|
||||
void bond_peer_notify_work_rearm(struct bonding *bond, unsigned long delay);
|
||||
void bond_work_init_all(struct bonding *bond);
|
||||
void bond_work_cancel_all(struct bonding *bond);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user