From: Jiri Pirko <j...@mellanox.com>

Currently the actions are stored in array with array size. To traverse
this array in fastpath, tcf_tree_lock is taken to protect it. Convert
the array into a singly linked list, similar to the filter chains style
and allow traversal protected by rcu.

Signed-off-by: Jiri Pirko <j...@mellanox.com>
---
 include/net/act_api.h    | 11 +++++++---
 include/net/pkt_cls.h    | 46 ++++++++++++++++++-----------------------
 net/sched/act_api.c      | 16 ++++++++-------
 net/sched/cls_api.c      | 31 ++++++++++++----------------
 net/sched/cls_basic.c    | 10 +++------
 net/sched/cls_bpf.c      | 10 +++------
 net/sched/cls_cgroup.c   | 10 +++------
 net/sched/cls_flow.c     | 10 +++------
 net/sched/cls_flower.c   | 10 +++------
 net/sched/cls_fw.c       | 16 ++++-----------
 net/sched/cls_matchall.c | 11 +++-------
 net/sched/cls_route.c    | 10 +++------
 net/sched/cls_rsvp.h     | 18 +++++-----------
 net/sched/cls_tcindex.c  | 53 ++++++++++++++----------------------------------
 net/sched/cls_u32.c      | 15 ++++----------
 15 files changed, 99 insertions(+), 178 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 26ffd83..74e2657 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -21,6 +21,8 @@ struct tcf_hashinfo {
 struct tc_action_ops;
 
 struct tc_action {
+       /* Fast access part */
+       struct tc_action __rcu          *next;
        const struct tc_action_ops      *ops;
        __u32                           type; /* for backward 
compat(TCA_OLD_COMPAT) */
        __u32                           order;
@@ -179,15 +181,18 @@ int tcf_register_action(struct tc_action_ops *a, struct 
pernet_operations *ops);
 int tcf_unregister_action(struct tc_action_ops *a,
                          struct pernet_operations *ops);
 int tcf_action_destroy(struct list_head *actions, int bind);
-int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
-                   int nr_actions, struct tcf_result *res);
+
+struct tcf_exts;
+
+int tcf_action_exec(struct sk_buff *skb, struct tcf_exts *exts,
+                   struct tcf_result *res);
 int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
                    struct nlattr *est, char *name, int ovr, int bind,
                    struct list_head *actions);
 struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
                                    struct nlattr *nla, struct nlattr *est,
                                    char *name, int ovr, int bind);
-int tcf_action_dump(struct sk_buff *skb, struct list_head *, int, int);
+int tcf_action_dump(struct sk_buff *skb, struct list_head *actions, int, int);
 int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
 int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
 int tcf_action_copy_stats(struct sk_buff *, struct tc_action *, int);
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index b8959c9..8257a4e 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -88,8 +88,7 @@ tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r)
 struct tcf_exts {
 #ifdef CONFIG_NET_CLS_ACT
        __u32   type; /* for backward compat(TCA_OLD_COMPAT) */
-       int nr_actions;
-       struct tc_action **actions;
+       struct tc_action __rcu *action_list;
 #endif
        /* Map to export classifier specific extension TLV types to the
         * generic extensions API. Unsupported extensions must be set to 0.
@@ -98,32 +97,32 @@ struct tcf_exts {
        int police;
 };
 
-static inline int tcf_exts_init(struct tcf_exts *exts, int action, int police)
+#define tcf_exts_for_each(a, exts)                             \
+       for (a = rtnl_dereference(exts->action_list);           \
+            a; a = rtnl_dereference(a->next))
+
+#define tcf_exts_for_each_rcu_bh(a, exts)                      \
+       for (a = rcu_dereference_bh(exts->action_list);         \
+            a; a = rcu_dereference_bh(a->next))
+
+static inline void tcf_exts_init(struct tcf_exts *exts, int action, int police)
 {
 #ifdef CONFIG_NET_CLS_ACT
        exts->type = 0;
-       exts->nr_actions = 0;
-       exts->actions = kcalloc(TCA_ACT_MAX_PRIO, sizeof(struct tc_action *),
-                               GFP_KERNEL);
-       if (!exts->actions)
-               return -ENOMEM;
+       RCU_INIT_POINTER(exts->action_list, NULL);
 #endif
        exts->action = action;
        exts->police = police;
-       return 0;
 }
 
 static inline void tcf_exts_to_list(const struct tcf_exts *exts,
                                    struct list_head *actions)
 {
 #ifdef CONFIG_NET_CLS_ACT
-       int i;
-
-       for (i = 0; i < exts->nr_actions; i++) {
-               struct tc_action *a = exts->actions[i];
+       struct tc_action *a;
 
+       tcf_exts_for_each(a, exts)
                list_add_tail(&a->list, actions);
-       }
 #endif
 }
 
@@ -132,16 +131,11 @@ tcf_exts_stats_update(const struct tcf_exts *exts,
                      u64 bytes, u64 packets, u64 lastuse)
 {
 #ifdef CONFIG_NET_CLS_ACT
-       int i;
+       struct tc_action *a;
 
        preempt_disable();
-
-       for (i = 0; i < exts->nr_actions; i++) {
-               struct tc_action *a = exts->actions[i];
-
+       tcf_exts_for_each(a, exts)
                tcf_action_stats_update(a, bytes, packets, lastuse);
-       }
-
        preempt_enable();
 #endif
 }
@@ -155,7 +149,7 @@ tcf_exts_stats_update(const struct tcf_exts *exts,
 static inline bool tcf_exts_has_actions(struct tcf_exts *exts)
 {
 #ifdef CONFIG_NET_CLS_ACT
-       return exts->nr_actions;
+       return rtnl_dereference(exts->action_list);
 #else
        return false;
 #endif
@@ -170,7 +164,8 @@ static inline bool tcf_exts_has_actions(struct tcf_exts 
*exts)
 static inline bool tcf_exts_has_one_action(struct tcf_exts *exts)
 {
 #ifdef CONFIG_NET_CLS_ACT
-       return exts->nr_actions == 1;
+       return rtnl_dereference(exts->action_list) &&
+              !rtnl_dereference(exts->action_list->next);
 #else
        return false;
 #endif
@@ -192,7 +187,7 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
              struct tcf_result *res)
 {
 #ifdef CONFIG_NET_CLS_ACT
-       return tcf_action_exec(skb, exts->actions, exts->nr_actions, res);
+       return tcf_action_exec(skb, exts, res);
 #endif
        return TC_ACT_OK;
 }
@@ -201,8 +196,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
                      struct nlattr **tb, struct nlattr *rate_tlv,
                      struct tcf_exts *exts, bool ovr);
 void tcf_exts_destroy(struct tcf_exts *exts);
-void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
-                    struct tcf_exts *src);
+void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src);
 int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts);
 int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts);
 int tcf_exts_get_dev(struct net_device *dev, struct tcf_exts *exts,
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 8d2e506..177b9ab 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -457,21 +457,19 @@ static struct tc_action_ops *tc_lookup_action(struct 
nlattr *kind)
 
 /*TCA_ACT_MAX_PRIO is 32, there count upto 32 */
 #define TCA_ACT_MAX_PRIO_MASK 0x1FF
-int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
-                   int nr_actions, struct tcf_result *res)
+int tcf_action_exec(struct sk_buff *skb, struct tcf_exts *exts,
+                   struct tcf_result *res)
 {
        u32 jmp_prgcnt = 0;
        u32 jmp_ttl = TCA_ACT_MAX_PRIO; /*matches actions per filter */
-       int i;
+       struct tc_action *a;
        int ret = TC_ACT_OK;
 
        if (skb_skip_tc_classify(skb))
                return TC_ACT_OK;
 
 restart_act_graph:
-       for (i = 0; i < nr_actions; i++) {
-               const struct tc_action *a = actions[i];
-
+       tcf_exts_for_each_rcu_bh(a, exts) {
                if (jmp_prgcnt > 0) {
                        jmp_prgcnt -= 1;
                        continue;
@@ -483,7 +481,7 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action 
**actions,
 
                if (TC_ACT_EXT_CMP(ret, TC_ACT_JUMP)) {
                        jmp_prgcnt = ret & TCA_ACT_MAX_PRIO_MASK;
-                       if (!jmp_prgcnt || (jmp_prgcnt > nr_actions)) {
+                       if (!jmp_prgcnt) {
                                /* faulty opcode, stop pipeline */
                                return TC_ACT_OK;
                        } else {
@@ -501,6 +499,10 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action 
**actions,
                        break;
        }
 
+       if (jmp_prgcnt > 0)
+               /* faulty opcode, stop pipeline */
+               return TC_ACT_OK;
+
        return ret;
 }
 EXPORT_SYMBOL(tcf_action_exec);
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 735d556..129f314 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -836,8 +836,6 @@ void tcf_exts_destroy(struct tcf_exts *exts)
 
        tcf_exts_to_list(exts, &actions);
        tcf_action_destroy(&actions, TCA_ACT_UNBIND);
-       kfree(exts->actions);
-       exts->nr_actions = 0;
 #endif
 }
 EXPORT_SYMBOL(tcf_exts_destroy);
@@ -857,20 +855,22 @@ int tcf_exts_validate(struct net *net, struct tcf_proto 
*tp, struct nlattr **tb,
                                return PTR_ERR(act);
 
                        act->type = exts->type = TCA_OLD_COMPAT;
-                       exts->actions[0] = act;
-                       exts->nr_actions = 1;
+                       exts->action_list = act;
                } else if (exts->action && tb[exts->action]) {
+                       struct tc_action **pprev;
                        LIST_HEAD(actions);
-                       int err, i = 0;
+                       int err;
 
                        err = tcf_action_init(net, tp, tb[exts->action],
                                              rate_tlv, NULL, ovr, TCA_ACT_BIND,
                                              &actions);
                        if (err)
                                return err;
-                       list_for_each_entry(act, &actions, list)
-                               exts->actions[i++] = act;
-                       exts->nr_actions = i;
+                       pprev = &exts->action_list;
+                       list_for_each_entry(act, &actions, list) {
+                               *pprev = act;
+                               pprev = &act->next;
+                       }
                }
        }
 #else
@@ -883,18 +883,16 @@ int tcf_exts_validate(struct net *net, struct tcf_proto 
*tp, struct nlattr **tb,
 }
 EXPORT_SYMBOL(tcf_exts_validate);
 
-void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
-                    struct tcf_exts *src)
+void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src)
 {
 #ifdef CONFIG_NET_CLS_ACT
        struct tcf_exts old = *dst;
 
-       tcf_tree_lock(tp);
-       dst->nr_actions = src->nr_actions;
-       dst->actions = src->actions;
+       rcu_assign_pointer(dst->action_list,
+                          rtnl_dereference(src->action_list));
        dst->type = src->type;
-       tcf_tree_unlock(tp);
 
+       synchronize_rcu();
        tcf_exts_destroy(&old);
 #endif
 }
@@ -903,10 +901,7 @@ EXPORT_SYMBOL(tcf_exts_change);
 #ifdef CONFIG_NET_CLS_ACT
 static struct tc_action *tcf_exts_first_act(struct tcf_exts *exts)
 {
-       if (exts->nr_actions == 0)
-               return NULL;
-       else
-               return exts->actions[0];
+       return exts->action_list;
 }
 #endif
 
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 979cd26..dc12d79 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -131,9 +131,7 @@ static int basic_set_parms(struct net *net, struct 
tcf_proto *tp,
        int err;
        struct tcf_exts e;
 
-       err = tcf_exts_init(&e, TCA_BASIC_ACT, TCA_BASIC_POLICE);
-       if (err < 0)
-               return err;
+       tcf_exts_init(&e, TCA_BASIC_ACT, TCA_BASIC_POLICE);
        err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
        if (err < 0)
                goto errout;
@@ -147,7 +145,7 @@ static int basic_set_parms(struct net *net, struct 
tcf_proto *tp,
                tcf_bind_filter(tp, &f->res, base);
        }
 
-       tcf_exts_change(tp, &f->exts, &e);
+       tcf_exts_change(&f->exts, &e);
        f->tp = tp;
 
        return 0;
@@ -183,9 +181,7 @@ static int basic_change(struct net *net, struct sk_buff 
*in_skb,
        if (!fnew)
                return -ENOBUFS;
 
-       err = tcf_exts_init(&fnew->exts, TCA_BASIC_ACT, TCA_BASIC_POLICE);
-       if (err < 0)
-               goto errout;
+       tcf_exts_init(&fnew->exts, TCA_BASIC_ACT, TCA_BASIC_POLICE);
 
        err = -EINVAL;
        if (handle) {
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index f57bd53..49f311a 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -397,9 +397,7 @@ static int cls_bpf_modify_existing(struct net *net, struct 
tcf_proto *tp,
        if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf))
                return -EINVAL;
 
-       ret = tcf_exts_init(&exts, TCA_BPF_ACT, TCA_BPF_POLICE);
-       if (ret < 0)
-               return ret;
+       tcf_exts_init(&exts, TCA_BPF_ACT, TCA_BPF_POLICE);
        ret = tcf_exts_validate(net, tp, tb, est, &exts, ovr);
        if (ret < 0)
                goto errout;
@@ -436,7 +434,7 @@ static int cls_bpf_modify_existing(struct net *net, struct 
tcf_proto *tp,
                tcf_bind_filter(tp, &prog->res, base);
        }
 
-       tcf_exts_change(tp, &prog->exts, &exts);
+       tcf_exts_change(&prog->exts, &exts);
        return 0;
 
 errout:
@@ -488,9 +486,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff 
*in_skb,
        if (!prog)
                return -ENOBUFS;
 
-       ret = tcf_exts_init(&prog->exts, TCA_BPF_ACT, TCA_BPF_POLICE);
-       if (ret < 0)
-               goto errout;
+       tcf_exts_init(&prog->exts, TCA_BPF_ACT, TCA_BPF_POLICE);
 
        if (oldprog) {
                if (handle && oldprog->handle != handle) {
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index ce7d38b..f6f302a 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -92,9 +92,7 @@ static int cls_cgroup_change(struct net *net, struct sk_buff 
*in_skb,
        if (!new)
                return -ENOBUFS;
 
-       err = tcf_exts_init(&new->exts, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
-       if (err < 0)
-               goto errout;
+       tcf_exts_init(&new->exts, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
        new->handle = handle;
        new->tp = tp;
        err = nla_parse_nested(tb, TCA_CGROUP_MAX, tca[TCA_OPTIONS],
@@ -102,9 +100,7 @@ static int cls_cgroup_change(struct net *net, struct 
sk_buff *in_skb,
        if (err < 0)
                goto errout;
 
-       err = tcf_exts_init(&e, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
-       if (err < 0)
-               goto errout;
+       tcf_exts_init(&e, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
        err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
        if (err < 0) {
                tcf_exts_destroy(&e);
@@ -117,7 +113,7 @@ static int cls_cgroup_change(struct net *net, struct 
sk_buff *in_skb,
                goto errout;
        }
 
-       tcf_exts_change(tp, &new->exts, &e);
+       tcf_exts_change(&new->exts, &e);
 
        rcu_assign_pointer(tp->root, new);
        if (head)
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 71fd1af..a2441c0 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -424,9 +424,7 @@ static int flow_change(struct net *net, struct sk_buff 
*in_skb,
                        return -EOPNOTSUPP;
        }
 
-       err = tcf_exts_init(&e, TCA_FLOW_ACT, TCA_FLOW_POLICE);
-       if (err < 0)
-               goto err1;
+       tcf_exts_init(&e, TCA_FLOW_ACT, TCA_FLOW_POLICE);
        err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
        if (err < 0)
                goto err1;
@@ -440,9 +438,7 @@ static int flow_change(struct net *net, struct sk_buff 
*in_skb,
        if (err < 0)
                goto err2;
 
-       err = tcf_exts_init(&fnew->exts, TCA_FLOW_ACT, TCA_FLOW_POLICE);
-       if (err < 0)
-               goto err3;
+       tcf_exts_init(&fnew->exts, TCA_FLOW_ACT, TCA_FLOW_POLICE);
 
        fold = (struct flow_filter *)*arg;
        if (fold) {
@@ -510,7 +506,7 @@ static int flow_change(struct net *net, struct sk_buff 
*in_skb,
        setup_deferrable_timer(&fnew->perturb_timer, flow_perturbation,
                               (unsigned long)fnew);
 
-       tcf_exts_change(tp, &fnew->exts, &e);
+       tcf_exts_change(&fnew->exts, &e);
 
        netif_keep_dst(qdisc_dev(tp->q));
 
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 7832eb9..4bba357 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -855,9 +855,7 @@ static int fl_set_parms(struct net *net, struct tcf_proto 
*tp,
        struct tcf_exts e;
        int err;
 
-       err = tcf_exts_init(&e, TCA_FLOWER_ACT, 0);
-       if (err < 0)
-               return err;
+       tcf_exts_init(&e, TCA_FLOWER_ACT, 0);
        err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
        if (err < 0)
                goto errout;
@@ -874,7 +872,7 @@ static int fl_set_parms(struct net *net, struct tcf_proto 
*tp,
        fl_mask_update_range(mask);
        fl_set_masked_key(&f->mkey, &f->key, mask);
 
-       tcf_exts_change(tp, &f->exts, &e);
+       tcf_exts_change(&f->exts, &e);
 
        return 0;
 errout:
@@ -938,9 +936,7 @@ static int fl_change(struct net *net, struct sk_buff 
*in_skb,
                goto errout_tb;
        }
 
-       err = tcf_exts_init(&fnew->exts, TCA_FLOWER_ACT, 0);
-       if (err < 0)
-               goto errout;
+       tcf_exts_init(&fnew->exts, TCA_FLOWER_ACT, 0);
 
        if (!handle) {
                handle = fl_grab_new_handle(tp, head);
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index a53fa75..46a0e32 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -200,9 +200,7 @@ fw_change_attrs(struct net *net, struct tcf_proto *tp, 
struct fw_filter *f,
        u32 mask;
        int err;
 
-       err = tcf_exts_init(&e, TCA_FW_ACT, TCA_FW_POLICE);
-       if (err < 0)
-               return err;
+       tcf_exts_init(&e, TCA_FW_ACT, TCA_FW_POLICE);
        err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
        if (err < 0)
                goto errout;
@@ -232,7 +230,7 @@ fw_change_attrs(struct net *net, struct tcf_proto *tp, 
struct fw_filter *f,
        } else if (head->mask != 0xFFFFFFFF)
                goto errout;
 
-       tcf_exts_change(tp, &f->exts, &e);
+       tcf_exts_change(&f->exts, &e);
 
        return 0;
 errout:
@@ -276,11 +274,7 @@ static int fw_change(struct net *net, struct sk_buff 
*in_skb,
 #endif /* CONFIG_NET_CLS_IND */
                fnew->tp = f->tp;
 
-               err = tcf_exts_init(&fnew->exts, TCA_FW_ACT, TCA_FW_POLICE);
-               if (err < 0) {
-                       kfree(fnew);
-                       return err;
-               }
+               tcf_exts_init(&fnew->exts, TCA_FW_ACT, TCA_FW_POLICE);
 
                err = fw_change_attrs(net, tp, fnew, tb, tca, base, ovr);
                if (err < 0) {
@@ -324,9 +318,7 @@ static int fw_change(struct net *net, struct sk_buff 
*in_skb,
        if (f == NULL)
                return -ENOBUFS;
 
-       err = tcf_exts_init(&f->exts, TCA_FW_ACT, TCA_FW_POLICE);
-       if (err < 0)
-               goto errout;
+       tcf_exts_init(&f->exts, TCA_FW_ACT, TCA_FW_POLICE);
        f->id = handle;
        f->tp = tp;
 
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c
index 9dc26c3..0b77f6e 100644
--- a/net/sched/cls_matchall.c
+++ b/net/sched/cls_matchall.c
@@ -123,9 +123,7 @@ static int mall_set_parms(struct net *net, struct tcf_proto 
*tp,
        struct tcf_exts e;
        int err;
 
-       err = tcf_exts_init(&e, TCA_MATCHALL_ACT, 0);
-       if (err)
-               return err;
+       tcf_exts_init(&e, TCA_MATCHALL_ACT, 0);
        err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
        if (err < 0)
                goto errout;
@@ -135,7 +133,7 @@ static int mall_set_parms(struct net *net, struct tcf_proto 
*tp,
                tcf_bind_filter(tp, &head->res, base);
        }
 
-       tcf_exts_change(tp, &head->exts, &e);
+       tcf_exts_change(&head->exts, &e);
 
        return 0;
 errout:
@@ -176,9 +174,7 @@ static int mall_change(struct net *net, struct sk_buff 
*in_skb,
        if (!new)
                return -ENOBUFS;
 
-       err = tcf_exts_init(&new->exts, TCA_MATCHALL_ACT, 0);
-       if (err)
-               goto err_exts_init;
+       tcf_exts_init(&new->exts, TCA_MATCHALL_ACT, 0);
 
        if (!handle)
                handle = 1;
@@ -209,7 +205,6 @@ static int mall_change(struct net *net, struct sk_buff 
*in_skb,
 err_replace_hw_filter:
 err_set_parms:
        tcf_exts_destroy(&new->exts);
-err_exts_init:
        kfree(new);
        return err;
 }
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index 26f8636..60be2c4 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -375,9 +375,7 @@ static int route4_set_parms(struct net *net, struct 
tcf_proto *tp,
        struct tcf_exts e;
        int err;
 
-       err = tcf_exts_init(&e, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE);
-       if (err < 0)
-               return err;
+       tcf_exts_init(&e, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE);
        err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
        if (err < 0)
                goto errout;
@@ -450,7 +448,7 @@ static int route4_set_parms(struct net *net, struct 
tcf_proto *tp,
                tcf_bind_filter(tp, &f->res, base);
        }
 
-       tcf_exts_change(tp, &f->exts, &e);
+       tcf_exts_change(&f->exts, &e);
 
        return 0;
 errout:
@@ -488,9 +486,7 @@ static int route4_change(struct net *net, struct sk_buff 
*in_skb,
        if (!f)
                goto errout;
 
-       err = tcf_exts_init(&f->exts, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE);
-       if (err < 0)
-               goto errout;
+       tcf_exts_init(&f->exts, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE);
 
        if (fold) {
                f->id = fold->id;
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 0d9d077..2088262 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -486,9 +486,7 @@ static int rsvp_change(struct net *net, struct sk_buff 
*in_skb,
        if (err < 0)
                return err;
 
-       err = tcf_exts_init(&e, TCA_RSVP_ACT, TCA_RSVP_POLICE);
-       if (err < 0)
-               return err;
+       tcf_exts_init(&e, TCA_RSVP_ACT, TCA_RSVP_POLICE);
        err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
        if (err < 0)
                goto errout2;
@@ -507,18 +505,14 @@ static int rsvp_change(struct net *net, struct sk_buff 
*in_skb,
                        goto errout2;
                }
 
-               err = tcf_exts_init(&n->exts, TCA_RSVP_ACT, TCA_RSVP_POLICE);
-               if (err < 0) {
-                       kfree(n);
-                       goto errout2;
-               }
+               tcf_exts_init(&n->exts, TCA_RSVP_ACT, TCA_RSVP_POLICE);
 
                if (tb[TCA_RSVP_CLASSID]) {
                        n->res.classid = nla_get_u32(tb[TCA_RSVP_CLASSID]);
                        tcf_bind_filter(tp, &n->res, base);
                }
 
-               tcf_exts_change(tp, &n->exts, &e);
+               tcf_exts_change(&n->exts, &e);
                rsvp_replace(tp, n, handle);
                return 0;
        }
@@ -535,9 +529,7 @@ static int rsvp_change(struct net *net, struct sk_buff 
*in_skb,
        if (f == NULL)
                goto errout2;
 
-       err = tcf_exts_init(&f->exts, TCA_RSVP_ACT, TCA_RSVP_POLICE);
-       if (err < 0)
-               goto errout;
+       tcf_exts_init(&f->exts, TCA_RSVP_ACT, TCA_RSVP_POLICE);
        h2 = 16;
        if (tb[TCA_RSVP_SRC]) {
                memcpy(f->src, nla_data(tb[TCA_RSVP_SRC]), sizeof(f->src));
@@ -591,7 +583,7 @@ static int rsvp_change(struct net *net, struct sk_buff 
*in_skb,
                        if (f->tunnelhdr == 0)
                                tcf_bind_filter(tp, &f->res, base);
 
-                       tcf_exts_change(tp, &f->exts, &e);
+                       tcf_exts_change(&f->exts, &e);
 
                        fp = &s->ht[h2];
                        for (nfp = rtnl_dereference(*fp); nfp;
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 66924d1..b2d771c 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -223,10 +223,10 @@ static const struct nla_policy 
tcindex_policy[TCA_TCINDEX_MAX + 1] = {
        [TCA_TCINDEX_CLASSID]           = { .type = NLA_U32 },
 };
 
-static int tcindex_filter_result_init(struct tcindex_filter_result *r)
+static void tcindex_filter_result_init(struct tcindex_filter_result *r)
 {
        memset(r, 0, sizeof(*r));
-       return tcf_exts_init(&r->exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
+       tcf_exts_init(&r->exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
 }
 
 static void __tcindex_partial_destroy(struct rcu_head *head)
@@ -248,25 +248,18 @@ static void tcindex_free_perfect_hash(struct tcindex_data 
*cp)
 
 static int tcindex_alloc_perfect_hash(struct tcindex_data *cp)
 {
-       int i, err = 0;
+       int i;
 
        cp->perfect = kcalloc(cp->hash, sizeof(struct tcindex_filter_result),
                              GFP_KERNEL);
        if (!cp->perfect)
                return -ENOMEM;
 
-       for (i = 0; i < cp->hash; i++) {
-               err = tcf_exts_init(&cp->perfect[i].exts,
-                                   TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
-               if (err < 0)
-                       goto errout;
-       }
+       for (i = 0; i < cp->hash; i++)
+               tcf_exts_init(&cp->perfect[i].exts,
+                             TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
 
        return 0;
-
-errout:
-       tcindex_free_perfect_hash(cp);
-       return err;
 }
 
 static int
@@ -282,9 +275,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, 
unsigned long base,
        int err, balloc = 0;
        struct tcf_exts e;
 
-       err = tcf_exts_init(&e, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
-       if (err < 0)
-               return err;
+       tcf_exts_init(&e, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
        err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
        if (err < 0)
                goto errout;
@@ -316,12 +307,8 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, 
unsigned long base,
        }
        cp->h = p->h;
 
-       err = tcindex_filter_result_init(&new_filter_result);
-       if (err < 0)
-               goto errout1;
-       err = tcindex_filter_result_init(&cr);
-       if (err < 0)
-               goto errout1;
+       tcindex_filter_result_init(&new_filter_result);
+       tcindex_filter_result_init(&cr);
        if (old_r)
                cr.res = r->res;
 
@@ -406,11 +393,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, 
unsigned long base,
                        goto errout_alloc;
                f->key = handle;
                f->next = NULL;
-               err = tcindex_filter_result_init(&f->result);
-               if (err < 0) {
-                       kfree(f);
-                       goto errout_alloc;
-               }
+               tcindex_filter_result_init(&f->result);
        }
 
        if (tb[TCA_TCINDEX_CLASSID]) {
@@ -419,17 +402,12 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, 
unsigned long base,
        }
 
        if (old_r)
-               tcf_exts_change(tp, &r->exts, &e);
+               tcf_exts_change(&r->exts, &e);
        else
-               tcf_exts_change(tp, &cr.exts, &e);
+               tcf_exts_change(&cr.exts, &e);
 
-       if (old_r && old_r != r) {
-               err = tcindex_filter_result_init(old_r);
-               if (err < 0) {
-                       kfree(f);
-                       goto errout_alloc;
-               }
-       }
+       if (old_r && old_r != r)
+               tcindex_filter_result_init(old_r);
 
        oldp = p;
        r->res = cr.res;
@@ -439,7 +417,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, 
unsigned long base,
                struct tcindex_filter *nfp;
                struct tcindex_filter __rcu **fp;
 
-               tcf_exts_change(tp, &f->result.exts, &r->exts);
+               tcf_exts_change(&f->result.exts, &r->exts);
 
                fp = cp->h + (handle % cp->hash);
                for (nfp = rtnl_dereference(*fp);
@@ -459,7 +437,6 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, 
unsigned long base,
                tcindex_free_perfect_hash(cp);
        else if (balloc == 2)
                kfree(cp->h);
-errout1:
        tcf_exts_destroy(&cr.exts);
        tcf_exts_destroy(&new_filter_result.exts);
 errout:
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 2d01195..2c834f3 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -726,9 +726,7 @@ static int u32_set_parms(struct net *net, struct tcf_proto 
*tp,
        struct tcf_exts e;
        int err;
 
-       err = tcf_exts_init(&e, TCA_U32_ACT, TCA_U32_POLICE);
-       if (err < 0)
-               return err;
+       tcf_exts_init(&e, TCA_U32_ACT, TCA_U32_POLICE);
        err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
        if (err < 0)
                goto errout;
@@ -769,7 +767,7 @@ static int u32_set_parms(struct net *net, struct tcf_proto 
*tp,
                n->ifindex = ret;
        }
 #endif
-       tcf_exts_change(tp, &n->exts, &e);
+       tcf_exts_change(&n->exts, &e);
 
        return 0;
 errout:
@@ -848,10 +846,7 @@ static struct tc_u_knode *u32_init_knode(struct tcf_proto 
*tp,
        new->tp = tp;
        memcpy(&new->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key));
 
-       if (tcf_exts_init(&new->exts, TCA_U32_ACT, TCA_U32_POLICE)) {
-               kfree(new);
-               return NULL;
-       }
+       tcf_exts_init(&new->exts, TCA_U32_ACT, TCA_U32_POLICE);
 
        return new;
 }
@@ -1007,9 +1002,7 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
        n->flags = flags;
        n->tp = tp;
 
-       err = tcf_exts_init(&n->exts, TCA_U32_ACT, TCA_U32_POLICE);
-       if (err < 0)
-               goto errout;
+       tcf_exts_init(&n->exts, TCA_U32_ACT, TCA_U32_POLICE);
 
 #ifdef CONFIG_CLS_U32_MARK
        n->pcpu_success = alloc_percpu(u32);
-- 
2.9.3

Reply via email to