openvswitch: Use RCU callback when detaching netdevices.
authorJesse Gross <jesse@nicira.com>
Wed, 28 Nov 2012 22:01:52 +0000 (14:01 -0800)
committerJesse Gross <jesse@nicira.com>
Wed, 28 Nov 2012 22:04:34 +0000 (14:04 -0800)
Currently, each time a device is detached from an OVS datapath
we call synchronize RCU before freeing associated data structures.
However, if a bridge is deleted (which detaches all ports) when
many devices are connected then there can be a long delay.  This
switches to use call_rcu() to group the cost together.

Reported-by: Justin Pettit <jpettit@nicira.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
net/openvswitch/vport-netdev.c
net/openvswitch/vport-netdev.h

index a9033481fa5e867b2264fa9f834a4041786ed166..a9327e2e48ce8450212feef7085f91e446766faa 100644 (file)
@@ -114,6 +114,15 @@ error:
        return ERR_PTR(err);
 }
 
+static void free_port_rcu(struct rcu_head *rcu)
+{
+       struct netdev_vport *netdev_vport = container_of(rcu,
+                                       struct netdev_vport, rcu);
+
+       dev_put(netdev_vport->dev);
+       ovs_vport_free(vport_from_priv(netdev_vport));
+}
+
 static void netdev_destroy(struct vport *vport)
 {
        struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
@@ -122,10 +131,7 @@ static void netdev_destroy(struct vport *vport)
        netdev_rx_handler_unregister(netdev_vport->dev);
        dev_set_promiscuity(netdev_vport->dev, -1);
 
-       synchronize_rcu();
-
-       dev_put(netdev_vport->dev);
-       ovs_vport_free(vport);
+       call_rcu(&netdev_vport->rcu, free_port_rcu);
 }
 
 const char *ovs_netdev_get_name(const struct vport *vport)
index f7072a25c60465a4b71455bd71282f57cf139a0c..6478079b3417fd460c9011048be234d62b3478c2 100644 (file)
 #define VPORT_NETDEV_H 1
 
 #include <linux/netdevice.h>
+#include <linux/rcupdate.h>
 
 #include "vport.h"
 
 struct vport *ovs_netdev_get_vport(struct net_device *dev);
 
 struct netdev_vport {
+       struct rcu_head rcu;
+
        struct net_device *dev;
 };