mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	net: introduce name_node struct to be used in hashlist
Introduce name_node structure to hold name of device and put it into hashlist instead of putting there struct net_device directly. Add a necessary infrastructure to manipulate the hashlist. This prepares the code to use the same hashlist for alternative names introduced later in this set. Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									6958c97a48
								
							
						
					
					
						commit
						ff92741270
					
				
					 2 changed files with 87 additions and 20 deletions
				
			
		| 
						 | 
					@ -925,6 +925,12 @@ struct dev_ifalias {
 | 
				
			||||||
struct devlink;
 | 
					struct devlink;
 | 
				
			||||||
struct tlsdev_ops;
 | 
					struct tlsdev_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct netdev_name_node {
 | 
				
			||||||
 | 
						struct hlist_node hlist;
 | 
				
			||||||
 | 
						struct net_device *dev;
 | 
				
			||||||
 | 
						const char *name;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * This structure defines the management hooks for network devices.
 | 
					 * This structure defines the management hooks for network devices.
 | 
				
			||||||
 * The following hooks can be defined; unless noted otherwise, they are
 | 
					 * The following hooks can be defined; unless noted otherwise, they are
 | 
				
			||||||
| 
						 | 
					@ -1564,7 +1570,7 @@ enum netdev_priv_flags {
 | 
				
			||||||
 *		(i.e. as seen by users in the "Space.c" file).  It is the name
 | 
					 *		(i.e. as seen by users in the "Space.c" file).  It is the name
 | 
				
			||||||
 *		of the interface.
 | 
					 *		of the interface.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	@name_hlist: 	Device name hash chain, please keep it close to name[]
 | 
					 *	@name_node:	Name hashlist node
 | 
				
			||||||
 *	@ifalias:	SNMP alias
 | 
					 *	@ifalias:	SNMP alias
 | 
				
			||||||
 *	@mem_end:	Shared memory end
 | 
					 *	@mem_end:	Shared memory end
 | 
				
			||||||
 *	@mem_start:	Shared memory start
 | 
					 *	@mem_start:	Shared memory start
 | 
				
			||||||
| 
						 | 
					@ -1774,7 +1780,7 @@ enum netdev_priv_flags {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct net_device {
 | 
					struct net_device {
 | 
				
			||||||
	char			name[IFNAMSIZ];
 | 
						char			name[IFNAMSIZ];
 | 
				
			||||||
	struct hlist_node	name_hlist;
 | 
						struct netdev_name_node	*name_node;
 | 
				
			||||||
	struct dev_ifalias	__rcu *ifalias;
 | 
						struct dev_ifalias	__rcu *ifalias;
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 *	I/O specific fields
 | 
						 *	I/O specific fields
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -228,6 +228,67 @@ static inline void rps_unlock(struct softnet_data *sd)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct netdev_name_node *netdev_name_node_alloc(struct net_device *dev,
 | 
				
			||||||
 | 
											       const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct netdev_name_node *name_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						name_node = kmalloc(sizeof(*name_node), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!name_node)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						INIT_HLIST_NODE(&name_node->hlist);
 | 
				
			||||||
 | 
						name_node->dev = dev;
 | 
				
			||||||
 | 
						name_node->name = name;
 | 
				
			||||||
 | 
						return name_node;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct netdev_name_node *
 | 
				
			||||||
 | 
					netdev_name_node_head_alloc(struct net_device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return netdev_name_node_alloc(dev, dev->name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void netdev_name_node_free(struct netdev_name_node *name_node)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						kfree(name_node);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void netdev_name_node_add(struct net *net,
 | 
				
			||||||
 | 
									 struct netdev_name_node *name_node)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						hlist_add_head_rcu(&name_node->hlist,
 | 
				
			||||||
 | 
								   dev_name_hash(net, name_node->name));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void netdev_name_node_del(struct netdev_name_node *name_node)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						hlist_del_rcu(&name_node->hlist);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct netdev_name_node *netdev_name_node_lookup(struct net *net,
 | 
				
			||||||
 | 
												const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hlist_head *head = dev_name_hash(net, name);
 | 
				
			||||||
 | 
						struct netdev_name_node *name_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hlist_for_each_entry(name_node, head, hlist)
 | 
				
			||||||
 | 
							if (!strcmp(name_node->name, name))
 | 
				
			||||||
 | 
								return name_node;
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct netdev_name_node *netdev_name_node_lookup_rcu(struct net *net,
 | 
				
			||||||
 | 
												    const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hlist_head *head = dev_name_hash(net, name);
 | 
				
			||||||
 | 
						struct netdev_name_node *name_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hlist_for_each_entry_rcu(name_node, head, hlist)
 | 
				
			||||||
 | 
							if (!strcmp(name_node->name, name))
 | 
				
			||||||
 | 
								return name_node;
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Device list insertion */
 | 
					/* Device list insertion */
 | 
				
			||||||
static void list_netdevice(struct net_device *dev)
 | 
					static void list_netdevice(struct net_device *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -237,7 +298,7 @@ static void list_netdevice(struct net_device *dev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	write_lock_bh(&dev_base_lock);
 | 
						write_lock_bh(&dev_base_lock);
 | 
				
			||||||
	list_add_tail_rcu(&dev->dev_list, &net->dev_base_head);
 | 
						list_add_tail_rcu(&dev->dev_list, &net->dev_base_head);
 | 
				
			||||||
	hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name));
 | 
						netdev_name_node_add(net, dev->name_node);
 | 
				
			||||||
	hlist_add_head_rcu(&dev->index_hlist,
 | 
						hlist_add_head_rcu(&dev->index_hlist,
 | 
				
			||||||
			   dev_index_hash(net, dev->ifindex));
 | 
								   dev_index_hash(net, dev->ifindex));
 | 
				
			||||||
	write_unlock_bh(&dev_base_lock);
 | 
						write_unlock_bh(&dev_base_lock);
 | 
				
			||||||
| 
						 | 
					@ -255,7 +316,7 @@ static void unlist_netdevice(struct net_device *dev)
 | 
				
			||||||
	/* Unlink dev from the device chain */
 | 
						/* Unlink dev from the device chain */
 | 
				
			||||||
	write_lock_bh(&dev_base_lock);
 | 
						write_lock_bh(&dev_base_lock);
 | 
				
			||||||
	list_del_rcu(&dev->dev_list);
 | 
						list_del_rcu(&dev->dev_list);
 | 
				
			||||||
	hlist_del_rcu(&dev->name_hlist);
 | 
						netdev_name_node_del(dev->name_node);
 | 
				
			||||||
	hlist_del_rcu(&dev->index_hlist);
 | 
						hlist_del_rcu(&dev->index_hlist);
 | 
				
			||||||
	write_unlock_bh(&dev_base_lock);
 | 
						write_unlock_bh(&dev_base_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -733,14 +794,10 @@ EXPORT_SYMBOL_GPL(dev_fill_metadata_dst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct net_device *__dev_get_by_name(struct net *net, const char *name)
 | 
					struct net_device *__dev_get_by_name(struct net *net, const char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_device *dev;
 | 
						struct netdev_name_node *node_name;
 | 
				
			||||||
	struct hlist_head *head = dev_name_hash(net, name);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hlist_for_each_entry(dev, head, name_hlist)
 | 
						node_name = netdev_name_node_lookup(net, name);
 | 
				
			||||||
		if (!strncmp(dev->name, name, IFNAMSIZ))
 | 
						return node_name ? node_name->dev : NULL;
 | 
				
			||||||
			return dev;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return NULL;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(__dev_get_by_name);
 | 
					EXPORT_SYMBOL(__dev_get_by_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -758,14 +815,10 @@ EXPORT_SYMBOL(__dev_get_by_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct net_device *dev_get_by_name_rcu(struct net *net, const char *name)
 | 
					struct net_device *dev_get_by_name_rcu(struct net *net, const char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_device *dev;
 | 
						struct netdev_name_node *node_name;
 | 
				
			||||||
	struct hlist_head *head = dev_name_hash(net, name);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hlist_for_each_entry_rcu(dev, head, name_hlist)
 | 
						node_name = netdev_name_node_lookup_rcu(net, name);
 | 
				
			||||||
		if (!strncmp(dev->name, name, IFNAMSIZ))
 | 
						return node_name ? node_name->dev : NULL;
 | 
				
			||||||
			return dev;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return NULL;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(dev_get_by_name_rcu);
 | 
					EXPORT_SYMBOL(dev_get_by_name_rcu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1232,13 +1285,13 @@ int dev_change_name(struct net_device *dev, const char *newname)
 | 
				
			||||||
	netdev_adjacent_rename_links(dev, oldname);
 | 
						netdev_adjacent_rename_links(dev, oldname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	write_lock_bh(&dev_base_lock);
 | 
						write_lock_bh(&dev_base_lock);
 | 
				
			||||||
	hlist_del_rcu(&dev->name_hlist);
 | 
						netdev_name_node_del(dev->name_node);
 | 
				
			||||||
	write_unlock_bh(&dev_base_lock);
 | 
						write_unlock_bh(&dev_base_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	synchronize_rcu();
 | 
						synchronize_rcu();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	write_lock_bh(&dev_base_lock);
 | 
						write_lock_bh(&dev_base_lock);
 | 
				
			||||||
	hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name));
 | 
						netdev_name_node_add(net, dev->name_node);
 | 
				
			||||||
	write_unlock_bh(&dev_base_lock);
 | 
						write_unlock_bh(&dev_base_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = call_netdevice_notifiers(NETDEV_CHANGENAME, dev);
 | 
						ret = call_netdevice_notifiers(NETDEV_CHANGENAME, dev);
 | 
				
			||||||
| 
						 | 
					@ -8264,6 +8317,8 @@ static void rollback_registered_many(struct list_head *head)
 | 
				
			||||||
		dev_uc_flush(dev);
 | 
							dev_uc_flush(dev);
 | 
				
			||||||
		dev_mc_flush(dev);
 | 
							dev_mc_flush(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							netdev_name_node_free(dev->name_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (dev->netdev_ops->ndo_uninit)
 | 
							if (dev->netdev_ops->ndo_uninit)
 | 
				
			||||||
			dev->netdev_ops->ndo_uninit(dev);
 | 
								dev->netdev_ops->ndo_uninit(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8706,6 +8761,10 @@ int register_netdevice(struct net_device *dev)
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev->name_node = netdev_name_node_head_alloc(dev);
 | 
				
			||||||
 | 
						if (!dev->name_node)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Init, if this function is available */
 | 
						/* Init, if this function is available */
 | 
				
			||||||
	if (dev->netdev_ops->ndo_init) {
 | 
						if (dev->netdev_ops->ndo_init) {
 | 
				
			||||||
		ret = dev->netdev_ops->ndo_init(dev);
 | 
							ret = dev->netdev_ops->ndo_init(dev);
 | 
				
			||||||
| 
						 | 
					@ -8827,6 +8886,8 @@ int register_netdevice(struct net_device *dev)
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_uninit:
 | 
					err_uninit:
 | 
				
			||||||
 | 
						if (dev->name_node)
 | 
				
			||||||
 | 
							netdev_name_node_free(dev->name_node);
 | 
				
			||||||
	if (dev->netdev_ops->ndo_uninit)
 | 
						if (dev->netdev_ops->ndo_uninit)
 | 
				
			||||||
		dev->netdev_ops->ndo_uninit(dev);
 | 
							dev->netdev_ops->ndo_uninit(dev);
 | 
				
			||||||
	if (dev->priv_destructor)
 | 
						if (dev->priv_destructor)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue