Commit 911aeb10 authored by David S. Miller's avatar David S. Miller

Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 706e282b b07c2651
...@@ -65,8 +65,7 @@ void ovs_dp_notify_wq(struct work_struct *work) ...@@ -65,8 +65,7 @@ void ovs_dp_notify_wq(struct work_struct *work)
continue; continue;
netdev_vport = netdev_vport_priv(vport); netdev_vport = netdev_vport_priv(vport);
if (netdev_vport->dev->reg_state == NETREG_UNREGISTERED || if (!(netdev_vport->dev->priv_flags & IFF_OVS_DATAPATH))
netdev_vport->dev->reg_state == NETREG_UNREGISTERING)
dp_detach_port_notify(vport); dp_detach_port_notify(vport);
} }
} }
...@@ -88,6 +87,10 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event, ...@@ -88,6 +87,10 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event,
return NOTIFY_DONE; return NOTIFY_DONE;
if (event == NETDEV_UNREGISTER) { 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); ovs_net = net_generic(dev_net(dev), ovs_net_id);
queue_work(system_wq, &ovs_net->dp_notify_work); queue_work(system_wq, &ovs_net->dp_notify_work);
} }
......
...@@ -150,15 +150,25 @@ static void free_port_rcu(struct rcu_head *rcu) ...@@ -150,15 +150,25 @@ static void free_port_rcu(struct rcu_head *rcu)
ovs_vport_free(vport_from_priv(netdev_vport)); 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); struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
rtnl_lock(); ASSERT_RTNL();
netdev_vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; netdev_vport->dev->priv_flags &= ~IFF_OVS_DATAPATH;
netdev_rx_handler_unregister(netdev_vport->dev); 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); 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(); rtnl_unlock();
call_rcu(&netdev_vport->rcu, free_port_rcu); call_rcu(&netdev_vport->rcu, free_port_rcu);
......
...@@ -39,5 +39,6 @@ netdev_vport_priv(const struct vport *vport) ...@@ -39,5 +39,6 @@ netdev_vport_priv(const struct vport *vport)
} }
const char *ovs_netdev_get_name(const struct vport *); const char *ovs_netdev_get_name(const struct vport *);
void ovs_netdev_detach_dev(struct vport *);
#endif /* vport_netdev.h */ #endif /* vport_netdev.h */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment