diff options
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/cls_cgroup.c | 13 | ||||
-rw-r--r-- | net/sched/cls_fw.c | 2 | ||||
-rw-r--r-- | net/sched/cls_tcindex.c | 19 | ||||
-rw-r--r-- | net/sched/cls_u32.c | 14 |
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; } |