|
@@ -650,8 +650,10 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
|
|
|
|
|
|
/* increase the refcounter of the related vlan */
|
|
/* increase the refcounter of the related vlan */
|
|
vlan = batadv_softif_vlan_get(bat_priv, vid);
|
|
vlan = batadv_softif_vlan_get(bat_priv, vid);
|
|
- if (WARN(!vlan, "adding TT local entry %pM to non-existent VLAN %d",
|
|
|
|
- addr, BATADV_PRINT_VID(vid))) {
|
|
|
|
|
|
+ if (!vlan) {
|
|
|
|
+ net_ratelimited_function(batadv_info, soft_iface,
|
|
|
|
+ "adding TT local entry %pM to non-existent VLAN %d\n",
|
|
|
|
+ addr, BATADV_PRINT_VID(vid));
|
|
kfree(tt_local);
|
|
kfree(tt_local);
|
|
tt_local = NULL;
|
|
tt_local = NULL;
|
|
goto out;
|
|
goto out;
|
|
@@ -691,7 +693,6 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
|
|
if (unlikely(hash_added != 0)) {
|
|
if (unlikely(hash_added != 0)) {
|
|
/* remove the reference for the hash */
|
|
/* remove the reference for the hash */
|
|
batadv_tt_local_entry_put(tt_local);
|
|
batadv_tt_local_entry_put(tt_local);
|
|
- batadv_softif_vlan_put(vlan);
|
|
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2269,6 +2270,29 @@ static u32 batadv_tt_local_crc(struct batadv_priv *bat_priv,
|
|
return crc;
|
|
return crc;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * batadv_tt_req_node_release - free tt_req node entry
|
|
|
|
+ * @ref: kref pointer of the tt req_node entry
|
|
|
|
+ */
|
|
|
|
+static void batadv_tt_req_node_release(struct kref *ref)
|
|
|
|
+{
|
|
|
|
+ struct batadv_tt_req_node *tt_req_node;
|
|
|
|
+
|
|
|
|
+ tt_req_node = container_of(ref, struct batadv_tt_req_node, refcount);
|
|
|
|
+
|
|
|
|
+ kfree(tt_req_node);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * batadv_tt_req_node_put - decrement the tt_req_node refcounter and
|
|
|
|
+ * possibly release it
|
|
|
|
+ * @tt_req_node: tt_req_node to be free'd
|
|
|
|
+ */
|
|
|
|
+static void batadv_tt_req_node_put(struct batadv_tt_req_node *tt_req_node)
|
|
|
|
+{
|
|
|
|
+ kref_put(&tt_req_node->refcount, batadv_tt_req_node_release);
|
|
|
|
+}
|
|
|
|
+
|
|
static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
|
|
static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
|
|
{
|
|
{
|
|
struct batadv_tt_req_node *node;
|
|
struct batadv_tt_req_node *node;
|
|
@@ -2278,7 +2302,7 @@ static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
|
|
|
|
|
|
hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
|
|
hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
|
|
hlist_del_init(&node->list);
|
|
hlist_del_init(&node->list);
|
|
- kfree(node);
|
|
|
|
|
|
+ batadv_tt_req_node_put(node);
|
|
}
|
|
}
|
|
|
|
|
|
spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
|
spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
|
@@ -2315,7 +2339,7 @@ static void batadv_tt_req_purge(struct batadv_priv *bat_priv)
|
|
if (batadv_has_timed_out(node->issued_at,
|
|
if (batadv_has_timed_out(node->issued_at,
|
|
BATADV_TT_REQUEST_TIMEOUT)) {
|
|
BATADV_TT_REQUEST_TIMEOUT)) {
|
|
hlist_del_init(&node->list);
|
|
hlist_del_init(&node->list);
|
|
- kfree(node);
|
|
|
|
|
|
+ batadv_tt_req_node_put(node);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
|
spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
|
@@ -2347,9 +2371,11 @@ batadv_tt_req_node_new(struct batadv_priv *bat_priv,
|
|
if (!tt_req_node)
|
|
if (!tt_req_node)
|
|
goto unlock;
|
|
goto unlock;
|
|
|
|
|
|
|
|
+ kref_init(&tt_req_node->refcount);
|
|
ether_addr_copy(tt_req_node->addr, orig_node->orig);
|
|
ether_addr_copy(tt_req_node->addr, orig_node->orig);
|
|
tt_req_node->issued_at = jiffies;
|
|
tt_req_node->issued_at = jiffies;
|
|
|
|
|
|
|
|
+ kref_get(&tt_req_node->refcount);
|
|
hlist_add_head(&tt_req_node->list, &bat_priv->tt.req_list);
|
|
hlist_add_head(&tt_req_node->list, &bat_priv->tt.req_list);
|
|
unlock:
|
|
unlock:
|
|
spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
|
spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
|
@@ -2613,13 +2639,19 @@ static bool batadv_send_tt_request(struct batadv_priv *bat_priv,
|
|
out:
|
|
out:
|
|
if (primary_if)
|
|
if (primary_if)
|
|
batadv_hardif_put(primary_if);
|
|
batadv_hardif_put(primary_if);
|
|
|
|
+
|
|
if (ret && tt_req_node) {
|
|
if (ret && tt_req_node) {
|
|
spin_lock_bh(&bat_priv->tt.req_list_lock);
|
|
spin_lock_bh(&bat_priv->tt.req_list_lock);
|
|
- /* hlist_del_init() verifies tt_req_node still is in the list */
|
|
|
|
- hlist_del_init(&tt_req_node->list);
|
|
|
|
|
|
+ if (!hlist_unhashed(&tt_req_node->list)) {
|
|
|
|
+ hlist_del_init(&tt_req_node->list);
|
|
|
|
+ batadv_tt_req_node_put(tt_req_node);
|
|
|
|
+ }
|
|
spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
|
spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
|
- kfree(tt_req_node);
|
|
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if (tt_req_node)
|
|
|
|
+ batadv_tt_req_node_put(tt_req_node);
|
|
|
|
+
|
|
kfree(tvlv_tt_data);
|
|
kfree(tvlv_tt_data);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -3055,7 +3087,7 @@ static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
|
|
if (!batadv_compare_eth(node->addr, resp_src))
|
|
if (!batadv_compare_eth(node->addr, resp_src))
|
|
continue;
|
|
continue;
|
|
hlist_del_init(&node->list);
|
|
hlist_del_init(&node->list);
|
|
- kfree(node);
|
|
|
|
|
|
+ batadv_tt_req_node_put(node);
|
|
}
|
|
}
|
|
|
|
|
|
spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
|
spin_unlock_bh(&bat_priv->tt.req_list_lock);
|