bridge: multicast router list manipulation
authorstephen hemminger <shemminger@vyatta.com>
Tue, 27 Apr 2010 07:13:11 +0000 (07:13 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 27 Apr 2010 19:53:24 +0000 (12:53 -0700)
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>
net/bridge/br_multicast.c

index 2048ef0..fcba313 100644 (file)
@@ -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,