summaryrefslogtreecommitdiff
path: root/net/bridge
diff options
context:
space:
mode:
authorstephen hemminger <shemminger@vyatta.com>2010-04-27 11:13:11 +0400
committerDavid S. Miller <davem@davemloft.net>2010-04-27 23:53:24 +0400
commitdcdca2c49bb6328bbc7cd8d73434c308b5dd0df2 (patch)
treea9cbb45b1cd4cffae2279f18989c5a40887a1b72 /net/bridge
parent7180f7751d5a1b6f1ef40285b5e928970cdd5306 (diff)
downloadlinux-dcdca2c49bb6328bbc7cd8d73434c308b5dd0df2.tar.xz
bridge: multicast router list manipulation
I prefer that the hlist be only accessed through the hlist macro objects. Explicit twiddling of links (especially with RCU) exposes the code to future bugs. Compile tested only. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_multicast.c30
1 files changed, 15 insertions, 15 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 2048ef0f9be5..fcba313f1894 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1042,21 +1042,21 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
static void br_multicast_add_router(struct net_bridge *br,
struct net_bridge_port *port)
{
- struct hlist_node *p;
- struct hlist_node **h;
-
- for (h = &br->router_list.first;
- (p = *h) &&
- (unsigned long)container_of(p, struct net_bridge_port, rlist) >
- (unsigned long)port;
- h = &p->next)
- ;
-
- port->rlist.pprev = h;
- port->rlist.next = p;
- rcu_assign_pointer(*h, &port->rlist);
- if (p)
- p->pprev = &port->rlist.next;
+ struct net_bridge_port *p;
+ struct hlist_node *n, *last = NULL;
+
+ hlist_for_each_entry(p, n, &br->router_list, rlist) {
+ if ((unsigned long) port >= (unsigned long) p) {
+ hlist_add_before_rcu(n, &port->rlist);
+ return;
+ }
+ last = n;
+ }
+
+ if (last)
+ hlist_add_after_rcu(last, &port->rlist);
+ else
+ hlist_add_head_rcu(&port->rlist, &br->router_list);
}
static void br_multicast_mark_router(struct net_bridge *br,