diff options
author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2006-09-22 17:44:24 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 18:20:26 -0400 |
commit | 8814c4b533817df825485ff32ce6ac406c3a54d1 (patch) | |
tree | b72cc3513e7dc4b60e98c7ddebe76bca188f88fc | |
parent | fbea49e1e2404baa2d88ab47e2db89e49551b53b (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>
-rw-r--r-- | include/net/addrconf.h | 10 | ||||
-rw-r--r-- | include/net/if_inet6.h | 1 | ||||
-rw-r--r-- | net/core/pktgen.c | 4 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 46 | ||||
-rw-r--r-- | net/ipv6/anycast.c | 4 | ||||
-rw-r--r-- | net/ipv6/ipv6_syms.c | 1 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 6 |
7 files changed, 36 insertions, 36 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 5fc8627435eb..aa2ed8f0a9dd 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h | |||
@@ -133,20 +133,18 @@ extern int unregister_inet6addr_notifier(struct notifier_block *nb); | |||
133 | static inline struct inet6_dev * | 133 | static inline struct inet6_dev * |
134 | __in6_dev_get(struct net_device *dev) | 134 | __in6_dev_get(struct net_device *dev) |
135 | { | 135 | { |
136 | return (struct inet6_dev *)dev->ip6_ptr; | 136 | return rcu_dereference(dev->ip6_ptr); |
137 | } | 137 | } |
138 | 138 | ||
139 | extern rwlock_t addrconf_lock; | ||
140 | |||
141 | static inline struct inet6_dev * | 139 | static inline struct inet6_dev * |
142 | in6_dev_get(struct net_device *dev) | 140 | in6_dev_get(struct net_device *dev) |
143 | { | 141 | { |
144 | struct inet6_dev *idev = NULL; | 142 | struct inet6_dev *idev = NULL; |
145 | read_lock(&addrconf_lock); | 143 | rcu_read_lock(); |
146 | idev = dev->ip6_ptr; | 144 | idev = __in6_dev_get(dev); |
147 | if (idev) | 145 | if (idev) |
148 | atomic_inc(&idev->refcnt); | 146 | atomic_inc(&idev->refcnt); |
149 | read_unlock(&addrconf_lock); | 147 | rcu_read_unlock(); |
150 | return idev; | 148 | return idev; |
151 | } | 149 | } |
152 | 150 | ||
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index e459e1a0ae4a..34489c13c119 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h | |||
@@ -189,6 +189,7 @@ struct inet6_dev | |||
189 | struct ipv6_devconf cnf; | 189 | struct ipv6_devconf cnf; |
190 | struct ipv6_devstat stats; | 190 | struct ipv6_devstat stats; |
191 | unsigned long tstamp; /* ipv6InterfaceTable update timestamp */ | 191 | unsigned long tstamp; /* ipv6InterfaceTable update timestamp */ |
192 | struct rcu_head rcu; | ||
192 | }; | 193 | }; |
193 | 194 | ||
194 | extern struct ipv6_devconf ipv6_devconf; | 195 | extern struct ipv6_devconf ipv6_devconf; |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 6a7320b39ed0..72145d4a2600 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -1786,7 +1786,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) | |||
1786 | * use ipv6_get_lladdr if/when it's get exported | 1786 | * use ipv6_get_lladdr if/when it's get exported |
1787 | */ | 1787 | */ |
1788 | 1788 | ||
1789 | read_lock(&addrconf_lock); | 1789 | rcu_read_lock(); |
1790 | if ((idev = __in6_dev_get(pkt_dev->odev)) != NULL) { | 1790 | if ((idev = __in6_dev_get(pkt_dev->odev)) != NULL) { |
1791 | struct inet6_ifaddr *ifp; | 1791 | struct inet6_ifaddr *ifp; |
1792 | 1792 | ||
@@ -1805,7 +1805,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) | |||
1805 | } | 1805 | } |
1806 | read_unlock_bh(&idev->lock); | 1806 | read_unlock_bh(&idev->lock); |
1807 | } | 1807 | } |
1808 | read_unlock(&addrconf_lock); | 1808 | rcu_read_unlock(); |
1809 | if (err) | 1809 | if (err) |
1810 | printk("pktgen: ERROR: IPv6 link address not availble.\n"); | 1810 | printk("pktgen: ERROR: IPv6 link address not availble.\n"); |
1811 | } | 1811 | } |
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); | |||
119 | static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE]; | 119 | static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE]; |
120 | static DEFINE_RWLOCK(addrconf_hash_lock); | 120 | static DEFINE_RWLOCK(addrconf_hash_lock); |
121 | 121 | ||
122 | /* Protects inet6 devices */ | ||
123 | DEFINE_RWLOCK(addrconf_lock); | ||
124 | |||
125 | static void addrconf_verify(unsigned long); | 122 | static void addrconf_verify(unsigned long); |
126 | 123 | ||
127 | static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0); | 124 | static 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 | ||
318 | static 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 | |||
321 | void in6_dev_finish_destroy(struct inet6_dev *idev) | 324 | void 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 | ||
338 | static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | 341 | static 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); |
614 | out2: | 616 | out2: |
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 | ||
1491 | out: | 1493 | out: |
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 | ||
3574 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | 3576 | static 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 |
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index b80fc502ca03..a9604764e015 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -56,7 +56,7 @@ ip6_onlink(struct in6_addr *addr, struct net_device *dev) | |||
56 | int onlink; | 56 | int onlink; |
57 | 57 | ||
58 | onlink = 0; | 58 | onlink = 0; |
59 | read_lock(&addrconf_lock); | 59 | rcu_read_lock(); |
60 | idev = __in6_dev_get(dev); | 60 | idev = __in6_dev_get(dev); |
61 | if (idev) { | 61 | if (idev) { |
62 | read_lock_bh(&idev->lock); | 62 | read_lock_bh(&idev->lock); |
@@ -68,7 +68,7 @@ ip6_onlink(struct in6_addr *addr, struct net_device *dev) | |||
68 | } | 68 | } |
69 | read_unlock_bh(&idev->lock); | 69 | read_unlock_bh(&idev->lock); |
70 | } | 70 | } |
71 | read_unlock(&addrconf_lock); | 71 | rcu_read_unlock(); |
72 | return onlink; | 72 | return onlink; |
73 | } | 73 | } |
74 | 74 | ||
diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c index 7b7b90d9c3d0..0e8e0676a033 100644 --- a/net/ipv6/ipv6_syms.c +++ b/net/ipv6/ipv6_syms.c | |||
@@ -14,7 +14,6 @@ EXPORT_SYMBOL(ndisc_mc_map); | |||
14 | EXPORT_SYMBOL(register_inet6addr_notifier); | 14 | EXPORT_SYMBOL(register_inet6addr_notifier); |
15 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | 15 | EXPORT_SYMBOL(unregister_inet6addr_notifier); |
16 | EXPORT_SYMBOL(ip6_route_output); | 16 | EXPORT_SYMBOL(ip6_route_output); |
17 | EXPORT_SYMBOL(addrconf_lock); | ||
18 | EXPORT_SYMBOL(ipv6_setsockopt); | 17 | EXPORT_SYMBOL(ipv6_setsockopt); |
19 | EXPORT_SYMBOL(ipv6_getsockopt); | 18 | EXPORT_SYMBOL(ipv6_getsockopt); |
20 | EXPORT_SYMBOL(inet6_register_protosw); | 19 | EXPORT_SYMBOL(inet6_register_protosw); |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index fd87e3ceb56e..249e5033c1a8 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -321,9 +321,9 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, | |||
321 | struct inet6_ifaddr *ifp; | 321 | struct inet6_ifaddr *ifp; |
322 | struct sctp_sockaddr_entry *addr; | 322 | struct sctp_sockaddr_entry *addr; |
323 | 323 | ||
324 | read_lock(&addrconf_lock); | 324 | rcu_read_lock(); |
325 | if ((in6_dev = __in6_dev_get(dev)) == NULL) { | 325 | if ((in6_dev = __in6_dev_get(dev)) == NULL) { |
326 | read_unlock(&addrconf_lock); | 326 | rcu_read_unlock(); |
327 | return; | 327 | return; |
328 | } | 328 | } |
329 | 329 | ||
@@ -342,7 +342,7 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, | |||
342 | } | 342 | } |
343 | 343 | ||
344 | read_unlock(&in6_dev->lock); | 344 | read_unlock(&in6_dev->lock); |
345 | read_unlock(&addrconf_lock); | 345 | rcu_read_unlock(); |
346 | } | 346 | } |
347 | 347 | ||
348 | /* Initialize a sockaddr_storage from in incoming skb. */ | 348 | /* Initialize a sockaddr_storage from in incoming skb. */ |