Skip to content

Commit

Permalink
batman-adv: protect bonding with rcu locks
Browse files Browse the repository at this point in the history
bonding / alternating candidates need to be secured by rcu locks
as well. This patch therefore converts the bonding list
from a plain pointer list to a rcu securable lists and references
the bonding candidates.

Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
  • Loading branch information
Simon Wunderlich authored and Marek Lindner committed Mar 5, 2011
1 parent 2ae2daf commit a4c135c
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 163 deletions.
2 changes: 1 addition & 1 deletion net/batman-adv/hard-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ static void hardif_activate_interface(struct batman_if *batman_if)
static void hardif_deactivate_interface(struct batman_if *batman_if)
{
if ((batman_if->if_status != IF_ACTIVE) &&
(batman_if->if_status != IF_TO_BE_ACTIVATED))
(batman_if->if_status != IF_TO_BE_ACTIVATED))
return;

batman_if->if_status = IF_INACTIVE;
Expand Down
25 changes: 21 additions & 4 deletions net/batman-adv/originator.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ static void neigh_node_free_rcu(struct rcu_head *rcu)
kref_put(&neigh_node->refcount, neigh_node_free_ref);
}

void neigh_node_free_rcu_bond(struct rcu_head *rcu)
{
struct neigh_node *neigh_node;

neigh_node = container_of(rcu, struct neigh_node, rcu_bond);
kref_put(&neigh_node->refcount, neigh_node_free_ref);
}

struct neigh_node *create_neighbor(struct orig_node *orig_node,
struct orig_node *orig_neigh_node,
uint8_t *neigh,
Expand All @@ -91,6 +99,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node,
return NULL;

INIT_HLIST_NODE(&neigh_node->list);
INIT_LIST_HEAD(&neigh_node->bonding_list);

memcpy(neigh_node->addr, neigh, ETH_ALEN);
neigh_node->orig_node = orig_neigh_node;
Expand All @@ -106,13 +115,20 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node,
void orig_node_free_ref(struct kref *refcount)
{
struct hlist_node *node, *node_tmp;
struct neigh_node *neigh_node;
struct neigh_node *neigh_node, *tmp_neigh_node;
struct orig_node *orig_node;

orig_node = container_of(refcount, struct orig_node, refcount);

spin_lock_bh(&orig_node->neigh_list_lock);

/* for all bonding members ... */
list_for_each_entry_safe(neigh_node, tmp_neigh_node,
&orig_node->bond_list, bonding_list) {
list_del_rcu(&neigh_node->bonding_list);
call_rcu(&neigh_node->rcu_bond, neigh_node_free_rcu_bond);
}

/* for all neighbors towards this originator ... */
hlist_for_each_entry_safe(neigh_node, node, node_tmp,
&orig_node->neigh_list, list) {
Expand Down Expand Up @@ -207,6 +223,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
return NULL;

INIT_HLIST_HEAD(&orig_node->neigh_list);
INIT_LIST_HEAD(&orig_node->bond_list);
spin_lock_init(&orig_node->ogm_cnt_lock);
spin_lock_init(&orig_node->neigh_list_lock);
kref_init(&orig_node->refcount);
Expand All @@ -220,6 +237,8 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
orig_node->batman_seqno_reset = jiffies - 1
- msecs_to_jiffies(RESET_PROTECTION_MS);

atomic_set(&orig_node->bond_candidates, 0);

size = bat_priv->num_ifaces * sizeof(unsigned long) * NUM_WORDS;

orig_node->bcast_own = kzalloc(size, GFP_ATOMIC);
Expand Down Expand Up @@ -295,6 +314,7 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
neigh_purged = true;

hlist_del_rcu(&neigh_node->list);
bonding_candidate_del(orig_node, neigh_node);
call_rcu(&neigh_node->rcu, neigh_node_free_rcu);
} else {
if ((!*best_neigh_node) ||
Expand Down Expand Up @@ -326,9 +346,6 @@ static bool purge_orig_node(struct bat_priv *bat_priv,
best_neigh_node,
orig_node->hna_buff,
orig_node->hna_buff_len);
/* update bonding candidates, we could have lost
* some candidates. */
update_bonding_candidates(orig_node);
}
}

Expand Down
1 change: 1 addition & 0 deletions net/batman-adv/originator.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ int originator_init(struct bat_priv *bat_priv);
void originator_free(struct bat_priv *bat_priv);
void purge_orig_ref(struct bat_priv *bat_priv);
void orig_node_free_ref(struct kref *refcount);
void neigh_node_free_rcu_bond(struct rcu_head *rcu);
struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr);
struct neigh_node *create_neighbor(struct orig_node *orig_node,
struct orig_node *orig_neigh_node,
Expand Down
Loading

0 comments on commit a4c135c

Please sign in to comment.