diff options
author | Simon Wunderlich <siwu@hrz.tu-chemnitz.de> | 2011-01-19 15:01:43 -0500 |
---|---|---|
committer | Marek Lindner <lindner_marek@yahoo.de> | 2011-03-05 06:50:01 -0500 |
commit | a4c135c561106c397bae33455acfca4aa8065a30 (patch) | |
tree | 09613dd5443fb6abfdab5b851eccdd610d1b0783 /net/batman-adv/originator.c | |
parent | 2ae2daf6c3f23364862a7d4f2ca79eab041b701b (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.c | 25 |
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 | ||
78 | void 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 | |||
78 | struct neigh_node *create_neighbor(struct orig_node *orig_node, | 86 | struct 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, | |||
106 | void orig_node_free_ref(struct kref *refcount) | 115 | void 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 | ||