bridge: multicast port group RCU fix
authorstephen hemminger <shemminger@vyatta.com>
Tue, 27 Apr 2010 15:01:06 +0000 (15:01 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 28 Apr 2010 01:13:54 +0000 (18:13 -0700)
The recently introduced bridge mulitcast port group list was only
partially using RCU correctly. It was missing rcu_dereference()
and missing the necessary barrier on deletion.

The code should have used one of the standard list methods (list or hlist)
instead of open coding a RCU based link list.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/bridge/br_forward.c
net/bridge/br_multicast.c

index 5b70fc0..5f9988a 100644 (file)
@@ -217,7 +217,7 @@ static void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
        prev = NULL;
 
        rp = rcu_dereference(br->router_list.first);
-       p = mdst ? mdst->ports : NULL;
+       p = mdst ? rcu_dereference(mdst->ports) : NULL;
        while (p || rp) {
                lport = p ? p->port : NULL;
                rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
@@ -231,7 +231,7 @@ static void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
                        goto out;
 
                if ((unsigned long)lport >= (unsigned long)port)
-                       p = p->next;
+                       p = rcu_dereference(p->next);
                if ((unsigned long)rport >= (unsigned long)port)
                        rp = rcu_dereference(rp->next);
        }
index d63868c..7128abd 100644 (file)
@@ -259,7 +259,7 @@ static void br_multicast_del_pg(struct net_bridge *br,
                if (p != pg)
                        continue;
 
-               *pp = p->next;
+               rcu_assign_pointer(*pp, p->next);
                hlist_del_init(&p->mglist);
                del_timer(&p->timer);
                del_timer(&p->query_timer);