forked from mirrors/linux
		
	net: Introduce for_each_netdev_rcu() iterator
Adds RCU management to the list of netdevices. Convert some for_each_netdev() users to RCU version, if it can avoid read_lock-ing dev_base_lock Ie: read_lock(&dev_base_loack); for_each_netdev(net, dev) some_action(); read_unlock(&dev_base_lock); becomes : rcu_read_lock(); for_each_netdev_rcu(net, dev) some_action(); rcu_read_unlock(); Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									d0075634cf
								
							
						
					
					
						commit
						c6d14c8456
					
				
					 11 changed files with 68 additions and 77 deletions
				
			
		| 
						 | 
					@ -1081,6 +1081,8 @@ extern rwlock_t				dev_base_lock;		/* Device list lock */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define for_each_netdev(net, d)		\
 | 
					#define for_each_netdev(net, d)		\
 | 
				
			||||||
		list_for_each_entry(d, &(net)->dev_base_head, dev_list)
 | 
							list_for_each_entry(d, &(net)->dev_base_head, dev_list)
 | 
				
			||||||
 | 
					#define for_each_netdev_rcu(net, d)		\
 | 
				
			||||||
 | 
							list_for_each_entry_rcu(d, &(net)->dev_base_head, dev_list)
 | 
				
			||||||
#define for_each_netdev_safe(net, d, n)	\
 | 
					#define for_each_netdev_safe(net, d, n)	\
 | 
				
			||||||
		list_for_each_entry_safe(d, n, &(net)->dev_base_head, dev_list)
 | 
							list_for_each_entry_safe(d, n, &(net)->dev_base_head, dev_list)
 | 
				
			||||||
#define for_each_netdev_continue(net, d)		\
 | 
					#define for_each_netdev_continue(net, d)		\
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -175,7 +175,7 @@ static struct list_head ptype_all __read_mostly;	/* Taps */
 | 
				
			||||||
 * The @dev_base_head list is protected by @dev_base_lock and the rtnl
 | 
					 * The @dev_base_head list is protected by @dev_base_lock and the rtnl
 | 
				
			||||||
 * semaphore.
 | 
					 * semaphore.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Pure readers hold dev_base_lock for reading.
 | 
					 * Pure readers hold dev_base_lock for reading, or rcu_read_lock()
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Writers must hold the rtnl semaphore while they loop through the
 | 
					 * 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
 | 
					 * dev_base_head list, and hold dev_base_lock for writing when they do the
 | 
				
			||||||
| 
						 | 
					@ -212,7 +212,7 @@ static int list_netdevice(struct net_device *dev)
 | 
				
			||||||
	ASSERT_RTNL();
 | 
						ASSERT_RTNL();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	write_lock_bh(&dev_base_lock);
 | 
						write_lock_bh(&dev_base_lock);
 | 
				
			||||||
	list_add_tail(&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));
 | 
						hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name));
 | 
				
			||||||
	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));
 | 
				
			||||||
| 
						 | 
					@ -229,7 +229,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(&dev->dev_list);
 | 
						list_del_rcu(&dev->dev_list);
 | 
				
			||||||
	hlist_del_rcu(&dev->name_hlist);
 | 
						hlist_del_rcu(&dev->name_hlist);
 | 
				
			||||||
	hlist_del_rcu(&dev->index_hlist);
 | 
						hlist_del_rcu(&dev->index_hlist);
 | 
				
			||||||
	write_unlock_bh(&dev_base_lock);
 | 
						write_unlock_bh(&dev_base_lock);
 | 
				
			||||||
| 
						 | 
					@ -799,15 +799,15 @@ struct net_device *dev_get_by_flags(struct net *net, unsigned short if_flags,
 | 
				
			||||||
	struct net_device *dev, *ret;
 | 
						struct net_device *dev, *ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = NULL;
 | 
						ret = NULL;
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
						rcu_read_lock();
 | 
				
			||||||
	for_each_netdev(net, dev) {
 | 
						for_each_netdev_rcu(net, dev) {
 | 
				
			||||||
		if (((dev->flags ^ if_flags) & mask) == 0) {
 | 
							if (((dev->flags ^ if_flags) & mask) == 0) {
 | 
				
			||||||
			dev_hold(dev);
 | 
								dev_hold(dev);
 | 
				
			||||||
			ret = dev;
 | 
								ret = dev;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
						rcu_read_unlock();
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(dev_get_by_flags);
 | 
					EXPORT_SYMBOL(dev_get_by_flags);
 | 
				
			||||||
| 
						 | 
					@ -3077,18 +3077,18 @@ static int dev_ifconf(struct net *net, char __user *arg)
 | 
				
			||||||
 *	in detail.
 | 
					 *	in detail.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void *dev_seq_start(struct seq_file *seq, loff_t *pos)
 | 
					void *dev_seq_start(struct seq_file *seq, loff_t *pos)
 | 
				
			||||||
	__acquires(dev_base_lock)
 | 
						__acquires(RCU)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net *net = seq_file_net(seq);
 | 
						struct net *net = seq_file_net(seq);
 | 
				
			||||||
	loff_t off;
 | 
						loff_t off;
 | 
				
			||||||
	struct net_device *dev;
 | 
						struct net_device *dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
						rcu_read_lock();
 | 
				
			||||||
	if (!*pos)
 | 
						if (!*pos)
 | 
				
			||||||
		return SEQ_START_TOKEN;
 | 
							return SEQ_START_TOKEN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	off = 1;
 | 
						off = 1;
 | 
				
			||||||
	for_each_netdev(net, dev)
 | 
						for_each_netdev_rcu(net, dev)
 | 
				
			||||||
		if (off++ == *pos)
 | 
							if (off++ == *pos)
 | 
				
			||||||
			return dev;
 | 
								return dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3097,16 +3097,18 @@ void *dev_seq_start(struct seq_file *seq, loff_t *pos)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 | 
					void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net *net = seq_file_net(seq);
 | 
						struct net_device *dev = (v == SEQ_START_TOKEN) ?
 | 
				
			||||||
 | 
									  first_net_device(seq_file_net(seq)) :
 | 
				
			||||||
 | 
									  next_net_device((struct net_device *)v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	++*pos;
 | 
						++*pos;
 | 
				
			||||||
	return v == SEQ_START_TOKEN ?
 | 
						return rcu_dereference(dev);
 | 
				
			||||||
		first_net_device(net) : next_net_device((struct net_device *)v);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void dev_seq_stop(struct seq_file *seq, void *v)
 | 
					void dev_seq_stop(struct seq_file *seq, void *v)
 | 
				
			||||||
	__releases(dev_base_lock)
 | 
						__releases(RCU)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
						rcu_read_unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev)
 | 
					static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -749,9 +749,9 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!(saddr->sdn_flags & SDF_WILD)) {
 | 
						if (!(saddr->sdn_flags & SDF_WILD)) {
 | 
				
			||||||
		if (le16_to_cpu(saddr->sdn_nodeaddrl)) {
 | 
							if (le16_to_cpu(saddr->sdn_nodeaddrl)) {
 | 
				
			||||||
			read_lock(&dev_base_lock);
 | 
								rcu_read_lock();
 | 
				
			||||||
			ldev = NULL;
 | 
								ldev = NULL;
 | 
				
			||||||
			for_each_netdev(&init_net, dev) {
 | 
								for_each_netdev_rcu(&init_net, dev) {
 | 
				
			||||||
				if (!dev->dn_ptr)
 | 
									if (!dev->dn_ptr)
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
				if (dn_dev_islocal(dev, dn_saddr2dn(saddr))) {
 | 
									if (dn_dev_islocal(dev, dn_saddr2dn(saddr))) {
 | 
				
			||||||
| 
						 | 
					@ -759,7 +759,7 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			read_unlock(&dev_base_lock);
 | 
								rcu_read_unlock();
 | 
				
			||||||
			if (ldev == NULL)
 | 
								if (ldev == NULL)
 | 
				
			||||||
				return -EADDRNOTAVAIL;
 | 
									return -EADDRNOTAVAIL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -607,8 +607,8 @@ static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa)
 | 
				
			||||||
	ASSERT_RTNL();
 | 
						ASSERT_RTNL();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Scan device list */
 | 
						/* Scan device list */
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
						rcu_read_lock();
 | 
				
			||||||
	for_each_netdev(&init_net, dev) {
 | 
						for_each_netdev_rcu(&init_net, dev) {
 | 
				
			||||||
		dn_db = dev->dn_ptr;
 | 
							dn_db = dev->dn_ptr;
 | 
				
			||||||
		if (dn_db == NULL)
 | 
							if (dn_db == NULL)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
| 
						 | 
					@ -619,7 +619,7 @@ static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
						rcu_read_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (found_it == 0) {
 | 
						if (found_it == 0) {
 | 
				
			||||||
		fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa);
 | 
							fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -908,8 +908,8 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
 | 
				
			||||||
			dev_put(dev_out);
 | 
								dev_put(dev_out);
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		read_lock(&dev_base_lock);
 | 
							rcu_read_lock();
 | 
				
			||||||
		for_each_netdev(&init_net, dev) {
 | 
							for_each_netdev_rcu(&init_net, dev) {
 | 
				
			||||||
			if (!dev->dn_ptr)
 | 
								if (!dev->dn_ptr)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			if (!dn_dev_islocal(dev, oldflp->fld_src))
 | 
								if (!dn_dev_islocal(dev, oldflp->fld_src))
 | 
				
			||||||
| 
						 | 
					@ -922,7 +922,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
 | 
				
			||||||
			dev_out = dev;
 | 
								dev_out = dev;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		read_unlock(&dev_base_lock);
 | 
							rcu_read_unlock();
 | 
				
			||||||
		if (dev_out == NULL)
 | 
							if (dev_out == NULL)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		dev_hold(dev_out);
 | 
							dev_hold(dev_out);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -876,19 +876,16 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
 | 
				
			||||||
		if (!addr)
 | 
							if (!addr)
 | 
				
			||||||
			addr = ifa->ifa_local;
 | 
								addr = ifa->ifa_local;
 | 
				
			||||||
	} endfor_ifa(in_dev);
 | 
						} endfor_ifa(in_dev);
 | 
				
			||||||
no_in_dev:
 | 
					 | 
				
			||||||
	rcu_read_unlock();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					no_in_dev:
 | 
				
			||||||
	if (addr)
 | 
						if (addr)
 | 
				
			||||||
		goto out;
 | 
							goto out_unlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Not loopback addresses on loopback should be preferred
 | 
						/* Not loopback addresses on loopback should be preferred
 | 
				
			||||||
	   in this case. It is importnat that lo is the first interface
 | 
						   in this case. It is importnat that lo is the first interface
 | 
				
			||||||
	   in dev_base list.
 | 
						   in dev_base list.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
						for_each_netdev_rcu(net, dev) {
 | 
				
			||||||
	rcu_read_lock();
 | 
					 | 
				
			||||||
	for_each_netdev(net, dev) {
 | 
					 | 
				
			||||||
		if ((in_dev = __in_dev_get_rcu(dev)) == NULL)
 | 
							if ((in_dev = __in_dev_get_rcu(dev)) == NULL)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -896,12 +893,11 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
 | 
				
			||||||
			if (ifa->ifa_scope != RT_SCOPE_LINK &&
 | 
								if (ifa->ifa_scope != RT_SCOPE_LINK &&
 | 
				
			||||||
			    ifa->ifa_scope <= scope) {
 | 
								    ifa->ifa_scope <= scope) {
 | 
				
			||||||
				addr = ifa->ifa_local;
 | 
									addr = ifa->ifa_local;
 | 
				
			||||||
				goto out_unlock_both;
 | 
									goto out_unlock;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} endfor_ifa(in_dev);
 | 
							} endfor_ifa(in_dev);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
out_unlock_both:
 | 
					out_unlock:
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
					 | 
				
			||||||
	rcu_read_unlock();
 | 
						rcu_read_unlock();
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return addr;
 | 
						return addr;
 | 
				
			||||||
| 
						 | 
					@ -962,9 +958,8 @@ __be32 inet_confirm_addr(struct in_device *in_dev,
 | 
				
			||||||
		return confirm_addr_indev(in_dev, dst, local, scope);
 | 
							return confirm_addr_indev(in_dev, dst, local, scope);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	net = dev_net(in_dev->dev);
 | 
						net = dev_net(in_dev->dev);
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
					 | 
				
			||||||
	rcu_read_lock();
 | 
						rcu_read_lock();
 | 
				
			||||||
	for_each_netdev(net, dev) {
 | 
						for_each_netdev_rcu(net, dev) {
 | 
				
			||||||
		if ((in_dev = __in_dev_get_rcu(dev))) {
 | 
							if ((in_dev = __in_dev_get_rcu(dev))) {
 | 
				
			||||||
			addr = confirm_addr_indev(in_dev, dst, local, scope);
 | 
								addr = confirm_addr_indev(in_dev, dst, local, scope);
 | 
				
			||||||
			if (addr)
 | 
								if (addr)
 | 
				
			||||||
| 
						 | 
					@ -972,7 +967,6 @@ __be32 inet_confirm_addr(struct in_device *in_dev,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rcu_read_unlock();
 | 
						rcu_read_unlock();
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return addr;
 | 
						return addr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1240,18 +1234,18 @@ static void devinet_copy_dflt_conf(struct net *net, int i)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_device *dev;
 | 
						struct net_device *dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
						rcu_read_lock();
 | 
				
			||||||
	for_each_netdev(net, dev) {
 | 
						for_each_netdev_rcu(net, dev) {
 | 
				
			||||||
		struct in_device *in_dev;
 | 
							struct in_device *in_dev;
 | 
				
			||||||
		rcu_read_lock();
 | 
					
 | 
				
			||||||
		in_dev = __in_dev_get_rcu(dev);
 | 
							in_dev = __in_dev_get_rcu(dev);
 | 
				
			||||||
		if (in_dev && !test_bit(i, in_dev->cnf.state))
 | 
							if (in_dev && !test_bit(i, in_dev->cnf.state))
 | 
				
			||||||
			in_dev->cnf.data[i] = net->ipv4.devconf_dflt->data[i];
 | 
								in_dev->cnf.data[i] = net->ipv4.devconf_dflt->data[i];
 | 
				
			||||||
		rcu_read_unlock();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
						rcu_read_unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* called with RTNL locked */
 | 
				
			||||||
static void inet_forward_change(struct net *net)
 | 
					static void inet_forward_change(struct net *net)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_device *dev;
 | 
						struct net_device *dev;
 | 
				
			||||||
| 
						 | 
					@ -1260,7 +1254,6 @@ static void inet_forward_change(struct net *net)
 | 
				
			||||||
	IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on;
 | 
						IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on;
 | 
				
			||||||
	IPV4_DEVCONF_DFLT(net, FORWARDING) = on;
 | 
						IPV4_DEVCONF_DFLT(net, FORWARDING) = on;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
					 | 
				
			||||||
	for_each_netdev(net, dev) {
 | 
						for_each_netdev(net, dev) {
 | 
				
			||||||
		struct in_device *in_dev;
 | 
							struct in_device *in_dev;
 | 
				
			||||||
		if (on)
 | 
							if (on)
 | 
				
			||||||
| 
						 | 
					@ -1271,7 +1264,6 @@ static void inet_forward_change(struct net *net)
 | 
				
			||||||
			IN_DEV_CONF_SET(in_dev, FORWARDING, on);
 | 
								IN_DEV_CONF_SET(in_dev, FORWARDING, on);
 | 
				
			||||||
		rcu_read_unlock();
 | 
							rcu_read_unlock();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int devinet_conf_proc(ctl_table *ctl, int write,
 | 
					static int devinet_conf_proc(ctl_table *ctl, int write,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -481,9 +481,8 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
 | 
				
			||||||
	struct net_device *dev;
 | 
						struct net_device *dev;
 | 
				
			||||||
	struct inet6_dev *idev;
 | 
						struct inet6_dev *idev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
						rcu_read_lock();
 | 
				
			||||||
	for_each_netdev(net, dev) {
 | 
						for_each_netdev_rcu(net, dev) {
 | 
				
			||||||
		rcu_read_lock();
 | 
					 | 
				
			||||||
		idev = __in6_dev_get(dev);
 | 
							idev = __in6_dev_get(dev);
 | 
				
			||||||
		if (idev) {
 | 
							if (idev) {
 | 
				
			||||||
			int changed = (!idev->cnf.forwarding) ^ (!newf);
 | 
								int changed = (!idev->cnf.forwarding) ^ (!newf);
 | 
				
			||||||
| 
						 | 
					@ -491,9 +490,8 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
 | 
				
			||||||
			if (changed)
 | 
								if (changed)
 | 
				
			||||||
				dev_forward_change(idev);
 | 
									dev_forward_change(idev);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		rcu_read_unlock();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
						rcu_read_unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
 | 
					static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
 | 
				
			||||||
| 
						 | 
					@ -1137,10 +1135,9 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
 | 
				
			||||||
	hiscore->rule = -1;
 | 
						hiscore->rule = -1;
 | 
				
			||||||
	hiscore->ifa = NULL;
 | 
						hiscore->ifa = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
					 | 
				
			||||||
	rcu_read_lock();
 | 
						rcu_read_lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for_each_netdev(net, dev) {
 | 
						for_each_netdev_rcu(net, dev) {
 | 
				
			||||||
		struct inet6_dev *idev;
 | 
							struct inet6_dev *idev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Candidate Source Address (section 4)
 | 
							/* Candidate Source Address (section 4)
 | 
				
			||||||
| 
						 | 
					@ -1235,7 +1232,6 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
 | 
				
			||||||
		read_unlock_bh(&idev->lock);
 | 
							read_unlock_bh(&idev->lock);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rcu_read_unlock();
 | 
						rcu_read_unlock();
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!hiscore->ifa)
 | 
						if (!hiscore->ifa)
 | 
				
			||||||
		return -EADDRNOTAVAIL;
 | 
							return -EADDRNOTAVAIL;
 | 
				
			||||||
| 
						 | 
					@ -4052,9 +4048,8 @@ static void addrconf_disable_change(struct net *net, __s32 newf)
 | 
				
			||||||
	struct net_device *dev;
 | 
						struct net_device *dev;
 | 
				
			||||||
	struct inet6_dev *idev;
 | 
						struct inet6_dev *idev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
						rcu_read_lock();
 | 
				
			||||||
	for_each_netdev(net, dev) {
 | 
						for_each_netdev_rcu(net, dev) {
 | 
				
			||||||
		rcu_read_lock();
 | 
					 | 
				
			||||||
		idev = __in6_dev_get(dev);
 | 
							idev = __in6_dev_get(dev);
 | 
				
			||||||
		if (idev) {
 | 
							if (idev) {
 | 
				
			||||||
			int changed = (!idev->cnf.disable_ipv6) ^ (!newf);
 | 
								int changed = (!idev->cnf.disable_ipv6) ^ (!newf);
 | 
				
			||||||
| 
						 | 
					@ -4062,9 +4057,8 @@ static void addrconf_disable_change(struct net *net, __s32 newf)
 | 
				
			||||||
			if (changed)
 | 
								if (changed)
 | 
				
			||||||
				dev_disable_change(idev);
 | 
									dev_disable_change(idev);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		rcu_read_unlock();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
						rcu_read_unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old)
 | 
					static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -404,13 +404,13 @@ int ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dev)
 | 
						if (dev)
 | 
				
			||||||
		return ipv6_chk_acast_dev(dev, addr);
 | 
							return ipv6_chk_acast_dev(dev, addr);
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
						rcu_read_lock();
 | 
				
			||||||
	for_each_netdev(net, dev)
 | 
						for_each_netdev_rcu(net, dev)
 | 
				
			||||||
		if (ipv6_chk_acast_dev(dev, addr)) {
 | 
							if (ipv6_chk_acast_dev(dev, addr)) {
 | 
				
			||||||
			found = 1;
 | 
								found = 1;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
						rcu_read_unlock();
 | 
				
			||||||
	return found;
 | 
						return found;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -597,15 +597,15 @@ struct net_device *nr_dev_first(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_device *dev, *first = NULL;
 | 
						struct net_device *dev, *first = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
						rcu_read_lock();
 | 
				
			||||||
	for_each_netdev(&init_net, dev) {
 | 
						for_each_netdev_rcu(&init_net, dev) {
 | 
				
			||||||
		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM)
 | 
							if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM)
 | 
				
			||||||
			if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
 | 
								if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
 | 
				
			||||||
				first = dev;
 | 
									first = dev;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (first)
 | 
						if (first)
 | 
				
			||||||
		dev_hold(first);
 | 
							dev_hold(first);
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
						rcu_read_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return first;
 | 
						return first;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -617,16 +617,17 @@ struct net_device *nr_dev_get(ax25_address *addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_device *dev;
 | 
						struct net_device *dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
						rcu_read_lock();
 | 
				
			||||||
	for_each_netdev(&init_net, dev) {
 | 
						for_each_netdev_rcu(&init_net, dev) {
 | 
				
			||||||
		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) {
 | 
							if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM &&
 | 
				
			||||||
 | 
							    ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) {
 | 
				
			||||||
			dev_hold(dev);
 | 
								dev_hold(dev);
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dev = NULL;
 | 
						dev = NULL;
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
						rcu_read_unlock();
 | 
				
			||||||
	return dev;
 | 
						return dev;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -600,13 +600,13 @@ struct net_device *rose_dev_first(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_device *dev, *first = NULL;
 | 
						struct net_device *dev, *first = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
						rcu_read_lock();
 | 
				
			||||||
	for_each_netdev(&init_net, dev) {
 | 
						for_each_netdev_rcu(&init_net, dev) {
 | 
				
			||||||
		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE)
 | 
							if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE)
 | 
				
			||||||
			if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
 | 
								if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
 | 
				
			||||||
				first = dev;
 | 
									first = dev;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
						rcu_read_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return first;
 | 
						return first;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -618,8 +618,8 @@ struct net_device *rose_dev_get(rose_address *addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_device *dev;
 | 
						struct net_device *dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
						rcu_read_lock();
 | 
				
			||||||
	for_each_netdev(&init_net, dev) {
 | 
						for_each_netdev_rcu(&init_net, dev) {
 | 
				
			||||||
		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) {
 | 
							if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) {
 | 
				
			||||||
			dev_hold(dev);
 | 
								dev_hold(dev);
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
| 
						 | 
					@ -627,7 +627,7 @@ struct net_device *rose_dev_get(rose_address *addr)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dev = NULL;
 | 
						dev = NULL;
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
						rcu_read_unlock();
 | 
				
			||||||
	return dev;
 | 
						return dev;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -635,14 +635,14 @@ static int rose_dev_exists(rose_address *addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_device *dev;
 | 
						struct net_device *dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
						rcu_read_lock();
 | 
				
			||||||
	for_each_netdev(&init_net, dev) {
 | 
						for_each_netdev_rcu(&init_net, dev) {
 | 
				
			||||||
		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0)
 | 
							if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dev = NULL;
 | 
						dev = NULL;
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
						rcu_read_unlock();
 | 
				
			||||||
	return dev != NULL;
 | 
						return dev != NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -205,14 +205,14 @@ static void sctp_get_local_addr_list(void)
 | 
				
			||||||
	struct list_head *pos;
 | 
						struct list_head *pos;
 | 
				
			||||||
	struct sctp_af *af;
 | 
						struct sctp_af *af;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	read_lock(&dev_base_lock);
 | 
						rcu_read_lock();
 | 
				
			||||||
	for_each_netdev(&init_net, dev) {
 | 
						for_each_netdev_rcu(&init_net, dev) {
 | 
				
			||||||
		__list_for_each(pos, &sctp_address_families) {
 | 
							__list_for_each(pos, &sctp_address_families) {
 | 
				
			||||||
			af = list_entry(pos, struct sctp_af, list);
 | 
								af = list_entry(pos, struct sctp_af, list);
 | 
				
			||||||
			af->copy_addrlist(&sctp_local_addr_list, dev);
 | 
								af->copy_addrlist(&sctp_local_addr_list, dev);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	read_unlock(&dev_base_lock);
 | 
						rcu_read_unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Free the existing local addresses.  */
 | 
					/* Free the existing local addresses.  */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue