gentoo-full-overlay/net-misc/openvswitch/files/prevent-traceback.patch

107 lines
3.5 KiB
Diff

commit d4d1107c3a49a4dadf6dc8ac55d6fefa25a8e06a
Author: Alexei Starovoitov <ast@plumgrid.com>
Date: Wed Oct 16 15:28:23 2013 -0700
cherry-pick 8e04c6e10c28e42c715eb9fef749554c123bddbc
diff --git a/AUTHORS b/AUTHORS
index 2d29e66..7a62704 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -2,6 +2,8 @@ The following people, in alphabetical order, have either authored or
signed off on commits in the Open vSwitch version control repository.
Aaron Rosen arosen@clemson.edu
+Alexandru Copot alex.mihai.c@gmail.com
+Alexei Starovoitov ast@plumgrid.com
Alexey I. Froloff raorn@altlinux.org
Alex Wang alexw@nicira.com
Andrew Evans aevans@nicira.com
diff --git a/datapath/dp_notify.c b/datapath/dp_notify.c
index 847f611..a973623 100644
--- a/datapath/dp_notify.c
+++ b/datapath/dp_notify.c
@@ -66,8 +66,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 (!(ovs_netdev_get_vport(netdev_vport->dev)))
dp_detach_port_notify(vport);
}
}
@@ -89,6 +88,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(&ovs_net->dp_notify_work);
}
diff --git a/datapath/linux/compat/include/linux/netdevice.h b/datapath/linux/compat/include/linux/netdevice.h
index 4e2b7f5..908ed86 100644
--- a/datapath/linux/compat/include/linux/netdevice.h
+++ b/datapath/linux/compat/include/linux/netdevice.h
@@ -118,6 +118,11 @@ static inline void netdev_upper_dev_unlink(struct net_device *dev,
struct net_device *upper_dev)
{
}
+
+static inline struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
+{
+ return NULL;
+}
#endif
#endif
diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c
index 215a47e..0c9f603 100644
--- a/datapath/vport-netdev.c
+++ b/datapath/vport-netdev.c
@@ -201,16 +201,27 @@ 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);
- netdev_exit();
- 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);
+
+ netdev_exit();
+
+ rtnl_lock();
+ if (ovs_netdev_get_vport(netdev_vport->dev))
+ ovs_netdev_detach_dev(vport);
rtnl_unlock();
call_rcu(&netdev_vport->rcu, free_port_rcu);
diff --git a/datapath/vport-netdev.h b/datapath/vport-netdev.h
index dd298b5..8df01c1 100644
--- a/datapath/vport-netdev.h
+++ b/datapath/vport-netdev.h
@@ -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 */