forked from mirrors/linux
		
	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 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. | ||||
|  * 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 | ||||
|  *		of the interface. | ||||
|  * | ||||
|  *	@name_hlist: 	Device name hash chain, please keep it close to name[] | ||||
|  *	@name_node:	Name hashlist node | ||||
|  *	@ifalias:	SNMP alias | ||||
|  *	@mem_end:	Shared memory end | ||||
|  *	@mem_start:	Shared memory start | ||||
|  | @ -1774,7 +1780,7 @@ enum netdev_priv_flags { | |||
| 
 | ||||
| struct net_device { | ||||
| 	char			name[IFNAMSIZ]; | ||||
| 	struct hlist_node	name_hlist; | ||||
| 	struct netdev_name_node	*name_node; | ||||
| 	struct dev_ifalias	__rcu *ifalias; | ||||
| 	/*
 | ||||
| 	 *	I/O specific fields | ||||
|  |  | |||
|  | @ -228,6 +228,67 @@ static inline void rps_unlock(struct softnet_data *sd) | |||
| #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 */ | ||||
| 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); | ||||
| 	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, | ||||
| 			   dev_index_hash(net, dev->ifindex)); | ||||
| 	write_unlock_bh(&dev_base_lock); | ||||
|  | @ -255,7 +316,7 @@ static void unlist_netdevice(struct net_device *dev) | |||
| 	/* Unlink dev from the device chain */ | ||||
| 	write_lock_bh(&dev_base_lock); | ||||
| 	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); | ||||
| 	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; | ||||
| 	struct hlist_head *head = dev_name_hash(net, name); | ||||
| 	struct netdev_name_node *node_name; | ||||
| 
 | ||||
| 	hlist_for_each_entry(dev, head, name_hlist) | ||||
| 		if (!strncmp(dev->name, name, IFNAMSIZ)) | ||||
| 			return dev; | ||||
| 
 | ||||
| 	return NULL; | ||||
| 	node_name = netdev_name_node_lookup(net, name); | ||||
| 	return node_name ? node_name->dev : NULL; | ||||
| } | ||||
| 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; | ||||
| 	struct hlist_head *head = dev_name_hash(net, name); | ||||
| 	struct netdev_name_node *node_name; | ||||
| 
 | ||||
| 	hlist_for_each_entry_rcu(dev, head, name_hlist) | ||||
| 		if (!strncmp(dev->name, name, IFNAMSIZ)) | ||||
| 			return dev; | ||||
| 
 | ||||
| 	return NULL; | ||||
| 	node_name = netdev_name_node_lookup_rcu(net, name); | ||||
| 	return node_name ? node_name->dev : NULL; | ||||
| } | ||||
| 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); | ||||
| 
 | ||||
| 	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); | ||||
| 
 | ||||
| 	synchronize_rcu(); | ||||
| 
 | ||||
| 	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); | ||||
| 
 | ||||
| 	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_mc_flush(dev); | ||||
| 
 | ||||
| 		netdev_name_node_free(dev->name_node); | ||||
| 
 | ||||
| 		if (dev->netdev_ops->ndo_uninit) | ||||
| 			dev->netdev_ops->ndo_uninit(dev); | ||||
| 
 | ||||
|  | @ -8706,6 +8761,10 @@ int register_netdevice(struct net_device *dev) | |||
| 	if (ret < 0) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	dev->name_node = netdev_name_node_head_alloc(dev); | ||||
| 	if (!dev->name_node) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	/* Init, if this function is available */ | ||||
| 	if (dev->netdev_ops->ndo_init) { | ||||
| 		ret = dev->netdev_ops->ndo_init(dev); | ||||
|  | @ -8827,6 +8886,8 @@ int register_netdevice(struct net_device *dev) | |||
| 	return ret; | ||||
| 
 | ||||
| err_uninit: | ||||
| 	if (dev->name_node) | ||||
| 		netdev_name_node_free(dev->name_node); | ||||
| 	if (dev->netdev_ops->ndo_uninit) | ||||
| 		dev->netdev_ops->ndo_uninit(dev); | ||||
| 	if (dev->priv_destructor) | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Jiri Pirko
						Jiri Pirko