Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5ed6399 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller
Browse files

[IPV4]: Replace __in_dev_get with __in_dev_get_rcu/rtnl



The following patch renames __in_dev_get() to __in_dev_get_rtnl() and
introduces __in_dev_get_rcu() to cover the second case.

1) RCU with refcnt should use in_dev_get().
2) RCU without refcnt should use __in_dev_get_rcu().
3) All others must hold RTNL and use __in_dev_get_rtnl().

There is one exception in net/ipv4/route.c which is in fact a pre-existing
race condition.  I've marked it as such so that we remember to fix it.

This patch is based on suggestions and prior work by Suzanne Wood and
Paul McKenney.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a5e7c210
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2776,7 +2776,7 @@ static u32 bond_glean_dev_ip(struct net_device *dev)
		return 0;

	rcu_read_lock();
	idev = __in_dev_get(dev);
	idev = __in_dev_get_rcu(dev);
	if (!idev)
		goto out;

+14 −9
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@
#include <linux/ioport.h>	/* request_region(), release_region() */
#include <linux/wanrouter.h>	/* WAN router definitions */
#include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
#include <linux/rcupdate.h>

#include <linux/in.h>
#include <asm/io.h>		/* phys_to_virt() */
@@ -1268,37 +1269,41 @@ unsigned long get_ip_address(struct net_device *dev, int option)
	
	struct in_ifaddr *ifaddr;
	struct in_device *in_dev;
	unsigned long addr = 0;

	if ((in_dev = __in_dev_get(dev)) == NULL){
		return 0;
	rcu_read_lock();
	if ((in_dev = __in_dev_get_rcu(dev)) == NULL){
		goto out;
	}

	if ((ifaddr = in_dev->ifa_list)== NULL ){
		return 0;
		goto out;
	}
	
	switch (option){

	case WAN_LOCAL_IP:
		return ifaddr->ifa_local;
		addr = ifaddr->ifa_local;
		break;
	
	case WAN_POINTOPOINT_IP:
		return ifaddr->ifa_address;
		addr = ifaddr->ifa_address;
		break;	

	case WAN_NETMASK_IP:
		return ifaddr->ifa_mask;
		addr = ifaddr->ifa_mask;
		break;

	case WAN_BROADCAST_IP:
		return ifaddr->ifa_broadcast;
		addr = ifaddr->ifa_broadcast;
		break;
	default:
		return 0;
		break;
	}

	return 0;
out:
	rcu_read_unlock();
	return addr;
}	

void add_gateway(sdla_t *card, struct net_device *dev)
+1 −1
Original line number Diff line number Diff line
@@ -769,7 +769,7 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb)
		u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */
#ifdef CONFIG_INET
		rcu_read_lock();
		if ((in_dev = __in_dev_get(dev)) != NULL)
		if ((in_dev = __in_dev_get_rcu(dev)) != NULL)
		{
			for (ifa=in_dev->ifa_list; ifa != NULL;
				ifa=ifa->ifa_next) {
+2 −2
Original line number Diff line number Diff line
@@ -1352,7 +1352,7 @@ static unsigned char *strip_make_packet(unsigned char *buffer,
		struct in_device *in_dev;

		rcu_read_lock();
		in_dev = __in_dev_get(strip_info->dev);
		in_dev = __in_dev_get_rcu(strip_info->dev);
		if (in_dev == NULL) {
			rcu_read_unlock();
			return NULL;
@@ -1508,7 +1508,7 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb)

		brd = addr = 0;
		rcu_read_lock();
		in_dev = __in_dev_get(strip_info->dev);
		in_dev = __in_dev_get_rcu(strip_info->dev);
		if (in_dev) {
			if (in_dev->ifa_list) {
				brd = in_dev->ifa_list->ifa_broadcast;
+4 −1
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include <linux/proc_fs.h>
#include <linux/ctype.h>
#include <linux/blkdev.h>
#include <linux/rcupdate.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/hardware.h>
@@ -358,9 +359,10 @@ static __inline__ int led_get_net_activity(void)
	/* we are running as tasklet, so locking dev_base 
	 * for reading should be OK */
	read_lock(&dev_base_lock);
	rcu_read_lock();
	for (dev = dev_base; dev; dev = dev->next) {
	    struct net_device_stats *stats;
	    struct in_device *in_dev = __in_dev_get(dev);
	    struct in_device *in_dev = __in_dev_get_rcu(dev);
	    if (!in_dev || !in_dev->ifa_list)
		continue;
	    if (LOOPBACK(in_dev->ifa_list->ifa_local))
@@ -371,6 +373,7 @@ static __inline__ int led_get_net_activity(void)
	    rx_total += stats->rx_packets;
	    tx_total += stats->tx_packets;
	}
	rcu_read_unlock();
	read_unlock(&dev_base_lock);

	retval = 0;
Loading