datapath: Don't directly access port array in query_port().
authorJesse Gross <jesse@nicira.com>
Fri, 24 Dec 2010 01:56:29 +0000 (17:56 -0800)
committerJesse Gross <jesse@nicira.com>
Wed, 29 Dec 2010 18:30:09 +0000 (10:30 -0800)
query_port() directly accesses the datapath port array, without
using any kind of RCU dereference.  It's OK, since it is holding
DP mutex but this adds an explicit check to make sparse happy.
It also simplifies the code path somewhat.

Found with sparse.

Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
datapath/datapath.c

index 4df7e9f..3d5629d 100644 (file)
@@ -1281,45 +1281,32 @@ static int put_port(const struct vport *p, struct odp_port __user *uop)
 static int query_port(struct datapath *dp, struct odp_port __user *uport)
 {
        struct odp_port port;
+       struct vport *vport;
 
        if (copy_from_user(&port, uport, sizeof port))
                return -EFAULT;
 
        if (port.devname[0]) {
-               struct vport *vport;
-               int err = 0;
-
                port.devname[IFNAMSIZ - 1] = '\0';
 
                vport_lock();
-               rcu_read_lock();
-
                vport = vport_locate(port.devname);
-               if (!vport) {
-                       err = -ENODEV;
-                       goto error_unlock;
-               }
-               if (vport->dp != dp) {
-                       err = -ENOENT;
-                       goto error_unlock;
-               }
-
-               port.port = vport->port_no;
-
-error_unlock:
-               rcu_read_unlock();
                vport_unlock();
 
-               if (err)
-                       return err;
+               if (!vport)
+                       return -ENODEV;
+               if (vport->dp != dp)
+                       return -ENOENT;
        } else {
                if (port.port >= DP_MAX_PORTS)
                        return -EINVAL;
-               if (!dp->ports[port.port])
+
+               vport = get_vport_protected(dp, port.port);
+               if (!vport)
                        return -ENOENT;
        }
 
-       return put_port(dp->ports[port.port], uport);
+       return put_port(vport, uport);
 }
 
 static int do_list_ports(struct datapath *dp, struct odp_port __user *uports,