summaryrefslogtreecommitdiff
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a9e53f5942fa..b0ef65eb9bd2 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2358,7 +2358,7 @@ regen:
/* <draft-ietf-6man-rfc4941bis-08.txt>, Section 3.3.1:
* check if generated address is not inappropriate:
*
- * - Reserved IPv6 Interface Identifers
+ * - Reserved IPv6 Interface Identifiers
* - XXX: already assigned to an address on the device
*/
@@ -4485,7 +4485,9 @@ restart:
age >= ifp->valid_lft) {
spin_unlock(&ifp->lock);
in6_ifa_hold(ifp);
+ rcu_read_unlock_bh();
ipv6_del_addr(ifp);
+ rcu_read_lock_bh();
goto restart;
} else if (ifp->prefered_lft == INFINITY_LIFE_TIME) {
spin_unlock(&ifp->lock);
@@ -5107,17 +5109,20 @@ next:
break;
}
case MULTICAST_ADDR:
+ read_unlock_bh(&idev->lock);
fillargs->event = RTM_GETMULTICAST;
/* multicast address */
- for (ifmca = idev->mc_list; ifmca;
- ifmca = ifmca->next, ip_idx++) {
+ for (ifmca = rcu_dereference(idev->mc_list);
+ ifmca;
+ ifmca = rcu_dereference(ifmca->next), ip_idx++) {
if (ip_idx < s_ip_idx)
continue;
err = inet6_fill_ifmcaddr(skb, ifmca, fillargs);
if (err < 0)
break;
}
+ read_lock_bh(&idev->lock);
break;
case ANYCAST_ADDR:
fillargs->event = RTM_GETANYCAST;
@@ -6113,10 +6118,8 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
{
- rcu_read_lock_bh();
if (likely(ifp->idev->dead == 0))
__ipv6_ifa_notify(event, ifp);
- rcu_read_unlock_bh();
}
#ifdef CONFIG_SYSCTL