dpif: Hide the contents of struct dpif.
[openvswitch] / datapath / datapath.c
index 3233361cebc058eeee3bbe765e835ece577f8ca0..14d83cd9238b55e075e56e10308dfa7836adff7c 100644 (file)
@@ -1,6 +1,9 @@
 /*
- * Distributed under the terms of the GNU GPL version 2.
  * Copyright (c) 2007, 2008, 2009 Nicira Networks.
+ * Distributed under the terms of the GNU GPL version 2.
+ *
+ * Significant portions of this file may be copied from parts of the Linux
+ * kernel, by Linus Torvalds and others.
  */
 
 /* Functions for managing the dp interface/device. */
@@ -174,7 +177,8 @@ static void dp_ifinfo_notify(int event, struct net_bridge_port *port)
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
+       rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
+       return;
 errout:
        if (err < 0)
                rtnl_set_sk_err(net, RTNLGRP_LINK, err);
@@ -273,19 +277,19 @@ static void do_destroy_dp(struct datapath *dp, struct list_head *dp_devs)
        struct net_bridge_port *p, *n;
        int i;
 
+       list_for_each_entry_safe (p, n, &dp->port_list, node)
+               if (p->port_no != ODPP_LOCAL)
+                       dp_del_port(p, dp_devs);
+
        if (dp_del_dp_hook)
                dp_del_dp_hook(dp);
 
-       /* Drop references to DP. */
-       list_for_each_entry_safe (p, n, &dp->port_list, node)
-               dp_del_port(p, dp_devs);
-
        rcu_assign_pointer(dps[dp->dp_idx], NULL);
-       synchronize_rcu();
 
-       /* Wait until no longer in use, then destroy it. */
-       synchronize_rcu();
+       dp_del_port(dp->ports[ODPP_LOCAL], dp_devs);
+
        dp_table_destroy(dp->table, 1);
+
        for (i = 0; i < DP_N_QUEUES; i++)
                skb_queue_purge(&dp->queues[i]);
        for (i = 0; i < DP_MAX_GROUPS; i++)
@@ -1466,6 +1470,7 @@ static int dp_has_packet_of_interest(struct datapath *dp, int listeners)
 ssize_t openvswitch_read(struct file *f, char __user *buf, size_t nbytes,
                      loff_t *ppos)
 {
+       /* XXX is there sufficient synchronization here? */
        int listeners = (int) f->private_data;
        int dp_idx = iminor(f->f_dentry->d_inode);
        struct datapath *dp = get_dp(dp_idx);
@@ -1520,6 +1525,7 @@ error:
 
 static unsigned int openvswitch_poll(struct file *file, poll_table *wait)
 {
+       /* XXX is there sufficient synchronization here? */
        int dp_idx = iminor(file->f_dentry->d_inode);
        struct datapath *dp = get_dp(dp_idx);
        unsigned int mask;