diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 68f79853032e..915f5589e056 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -1386,21 +1386,29 @@ static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv, * inactive or not */ static void batadv_tt_local_purge(struct batadv_priv *bat_priv, - int timeout) + int timeout, bool may_sleep) { spinlock_t *list_lock; /* protects write access to the hash lists */ struct batadv_hashtable *hash = bat_priv->tt.local_hash; struct hlist_head *head; u32 i; + local_bh_disable(); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; list_lock = &hash->list_locks[i]; - spin_lock_bh(list_lock); + spin_lock(list_lock); batadv_tt_local_purge_list(bat_priv, head, timeout); - spin_unlock_bh(list_lock); + spin_unlock(list_lock); + + if (may_sleep && (i & 63) == 63) { + local_bh_enable(); + cond_resched(); + local_bh_disable(); + } } + local_bh_enable(); } /** @@ -2363,11 +2371,12 @@ static void batadv_tt_global_purge(struct batadv_priv *bat_priv) char *msg = NULL; u32 i; + local_bh_disable(); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; list_lock = &hash->list_locks[i]; - spin_lock_bh(list_lock); + spin_lock(list_lock); hlist_for_each_entry_safe(tt_common, node_tmp, head, hash_entry) { tt_global = container_of(tt_common, @@ -2387,8 +2396,15 @@ static void batadv_tt_global_purge(struct batadv_priv *bat_priv) batadv_tt_global_entry_put(tt_global); } - spin_unlock_bh(list_lock); + spin_unlock(list_lock); + + if ((i & 63) == 63) { + local_bh_enable(); + cond_resched(); + local_bh_disable(); + } } + local_bh_enable(); } /** @@ -3750,7 +3766,7 @@ static void batadv_tt_purge(struct work_struct *work) priv_tt = container_of(delayed_work, struct batadv_priv_tt, work); bat_priv = container_of(priv_tt, struct batadv_priv, tt); - batadv_tt_local_purge(bat_priv, BATADV_TT_LOCAL_TIMEOUT); + batadv_tt_local_purge(bat_priv, BATADV_TT_LOCAL_TIMEOUT, true); batadv_tt_global_purge(bat_priv); batadv_tt_req_purge(bat_priv); batadv_tt_roam_purge(bat_priv); @@ -4156,7 +4172,7 @@ void batadv_tt_local_resize_to_mtu(struct net_device *mesh_iface) if (packet_size_max >= table_size) break; - batadv_tt_local_purge(bat_priv, timeout); + batadv_tt_local_purge(bat_priv, timeout, false); batadv_tt_local_purge_pending_clients(bat_priv); timeout /= 2;