Message ID | 1517011843.3715.68.camel@gmail.com |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
Series | [net] ipv6: addrconf: break critical section in addrconf_verify_rtnl() | expand |
On Fri, Jan 26, 2018 at 04:10:43PM -0800, Eric Dumazet wrote: > From: Eric Dumazet <edumazet@google.com> > > Heiner reported a lockdep splat [1] > > This is caused by attempting GFP_KERNEL allocation while RCU lock is > held and BH blocked. > > We believe that addrconf_verify_rtnl() could run for a long period, > so instead of using GFP_ATOMIC here as Ido suggested, we should break > the critical section and restart it after the allocation. [...] > Fixes: f3d9832e56c4 ("ipv6: addrconf: cleanup locking in ipv6_add_addr") > Signed-off-by: Eric Dumazet <edumazet@google.com> > Reported-by: Heiner Kallweit <hkallweit1@gmail.com> Reviewed-by: Ido Schimmel <idosch@mellanox.com> Thanks!
From: Eric Dumazet <eric.dumazet@gmail.com> Date: Fri, 26 Jan 2018 16:10:43 -0800 > From: Eric Dumazet <edumazet@google.com> > > Heiner reported a lockdep splat [1] > > This is caused by attempting GFP_KERNEL allocation while RCU lock is > held and BH blocked. > > We believe that addrconf_verify_rtnl() could run for a long period, > so instead of using GFP_ATOMIC here as Ido suggested, we should break > the critical section and restart it after the allocation. > > > [1] ... > Fixes: f3d9832e56c4 ("ipv6: addrconf: cleanup locking in ipv6_add_addr") > Signed-off-by: Eric Dumazet <edumazet@google.com> > Reported-by: Heiner Kallweit <hkallweit1@gmail.com> Applied and queued up for v4.15 -stable, thanks.
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f49bd7897e95f15a381e4700660991f2d3c3fed4..10facd174210974ac82b2304211061b90714aac8 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4352,9 +4352,11 @@ static void addrconf_verify_rtnl(void) spin_lock(&ifpub->lock); ifpub->regen_count = 0; spin_unlock(&ifpub->lock); + rcu_read_unlock_bh(); ipv6_create_tempaddr(ifpub, ifp, true); in6_ifa_put(ifpub); in6_ifa_put(ifp); + rcu_read_lock_bh(); goto restart; } } else if (time_before(ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ, next))