[PATCH v2 2/2] net: add trace events for net_device refcnt
From: Tony Lu <tonylu@linux.alibaba.com>
Date: 2019-11-12 13:08:10
Also in:
lkml
Subsystem:
networking [general], the rest, tracing · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds, Steven Rostedt, Masami Hiramatsu
The net_device refcnt leak is hard to trace and debug for now. We need the ability to know when and who manipulated the refcnt. Adding the trace events for net_device pcpu_refcnt and also tracepoints in dev_put()/dev_hold(), provides the history of net_device refcnt inc and desc. With trace logs analysis, paring the put and hold history, we can find out who leaked. Signed-off-by: Dust Li <dust.li@linux.alibaba.com> Signed-off-by: Tony Lu <tonylu@linux.alibaba.com> --- include/trace/events/net.h | 41 ++++++++++++++++++++++++++++++++++++++ net/core/dev.c | 4 ++++ 2 files changed, 45 insertions(+)
diff --git a/include/trace/events/net.h b/include/trace/events/net.h
index 3b28843652d2..3bf6dd738882 100644
--- a/include/trace/events/net.h
+++ b/include/trace/events/net.h@@ -326,6 +326,47 @@ DEFINE_EVENT(net_dev_rx_exit_template, netif_receive_skb_list_exit, TP_ARGS(ret) ); +DECLARE_EVENT_CLASS(net_dev_refcnt_template, + + TP_PROTO(struct net_device *dev, void *location), + + TP_ARGS(dev, location), + + TP_STRUCT__entry( + __string( name, dev->name ) + __field( int, refcnt ) + __field( void *, location ) + ), + + TP_fast_assign( + int i, refcnt = 0; + + for_each_possible_cpu(i) + refcnt += *per_cpu_ptr(dev->pcpu_refcnt, i); + + __assign_str(name, dev->name); + __entry->refcnt = refcnt; + __entry->location = location; + ), + + TP_printk("dev=%s refcnt=%d location=%p", + __get_str(name), __entry->refcnt, __entry->location) +); + +DEFINE_EVENT(net_dev_refcnt_template, net_dev_put, + + TP_PROTO(struct net_device *dev, void *location), + + TP_ARGS(dev, location) +); + +DEFINE_EVENT(net_dev_refcnt_template, net_dev_hold, + + TP_PROTO(struct net_device *dev, void *location), + + TP_ARGS(dev, location) +); + #endif /* _TRACE_NET_H */ /* This part must be outside protection */
diff --git a/net/core/dev.c b/net/core/dev.c
index 620fb3d6718a..163870a09984 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c@@ -1302,6 +1302,8 @@ EXPORT_SYMBOL(netdev_notify_peers); */ void dev_put(struct net_device *dev) { + trace_net_dev_put(dev, __builtin_return_address(0)); + this_cpu_dec(*dev->pcpu_refcnt); } EXPORT_SYMBOL(dev_put);
@@ -1314,6 +1316,8 @@ EXPORT_SYMBOL(dev_put); */ void dev_hold(struct net_device *dev) { + trace_net_dev_hold(dev, __builtin_return_address(0)); + this_cpu_inc(*dev->pcpu_refcnt); } EXPORT_SYMBOL(dev_hold);
--
2.24.0