Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[linux-2.6-block.git] / net / sched / cls_tcindex.c
index 14d6b4058045d70279294a5ec14379502a4169e1..e1981628047b0d022731b59965207fcbe8055213 100644 (file)
@@ -275,7 +275,7 @@ static void tcindex_free_perfect_hash(struct tcindex_data *cp)
        kfree(cp->perfect);
 }
 
-static int tcindex_alloc_perfect_hash(struct tcindex_data *cp)
+static int tcindex_alloc_perfect_hash(struct net *net, struct tcindex_data *cp)
 {
        int i, err = 0;
 
@@ -289,6 +289,9 @@ static int tcindex_alloc_perfect_hash(struct tcindex_data *cp)
                                    TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
                if (err < 0)
                        goto errout;
+#ifdef CONFIG_NET_CLS_ACT
+               cp->perfect[i].exts.net = net;
+#endif
        }
 
        return 0;
@@ -305,9 +308,9 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
                  struct nlattr *est, bool ovr, struct netlink_ext_ack *extack)
 {
        struct tcindex_filter_result new_filter_result, *old_r = r;
-       struct tcindex_filter_result cr;
        struct tcindex_data *cp = NULL, *oldp;
        struct tcindex_filter *f = NULL; /* make gcc behave */
+       struct tcf_result cr = {};
        int err, balloc = 0;
        struct tcf_exts e;
 
@@ -337,7 +340,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        if (p->perfect) {
                int i;
 
-               if (tcindex_alloc_perfect_hash(cp) < 0)
+               if (tcindex_alloc_perfect_hash(net, cp) < 0)
                        goto errout;
                for (i = 0; i < cp->hash; i++)
                        cp->perfect[i].res = p->perfect[i].res;
@@ -346,13 +349,10 @@ 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;
        if (old_r)
-               cr.res = r->res;
+               cr = r->res;
 
        if (tb[TCA_TCINDEX_HASH])
                cp->hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
@@ -406,7 +406,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        err = -ENOMEM;
        if (!cp->perfect && !cp->h) {
                if (valid_perfect_hash(cp)) {
-                       if (tcindex_alloc_perfect_hash(cp) < 0)
+                       if (tcindex_alloc_perfect_hash(net, cp) < 0)
                                goto errout_alloc;
                        balloc = 1;
                } else {
@@ -443,8 +443,8 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        }
 
        if (tb[TCA_TCINDEX_CLASSID]) {
-               cr.res.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
-               tcf_bind_filter(tp, &cr.res, base);
+               cr.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
+               tcf_bind_filter(tp, &cr, base);
        }
 
        if (old_r && old_r != r) {
@@ -456,7 +456,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        }
 
        oldp = p;
-       r->res = cr.res;
+       r->res = cr;
        tcf_exts_change(&r->exts, &e);
 
        rcu_assign_pointer(tp->root, cp);
@@ -475,6 +475,8 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
                                ; /* nothing */
 
                rcu_assign_pointer(*fp, f);
+       } else {
+               tcf_exts_destroy(&new_filter_result.exts);
        }
 
        if (oldp)
@@ -487,7 +489,6 @@ errout_alloc:
        else if (balloc == 2)
                kfree(cp->h);
 errout1:
-       tcf_exts_destroy(&cr.exts);
        tcf_exts_destroy(&new_filter_result.exts);
 errout:
        kfree(cp);