On 9/8/16 6:35 PM, Jojy Varghese wrote: > Thanks for the feedback guys. I appreciate it. > > I am working with 4.4.3 kernel. I will try to reproduce the issue > with the kernel tree at > https://git.kernel.org/cgit/linux/kernel/git/davem/net.git. > > In the meantime, the only data I have now is : > - "dst-ifdown" does not look correct since it will never release > reference to loopback device. > - One way to fix might be to assign the 'dst''s net device to the > init net device. I thought adding reference to init net device's > loopback might be safe. > > Any suggestion on debugging further is much appreciated. >
Last 2 times I chased down netdev refcnts I used the attach patch. It adds tracepoints to dev_hold and dev_put. perf record -e net:dev_hold,net:dev_put -a -g -- <run your test> You probably will need to increase memory for perf buffers (e.g., -m 8192). It will dump a lot of data but you will find the missing put; you just have to be patient wading through the data and matching up hold and put references. python/perl script with perf script can make that easier. --- Have you looked at whether there are open sockets? e.g., perhaps a dst reference is cached on a socket
From 068b1b8362ec5fd1b9dffdbd6e84474ada2eb829 Mon Sep 17 00:00:00 2001 From: David Ahern <d...@cumulusnetworks.com> Date: Thu, 11 Feb 2016 02:40:12 -0800 Subject: [PATCH] Add tracepoints to dev_hold and dev_put Signed-off-by: David Ahern <d...@cumulusnetworks.com> --- include/linux/netdevice.h | 6 ++++++ include/trace/events/net.h | 38 ++++++++++++++++++++++++++++++++++++++ net/core/dev.c | 21 +++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 219f53c30cb3..7ef6fc672dfb 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3193,6 +3193,7 @@ extern int netdev_budget; /* Called by rtnetlink.c:rtnl_unlock() */ void netdev_run_todo(void); +#if 0 /** * dev_put - release reference to device * @dev: network device @@ -3214,6 +3215,11 @@ static inline void dev_hold(struct net_device *dev) { this_cpu_inc(*dev->pcpu_refcnt); } +#else +void dev_put(struct net_device *dev); +void dev_hold(struct net_device *dev); + +#endif /* Carrier loss detection, dial on demand. The functions netif_carrier_on * and _off may be called from IRQ context, but it is caller diff --git a/include/trace/events/net.h b/include/trace/events/net.h index 49cc7c3de252..9ed73dfe9d09 100644 --- a/include/trace/events/net.h +++ b/include/trace/events/net.h @@ -236,6 +236,44 @@ DEFINE_EVENT(net_dev_rx_verbose_template, netif_rx_ni_entry, TP_ARGS(skb) ); +TRACE_EVENT(dev_put, + + TP_PROTO(struct net_device *dev), + + TP_ARGS(dev), + + TP_STRUCT__entry( + __string( name, dev->name ) + __field( int, refcnt ) + ), + + TP_fast_assign( + __assign_str(name, dev->name); + __entry->refcnt = netdev_refcnt_read(dev); + ), + + TP_printk("dev=%s refcnt %d", __get_str(name), __entry->refcnt) +); + +TRACE_EVENT(dev_hold, + + TP_PROTO(struct net_device *dev), + + TP_ARGS(dev), + + TP_STRUCT__entry( + __string( name, dev->name ) + __field( int, refcnt ) + ), + + TP_fast_assign( + __assign_str(name, dev->name); + __entry->refcnt = netdev_refcnt_read(dev); + ), + + TP_printk("dev=%s refcnt %d", __get_str(name), __entry->refcnt) +); + #endif /* _TRACE_NET_H */ /* This part must be outside protection */ diff --git a/net/core/dev.c b/net/core/dev.c index f1284835b8c9..99ac067afd18 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -8117,3 +8117,24 @@ static int __init net_dev_init(void) } subsys_initcall(net_dev_init); + + +void dev_put(struct net_device *dev) +{ + this_cpu_dec(*dev->pcpu_refcnt); + trace_dev_put(dev); +} +EXPORT_SYMBOL(dev_put); + +/** + * dev_hold - get reference to device + * @dev: network device + * + * Hold reference to device to keep it from being freed. + */ +void dev_hold(struct net_device *dev) +{ + this_cpu_inc(*dev->pcpu_refcnt); + trace_dev_hold(dev); +} +EXPORT_SYMBOL(dev_hold); -- 2.1.4