datapath: Hold rcu_read_lock where we claim to.
authorJesse Gross <jesse@nicira.com>
Wed, 12 May 2010 20:45:49 +0000 (13:45 -0700)
committerJesse Gross <jesse@nicira.com>
Fri, 14 May 2010 22:10:45 +0000 (15:10 -0700)
Many of the vport operations require that either RTNL lock or
rcu_read_lock be held.  However, operations from userspace often
hold a different lock so grab rcu_read_lock as well.

datapath/datapath.c
datapath/vport.c

index 67c422adc816eb3cc148c4977b6193755322e72c..a083274b5abb8f3d80acf247da8d9da1e63473c3 100644 (file)
@@ -1305,8 +1305,12 @@ static int do_execute(struct datapath *dp, const struct odp_execute *execute)
                skb->protocol = htons(ETH_P_802_2);
 
        flow_extract(skb, execute->in_port, &key);
+
+       rcu_read_lock();
        err = execute_actions(dp, skb, &key, actions->actions,
                              actions->n_actions, GFP_KERNEL);
+       rcu_read_unlock();
+
        kfree(actions);
        return err;
 
index cc20959372eb3f86a1d0b8c0b8dc5074a06e5f4e..691ab84ba8a15af10c6ee1d172fa0ca0aec14c0c 100644 (file)
@@ -400,9 +400,12 @@ vport_stats_get(struct odp_vport_stats_req __user *ustats_req)
                goto out;
        }
 
-       if (vport->ops->get_stats)
+       if (vport->ops->get_stats) {
+               rcu_read_lock();
                err = vport->ops->get_stats(vport, &stats_req.stats);
-       else if (vport->ops->flags & VPORT_F_GEN_STATS) {
+               rcu_read_unlock();
+
+       } else if (vport->ops->flags & VPORT_F_GEN_STATS) {
                int i;
 
                memset(&stats_req.stats, 0, sizeof(struct odp_vport_stats));
@@ -475,7 +478,9 @@ vport_ether_get(struct odp_vport_ether __user *uvport_ether)
                goto out;
        }
 
+       rcu_read_lock();
        memcpy(vport_ether.ether_addr, vport_get_addr(vport), ETH_ALEN);
+       rcu_read_unlock();
 
 out:
        vport_unlock();
@@ -632,11 +637,17 @@ vport_locate(const char *name)
                dump_stack();
        }
 
+       rcu_read_lock();
+
        hlist_for_each_entry(vport, node, bucket, hash_node)
                if (!strcmp(name, vport_get_name(vport)))
-                       return vport;
+                       goto out;
 
-       return NULL;
+       vport = NULL;
+
+out:
+       rcu_read_unlock();
+       return vport;
 }
 
 static void