From: Sven Eckelmann <sven@narfation.org>
batadv_tt_local_purge_pending_clients() decreases vlan->tt.num_entries for
every entry it unlinks, but an entry which still carries
BATADV_TT_CLIENT_NEW was never counted by batadv_tt_local_transition_new().
batadv_tt_local_resize_to_mtu() calls batadv_tt_local_purge() and
batadv_tt_local_purge_pending_clients() directly, without committing in
between, and it halves its timeout down towards zero. Once the timeout is
short enough, batadv_tt_local_purge_list() marks even freshly added clients
as pending. And each of them decreases a counter it never increased.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/translation-table.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index a870d9a97e329..794692170b611 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -349,6 +349,10 @@ static void batadv_tt_local_size_inc(struct batadv_priv *bat_priv,
* given vid
* @bat_priv: the bat priv with all the mesh interface information
* @vid: the VLAN identifier
+ *
+ * It must only be called after a batadv_tt_local_entry without NEW flag
+ * was removed from bat_priv->tt.local_hash (under the specific
+ * list_locks[i]).
*/
static void batadv_tt_local_size_dec(struct batadv_priv *bat_priv,
unsigned short vid)
@@ -4019,8 +4023,13 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
tt_common->addr,
batadv_print_vid(tt_common->vid));
- batadv_tt_local_size_dec(bat_priv, tt_common->vid);
hlist_del_rcu(&tt_common->hash_entry);
+
+ /* An entry which still carries BATADV_TT_CLIENT_NEW was
+ * never counted and must not be uncounted here.
+ */
+ if (!(tt_common->flags & BATADV_TT_CLIENT_NEW))
+ batadv_tt_local_size_dec(bat_priv, tt_common->vid);
}
if (cont)
--
2.47.3