From: stephen hemminger Date: Tue, 27 Apr 2010 07:13:11 +0000 (+0000) Subject: bridge: multicast router list manipulation X-Git-Tag: v2.6.35-rc1~473^2~375 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dcdca2c49bb6328bbc7cd8d73434c308b5dd0df2;p=platform%2Fkernel%2Flinux-3.10.git 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 Signed-off-by: David S. Miller --- diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 2048ef0..fcba313 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,