Skip to content

Commit 9038c32

Browse files
edumazetkuba-moo
authored andcommitted
net: dst: add net device refcount tracking to dst_entry
We want to track all dev_hold()/dev_put() to ease leak hunting. Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 4dbd24f commit 9038c32

File tree

5 files changed

+29
-9
lines changed

5 files changed

+29
-9
lines changed

include/linux/netdevice.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3883,6 +3883,23 @@ static inline void dev_put_track(struct net_device *dev,
38833883
}
38843884
}
38853885

3886+
static inline void dev_replace_track(struct net_device *odev,
3887+
struct net_device *ndev,
3888+
netdevice_tracker *tracker,
3889+
gfp_t gfp)
3890+
{
3891+
#ifdef CONFIG_NET_DEV_REFCNT_TRACKER
3892+
if (odev)
3893+
ref_tracker_free(&odev->refcnt_tracker, tracker);
3894+
#endif
3895+
dev_hold(ndev);
3896+
dev_put(odev);
3897+
#ifdef CONFIG_NET_DEV_REFCNT_TRACKER
3898+
if (ndev)
3899+
ref_tracker_alloc(&ndev->refcnt_tracker, tracker, gfp);
3900+
#endif
3901+
}
3902+
38863903
/* Carrier loss detection, dial on demand. The functions netif_carrier_on
38873904
* and _off may be called from IRQ context, but it is caller
38883905
* who is responsible for serialization of these calls.

include/net/dst.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ struct dst_entry {
7777
#ifndef CONFIG_64BIT
7878
atomic_t __refcnt; /* 32-bit offset 64 */
7979
#endif
80+
netdevice_tracker dev_tracker;
8081
};
8182

8283
struct dst_metrics {

net/core/dst.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops,
4949
unsigned short flags)
5050
{
5151
dst->dev = dev;
52-
dev_hold(dev);
52+
dev_hold_track(dev, &dst->dev_tracker, GFP_ATOMIC);
5353
dst->ops = ops;
5454
dst_init_metrics(dst, dst_default_metrics.metrics, true);
5555
dst->expires = 0UL;
@@ -117,7 +117,7 @@ struct dst_entry *dst_destroy(struct dst_entry * dst)
117117

118118
if (dst->ops->destroy)
119119
dst->ops->destroy(dst);
120-
dev_put(dst->dev);
120+
dev_put_track(dst->dev, &dst->dev_tracker);
121121

122122
lwtstate_put(dst->lwtstate);
123123

@@ -159,8 +159,8 @@ void dst_dev_put(struct dst_entry *dst)
159159
dst->input = dst_discard;
160160
dst->output = dst_discard_out;
161161
dst->dev = blackhole_netdev;
162-
dev_hold(dst->dev);
163-
dev_put(dev);
162+
dev_replace_track(dev, blackhole_netdev, &dst->dev_tracker,
163+
GFP_ATOMIC);
164164
}
165165
EXPORT_SYMBOL(dst_dev_put);
166166

net/ipv4/route.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,8 +1531,9 @@ void rt_flush_dev(struct net_device *dev)
15311531
if (rt->dst.dev != dev)
15321532
continue;
15331533
rt->dst.dev = blackhole_netdev;
1534-
dev_hold(rt->dst.dev);
1535-
dev_put(dev);
1534+
dev_replace_track(dev, blackhole_netdev,
1535+
&rt->dst.dev_tracker,
1536+
GFP_ATOMIC);
15361537
}
15371538
spin_unlock_bh(&ul->lock);
15381539
}
@@ -2819,7 +2820,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
28192820
new->output = dst_discard_out;
28202821

28212822
new->dev = net->loopback_dev;
2822-
dev_hold(new->dev);
2823+
dev_hold_track(new->dev, &new->dev_tracker, GFP_ATOMIC);
28232824

28242825
rt->rt_is_input = ort->rt_is_input;
28252826
rt->rt_iif = ort->rt_iif;

net/ipv6/route.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,9 @@ static void rt6_uncached_list_flush_dev(struct net *net, struct net_device *dev)
182182

183183
if (rt_dev == dev) {
184184
rt->dst.dev = blackhole_netdev;
185-
dev_hold(rt->dst.dev);
186-
dev_put(rt_dev);
185+
dev_replace_track(rt_dev, blackhole_netdev,
186+
&rt->dst.dev_tracker,
187+
GFP_ATOMIC);
187188
}
188189
}
189190
spin_unlock_bh(&ul->lock);

0 commit comments

Comments
 (0)