]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch
authorDavid S. Miller <davem@davemloft.net>
Tue, 29 Oct 2013 21:36:39 +0000 (17:36 -0400)
committerDavid S. Miller <davem@davemloft.net>
Tue, 29 Oct 2013 21:36:39 +0000 (17:36 -0400)
Jesse Gross says:

====================
One patch for net/3.12 fixing an issue where devices could be in an
invalid state they are removed while still attached to OVS.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
net/openvswitch/dp_notify.c
net/openvswitch/vport-netdev.c
net/openvswitch/vport-netdev.h

index c3235675f35997169ad4961722344537005a8f6e..5c2dab27610962caed49d6017a6cda5b5ac855fc 100644 (file)
@@ -65,8 +65,7 @@ void ovs_dp_notify_wq(struct work_struct *work)
                                        continue;
 
                                netdev_vport = netdev_vport_priv(vport);
-                               if (netdev_vport->dev->reg_state == NETREG_UNREGISTERED ||
-                                   netdev_vport->dev->reg_state == NETREG_UNREGISTERING)
+                               if (!(netdev_vport->dev->priv_flags & IFF_OVS_DATAPATH))
                                        dp_detach_port_notify(vport);
                        }
                }
@@ -88,6 +87,10 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event,
                return NOTIFY_DONE;
 
        if (event == NETDEV_UNREGISTER) {
+               /* upper_dev_unlink and decrement promisc immediately */
+               ovs_netdev_detach_dev(vport);
+
+               /* schedule vport destroy, dev_put and genl notification */
                ovs_net = net_generic(dev_net(dev), ovs_net_id);
                queue_work(system_wq, &ovs_net->dp_notify_work);
        }
index 09d93c13cfd69a295d533cad35ab857c9eeee2f0..d21f77d875ba7b690a0c46231e0b539172488562 100644 (file)
@@ -150,15 +150,25 @@ static void free_port_rcu(struct rcu_head *rcu)
        ovs_vport_free(vport_from_priv(netdev_vport));
 }
 
-static void netdev_destroy(struct vport *vport)
+void ovs_netdev_detach_dev(struct vport *vport)
 {
        struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
 
-       rtnl_lock();
+       ASSERT_RTNL();
        netdev_vport->dev->priv_flags &= ~IFF_OVS_DATAPATH;
        netdev_rx_handler_unregister(netdev_vport->dev);
-       netdev_upper_dev_unlink(netdev_vport->dev, get_dpdev(vport->dp));
+       netdev_upper_dev_unlink(netdev_vport->dev,
+                               netdev_master_upper_dev_get(netdev_vport->dev));
        dev_set_promiscuity(netdev_vport->dev, -1);
+}
+
+static void netdev_destroy(struct vport *vport)
+{
+       struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
+
+       rtnl_lock();
+       if (netdev_vport->dev->priv_flags & IFF_OVS_DATAPATH)
+               ovs_netdev_detach_dev(vport);
        rtnl_unlock();
 
        call_rcu(&netdev_vport->rcu, free_port_rcu);
index dd298b5c5cdb25e1a721e5b845353ce055c02e60..8df01c1127e546d06ba2f8c3fde44b51c58ad0de 100644 (file)
@@ -39,5 +39,6 @@ netdev_vport_priv(const struct vport *vport)
 }
 
 const char *ovs_netdev_get_name(const struct vport *);
+void ovs_netdev_detach_dev(struct vport *);
 
 #endif /* vport_netdev.h */