diff options
Diffstat (limited to 'net/ipv4/devinet.c')
| -rw-r--r-- | net/ipv4/devinet.c | 11 | 
1 files changed, 6 insertions, 5 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index da14c49284f..dc94b0316b7 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -209,7 +209,7 @@ static void inetdev_destroy(struct in_device *in_dev)  		inet_free_ifa(ifa);  	} -	dev->ip_ptr = NULL; +	rcu_assign_pointer(dev->ip_ptr, NULL);  	devinet_sysctl_unregister(in_dev);  	neigh_parms_release(&arp_tbl, in_dev->arp_parms); @@ -403,6 +403,9 @@ static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)  	return inet_insert_ifa(ifa);  } +/* Caller must hold RCU or RTNL : + * We dont take a reference on found in_device + */  struct in_device *inetdev_by_index(struct net *net, int ifindex)  {  	struct net_device *dev; @@ -411,7 +414,7 @@ struct in_device *inetdev_by_index(struct net *net, int ifindex)  	rcu_read_lock();  	dev = dev_get_by_index_rcu(net, ifindex);  	if (dev) -		in_dev = in_dev_get(dev); +		in_dev = rcu_dereference_rtnl(dev->ip_ptr);  	rcu_read_unlock();  	return in_dev;  } @@ -453,8 +456,6 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg  		goto errout;  	} -	__in_dev_put(in_dev); -  	for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;  	     ifap = &ifa->ifa_next) {  		if (tb[IFA_LOCAL] && @@ -1059,7 +1060,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,  	switch (event) {  	case NETDEV_REGISTER:  		printk(KERN_DEBUG "inetdev_event: bug\n"); -		dev->ip_ptr = NULL; +		rcu_assign_pointer(dev->ip_ptr, NULL);  		break;  	case NETDEV_UP:  		if (!inetdev_valid_mtu(dev->mtu))  |