net: sched: act_mirred: add net device refcount tracker

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Eric Dumazet
2021-12-06 17:30:39 -08:00
committed by Jakub Kicinski
parent e7c8ab8419
commit ada066b2e0
2 changed files with 11 additions and 8 deletions

View File

@@ -10,6 +10,7 @@ struct tcf_mirred {
int tcfm_eaction; int tcfm_eaction;
bool tcfm_mac_header_xmit; bool tcfm_mac_header_xmit;
struct net_device __rcu *tcfm_dev; struct net_device __rcu *tcfm_dev;
netdevice_tracker tcfm_dev_tracker;
struct list_head tcfm_list; struct list_head tcfm_list;
}; };
#define to_mirred(a) ((struct tcf_mirred *)a) #define to_mirred(a) ((struct tcf_mirred *)a)

View File

@@ -79,7 +79,7 @@ static void tcf_mirred_release(struct tc_action *a)
/* last reference to action, no need to lock */ /* last reference to action, no need to lock */
dev = rcu_dereference_protected(m->tcfm_dev, 1); dev = rcu_dereference_protected(m->tcfm_dev, 1);
dev_put(dev); dev_put_track(dev, &m->tcfm_dev_tracker);
} }
static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = { static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
@@ -101,7 +101,6 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
bool mac_header_xmit = false; bool mac_header_xmit = false;
struct tc_mirred *parm; struct tc_mirred *parm;
struct tcf_mirred *m; struct tcf_mirred *m;
struct net_device *dev;
bool exists = false; bool exists = false;
int ret, err; int ret, err;
u32 index; u32 index;
@@ -171,16 +170,19 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
spin_lock_bh(&m->tcf_lock); spin_lock_bh(&m->tcf_lock);
if (parm->ifindex) { if (parm->ifindex) {
dev = dev_get_by_index(net, parm->ifindex); struct net_device *odev, *ndev;
if (!dev) {
ndev = dev_get_by_index(net, parm->ifindex);
if (!ndev) {
spin_unlock_bh(&m->tcf_lock); spin_unlock_bh(&m->tcf_lock);
err = -ENODEV; err = -ENODEV;
goto put_chain; goto put_chain;
} }
mac_header_xmit = dev_is_mac_header_xmit(dev); mac_header_xmit = dev_is_mac_header_xmit(ndev);
dev = rcu_replace_pointer(m->tcfm_dev, dev, odev = rcu_replace_pointer(m->tcfm_dev, ndev,
lockdep_is_held(&m->tcf_lock)); lockdep_is_held(&m->tcf_lock));
dev_put(dev); dev_put_track(odev, &m->tcfm_dev_tracker);
netdev_tracker_alloc(ndev, &m->tcfm_dev_tracker, GFP_ATOMIC);
m->tcfm_mac_header_xmit = mac_header_xmit; m->tcfm_mac_header_xmit = mac_header_xmit;
} }
goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
@@ -400,7 +402,7 @@ static int mirred_device_event(struct notifier_block *unused,
list_for_each_entry(m, &mirred_list, tcfm_list) { list_for_each_entry(m, &mirred_list, tcfm_list) {
spin_lock_bh(&m->tcf_lock); spin_lock_bh(&m->tcf_lock);
if (tcf_mirred_dev_dereference(m) == dev) { if (tcf_mirred_dev_dereference(m) == dev) {
dev_put(dev); dev_put_track(dev, &m->tcfm_dev_tracker);
/* Note : no rcu grace period necessary, as /* Note : no rcu grace period necessary, as
* net_device are already rcu protected. * net_device are already rcu protected.
*/ */