Commit 723de3eb authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller

net: free altname using an RCU callback

We had to add another synchronize_rcu() in recent fix.
Bite the bullet and add an rcu_head to netdev_name_node,
free from RCU.

Note that name_node does not hold any reference on dev
to which it points, but there must be a synchronize_rcu()
on device removal path, so we should be fine.
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9e1aa985
...@@ -341,13 +341,22 @@ int netdev_name_node_alt_create(struct net_device *dev, const char *name) ...@@ -341,13 +341,22 @@ int netdev_name_node_alt_create(struct net_device *dev, const char *name)
return 0; return 0;
} }
static void __netdev_name_node_alt_destroy(struct netdev_name_node *name_node) static void netdev_name_node_alt_free(struct rcu_head *head)
{ {
list_del(&name_node->list); struct netdev_name_node *name_node =
container_of(head, struct netdev_name_node, rcu);
kfree(name_node->name); kfree(name_node->name);
netdev_name_node_free(name_node); netdev_name_node_free(name_node);
} }
static void __netdev_name_node_alt_destroy(struct netdev_name_node *name_node)
{
netdev_name_node_del(name_node);
list_del(&name_node->list);
call_rcu(&name_node->rcu, netdev_name_node_alt_free);
}
int netdev_name_node_alt_destroy(struct net_device *dev, const char *name) int netdev_name_node_alt_destroy(struct net_device *dev, const char *name)
{ {
struct netdev_name_node *name_node; struct netdev_name_node *name_node;
...@@ -362,10 +371,7 @@ int netdev_name_node_alt_destroy(struct net_device *dev, const char *name) ...@@ -362,10 +371,7 @@ int netdev_name_node_alt_destroy(struct net_device *dev, const char *name)
if (name_node == dev->name_node || name_node->dev != dev) if (name_node == dev->name_node || name_node->dev != dev)
return -EINVAL; return -EINVAL;
netdev_name_node_del(name_node);
synchronize_rcu();
__netdev_name_node_alt_destroy(name_node); __netdev_name_node_alt_destroy(name_node);
return 0; return 0;
} }
...@@ -373,8 +379,10 @@ static void netdev_name_node_alt_flush(struct net_device *dev) ...@@ -373,8 +379,10 @@ static void netdev_name_node_alt_flush(struct net_device *dev)
{ {
struct netdev_name_node *name_node, *tmp; struct netdev_name_node *name_node, *tmp;
list_for_each_entry_safe(name_node, tmp, &dev->name_node->list, list) list_for_each_entry_safe(name_node, tmp, &dev->name_node->list, list) {
__netdev_name_node_alt_destroy(name_node); list_del(&name_node->list);
netdev_name_node_alt_free(&name_node->rcu);
}
} }
/* Device list insertion */ /* Device list insertion */
...@@ -11576,11 +11584,8 @@ static void __net_exit default_device_exit_net(struct net *net) ...@@ -11576,11 +11584,8 @@ static void __net_exit default_device_exit_net(struct net *net)
snprintf(fb_name, IFNAMSIZ, "dev%%d"); snprintf(fb_name, IFNAMSIZ, "dev%%d");
netdev_for_each_altname_safe(dev, name_node, tmp) netdev_for_each_altname_safe(dev, name_node, tmp)
if (netdev_name_in_use(&init_net, name_node->name)) { if (netdev_name_in_use(&init_net, name_node->name))
netdev_name_node_del(name_node);
synchronize_rcu();
__netdev_name_node_alt_destroy(name_node); __netdev_name_node_alt_destroy(name_node);
}
err = dev_change_net_namespace(dev, &init_net, fb_name); err = dev_change_net_namespace(dev, &init_net, fb_name);
if (err) { if (err) {
......
...@@ -56,6 +56,7 @@ struct netdev_name_node { ...@@ -56,6 +56,7 @@ struct netdev_name_node {
struct list_head list; struct list_head list;
struct net_device *dev; struct net_device *dev;
const char *name; const char *name;
struct rcu_head rcu;
}; };
int netdev_get_name(struct net *net, char *name, int ifindex); int netdev_get_name(struct net *net, char *name, int ifindex);
......
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