net: sched: change type of reference and bind counters
authorVlad Buslov <vladbu@mellanox.com>
Thu, 5 Jul 2018 14:24:24 +0000 (17:24 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sun, 8 Jul 2018 03:42:28 +0000 (12:42 +0900)
Change type of action reference counter to refcount_t.

Change type of action bind counter to atomic_t.
This type is used to allow decrementing bind counter without testing
for 0 result.

Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
18 files changed:
include/net/act_api.h
net/sched/act_api.c
net/sched/act_bpf.c
net/sched/act_connmark.c
net/sched/act_csum.c
net/sched/act_gact.c
net/sched/act_ife.c
net/sched/act_ipt.c
net/sched/act_mirred.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_sample.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/act_skbmod.c
net/sched/act_tunnel_key.c
net/sched/act_vlan.c

index ffc3ef32177612a790b99e656a0689fd58aafa17..2759226527a22b391568046e57a5acd4ebe598de 100644 (file)
@@ -6,6 +6,7 @@
  * Public action API for classifiers/qdiscs
 */
 
+#include <linux/refcount.h>
 #include <net/sch_generic.h>
 #include <net/pkt_sched.h>
 #include <net/net_namespace.h>
@@ -26,8 +27,8 @@ struct tc_action {
        struct tcf_idrinfo              *idrinfo;
 
        u32                             tcfa_index;
-       int                             tcfa_refcnt;
-       int                             tcfa_bindcnt;
+       refcount_t                      tcfa_refcnt;
+       atomic_t                        tcfa_bindcnt;
        u32                             tcfa_capab;
        int                             tcfa_action;
        struct tcf_t                    tcfa_tm;
index 02670c7489e30fe8201572a0d7bb3b5b1ace245b..4f064ecab882bc43076bb3f844bd900986a13669 100644 (file)
@@ -105,14 +105,26 @@ int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
 
        ASSERT_RTNL();
 
+       /* Release with strict==1 and bind==0 is only called through act API
+        * interface (classifiers always bind). Only case when action with
+        * positive reference count and zero bind count can exist is when it was
+        * also created with act API (unbinding last classifier will destroy the
+        * action if it was created by classifier). So only case when bind count
+        * can be changed after initial check is when unbound action is
+        * destroyed by act API while classifier binds to action with same id
+        * concurrently. This result either creation of new action(same behavior
+        * as before), or reusing existing action if concurrent process
+        * increments reference count before action is deleted. Both scenarios
+        * are acceptable.
+        */
        if (p) {
                if (bind)
-                       p->tcfa_bindcnt--;
-               else if (strict && p->tcfa_bindcnt > 0)
+                       atomic_dec(&p->tcfa_bindcnt);
+               else if (strict && atomic_read(&p->tcfa_bindcnt) > 0)
                        return -EPERM;
 
-               p->tcfa_refcnt--;
-               if (p->tcfa_bindcnt <= 0 && p->tcfa_refcnt <= 0) {
+               if (atomic_read(&p->tcfa_bindcnt) <= 0 &&
+                   refcount_dec_and_test(&p->tcfa_refcnt)) {
                        if (p->ops->cleanup)
                                p->ops->cleanup(p);
                        tcf_idr_remove(p->idrinfo, p);
@@ -304,8 +316,8 @@ bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
 
        if (index && p) {
                if (bind)
-                       p->tcfa_bindcnt++;
-               p->tcfa_refcnt++;
+                       atomic_inc(&p->tcfa_bindcnt);
+               refcount_inc(&p->tcfa_refcnt);
                *a = p;
                return true;
        }
@@ -324,9 +336,9 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
 
        if (unlikely(!p))
                return -ENOMEM;
-       p->tcfa_refcnt = 1;
+       refcount_set(&p->tcfa_refcnt, 1);
        if (bind)
-               p->tcfa_bindcnt = 1;
+               atomic_set(&p->tcfa_bindcnt, 1);
 
        if (cpustats) {
                p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
@@ -782,7 +794,7 @@ static void cleanup_a(struct list_head *actions, int ovr)
                return;
 
        list_for_each_entry(a, actions, list)
-               a->tcfa_refcnt--;
+               refcount_dec(&a->tcfa_refcnt);
 }
 
 int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
@@ -810,7 +822,7 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
                act->order = i;
                sz += tcf_action_fill_size(act);
                if (ovr)
-                       act->tcfa_refcnt++;
+                       refcount_inc(&act->tcfa_refcnt);
                list_add_tail(&act->list, actions);
        }
 
index 18089c02e55719d9818842f8cd3b35fa6cf94497..15a2a53cbde17b47b631eb33027141c1c1e71c48 100644 (file)
@@ -141,8 +141,8 @@ static int tcf_bpf_dump(struct sk_buff *skb, struct tc_action *act,
        struct tcf_bpf *prog = to_bpf(act);
        struct tc_act_bpf opt = {
                .index   = prog->tcf_index,
-               .refcnt  = prog->tcf_refcnt - ref,
-               .bindcnt = prog->tcf_bindcnt - bind,
+               .refcnt  = refcount_read(&prog->tcf_refcnt) - ref,
+               .bindcnt = atomic_read(&prog->tcf_bindcnt) - bind,
                .action  = prog->tcf_action,
        };
        struct tcf_t tm;
index e4b880fa51fec90fa1a1d92c11f8a337637d3509..188865034f9a78d9e626ce90f1689b94e433cdb9 100644 (file)
@@ -154,8 +154,8 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
 
        struct tc_connmark opt = {
                .index   = ci->tcf_index,
-               .refcnt  = ci->tcf_refcnt - ref,
-               .bindcnt = ci->tcf_bindcnt - bind,
+               .refcnt  = refcount_read(&ci->tcf_refcnt) - ref,
+               .bindcnt = atomic_read(&ci->tcf_bindcnt) - bind,
                .action  = ci->tcf_action,
                .zone   = ci->zone,
        };
index 526a8e491626efb65fcda10d875e6f55ca2168e8..da865f7b390abc84c18e85ecf7475a936f89d593 100644 (file)
@@ -597,8 +597,8 @@ static int tcf_csum_dump(struct sk_buff *skb, struct tc_action *a, int bind,
        struct tcf_csum_params *params;
        struct tc_csum opt = {
                .index   = p->tcf_index,
-               .refcnt  = p->tcf_refcnt - ref,
-               .bindcnt = p->tcf_bindcnt - bind,
+               .refcnt  = refcount_read(&p->tcf_refcnt) - ref,
+               .bindcnt = atomic_read(&p->tcf_bindcnt) - bind,
        };
        struct tcf_t t;
 
index 4dc4f153cad80861d38f975f7f70b7ce433dbc80..ca83debd5a70095435a62a582deba2239c3e568e 100644 (file)
@@ -169,8 +169,8 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a,
        struct tcf_gact *gact = to_gact(a);
        struct tc_gact opt = {
                .index   = gact->tcf_index,
-               .refcnt  = gact->tcf_refcnt - ref,
-               .bindcnt = gact->tcf_bindcnt - bind,
+               .refcnt  = refcount_read(&gact->tcf_refcnt) - ref,
+               .bindcnt = atomic_read(&gact->tcf_bindcnt) - bind,
                .action  = gact->tcf_action,
        };
        struct tcf_t t;
index 20d7d36b2fc9b9d3af256f48795da6e387f7f781..3536a23f46b5f39c8440909c19e1757bae9390a5 100644 (file)
@@ -596,8 +596,8 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind,
        struct tcf_ife_params *p = rtnl_dereference(ife->params);
        struct tc_ife opt = {
                .index = ife->tcf_index,
-               .refcnt = ife->tcf_refcnt - ref,
-               .bindcnt = ife->tcf_bindcnt - bind,
+               .refcnt = refcount_read(&ife->tcf_refcnt) - ref,
+               .bindcnt = atomic_read(&ife->tcf_bindcnt) - bind,
                .action = ife->tcf_action,
                .flags = p->flags,
        };
index 14c312d7908f535cb4f43d8d0a73e4cbe445d362..7bce88dc11c907d3deb1612462a330f9916258eb 100644 (file)
@@ -280,8 +280,8 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind,
        if (unlikely(!t))
                goto nla_put_failure;
 
-       c.bindcnt = ipt->tcf_bindcnt - bind;
-       c.refcnt = ipt->tcf_refcnt - ref;
+       c.bindcnt = atomic_read(&ipt->tcf_bindcnt) - bind;
+       c.refcnt = refcount_read(&ipt->tcf_refcnt) - ref;
        strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name);
 
        if (nla_put(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t) ||
index fd34015331ab86c395a2e599546a51b64efb8625..82a8bdd67c47b3d4bf863ef0edcd4e9a905ca8f0 100644 (file)
@@ -250,8 +250,8 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind,
        struct tc_mirred opt = {
                .index   = m->tcf_index,
                .action  = m->tcf_action,
-               .refcnt  = m->tcf_refcnt - ref,
-               .bindcnt = m->tcf_bindcnt - bind,
+               .refcnt  = refcount_read(&m->tcf_refcnt) - ref,
+               .bindcnt = atomic_read(&m->tcf_bindcnt) - bind,
                .eaction = m->tcfm_eaction,
                .ifindex = dev ? dev->ifindex : 0,
        };
index 4b5848b6c25207ac74b0508259f9f3019020d3c9..457c2ae3de46e1fcd5b11fbbfe6723ddfc829084 100644 (file)
@@ -257,8 +257,8 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a,
 
                .index    = p->tcf_index,
                .action   = p->tcf_action,
-               .refcnt   = p->tcf_refcnt - ref,
-               .bindcnt  = p->tcf_bindcnt - bind,
+               .refcnt   = refcount_read(&p->tcf_refcnt) - ref,
+               .bindcnt  = atomic_read(&p->tcf_bindcnt) - bind,
        };
        struct tcf_t t;
 
index e43aef28fdacc115c9fa12a53f8705a511477124..889690e0ec39de0fb35d4237f40523f3edbc27a2 100644 (file)
@@ -409,8 +409,8 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
        opt->nkeys = p->tcfp_nkeys;
        opt->flags = p->tcfp_flags;
        opt->action = p->tcf_action;
-       opt->refcnt = p->tcf_refcnt - ref;
-       opt->bindcnt = p->tcf_bindcnt - bind;
+       opt->refcnt = refcount_read(&p->tcf_refcnt) - ref;
+       opt->bindcnt = atomic_read(&p->tcf_bindcnt) - bind;
 
        if (p->tcfp_keys_ex) {
                tcf_pedit_key_ex_dump(skb, p->tcfp_keys_ex, p->tcfp_nkeys);
index 4e72bc2a0dfb525df3cc4ac582f417ce5c537af3..a789b806096816851f865c744dbdd0e7571f62ea 100644 (file)
@@ -274,8 +274,8 @@ static int tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a,
                .action = police->tcf_action,
                .mtu = police->tcfp_mtu,
                .burst = PSCHED_NS2TICKS(police->tcfp_burst),
-               .refcnt = police->tcf_refcnt - ref,
-               .bindcnt = police->tcf_bindcnt - bind,
+               .refcnt = refcount_read(&police->tcf_refcnt) - ref,
+               .bindcnt = atomic_read(&police->tcf_bindcnt) - bind,
        };
        struct tcf_t t;
 
index 5db358497c9ee610c499c88d0dd6eff463ccd70d..4a46978db0924d47037f3084823d036088cdea71 100644 (file)
@@ -173,8 +173,8 @@ static int tcf_sample_dump(struct sk_buff *skb, struct tc_action *a,
        struct tc_sample opt = {
                .index      = s->tcf_index,
                .action     = s->tcf_action,
-               .refcnt     = s->tcf_refcnt - ref,
-               .bindcnt    = s->tcf_bindcnt - bind,
+               .refcnt     = refcount_read(&s->tcf_refcnt) - ref,
+               .bindcnt    = atomic_read(&s->tcf_bindcnt) - bind,
        };
        struct tcf_t t;
 
index 98c4afe7c15b29a99a3d18e06934e34f0732110d..c3a761097b01fa667e1f96297477971e912e1bc6 100644 (file)
@@ -145,8 +145,8 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
        struct tcf_defact *d = to_defact(a);
        struct tc_defact opt = {
                .index   = d->tcf_index,
-               .refcnt  = d->tcf_refcnt - ref,
-               .bindcnt = d->tcf_bindcnt - bind,
+               .refcnt  = refcount_read(&d->tcf_refcnt) - ref,
+               .bindcnt = atomic_read(&d->tcf_bindcnt) - bind,
                .action  = d->tcf_action,
        };
        struct tcf_t t;
index dfaf5d8028dda324ddfee2cc63a2fd03fd9c90ee..cfd20d3d2ca9c0da0780a5bd668667bd76d6d65e 100644 (file)
@@ -208,8 +208,8 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
        struct tcf_skbedit *d = to_skbedit(a);
        struct tc_skbedit opt = {
                .index   = d->tcf_index,
-               .refcnt  = d->tcf_refcnt - ref,
-               .bindcnt = d->tcf_bindcnt - bind,
+               .refcnt  = refcount_read(&d->tcf_refcnt) - ref,
+               .bindcnt = atomic_read(&d->tcf_bindcnt) - bind,
                .action  = d->tcf_action,
        };
        struct tcf_t t;
index ad050d7d4b46a2d45f85e15bb7e68d28915f1d54..ff90d720eda380decc324b4736dbd64fa0293c49 100644 (file)
@@ -205,8 +205,8 @@ static int tcf_skbmod_dump(struct sk_buff *skb, struct tc_action *a,
        struct tcf_skbmod_params  *p = rtnl_dereference(d->skbmod_p);
        struct tc_skbmod opt = {
                .index   = d->tcf_index,
-               .refcnt  = d->tcf_refcnt - ref,
-               .bindcnt = d->tcf_bindcnt - bind,
+               .refcnt  = refcount_read(&d->tcf_refcnt) - ref,
+               .bindcnt = atomic_read(&d->tcf_bindcnt) - bind,
                .action  = d->tcf_action,
        };
        struct tcf_t t;
index ea203e386a9252bca1a4050b6160438b06c5bc47..2354f07eba1574e58937ee06a0ed5de8ff6388c3 100644 (file)
@@ -474,8 +474,8 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a,
        struct tcf_tunnel_key_params *params;
        struct tc_tunnel_key opt = {
                .index    = t->tcf_index,
-               .refcnt   = t->tcf_refcnt - ref,
-               .bindcnt  = t->tcf_bindcnt - bind,
+               .refcnt   = refcount_read(&t->tcf_refcnt) - ref,
+               .bindcnt  = atomic_read(&t->tcf_bindcnt) - bind,
        };
        struct tcf_t tm;
 
index 1fb39e1f9d077beb4fdb440459f18116b561f334..799e3deb44ac43daa29d7f059c7b690a3e9cb762 100644 (file)
@@ -239,8 +239,8 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
        struct tcf_vlan_params *p = rtnl_dereference(v->vlan_p);
        struct tc_vlan opt = {
                .index    = v->tcf_index,
-               .refcnt   = v->tcf_refcnt - ref,
-               .bindcnt  = v->tcf_bindcnt - bind,
+               .refcnt   = refcount_read(&v->tcf_refcnt) - ref,
+               .bindcnt  = atomic_read(&v->tcf_bindcnt) - bind,
                .action   = v->tcf_action,
                .v_action = p->tcfv_action,
        };