aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/originator.c
diff options
context:
space:
mode:
authorSimon Wunderlich <siwu@hrz.tu-chemnitz.de>2011-01-19 15:01:43 -0500
committerMarek Lindner <lindner_marek@yahoo.de>2011-03-05 06:50:01 -0500
commita4c135c561106c397bae33455acfca4aa8065a30 (patch)
tree09613dd5443fb6abfdab5b851eccdd610d1b0783 /net/batman-adv/originator.c
parent2ae2daf6c3f23364862a7d4f2ca79eab041b701b (diff)
batman-adv: protect bonding with rcu locks
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>
Diffstat (limited to 'net/batman-adv/originator.c')
-rw-r--r--net/batman-adv/originator.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 71dfc24e961b..a85eadca6b2d 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -75,6 +75,14 @@ static void neigh_node_free_rcu(struct rcu_head *rcu)
75 kref_put(&neigh_node->refcount, neigh_node_free_ref); 75 kref_put(&neigh_node->refcount, neigh_node_free_ref);
76} 76}
77 77
78void neigh_node_free_rcu_bond(struct rcu_head *rcu)
79{
80 struct neigh_node *neigh_node;
81
82 neigh_node = container_of(rcu, struct neigh_node, rcu_bond);
83 kref_put(&neigh_node->refcount, neigh_node_free_ref);
84}
85
78struct neigh_node *create_neighbor(struct orig_node *orig_node, 86struct neigh_node *create_neighbor(struct orig_node *orig_node,
79 struct orig_node *orig_neigh_node, 87 struct orig_node *orig_neigh_node,
80 uint8_t *neigh, 88 uint8_t *neigh,
@@ -91,6 +99,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node,
91 return NULL; 99 return NULL;
92 100
93 INIT_HLIST_NODE(&neigh_node->list); 101 INIT_HLIST_NODE(&neigh_node->list);
102 INIT_LIST_HEAD(&neigh_node->bonding_list);
94 103
95 memcpy(neigh_node->addr, neigh, ETH_ALEN); 104 memcpy(neigh_node->addr, neigh, ETH_ALEN);
96 neigh_node->orig_node = orig_neigh_node; 105 neigh_node->orig_node = orig_neigh_node;
@@ -106,13 +115,20 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node,
106void orig_node_free_ref(struct kref *refcount) 115void orig_node_free_ref(struct kref *refcount)
107{ 116{
108 struct hlist_node *node, *node_tmp; 117 struct hlist_node *node, *node_tmp;
109 struct neigh_node *neigh_node; 118 struct neigh_node *neigh_node, *tmp_neigh_node;
110 struct orig_node *orig_node; 119 struct orig_node *orig_node;
111 120
112 orig_node = container_of(refcount, struct orig_node, refcount); 121 orig_node = container_of(refcount, struct orig_node, refcount);
113 122
114 spin_lock_bh(&orig_node->neigh_list_lock); 123 spin_lock_bh(&orig_node->neigh_list_lock);
115 124
125 /* for all bonding members ... */
126 list_for_each_entry_safe(neigh_node, tmp_neigh_node,
127 &orig_node->bond_list, bonding_list) {
128 list_del_rcu(&neigh_node->bonding_list);
129 call_rcu(&neigh_node->rcu_bond, neigh_node_free_rcu_bond);
130 }
131
116 /* for all neighbors towards this originator ... */ 132 /* for all neighbors towards this originator ... */
117 hlist_for_each_entry_safe(neigh_node, node, node_tmp, 133 hlist_for_each_entry_safe(neigh_node, node, node_tmp,
118 &orig_node->neigh_list, list) { 134 &orig_node->neigh_list, list) {
@@ -207,6 +223,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
207 return NULL; 223 return NULL;
208 224
209 INIT_HLIST_HEAD(&orig_node->neigh_list); 225 INIT_HLIST_HEAD(&orig_node->neigh_list);
226 INIT_LIST_HEAD(&orig_node->bond_list);
210 spin_lock_init(&orig_node->ogm_cnt_lock); 227 spin_lock_init(&orig_node->ogm_cnt_lock);
211 spin_lock_init(&orig_node->neigh_list_lock); 228 spin_lock_init(&orig_node->neigh_list_lock);
212 kref_init(&orig_node->refcount); 229 kref_init(&orig_node->refcount);
@@ -220,6 +237,8 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
220 orig_node->batman_seqno_reset = jiffies - 1 237 orig_node->batman_seqno_reset = jiffies - 1
221 - msecs_to_jiffies(RESET_PROTECTION_MS); 238 - msecs_to_jiffies(RESET_PROTECTION_MS);
222 239
240 atomic_set(&orig_node->bond_candidates, 0);
241
223 size = bat_priv->num_ifaces * sizeof(unsigned long) * NUM_WORDS; 242 size = bat_priv->num_ifaces * sizeof(unsigned long) * NUM_WORDS;
224 243
225 orig_node->bcast_own = kzalloc(size, GFP_ATOMIC); 244 orig_node->bcast_own = kzalloc(size, GFP_ATOMIC);
@@ -295,6 +314,7 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
295 neigh_purged = true; 314 neigh_purged = true;
296 315
297 hlist_del_rcu(&neigh_node->list); 316 hlist_del_rcu(&neigh_node->list);
317 bonding_candidate_del(orig_node, neigh_node);
298 call_rcu(&neigh_node->rcu, neigh_node_free_rcu); 318 call_rcu(&neigh_node->rcu, neigh_node_free_rcu);
299 } else { 319 } else {
300 if ((!*best_neigh_node) || 320 if ((!*best_neigh_node) ||
@@ -326,9 +346,6 @@ static bool purge_orig_node(struct bat_priv *bat_priv,
326 best_neigh_node, 346 best_neigh_node,
327 orig_node->hna_buff, 347 orig_node->hna_buff,
328 orig_node->hna_buff_len); 348 orig_node->hna_buff_len);
329 /* update bonding candidates, we could have lost
330 * some candidates. */
331 update_bonding_candidates(orig_node);
332 } 349 }
333 } 350 }
334 351