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.
Unified · Split
| @@ -925,6 +925,12 @@ struct dev_ifalias { · 924 unmodified lines | ||
| 925 | 925 | struct devlink; |
| 926 | 926 | struct tlsdev_ops; |
| 927 | 927 | |
| 928 | +struct netdev_name_node { | |
| 929 | + struct hlist_node hlist; | |
| 930 | + struct net_device *dev; | |
| 931 | + const char *name; | |
| 932 | +}; | |
| 933 | + | |
| 928 | 934 | /* |
| 929 | 935 | * This structure defines the management hooks for network devices. |
| 930 | 936 | * The following hooks can be defined; unless noted otherwise, they are |
| @@ -1564,7 +1570,7 @@ enum netdev_priv_flags { · 633 unmodified lines | ||
| 1564 | 1570 | * (i.e. as seen by users in the "Space.c" file). It is the name |
| 1565 | 1571 | * of the interface. |
| 1566 | 1572 | * |
| 1567 | − * @name_hlist: Device name hash chain, please keep it close to name[] | |
| 1573 | + * @name_node: Name hashlist node | |
| 1568 | 1574 | * @ifalias: SNMP alias |
| 1569 | 1575 | * @mem_end: Shared memory end |
| 1570 | 1576 | * @mem_start: Shared memory start |
| @@ -1774,7 +1780,7 @@ enum netdev_priv_flags { · 203 unmodified lines | ||
| 1774 | 1780 | |
| 1775 | 1781 | struct net_device { |
| 1776 | 1782 | char name[IFNAMSIZ]; |
| 1777 | − struct hlist_node name_hlist; | |
| 1783 | + struct netdev_name_node *name_node; | |
| 1778 | 1784 | struct dev_ifalias __rcu *ifalias; |
| 1779 | 1785 | /* |
| 1780 | 1786 | * I/O specific fields |
| @@ -228,6 +228,67 @@ static inline void rps_unlock(struct softnet_data *sd) · 227 unmodified lines | ||
| 228 | 228 | #endif |
| 229 | 229 | } |
| 230 | 230 | |
| 231 | +static struct netdev_name_node *netdev_name_node_alloc(struct net_device *dev, | |
| 232 | + const char *name) | |
| 233 | +{ | |
| 234 | + struct netdev_name_node *name_node; | |
| 235 | + | |
| 236 | + name_node = kmalloc(sizeof(*name_node), GFP_KERNEL); | |
| 237 | + if (!name_node) | |
| 238 | + return NULL; | |
| 239 | + INIT_HLIST_NODE(&name_node->hlist); | |
| 240 | + name_node->dev = dev; | |
| 241 | + name_node->name = name; | |
| 242 | + return name_node; | |
| 243 | +} | |
| 244 | + | |
| 245 | +static struct netdev_name_node * | |
| 246 | +netdev_name_node_head_alloc(struct net_device *dev) | |
| 247 | +{ | |
| 248 | + return netdev_name_node_alloc(dev, dev->name); | |
| 249 | +} | |
| 250 | + | |
| 251 | +static void netdev_name_node_free(struct netdev_name_node *name_node) | |
| 252 | +{ | |
| 253 | + kfree(name_node); | |
| 254 | +} | |
| 255 | + | |
| 256 | +static void netdev_name_node_add(struct net *net, | |
| 257 | + struct netdev_name_node *name_node) | |
| 258 | +{ | |
| 259 | + hlist_add_head_rcu(&name_node->hlist, | |
| 260 | + dev_name_hash(net, name_node->name)); | |
| 261 | +} | |
| 262 | + | |
| 263 | +static void netdev_name_node_del(struct netdev_name_node *name_node) | |
| 264 | +{ | |
| 265 | + hlist_del_rcu(&name_node->hlist); | |
| 266 | +} | |
| 267 | + | |
| 268 | +static struct netdev_name_node *netdev_name_node_lookup(struct net *net, | |
| 269 | + const char *name) | |
| 270 | +{ | |
| 271 | + struct hlist_head *head = dev_name_hash(net, name); | |
| 272 | + struct netdev_name_node *name_node; | |
| 273 | + | |
| 274 | + hlist_for_each_entry(name_node, head, hlist) | |
| 275 | + if (!strcmp(name_node->name, name)) | |
| 276 | + return name_node; | |
| 277 | + return NULL; | |
| 278 | +} | |
| 279 | + | |
| 280 | +static struct netdev_name_node *netdev_name_node_lookup_rcu(struct net *net, | |
| 281 | + const char *name) | |
| 282 | +{ | |
| 283 | + struct hlist_head *head = dev_name_hash(net, name); | |
| 284 | + struct netdev_name_node *name_node; | |
| 285 | + | |
| 286 | + hlist_for_each_entry_rcu(name_node, head, hlist) | |
| 287 | + if (!strcmp(name_node->name, name)) | |
| 288 | + return name_node; | |
| 289 | + return NULL; | |
| 290 | +} | |
| 291 | + | |
| 231 | 292 | /* Device list insertion */ |
| 232 | 293 | static void list_netdevice(struct net_device *dev) |
| 233 | 294 | { |
| @@ -237,7 +298,7 @@ static void list_netdevice(struct net_device *dev) · 3 unmodified lines | ||
| 237 | 298 | |
| 238 | 299 | write_lock_bh(&dev_base_lock); |
| 239 | 300 | list_add_tail_rcu(&dev->dev_list, &net->dev_base_head); |
| 240 | − hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name)); | |
| 301 | + netdev_name_node_add(net, dev->name_node); | |
| 241 | 302 | hlist_add_head_rcu(&dev->index_hlist, |
| 242 | 303 | dev_index_hash(net, dev->ifindex)); |
| 243 | 304 | write_unlock_bh(&dev_base_lock); |
| @@ -255,7 +316,7 @@ static void unlist_netdevice(struct net_device *dev) · 11 unmodified lines | ||
| 255 | 316 | /* Unlink dev from the device chain */ |
| 256 | 317 | write_lock_bh(&dev_base_lock); |
| 257 | 318 | list_del_rcu(&dev->dev_list); |
| 258 | − hlist_del_rcu(&dev->name_hlist); | |
| 319 | + netdev_name_node_del(dev->name_node); | |
| 259 | 320 | hlist_del_rcu(&dev->index_hlist); |
| 260 | 321 | write_unlock_bh(&dev_base_lock); |
| 261 | 322 | |
| @@ -733,14 +794,10 @@ EXPORT_SYMBOL_GPL(dev_fill_metadata_dst); · 471 unmodified lines | ||
| 733 | 794 | |
| 734 | 795 | struct net_device *__dev_get_by_name(struct net *net, const char *name) |
| 735 | 796 | { |
| 736 | − struct net_device *dev; | |
| 737 | − struct hlist_head *head = dev_name_hash(net, name); | |
| 797 | + struct netdev_name_node *node_name; | |
| 738 | 798 | |
| 739 | − hlist_for_each_entry(dev, head, name_hlist) | |
| 740 | − if (!strncmp(dev->name, name, IFNAMSIZ)) | |
| 741 | − return dev; | |
| 742 | − | |
| 743 | − return NULL; | |
| 799 | + node_name = netdev_name_node_lookup(net, name); | |
| 800 | + return node_name ? node_name->dev : NULL; | |
| 744 | 801 | } |
| 745 | 802 | EXPORT_SYMBOL(__dev_get_by_name); |
| 746 | 803 | |
| @@ -758,14 +815,10 @@ EXPORT_SYMBOL(__dev_get_by_name); · 11 unmodified lines | ||
| 758 | 815 | |
| 759 | 816 | struct net_device *dev_get_by_name_rcu(struct net *net, const char *name) |
| 760 | 817 | { |
| 761 | − struct net_device *dev; | |
| 762 | − struct hlist_head *head = dev_name_hash(net, name); | |
| 763 | − | |
| 764 | − hlist_for_each_entry_rcu(dev, head, name_hlist) | |
| 765 | − if (!strncmp(dev->name, name, IFNAMSIZ)) | |
| 766 | − return dev; | |
| 818 | + struct netdev_name_node *node_name; | |
| 767 | 819 | |
| 768 | − return NULL; | |
| 820 | + node_name = netdev_name_node_lookup_rcu(net, name); | |
| 821 | + return node_name ? node_name->dev : NULL; | |
| 769 | 822 | } |
| 770 | 823 | EXPORT_SYMBOL(dev_get_by_name_rcu); |
| 771 | 824 | |
| @@ -1232,13 +1285,13 @@ rollback: · 460 unmodified lines | ||
| 1232 | 1285 | netdev_adjacent_rename_links(dev, oldname); |
| 1233 | 1286 | |
| 1234 | 1287 | write_lock_bh(&dev_base_lock); |
| 1235 | − hlist_del_rcu(&dev->name_hlist); | |
| 1288 | + netdev_name_node_del(dev->name_node); | |
| 1236 | 1289 | write_unlock_bh(&dev_base_lock); |
| 1237 | 1290 | |
| 1238 | 1291 | synchronize_rcu(); |
| 1239 | 1292 | |
| 1240 | 1293 | write_lock_bh(&dev_base_lock); |
| 1241 | − hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name)); | |
| 1294 | + netdev_name_node_add(net, dev->name_node); | |
| 1242 | 1295 | write_unlock_bh(&dev_base_lock); |
| 1243 | 1296 | |
| 1244 | 1297 | ret = call_netdevice_notifiers(NETDEV_CHANGENAME, dev); |
| @@ -8264,6 +8317,8 @@ static void rollback_registered_many(struct list_head *head) · 7019 unmodified lines | ||
| 8264 | 8317 | dev_uc_flush(dev); |
| 8265 | 8318 | dev_mc_flush(dev); |
| 8266 | 8319 | |
| 8320 | + netdev_name_node_free(dev->name_node); | |
| 8321 | + | |
| 8267 | 8322 | if (dev->netdev_ops->ndo_uninit) |
| 8268 | 8323 | dev->netdev_ops->ndo_uninit(dev); |
| 8269 | 8324 | |
| @@ -8706,6 +8761,10 @@ int register_netdevice(struct net_device *dev) · 436 unmodified lines | ||
| 8706 | 8761 | if (ret < 0) |
| 8707 | 8762 | goto out; |
| 8708 | 8763 | |
| 8764 | + dev->name_node = netdev_name_node_head_alloc(dev); | |
| 8765 | + if (!dev->name_node) | |
| 8766 | + goto out; | |
| 8767 | + | |
| 8709 | 8768 | /* Init, if this function is available */ |
| 8710 | 8769 | if (dev->netdev_ops->ndo_init) { |
| 8711 | 8770 | ret = dev->netdev_ops->ndo_init(dev); |
| @@ -8827,6 +8886,8 @@ out: · 115 unmodified lines | ||
| 8827 | 8886 | return ret; |
| 8828 | 8887 | |
| 8829 | 8888 | err_uninit: |
| 8889 | + if (dev->name_node) | |
| 8890 | + netdev_name_node_free(dev->name_node); | |
| 8830 | 8891 | if (dev->netdev_ops->ndo_uninit) |
| 8831 | 8892 | dev->netdev_ops->ndo_uninit(dev); |
| 8832 | 8893 | if (dev->priv_destructor) |