summaryrefslogtreecommitdiffstats
path: root/net/batman-adv/vis.c
diff options
context:
space:
mode:
authorMarek Lindner2011-01-19 21:01:40 +0100
committerMarek Lindner2011-03-05 12:49:58 +0100
commitfb778ea173fcd58b8fc3d75c674f07fab187b55f (patch)
treeb14cfc99b7ca61ddcb49cc56c9a8e2822675debc /net/batman-adv/vis.c
parentbatman-adv: protect neigh_nodes used outside of rcu_locks with refcounting (diff)
downloadkernel-qcow2-linux-fb778ea173fcd58b8fc3d75c674f07fab187b55f.tar.gz
kernel-qcow2-linux-fb778ea173fcd58b8fc3d75c674f07fab187b55f.tar.xz
kernel-qcow2-linux-fb778ea173fcd58b8fc3d75c674f07fab187b55f.zip
batman-adv: protect each hash row with rcu locks
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Diffstat (limited to 'net/batman-adv/vis.c')
-rw-r--r--net/batman-adv/vis.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index a77b773b0868..8092eadcbdee 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -380,8 +380,10 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
sizeof(struct vis_packet));
memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN);
+ rcu_read_lock();
old_info = hash_find(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
&search_elem);
+ rcu_read_unlock();
kfree_skb(search_elem.skb_packet);
if (old_info) {
@@ -540,7 +542,8 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
for (i = 0; i < hash->size; i++) {
head = &hash->table[i];
- hlist_for_each_entry(bucket, walk, head, hlist) {
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(bucket, walk, head, hlist) {
orig_node = bucket->data;
if ((orig_node) && (orig_node->router) &&
(orig_node->flags & VIS_SERVER) &&
@@ -550,6 +553,7 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
ETH_ALEN);
}
}
+ rcu_read_unlock();
}
return best_tq;
@@ -605,7 +609,8 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
for (i = 0; i < hash->size; i++) {
head = &hash->table[i];
- hlist_for_each_entry(bucket, walk, head, hlist) {
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(bucket, walk, head, hlist) {
orig_node = bucket->data;
neigh_node = orig_node->router;
@@ -632,10 +637,12 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
packet->entries++;
if (vis_packet_full(info)) {
+ rcu_read_unlock();
spin_unlock_bh(&bat_priv->orig_hash_lock);
return 0;
}
}
+ rcu_read_unlock();
}
spin_unlock_bh(&bat_priv->orig_hash_lock);
@@ -721,7 +728,8 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
for (i = 0; i < hash->size; i++) {
head = &hash->table[i];
- hlist_for_each_entry(bucket, walk, head, hlist) {
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(bucket, walk, head, hlist) {
orig_node = bucket->data;
/* if it's a vis server and reachable, send it. */
@@ -746,7 +754,7 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
spin_lock_bh(&bat_priv->orig_hash_lock);
}
-
+ rcu_read_unlock();
}
spin_unlock_bh(&bat_priv->orig_hash_lock);
@@ -763,9 +771,11 @@ static void unicast_vis_packet(struct bat_priv *bat_priv,
spin_lock_bh(&bat_priv->orig_hash_lock);
packet = (struct vis_packet *)info->skb_packet->data;
+ rcu_read_lock();
orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
compare_orig, choose_orig,
packet->target_orig));
+ rcu_read_unlock();
if ((!orig_node) || (!orig_node->router))
goto out;