aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2006-09-22 17:44:24 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 18:20:26 -0400
commit8814c4b533817df825485ff32ce6ac406c3a54d1 (patch)
treeb72cc3513e7dc4b60e98c7ddebe76bca188f88fc /net/ipv6/addrconf.c
parentfbea49e1e2404baa2d88ab47e2db89e49551b53b (diff)
[IPV6] ADDRCONF: Convert addrconf_lock to RCU.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c46
1 files changed, 24 insertions, 22 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 825a291d5aa5..c09ebb7bb98a 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -119,9 +119,6 @@ static int ipv6_count_addresses(struct inet6_dev *idev);
119static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE]; 119static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE];
120static DEFINE_RWLOCK(addrconf_hash_lock); 120static DEFINE_RWLOCK(addrconf_hash_lock);
121 121
122/* Protects inet6 devices */
123DEFINE_RWLOCK(addrconf_lock);
124
125static void addrconf_verify(unsigned long); 122static void addrconf_verify(unsigned long);
126 123
127static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0); 124static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0);
@@ -318,6 +315,12 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp,
318 315
319/* Nobody refers to this device, we may destroy it. */ 316/* Nobody refers to this device, we may destroy it. */
320 317
318static void in6_dev_finish_destroy_rcu(struct rcu_head *head)
319{
320 struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu);
321 kfree(idev);
322}
323
321void in6_dev_finish_destroy(struct inet6_dev *idev) 324void in6_dev_finish_destroy(struct inet6_dev *idev)
322{ 325{
323 struct net_device *dev = idev->dev; 326 struct net_device *dev = idev->dev;
@@ -332,7 +335,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
332 return; 335 return;
333 } 336 }
334 snmp6_free_dev(idev); 337 snmp6_free_dev(idev);
335 kfree(idev); 338 call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu);
336} 339}
337 340
338static struct inet6_dev * ipv6_add_dev(struct net_device *dev) 341static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
@@ -408,9 +411,8 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
408 if (netif_carrier_ok(dev)) 411 if (netif_carrier_ok(dev))
409 ndev->if_flags |= IF_READY; 412 ndev->if_flags |= IF_READY;
410 413
411 write_lock_bh(&addrconf_lock); 414 /* protected by rtnl_lock */
412 dev->ip6_ptr = ndev; 415 rcu_assign_pointer(dev->ip6_ptr, ndev);
413 write_unlock_bh(&addrconf_lock);
414 416
415 ipv6_mc_init_dev(ndev); 417 ipv6_mc_init_dev(ndev);
416 ndev->tstamp = jiffies; 418 ndev->tstamp = jiffies;
@@ -474,7 +476,7 @@ static void addrconf_forward_change(void)
474 476
475 read_lock(&dev_base_lock); 477 read_lock(&dev_base_lock);
476 for (dev=dev_base; dev; dev=dev->next) { 478 for (dev=dev_base; dev; dev=dev->next) {
477 read_lock(&addrconf_lock); 479 rcu_read_lock();
478 idev = __in6_dev_get(dev); 480 idev = __in6_dev_get(dev);
479 if (idev) { 481 if (idev) {
480 int changed = (!idev->cnf.forwarding) ^ (!ipv6_devconf.forwarding); 482 int changed = (!idev->cnf.forwarding) ^ (!ipv6_devconf.forwarding);
@@ -482,7 +484,7 @@ static void addrconf_forward_change(void)
482 if (changed) 484 if (changed)
483 dev_forward_change(idev); 485 dev_forward_change(idev);
484 } 486 }
485 read_unlock(&addrconf_lock); 487 rcu_read_unlock();
486 } 488 }
487 read_unlock(&dev_base_lock); 489 read_unlock(&dev_base_lock);
488} 490}
@@ -543,7 +545,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
543 int hash; 545 int hash;
544 int err = 0; 546 int err = 0;
545 547
546 read_lock_bh(&addrconf_lock); 548 rcu_read_lock_bh();
547 if (idev->dead) { 549 if (idev->dead) {
548 err = -ENODEV; /*XXX*/ 550 err = -ENODEV; /*XXX*/
549 goto out2; 551 goto out2;
@@ -612,7 +614,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
612 in6_ifa_hold(ifa); 614 in6_ifa_hold(ifa);
613 write_unlock(&idev->lock); 615 write_unlock(&idev->lock);
614out2: 616out2:
615 read_unlock_bh(&addrconf_lock); 617 rcu_read_unlock_bh();
616 618
617 if (likely(err == 0)) 619 if (likely(err == 0))
618 atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa); 620 atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
@@ -915,7 +917,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
915 memset(&hiscore, 0, sizeof(hiscore)); 917 memset(&hiscore, 0, sizeof(hiscore));
916 918
917 read_lock(&dev_base_lock); 919 read_lock(&dev_base_lock);
918 read_lock(&addrconf_lock); 920 rcu_read_lock();
919 921
920 for (dev = dev_base; dev; dev=dev->next) { 922 for (dev = dev_base; dev; dev=dev->next) {
921 struct inet6_dev *idev; 923 struct inet6_dev *idev;
@@ -1127,7 +1129,7 @@ record_it:
1127 } 1129 }
1128 read_unlock_bh(&idev->lock); 1130 read_unlock_bh(&idev->lock);
1129 } 1131 }
1130 read_unlock(&addrconf_lock); 1132 rcu_read_unlock();
1131 read_unlock(&dev_base_lock); 1133 read_unlock(&dev_base_lock);
1132 1134
1133 if (!ifa_result) 1135 if (!ifa_result)
@@ -1151,7 +1153,7 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr)
1151 struct inet6_dev *idev; 1153 struct inet6_dev *idev;
1152 int err = -EADDRNOTAVAIL; 1154 int err = -EADDRNOTAVAIL;
1153 1155
1154 read_lock(&addrconf_lock); 1156 rcu_read_lock();
1155 if ((idev = __in6_dev_get(dev)) != NULL) { 1157 if ((idev = __in6_dev_get(dev)) != NULL) {
1156 struct inet6_ifaddr *ifp; 1158 struct inet6_ifaddr *ifp;
1157 1159
@@ -1165,7 +1167,7 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr)
1165 } 1167 }
1166 read_unlock_bh(&idev->lock); 1168 read_unlock_bh(&idev->lock);
1167 } 1169 }
1168 read_unlock(&addrconf_lock); 1170 rcu_read_unlock();
1169 return err; 1171 return err;
1170} 1172}
1171 1173
@@ -1466,7 +1468,7 @@ static void ipv6_regen_rndid(unsigned long data)
1466 struct inet6_dev *idev = (struct inet6_dev *) data; 1468 struct inet6_dev *idev = (struct inet6_dev *) data;
1467 unsigned long expires; 1469 unsigned long expires;
1468 1470
1469 read_lock_bh(&addrconf_lock); 1471 rcu_read_lock_bh();
1470 write_lock_bh(&idev->lock); 1472 write_lock_bh(&idev->lock);
1471 1473
1472 if (idev->dead) 1474 if (idev->dead)
@@ -1490,7 +1492,7 @@ static void ipv6_regen_rndid(unsigned long data)
1490 1492
1491out: 1493out:
1492 write_unlock_bh(&idev->lock); 1494 write_unlock_bh(&idev->lock);
1493 read_unlock_bh(&addrconf_lock); 1495 rcu_read_unlock_bh();
1494 in6_dev_put(idev); 1496 in6_dev_put(idev);
1495} 1497}
1496 1498
@@ -2342,10 +2344,10 @@ static int addrconf_ifdown(struct net_device *dev, int how)
2342 Do not dev_put! 2344 Do not dev_put!
2343 */ 2345 */
2344 if (how == 1) { 2346 if (how == 1) {
2345 write_lock_bh(&addrconf_lock);
2346 dev->ip6_ptr = NULL;
2347 idev->dead = 1; 2347 idev->dead = 1;
2348 write_unlock_bh(&addrconf_lock); 2348
2349 /* protected by rtnl_lock */
2350 rcu_assign_pointer(dev->ip6_ptr, NULL);
2349 2351
2350 /* Step 1.5: remove snmp6 entry */ 2352 /* Step 1.5: remove snmp6 entry */
2351 snmp6_unregister_dev(idev); 2353 snmp6_unregister_dev(idev);
@@ -3573,10 +3575,10 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
3573 3575
3574static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) 3576static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
3575{ 3577{
3576 read_lock_bh(&addrconf_lock); 3578 rcu_read_lock_bh();
3577 if (likely(ifp->idev->dead == 0)) 3579 if (likely(ifp->idev->dead == 0))
3578 __ipv6_ifa_notify(event, ifp); 3580 __ipv6_ifa_notify(event, ifp);
3579 read_unlock_bh(&addrconf_lock); 3581 rcu_read_unlock_bh();
3580} 3582}
3581 3583
3582#ifdef CONFIG_SYSCTL 3584#ifdef CONFIG_SYSCTL