[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <fce85b872c03cee379cb30ae46100ff42bea8e0d.1566807905.git.lucien.xin@gmail.com>
Date: Mon, 26 Aug 2019 16:25:05 +0800
From: Xin Long <lucien.xin@...il.com>
To: network dev <netdev@...r.kernel.org>
Cc: davem@...emloft.net,
Steffen Klassert <steffen.klassert@...unet.com>
Subject: [PATCH net] xfrm: add NETDEV_UNREGISTER event process for xfrmi
When creating a xfrmi dev, it always holds the phydev. The xfrmi dev should
be deleted when the phydev is being unregistered, so that the phydev can be
put on time. Otherwise the phydev's deleting will get stuck:
# ip link add dummy10 type dummy
# ip link add xfrmi10 type xfrm dev dummy10
# ip link del dummy10
The last command blocks and dmesg shows:
unregister_netdevice: waiting for dummy10 to become free. Usage count = 1
This patch fixes it by adding NETDEV_UNREGISTER event process for xfrmi.
Fixes: f203b76d7809 ("xfrm: Add virtual xfrm interfaces")
Reported-by: Xiumei Mu <xmu@...hat.com>
Signed-off-by: Xin Long <lucien.xin@...il.com>
---
net/xfrm/xfrm_interface.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index 74868f9..f3de1f5 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -877,6 +877,35 @@ static const struct xfrm_if_cb xfrm_if_cb = {
.decode_session = xfrmi_decode_session,
};
+static int xfrmi_event(struct notifier_block *this, unsigned long e, void *ptr)
+{
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+ struct xfrmi_net *xfrmn = net_generic(dev_net(dev), xfrmi_net_id);
+ struct xfrm_if *xi;
+ LIST_HEAD(list);
+
+ if (e != NETDEV_UNREGISTER)
+ return NOTIFY_DONE;
+
+ rcu_read_lock();
+ for_each_xfrmi_rcu(xfrmn->xfrmi[0], xi) {
+ if (xi->phydev != dev)
+ continue;
+ unregister_netdevice_queue(xi->dev, &list);
+ }
+ rcu_read_unlock();
+
+ if (list_empty(&list))
+ return NOTIFY_DONE;
+
+ unregister_netdevice_many(&list);
+ return NOTIFY_OK;
+}
+
+static struct notifier_block xfrmi_notifier = {
+ .notifier_call = xfrmi_event,
+};
+
static int __init xfrmi_init(void)
{
const char *msg;
@@ -906,6 +935,7 @@ static int __init xfrmi_init(void)
goto rtnl_link_failed;
xfrm_if_register_cb(&xfrm_if_cb);
+ register_netdevice_notifier(&xfrmi_notifier);
return err;
@@ -922,6 +952,7 @@ static int __init xfrmi_init(void)
static void __exit xfrmi_fini(void)
{
+ unregister_netdevice_notifier(&xfrmi_notifier);
xfrm_if_unregister_cb();
rtnl_link_unregister(&xfrmi_link_ops);
xfrmi4_fini();
--
2.1.0
Powered by blists - more mailing lists