--- a/include/linux/device/class.h +++ b/include/linux/device/class.h @@ -49,6 +49,7 @@ struct fwnode_handle; */ struct class { const char *name; + struct module *owner; const struct attribute_group **class_groups; const struct attribute_group **dev_groups; --- a/include/linux/prandom.h +++ b/include/linux/prandom.h @@ -23,6 +23,12 @@ void prandom_seed_full_state(struct rnd_ #define prandom_init_once(pcpu_state) \ DO_ONCE(prandom_seed_full_state, (pcpu_state)) +/* Deprecated: use get_random_u32_below() instead. */ +static inline u32 prandom_u32_max(u32 ep_ro) +{ + return get_random_u32_below(ep_ro); +} + /* * Handle minimum values for seeds */ --- a/include/linux/u64_stats_sync.h +++ b/include/linux/u64_stats_sync.h @@ -214,4 +214,16 @@ static inline bool u64_stats_fetch_retry return __u64_stats_fetch_retry(syncp, start); } +/* Obsolete interfaces */ +static inline unsigned int u64_stats_fetch_begin_irq(const struct u64_stats_sync *syncp) +{ + return u64_stats_fetch_begin(syncp); +} + +static inline bool u64_stats_fetch_retry_irq(const struct u64_stats_sync *syncp, + unsigned int start) +{ + return u64_stats_fetch_retry(syncp, start); +} + #endif /* _LINUX_U64_STATS_SYNC_H */ --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3002,6 +3002,8 @@ int call_netdevice_notifiers(unsigned lo int call_netdevice_notifiers_info(unsigned long val, struct netdev_notifier_info *info); +extern rwlock_t dev_base_lock; /* Device list lock */ + #define for_each_netdev(net, d) \ list_for_each_entry(d, &(net)->dev_base_head, dev_list) #define for_each_netdev_reverse(net, d) \ --- a/net/core/dev.c +++ b/net/core/dev.c @@ -172,6 +172,28 @@ static int call_netdevice_notifiers_exta struct net_device *dev, struct netlink_ext_ack *extack); +/* + * The @dev_base_head list is protected by @dev_base_lock and the rtnl + * semaphore. + * + * Pure readers hold dev_base_lock for reading, or rcu_read_lock() + * + * Writers must hold the rtnl semaphore while they loop through the + * dev_base_head list, and hold dev_base_lock for writing when they do the + * actual updates. This allows pure readers to access the list even + * while a writer is preparing to update it. + * + * To put it another way, dev_base_lock is held for writing only to + * protect against pure readers; the rtnl semaphore provides the + * protection against other writers. + * + * See, for example usages, register_netdevice() and + * unregister_netdevice(), which must be called with the rtnl + * semaphore held. + */ +DEFINE_RWLOCK(dev_base_lock); +EXPORT_SYMBOL(dev_base_lock); + static DEFINE_MUTEX(ifalias_mutex); /* protects napi_hash addition/deletion and napi_gen_id */ @@ -403,10 +425,12 @@ static void list_netdevice(struct net_de ASSERT_RTNL(); + write_lock(&dev_base_lock); list_add_tail_rcu(&dev->dev_list, &net->dev_base_head); netdev_name_node_add(net, dev->name_node); hlist_add_head_rcu(&dev->index_hlist, dev_index_hash(net, dev->ifindex)); + write_unlock(&dev_base_lock); netdev_for_each_altname(dev, name_node) netdev_name_node_add(net, name_node); @@ -433,9 +457,11 @@ static void unlist_netdevice(struct net_ netdev_name_node_del(name_node); /* Unlink dev from the device chain */ + write_lock(&dev_base_lock); list_del_rcu(&dev->dev_list); netdev_name_node_del(dev->name_node); hlist_del_rcu(&dev->index_hlist); + write_unlock(&dev_base_lock); dev_base_seq_inc(dev_net(dev)); } @@ -788,9 +814,9 @@ struct napi_struct *netdev_napi_by_id(st * @net: the applicable net namespace * @name: name to find * - * Find an interface by name. Must be called under RTNL semaphore. - * If the name is found a pointer to the device is returned. - * If the name is not found then %NULL is returned. The + * Find an interface by name. Must be called under RTNL semaphore + * or @dev_base_lock. If the name is found a pointer to the device + * is returned. If the name is not found then %NULL is returned. The * reference counters are not incremented so the caller must be * careful with locks. */ @@ -871,7 +897,8 @@ EXPORT_SYMBOL(netdev_get_by_name); * Search for an interface by index. Returns %NULL if the device * is not found or a pointer to the device. The device has not * had its reference counter increased so the caller must be careful - * about locking. The caller must hold the RTNL semaphore. + * about locking. The caller must hold either the RTNL semaphore + * or @dev_base_lock. */ struct net_device *__dev_get_by_index(struct net *net, int ifindex) @@ -1322,11 +1349,15 @@ rollback: netdev_adjacent_rename_links(dev, oldname); + write_lock(&dev_base_lock); netdev_name_node_del(dev->name_node); + write_unlock(&dev_base_lock); synchronize_net(); + write_lock(&dev_base_lock); netdev_name_node_add(net, dev->name_node); + write_unlock(&dev_base_lock); ret = call_netdevice_notifiers(NETDEV_CHANGENAME, dev); ret = notifier_to_errno(ret);