aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-10-29 17:36:39 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-29 17:36:39 -0400
commit911aeb108493caa45b4ca08313ee0600e943cd2b (patch)
treec4f8cab9590194c7c0e0d38a8278d76f02ea3618
parent706e282b6975305285980ddd903bcd246d2e4fcd (diff)
parentb07c26511e94ab856f3700c56d582c0da36d5b4d (diff)
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: David S. Miller <davem@davemloft.net>
-rw-r--r--net/openvswitch/dp_notify.c7
-rw-r--r--net/openvswitch/vport-netdev.c16
-rw-r--r--net/openvswitch/vport-netdev.h1
3 files changed, 19 insertions, 5 deletions
diff --git a/net/openvswitch/dp_notify.c b/net/openvswitch/dp_notify.c
index c3235675f359..5c2dab276109 100644
--- a/net/openvswitch/dp_notify.c
+++ b/net/openvswitch/dp_notify.c
@@ -65,8 +65,7 @@ void ovs_dp_notify_wq(struct work_struct *work)
65 continue; 65 continue;
66 66
67 netdev_vport = netdev_vport_priv(vport); 67 netdev_vport = netdev_vport_priv(vport);
68 if (netdev_vport->dev->reg_state == NETREG_UNREGISTERED || 68 if (!(netdev_vport->dev->priv_flags & IFF_OVS_DATAPATH))
69 netdev_vport->dev->reg_state == NETREG_UNREGISTERING)
70 dp_detach_port_notify(vport); 69 dp_detach_port_notify(vport);
71 } 70 }
72 } 71 }
@@ -88,6 +87,10 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event,
88 return NOTIFY_DONE; 87 return NOTIFY_DONE;
89 88
90 if (event == NETDEV_UNREGISTER) { 89 if (event == NETDEV_UNREGISTER) {
90 /* upper_dev_unlink and decrement promisc immediately */
91 ovs_netdev_detach_dev(vport);
92
93 /* schedule vport destroy, dev_put and genl notification */
91 ovs_net = net_generic(dev_net(dev), ovs_net_id); 94 ovs_net = net_generic(dev_net(dev), ovs_net_id);
92 queue_work(system_wq, &ovs_net->dp_notify_work); 95 queue_work(system_wq, &ovs_net->dp_notify_work);
93 } 96 }
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index 09d93c13cfd6..d21f77d875ba 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -150,15 +150,25 @@ static void free_port_rcu(struct rcu_head *rcu)
150 ovs_vport_free(vport_from_priv(netdev_vport)); 150 ovs_vport_free(vport_from_priv(netdev_vport));
151} 151}
152 152
153static void netdev_destroy(struct vport *vport) 153void ovs_netdev_detach_dev(struct vport *vport)
154{ 154{
155 struct netdev_vport *netdev_vport = netdev_vport_priv(vport); 155 struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
156 156
157 rtnl_lock(); 157 ASSERT_RTNL();
158 netdev_vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; 158 netdev_vport->dev->priv_flags &= ~IFF_OVS_DATAPATH;
159 netdev_rx_handler_unregister(netdev_vport->dev); 159 netdev_rx_handler_unregister(netdev_vport->dev);
160 netdev_upper_dev_unlink(netdev_vport->dev, get_dpdev(vport->dp)); 160 netdev_upper_dev_unlink(netdev_vport->dev,
161 netdev_master_upper_dev_get(netdev_vport->dev));
161 dev_set_promiscuity(netdev_vport->dev, -1); 162 dev_set_promiscuity(netdev_vport->dev, -1);
163}
164
165static void netdev_destroy(struct vport *vport)
166{
167 struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
168
169 rtnl_lock();
170 if (netdev_vport->dev->priv_flags & IFF_OVS_DATAPATH)
171 ovs_netdev_detach_dev(vport);
162 rtnl_unlock(); 172 rtnl_unlock();
163 173
164 call_rcu(&netdev_vport->rcu, free_port_rcu); 174 call_rcu(&netdev_vport->rcu, free_port_rcu);
diff --git a/net/openvswitch/vport-netdev.h b/net/openvswitch/vport-netdev.h
index dd298b5c5cdb..8df01c1127e5 100644
--- a/net/openvswitch/vport-netdev.h
+++ b/net/openvswitch/vport-netdev.h
@@ -39,5 +39,6 @@ netdev_vport_priv(const struct vport *vport)
39} 39}
40 40
41const char *ovs_netdev_get_name(const struct vport *); 41const char *ovs_netdev_get_name(const struct vport *);
42void ovs_netdev_detach_dev(struct vport *);
42 43
43#endif /* vport_netdev.h */ 44#endif /* vport_netdev.h */