Hi John, Is it possible to try the attached patch? I am not sure if it actually fixes the issue. But I think it is worth a try. Also, could you get me all the ipv6 routes when you plug in the usb using "ip -6 route show"? (If you have multiple routing tables configured, could you dump them all?) Thanks a lot. Wei On Wed, Aug 9, 2017 at 6:36 PM, Wei Wang <weiwan@xxxxxxxxxx> wrote: > On Wed, Aug 9, 2017 at 6:26 PM, John Stultz <john.stultz@xxxxxxxxxx> wrote: >> On Wed, Aug 9, 2017 at 5:36 PM, Wei Wang <weiwan@xxxxxxxxxx> wrote: >>> On Wed, Aug 9, 2017 at 4:44 PM, John Stultz <john.stultz@xxxxxxxxxx> wrote: >>>> On Wed, Aug 9, 2017 at 4:34 PM, Cong Wang <xiyou.wangcong@xxxxxxxxx> wrote: >>>>> (Cc'ing Wei whose commit was blamed) >>>>> >>>>> On Mon, Aug 7, 2017 at 2:15 PM, John Stultz <john.stultz@xxxxxxxxxx> wrote: >>>>>> On Mon, Aug 7, 2017 at 2:05 PM, John Stultz <john.stultz@xxxxxxxxxx> wrote: >>>>>>> So, with recent testing with my HiKey board, I've been noticing some >>>>>>> quirky behavior with my USB eth adapter. >>>>>>> >>>>>>> Basically, pluging the usb eth adapter in and then removing it, when >>>>>>> plugging it back in I often find that its not detected, and the system >>>>>>> slowly spits out the following message over and over: >>>>>>> unregister_netdevice: waiting for eth0 to become free. Usage count = 1 >>>>>> >>>>>> The other bit is that after this starts printing, the board will no >>>>>> longer reboot (it hangs continuing to occasionally print the above >>>>>> message), and I have to manually reset the device. >>>>>> >>>>> >>>>> So this warning is not temporarily shown but lasts until a reboot, >>>>> right? If so it is a dst refcnt leak. >>>> >>>> Correct, once I get into the state it lasts until a reboot. >>>> >>>>> How reproducible is it for you? From my reading, it seems always >>>>> reproduced when you unplug and plug your usb eth interface? >>>>> Is there anything else involved? For example, network namespace. >>>> >>>> So with 4.13-rc3/4 I seem to trigger it easily, often with the first >>>> unplug of the USB eth adapter. >>>> >>>> But as I get back closer to 4.12, it seemingly becomes harder to >>>> trigger, but sometimes still happens. >>>> >>>> So far, I've not been able to trigger it with 4.12. >>>> >>>> I don't think network namespaces are involved? Though its out of my >>>> area, so AOSP may be using them these days. Is there a simple way to >>>> check? >>>> >>>> I'll also do another bisection to see if the bad point moves back any further. >> >> So I went through another bisection around and got 9514528d92d4 ipv6: >> call dst_dev_put() properly as the first bad commit again. >> >>> If you see the problem starts to happen on commit >>> 9514528d92d4cbe086499322370155ed69f5d06c, could you try reverting all >>> the following commits: >>> (from new to old) >>> 1eb04e7c9e63 net: reorder all the dst flags >>> a4c2fd7f7891 net: remove DST_NOCACHE flag >>> b2a9c0ed75a3 net: remove DST_NOGC flag >>> 5b7c9a8ff828 net: remove dst gc related code >>> db916649b5dd ipv6: get rid of icmp6 dst garbage collector >>> 587fea741134 ipv6: mark DST_NOGC and remove the operation of dst_free() >>> ad65a2f05695 ipv6: call dst_hold_safe() properly >>> 9514528d92d4 ipv6: call dst_dev_put() properly >> >> >> And reverting this set off of 4.13-rc4 seems to make the issue go away. >> >> Is there anything I can test to help narrow down the specific problem >> with that patchset? >> > > Thanks John for confirming. > Let me spend some time on the commits and I will let you know if I > have some debug image for you to try. > > Wei > > >> thanks >> -john
From 93f2836679c81915b110ff56617f9f5dae2e6927 Mon Sep 17 00:00:00 2001 From: Wei Wang <weiwan@xxxxxxxxxx> Date: Wed, 9 Aug 2017 22:27:36 -0700 Subject: [PATCH] ipv6: unregister netdev bug fix Change-Id: I30fa739989ac50fbc7f4cbc6a04130005589cc25 --- include/net/ip6_route.h | 1 + net/ipv6/addrconf.c | 10 +++++++--- net/ipv6/anycast.c | 3 ++- net/ipv6/route.c | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 907d39a42f6b..dec1424ce619 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -94,6 +94,7 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg); int ip6_route_add(struct fib6_config *cfg, struct netlink_ext_ack *extack); int ip6_ins_rt(struct rt6_info *); int ip6_del_rt(struct rt6_info *); +void rt6_uncached_list_add(struct rt6_info *rt); static inline int ip6_route_get_saddr(struct net *net, struct rt6_info *rt, const struct in6_addr *daddr, diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 3c46e9513a31..06a27addb93c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3079,7 +3079,8 @@ static void init_loopback(struct net_device *dev) /* Failure cases are ignored */ if (!IS_ERR(sp_rt)) { sp_ifa->rt = sp_rt; - ip6_ins_rt(sp_rt); + if (ip6_ins_rt(sp_rt)) + rt6_uncached_list_add(sp_rt); } } read_unlock_bh(&idev->lock); @@ -3711,6 +3712,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) rt = ifa->rt; ifa->rt = NULL; } else { + rt6_uncached_list_add(ifa->rt); state = ifa->state; ifa->state = INET6_IFADDR_STATE_DEAD; } @@ -3882,7 +3884,8 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp) * Frames right away */ if (ifp->flags & IFA_F_OPTIMISTIC) { - ip6_ins_rt(ifp->rt); + if (ip6_ins_rt(ifp->rt)) + rt6_uncached_list_add(ifp->rt); if (ipv6_use_optimistic_addr(idev)) { /* Because optimistic nodes can use this address, * notify listeners. If DAD fails, RTM_DELADDR is sent. @@ -5557,7 +5560,8 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) * to do it again */ if (!(ifp->rt->rt6i_node)) - ip6_ins_rt(ifp->rt); + if(ip6_ins_rt(ifp->rt)) + rt6_uncached_list_add(ifp->rt); if (ifp->idev->cnf.forwarding) addrconf_join_anycast(ifp); if (!ipv6_addr_any(&ifp->peer_addr)) diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 0bbab8a4b5d8..e21c2d6d9b95 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -283,7 +283,8 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr) aca_get(aca); write_unlock_bh(&idev->lock); - ip6_ins_rt(rt); + if (!ip6_ins_rt(rt)) + rt6_uncached_list_add(rt); addrconf_join_solict(idev->dev, &aca->aca_addr); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 4d30c96a819d..7a7299da4e09 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -124,7 +124,7 @@ struct uncached_list { static DEFINE_PER_CPU_ALIGNED(struct uncached_list, rt6_uncached_list); -static void rt6_uncached_list_add(struct rt6_info *rt) +void rt6_uncached_list_add(struct rt6_info *rt) { struct uncached_list *ul = raw_cpu_ptr(&rt6_uncached_list); -- 2.14.0.434.g98096fd7a8-goog