summaryrefslogtreecommitdiff
path: root/net/sched
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/cls_cgroup.c13
-rw-r--r--net/sched/cls_fw.c2
-rw-r--r--net/sched/cls_tcindex.c19
-rw-r--r--net/sched/cls_u32.c14
4 files changed, 30 insertions, 18 deletions
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index 3b7548759998..10c7ffde13e2 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -127,16 +127,18 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
err = nla_parse_nested(tb, TCA_CGROUP_MAX, tca[TCA_OPTIONS],
cgroup_policy);
if (err < 0)
- return err;
+ 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)
- return err;
+ goto errout;
err = tcf_em_tree_validate(tp, tb[TCA_CGROUP_EMATCHES], &t);
- if (err < 0)
- return err;
+ if (err < 0) {
+ tcf_exts_destroy(tp, &e);
+ goto errout;
+ }
tcf_exts_change(tp, &new->exts, &e);
tcf_em_tree_change(tp, &new->ematches, &t);
@@ -145,6 +147,9 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
if (head)
call_rcu(&head->rcu, cls_cgroup_destroy_rcu);
return 0;
+errout:
+ kfree(new);
+ return err;
}
static void cls_cgroup_destroy(struct tcf_proto *tp)
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 006b45a67fdd..2650285620ee 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -264,6 +264,8 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
#endif /* CONFIG_NET_CLS_IND */
fnew->tp = f->tp;
+ 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) {
kfree(fnew);
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index dd2d691f0bbb..5054fae33a48 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -242,8 +242,10 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
* perfect hash and hash pointers from old data.
*/
cp = kzalloc(sizeof(*cp), GFP_KERNEL);
- if (!cp)
- return -ENOMEM;
+ if (!cp) {
+ err = -ENOMEM;
+ goto errout;
+ }
cp->mask = p->mask;
cp->shift = p->shift;
@@ -257,6 +259,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
sizeof(*r) * cp->hash, GFP_KERNEL);
if (!cp->perfect)
goto errout;
+ balloc = 1;
}
cp->h = p->h;
@@ -282,9 +285,9 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
if (cp->perfect) {
if (!valid_perfect_hash(cp) ||
cp->hash > cp->alloc_hash)
- goto errout;
+ goto errout_alloc;
} else if (cp->h && cp->hash != cp->alloc_hash) {
- goto errout;
+ goto errout_alloc;
}
err = -EINVAL;
@@ -311,7 +314,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
*/
if (cp->perfect || valid_perfect_hash(cp))
if (handle >= cp->alloc_hash)
- goto errout;
+ goto errout_alloc;
err = -ENOMEM;
@@ -321,7 +324,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
cp->perfect = kcalloc(cp->hash, sizeof(*r), GFP_KERNEL);
if (!cp->perfect)
- goto errout;
+ goto errout_alloc;
for (i = 0; i < cp->hash; i++)
tcf_exts_init(&cp->perfect[i].exts,
TCA_TCINDEX_ACT,
@@ -335,7 +338,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
GFP_KERNEL);
if (!hash)
- goto errout;
+ goto errout_alloc;
cp->h = hash;
balloc = 2;
@@ -378,7 +381,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
f->result = new_filter_result;
f->next = NULL;
- fp = p->h + (handle % p->hash);
+ fp = cp->h + (handle % cp->hash);
for (nfp = rtnl_dereference(*fp);
nfp;
fp = &nfp->next, nfp = rtnl_dereference(*fp))
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 5ed5ac4361b1..eceeb0456d26 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -375,7 +375,7 @@ static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)
{
struct tc_u_knode __rcu **kp;
struct tc_u_knode *pkp;
- struct tc_u_hnode *ht = key->ht_up;
+ struct tc_u_hnode *ht = rtnl_dereference(key->ht_up);
if (ht) {
kp = &ht->ht[TC_U32_HASH(key->handle)];
@@ -607,7 +607,8 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
if (TC_U32_KEY(n->handle) == 0)
return -EINVAL;
- return u32_set_parms(net, tp, base, n->ht_up, n, tb,
+ return u32_set_parms(net, tp, base,
+ rtnl_dereference(n->ht_up), n, tb,
tca[TCA_RATE], ovr);
}
@@ -681,7 +682,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
#endif
memcpy(&n->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key));
- n->ht_up = ht;
+ RCU_INIT_POINTER(n->ht_up, ht);
n->handle = handle;
n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0;
tcf_exts_init(&n->exts, TCA_U32_ACT, TCA_U32_POLICE);
@@ -788,8 +789,8 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
} else {
#ifdef CONFIG_CLS_U32_PERF
struct tc_u32_pcnt *gpf;
-#endif
int cpu;
+#endif
if (nla_put(skb, TCA_U32_SEL,
sizeof(n->sel) + n->sel.nkeys*sizeof(struct tc_u32_key),
@@ -816,9 +817,10 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
struct tc_u32_mark mark = {.val = n->val,
.mask = n->mask,
.success = 0};
+ int cpum;
- for_each_possible_cpu(cpu) {
- __u32 cnt = *per_cpu_ptr(n->pcpu_success, cpu);
+ for_each_possible_cpu(cpum) {
+ __u32 cnt = *per_cpu_ptr(n->pcpu_success, cpum);
mark.success += cnt;
}