Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7ffc37fc authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'batman-adv-fix-for-davem' of git://git.open-mesh.org/linux-merge



Included changes:
- fix global protection fault by avoiding double call_rcu

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b0ce3508 72822225
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -156,12 +156,28 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
	kfree(orig_node);
}

/**
 * batadv_orig_node_free_ref - decrement the orig node refcounter and possibly
 * schedule an rcu callback for freeing it
 * @orig_node: the orig node to free
 */
void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node)
{
	if (atomic_dec_and_test(&orig_node->refcount))
		call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu);
}

/**
 * batadv_orig_node_free_ref_now - decrement the orig node refcounter and
 * possibly free it (without rcu callback)
 * @orig_node: the orig node to free
 */
void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node)
{
	if (atomic_dec_and_test(&orig_node->refcount))
		batadv_orig_node_free_rcu(&orig_node->rcu);
}

void batadv_originator_free(struct batadv_priv *bat_priv)
{
	struct batadv_hashtable *hash = bat_priv->orig_hash;
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ int batadv_originator_init(struct batadv_priv *bat_priv);
void batadv_originator_free(struct batadv_priv *bat_priv);
void batadv_purge_orig_ref(struct batadv_priv *bat_priv);
void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node);
void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node);
struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
					      const uint8_t *addr);
struct batadv_neigh_node *
+6 −1
Original line number Diff line number Diff line
@@ -144,7 +144,12 @@ static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
	struct batadv_tt_orig_list_entry *orig_entry;

	orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu);
	batadv_orig_node_free_ref(orig_entry->orig_node);

	/* We are in an rcu callback here, therefore we cannot use
	 * batadv_orig_node_free_ref() and its call_rcu():
	 * An rcu_barrier() wouldn't wait for that to finish
	 */
	batadv_orig_node_free_ref_now(orig_entry->orig_node);
	kfree(orig_entry);
}