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 da14c49284f4..dc94b0316b78 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -209,7 +209,7 @@ static void inetdev_destroy(struct in_device *in_dev) | |||
209 | inet_free_ifa(ifa); | 209 | inet_free_ifa(ifa); |
210 | } | 210 | } |
211 | 211 | ||
212 | dev->ip_ptr = NULL; | 212 | rcu_assign_pointer(dev->ip_ptr, NULL); |
213 | 213 | ||
214 | devinet_sysctl_unregister(in_dev); | 214 | devinet_sysctl_unregister(in_dev); |
215 | neigh_parms_release(&arp_tbl, in_dev->arp_parms); | 215 | 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) | |||
403 | return inet_insert_ifa(ifa); | 403 | return inet_insert_ifa(ifa); |
404 | } | 404 | } |
405 | 405 | ||
406 | /* Caller must hold RCU or RTNL : | ||
407 | * We dont take a reference on found in_device | ||
408 | */ | ||
406 | struct in_device *inetdev_by_index(struct net *net, int ifindex) | 409 | struct in_device *inetdev_by_index(struct net *net, int ifindex) |
407 | { | 410 | { |
408 | struct net_device *dev; | 411 | struct net_device *dev; |
@@ -411,7 +414,7 @@ struct in_device *inetdev_by_index(struct net *net, int ifindex) | |||
411 | rcu_read_lock(); | 414 | rcu_read_lock(); |
412 | dev = dev_get_by_index_rcu(net, ifindex); | 415 | dev = dev_get_by_index_rcu(net, ifindex); |
413 | if (dev) | 416 | if (dev) |
414 | in_dev = in_dev_get(dev); | 417 | in_dev = rcu_dereference_rtnl(dev->ip_ptr); |
415 | rcu_read_unlock(); | 418 | rcu_read_unlock(); |
416 | return in_dev; | 419 | return in_dev; |
417 | } | 420 | } |
@@ -453,8 +456,6 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg | |||
453 | goto errout; | 456 | goto errout; |
454 | } | 457 | } |
455 | 458 | ||
456 | __in_dev_put(in_dev); | ||
457 | |||
458 | for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; | 459 | for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; |
459 | ifap = &ifa->ifa_next) { | 460 | ifap = &ifa->ifa_next) { |
460 | if (tb[IFA_LOCAL] && | 461 | if (tb[IFA_LOCAL] && |
@@ -1059,7 +1060,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, | |||
1059 | switch (event) { | 1060 | switch (event) { |
1060 | case NETDEV_REGISTER: | 1061 | case NETDEV_REGISTER: |
1061 | printk(KERN_DEBUG "inetdev_event: bug\n"); | 1062 | printk(KERN_DEBUG "inetdev_event: bug\n"); |
1062 | dev->ip_ptr = NULL; | 1063 | rcu_assign_pointer(dev->ip_ptr, NULL); |
1063 | break; | 1064 | break; |
1064 | case NETDEV_UP: | 1065 | case NETDEV_UP: |
1065 | if (!inetdev_valid_mtu(dev->mtu)) | 1066 | if (!inetdev_valid_mtu(dev->mtu)) |