mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 18:21:24 +02:00
batman-adv: gw: don't deselect gateway with active hardif
The batadv_hardif_cnt() was previously checking if there is an
batadv_hard_iface->mesh_iface which is has the same mesh_iface. And since
batadv_hardif_disable_interface() was resetting the
batadv_hard_iface->mesh_iface after this check, it had to verify whether
*1* interface was still part of the mesh_iface before it started the
gateway deselection.
But after batadv_hardif_cnt() is now checking the lower interfaces of
mesh_iface and batadv_hardif_disable_interface() already removed the
interface via netdev_upper_dev_unlink() earlier in this function, the check
must now make sure that *0* interfaces can be found by batadv_hardif_cnt()
before selected gateway must be deselected. Otherwise the deselection would
already happen one batadv_hard_iface too early.
Because a 0 hardif count from batadv_hardif_cnt() is equal to an empty
list, it is possible to replace the counting with a simple list_empty().
Cc: stable@kernel.org
Fixes: 7dc284702b ("batman-adv: store hard_iface as iflink private data")
Reviewed-by: Nora Schiffer <neocturne@universe-factory.net>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
This commit is contained in:
parent
dad4d4b92a
commit
df97a7107b
|
|
@ -814,30 +814,6 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_hardif_cnt() - get number of interfaces enslaved to mesh interface
|
||||
* @mesh_iface: mesh interface to check
|
||||
*
|
||||
* This function is only using RCU for locking - the result can therefore be
|
||||
* off when another function is modifying the list at the same time. The
|
||||
* caller can use the rtnl_lock to make sure that the count is accurate.
|
||||
*
|
||||
* Return: number of connected/enslaved hard interfaces
|
||||
*/
|
||||
static size_t batadv_hardif_cnt(struct net_device *mesh_iface)
|
||||
{
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct list_head *iter;
|
||||
size_t count = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
netdev_for_each_lower_private_rcu(mesh_iface, hard_iface, iter)
|
||||
count++;
|
||||
rcu_read_unlock();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_hardif_disable_interface() - Remove hard interface from mesh interface
|
||||
* @hard_iface: hard interface to be removed
|
||||
|
|
@ -878,8 +854,8 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface)
|
|||
netdev_upper_dev_unlink(hard_iface->net_dev, hard_iface->mesh_iface);
|
||||
batadv_hardif_recalc_extra_skbroom(hard_iface->mesh_iface);
|
||||
|
||||
/* nobody uses this interface anymore */
|
||||
if (batadv_hardif_cnt(hard_iface->mesh_iface) <= 1)
|
||||
/* nobody uses this mesh interface anymore */
|
||||
if (list_empty(&hard_iface->mesh_iface->adj_list.lower))
|
||||
batadv_gw_check_client_stop(bat_priv);
|
||||
|
||||
hard_iface->mesh_iface = NULL;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user