Commit 13175303 authored by Paolo Abeni's avatar Paolo Abeni Committed by David S. Miller

openvswitch: fix hangup on vxlan/gre/geneve device deletion

Each openvswitch tunnel vport (vxlan,gre,geneve) holds a reference
to the underlying tunnel device, but never released it when such
device is deleted.
Deleting the underlying device via the ip tool cause the kernel to
hangup in the netdev_wait_allrefs() loop.
This commit ensure that on device unregistration dp_detach_port_notify()
is called for all vports that hold the device reference, properly
releasing it.

Fixes: 614732ea ("openvswitch: Use regular VXLAN net_device device")
Fixes: b2acd1dc ("openvswitch: Use regular GRE net_device instead of vport")
Fixes: 6b001e68 ("openvswitch: Use Geneve device.")
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Acked-by: default avatarFlavio Leitner <fbl@sysclose.org>
Acked-by: default avatarPravin B Shelar <pshelar@nicira.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4eba7bb1
...@@ -58,7 +58,7 @@ void ovs_dp_notify_wq(struct work_struct *work) ...@@ -58,7 +58,7 @@ void ovs_dp_notify_wq(struct work_struct *work)
struct hlist_node *n; struct hlist_node *n;
hlist_for_each_entry_safe(vport, n, &dp->ports[i], dp_hash_node) { hlist_for_each_entry_safe(vport, n, &dp->ports[i], dp_hash_node) {
if (vport->ops->type != OVS_VPORT_TYPE_NETDEV) if (vport->ops->type == OVS_VPORT_TYPE_INTERNAL)
continue; continue;
if (!(vport->dev->priv_flags & IFF_OVS_DATAPATH)) if (!(vport->dev->priv_flags & IFF_OVS_DATAPATH))
......
...@@ -180,9 +180,13 @@ void ovs_netdev_tunnel_destroy(struct vport *vport) ...@@ -180,9 +180,13 @@ void ovs_netdev_tunnel_destroy(struct vport *vport)
if (vport->dev->priv_flags & IFF_OVS_DATAPATH) if (vport->dev->priv_flags & IFF_OVS_DATAPATH)
ovs_netdev_detach_dev(vport); ovs_netdev_detach_dev(vport);
/* Early release so we can unregister the device */ /* We can be invoked by both explicit vport deletion and
dev_put(vport->dev); * underlying netdev deregistration; delete the link only
* if it's not already shutting down.
*/
if (vport->dev->reg_state == NETREG_REGISTERED)
rtnl_delete_link(vport->dev); rtnl_delete_link(vport->dev);
dev_put(vport->dev);
vport->dev = NULL; vport->dev = NULL;
rtnl_unlock(); rtnl_unlock();
......
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