OSDN Git Service

net: sched: act_bpf: remove dependency on rtnl lock
authorVlad Buslov <vladbu@mellanox.com>
Fri, 10 Aug 2018 17:51:41 +0000 (20:51 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sat, 11 Aug 2018 19:37:09 +0000 (12:37 -0700)
Use tcf spinlock to protect bpf action private data from concurrent
modification during dump and init. Remove rtnl lock assertion that is no
longer necessary.

Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sched/act_bpf.c

index 6203eb0..9e8a33f 100644 (file)
@@ -143,11 +143,12 @@ static int tcf_bpf_dump(struct sk_buff *skb, struct tc_action *act,
                .index   = prog->tcf_index,
                .refcnt  = refcount_read(&prog->tcf_refcnt) - ref,
                .bindcnt = atomic_read(&prog->tcf_bindcnt) - bind,
-               .action  = prog->tcf_action,
        };
        struct tcf_t tm;
        int ret;
 
+       spin_lock(&prog->tcf_lock);
+       opt.action = prog->tcf_action;
        if (nla_put(skb, TCA_ACT_BPF_PARMS, sizeof(opt), &opt))
                goto nla_put_failure;
 
@@ -163,9 +164,11 @@ static int tcf_bpf_dump(struct sk_buff *skb, struct tc_action *act,
                          TCA_ACT_BPF_PAD))
                goto nla_put_failure;
 
+       spin_unlock(&prog->tcf_lock);
        return skb->len;
 
 nla_put_failure:
+       spin_unlock(&prog->tcf_lock);
        nlmsg_trim(skb, tp);
        return -1;
 }
@@ -264,7 +267,7 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog,
 {
        cfg->is_ebpf = tcf_bpf_is_ebpf(prog);
        /* updates to prog->filter are prevented, since it's called either
-        * with rtnl lock or during final cleanup in rcu callback
+        * with tcf lock or during final cleanup in rcu callback
         */
        cfg->filter = rcu_dereference_protected(prog->filter, 1);
 
@@ -336,8 +339,8 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
                goto out;
 
        prog = to_bpf(*act);
-       ASSERT_RTNL();
 
+       spin_lock(&prog->tcf_lock);
        if (res != ACT_P_CREATED)
                tcf_bpf_prog_fill_cfg(prog, &old);
 
@@ -349,6 +352,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
 
        prog->tcf_action = parm->action;
        rcu_assign_pointer(prog->filter, cfg.filter);
+       spin_unlock(&prog->tcf_lock);
 
        if (res == ACT_P_CREATED) {
                tcf_idr_insert(tn, *act);