datapath: Change ODP_PORT_LIST semantics.
authorBen Pfaff <blp@nicira.com>
Wed, 17 Jun 2009 21:28:07 +0000 (14:28 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 6 Jul 2009 16:07:24 +0000 (09:07 -0700)
Until now, ODP_PORT_LIST has reported the number of ports actually copied
out.  It's better for the caller, however, if it reports the number of
ports that were available to be copied out.

datapath/datapath.c
lib/dpif.c

index e545cda..14779a6 100644 (file)
@@ -1260,7 +1260,7 @@ list_ports(struct datapath *dp, struct odp_portvec __user *pvp)
                                break;
                }
        }
-       return put_user(idx, &pvp->n_ports);
+       return put_user(dp->n_ports, &pvp->n_ports);
 }
 
 /* RCU callback for freeing a dp_port_group */
index e0e5f36..85d05bb 100644 (file)
@@ -337,33 +337,48 @@ dpif_port_get_name(struct dpif *dpif, uint16_t port_no,
 
 int
 dpif_port_list(const struct dpif *dpif,
-               struct odp_port **ports, size_t *n_ports)
+               struct odp_port **portsp, size_t *n_portsp)
 {
-    struct odp_portvec pv;
-    struct odp_stats stats;
+    struct odp_port *ports;
+    size_t n_ports;
     int error;
 
-    do {
+    for (;;) {
+        struct odp_stats stats;
+        struct odp_portvec pv;
+
         error = dpif_get_dp_stats(dpif, &stats);
         if (error) {
-            goto error;
+            goto exit;
         }
 
-        *ports = xcalloc(1, stats.n_ports * sizeof **ports);
-        pv.ports = *ports;
+        ports = xcalloc(stats.n_ports, sizeof *ports);
+        pv.ports = ports;
         pv.n_ports = stats.n_ports;
         error = do_ioctl(dpif, ODP_PORT_LIST, "ODP_PORT_LIST", &pv);
         if (error) {
-            free(*ports);
-            goto error;
+            /* Hard error. */
+            free(ports);
+            goto exit;
+        } else if (pv.n_ports <= stats.n_ports) {
+            /* Success. */
+            error = 0;
+            n_ports = pv.n_ports;
+            goto exit;
+        } else {
+            /* Soft error: port count increased behind our back.  Try again. */
+            free(ports);
         }
-    } while (pv.n_ports != stats.n_ports);
-    *n_ports = pv.n_ports;
-    return 0;
+    }
 
-error:
-    *ports = NULL;
-    *n_ports = 0;
+exit:
+    if (error) {
+        *portsp = NULL;
+        *n_portsp = 0;
+    } else {
+        *portsp = ports;
+        *n_portsp = n_ports;
+    }
     return error;
 }