[PATCH NET-PREV 22/51] vxlan: Use __register_netdevice in .newlink

From: Kirill Tkhai
Date: Sat Mar 22 2025 - 10:44:33 EST


The objective is to conform .newlink with its callers,
which already assign nd_lock (and matches master nd_lock
if there is one).

Also, use __unregister_netdevice() since we know
there is held lock in that path.

Signed-off-by: Kirill Tkhai <tkhai@xxxxx>
---
drivers/net/vxlan/vxlan_core.c | 36 +++++++++++++++++++++++++++++-------
1 file changed, 29 insertions(+), 7 deletions(-)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index b041ddc2ab34..369f7b667424 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3950,7 +3950,7 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
return err;
}

- err = register_netdevice(dev);
+ err = __register_netdevice(dev);
if (err)
goto errout;
unregister = true;
@@ -4001,7 +4001,7 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
__vxlan_fdb_free(f);
unregister:
if (unregister)
- unregister_netdevice(dev);
+ __unregister_netdevice(dev);
return err;
}

@@ -4604,22 +4604,37 @@ struct net_device *vxlan_dev_create(struct net *net, const char *name,
u8 name_assign_type,
struct vxlan_config *conf)
{
+ struct net_device *dev, *lowerdev = NULL;
struct nlattr *tb[IFLA_MAX + 1];
- struct net_device *dev;
+ struct nd_lock *nd_lock;
int err;

memset(&tb, 0, sizeof(tb));

+ if (conf->remote_ifindex) {
+ lowerdev = __dev_get_by_index(net, conf->remote_ifindex);
+ if (!lowerdev)
+ return ERR_PTR(-ENODEV);
+ }
+
dev = rtnl_create_link(net, name, name_assign_type,
&vxlan_link_ops, tb, NULL);
if (IS_ERR(dev))
return dev;

- err = __vxlan_dev_create(net, dev, conf, NULL);
- if (err < 0) {
- free_netdev(dev);
- return ERR_PTR(err);
+ if (lowerdev) {
+ lock_netdev(lowerdev, &nd_lock);
+ attach_nd_lock(dev, nd_lock);
+ } else {
+ err = -ENOMEM;
+ if (!attach_new_nd_lock(dev))
+ goto err_free;
+ lock_netdev(dev, &nd_lock);
}
+ err = __vxlan_dev_create(net, dev, conf, NULL);
+ if (err < 0)
+ goto err_detach;
+ unlock_netdev(nd_lock);

err = rtnl_configure_link(dev, NULL, 0, NULL);
if (err < 0) {
@@ -4631,6 +4646,13 @@ struct net_device *vxlan_dev_create(struct net *net, const char *name,
}

return dev;
+
+err_detach:
+ detach_nd_lock(dev);
+ unlock_netdev(nd_lock);
+err_free:
+ free_netdev(dev);
+ return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(vxlan_dev_create);