diff options
| -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. */ |
