diff options
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/act_bpf.c | 2 | ||||
-rw-r--r-- | net/sched/act_csum.c | 5 | ||||
-rw-r--r-- | net/sched/act_ipt.c | 9 | ||||
-rw-r--r-- | net/sched/act_pedit.c | 2 | ||||
-rw-r--r-- | net/sched/act_police.c | 2 | ||||
-rw-r--r-- | net/sched/act_sample.c | 3 | ||||
-rw-r--r-- | net/sched/act_simple.c | 2 | ||||
-rw-r--r-- | net/sched/act_skbmod.c | 5 | ||||
-rw-r--r-- | net/sched/act_tunnel_key.c | 10 | ||||
-rw-r--r-- | net/sched/act_vlan.c | 5 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 22 | ||||
-rw-r--r-- | net/sched/sch_netem.c | 2 |
12 files changed, 41 insertions, 28 deletions
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c index b3f2c15affa7..9d2cabf1dc7e 100644 --- a/net/sched/act_bpf.c +++ b/net/sched/act_bpf.c @@ -352,7 +352,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, return res; out: if (res == ACT_P_CREATED) - tcf_idr_cleanup(*act, est); + tcf_idr_release(*act, bind); return ret; } diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c index b7ba9b06b147..2a5c8fd860cf 100644 --- a/net/sched/act_csum.c +++ b/net/sched/act_csum.c @@ -350,7 +350,7 @@ static int tcf_csum_sctp(struct sk_buff *skb, unsigned int ihl, { struct sctphdr *sctph; - if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_SCTP) + if (skb_is_gso(skb) && skb_is_gso_sctp(skb)) return 1; sctph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*sctph)); @@ -626,7 +626,8 @@ static void tcf_csum_cleanup(struct tc_action *a) struct tcf_csum_params *params; params = rcu_dereference_protected(p->params, 1); - kfree_rcu(params, rcu); + if (params) + kfree_rcu(params, rcu); } static int tcf_csum_walker(struct net *net, struct sk_buff *skb, diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 06e380ae0928..7e06b9b62613 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -80,9 +80,12 @@ static void ipt_destroy_target(struct xt_entry_target *t) static void tcf_ipt_release(struct tc_action *a) { struct tcf_ipt *ipt = to_ipt(a); - ipt_destroy_target(ipt->tcfi_t); + + if (ipt->tcfi_t) { + ipt_destroy_target(ipt->tcfi_t); + kfree(ipt->tcfi_t); + } kfree(ipt->tcfi_tname); - kfree(ipt->tcfi_t); } static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = { @@ -187,7 +190,7 @@ err2: kfree(tname); err1: if (ret == ACT_P_CREATED) - tcf_idr_cleanup(*a, est); + tcf_idr_release(*a, bind); return err; } diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 349beaffb29e..fef08835f26d 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -176,7 +176,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, p = to_pedit(*a); keys = kmalloc(ksize, GFP_KERNEL); if (keys == NULL) { - tcf_idr_cleanup(*a, est); + tcf_idr_release(*a, bind); kfree(keys_ex); return -ENOMEM; } diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 95d3c9097b25..faebf82b99f1 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c @@ -194,7 +194,7 @@ failure: qdisc_put_rtab(P_tab); qdisc_put_rtab(R_tab); if (ret == ACT_P_CREATED) - tcf_idr_cleanup(*a, est); + tcf_idr_release(*a, bind); return err; } diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c index 1ba0df238756..74c5d7e6a0fa 100644 --- a/net/sched/act_sample.c +++ b/net/sched/act_sample.c @@ -103,7 +103,8 @@ static void tcf_sample_cleanup(struct tc_action *a) psample_group = rtnl_dereference(s->psample_group); RCU_INIT_POINTER(s->psample_group, NULL); - psample_group_put(psample_group); + if (psample_group) + psample_group_put(psample_group); } static bool tcf_sample_dev_ok_push(struct net_device *dev) diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 425eac11f6da..b1f38063ada0 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c @@ -121,7 +121,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, d = to_defact(*a); ret = alloc_defdata(d, defdata); if (ret < 0) { - tcf_idr_cleanup(*a, est); + tcf_idr_release(*a, bind); return ret; } d->tcf_action = parm->action; diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c index fa975262dbac..7b0700f52b50 100644 --- a/net/sched/act_skbmod.c +++ b/net/sched/act_skbmod.c @@ -152,7 +152,7 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, ASSERT_RTNL(); p = kzalloc(sizeof(struct tcf_skbmod_params), GFP_KERNEL); if (unlikely(!p)) { - if (ovr) + if (ret == ACT_P_CREATED) tcf_idr_release(*a, bind); return -ENOMEM; } @@ -190,7 +190,8 @@ static void tcf_skbmod_cleanup(struct tc_action *a) struct tcf_skbmod_params *p; p = rcu_dereference_protected(d->skbmod_p, 1); - kfree_rcu(p, rcu); + if (p) + kfree_rcu(p, rcu); } static int tcf_skbmod_dump(struct sk_buff *skb, struct tc_action *a, diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c index 0e23aac09ad6..1281ca463727 100644 --- a/net/sched/act_tunnel_key.c +++ b/net/sched/act_tunnel_key.c @@ -153,6 +153,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, metadata->u.tun_info.mode |= IP_TUNNEL_INFO_TX; break; default: + ret = -EINVAL; goto err_out; } @@ -207,11 +208,12 @@ static void tunnel_key_release(struct tc_action *a) struct tcf_tunnel_key_params *params; params = rcu_dereference_protected(t->params, 1); + if (params) { + if (params->tcft_action == TCA_TUNNEL_KEY_ACT_SET) + dst_release(¶ms->tcft_enc_metadata->dst); - if (params->tcft_action == TCA_TUNNEL_KEY_ACT_SET) - dst_release(¶ms->tcft_enc_metadata->dst); - - kfree_rcu(params, rcu); + kfree_rcu(params, rcu); + } } static int tunnel_key_dump_addresses(struct sk_buff *skb, diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c index e1a1b3f3983a..c49cb61adedf 100644 --- a/net/sched/act_vlan.c +++ b/net/sched/act_vlan.c @@ -195,7 +195,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ASSERT_RTNL(); p = kzalloc(sizeof(*p), GFP_KERNEL); if (!p) { - if (ovr) + if (ret == ACT_P_CREATED) tcf_idr_release(*a, bind); return -ENOMEM; } @@ -225,7 +225,8 @@ static void tcf_vlan_cleanup(struct tc_action *a) struct tcf_vlan_params *p; p = rcu_dereference_protected(v->vlan_p, 1); - kfree_rcu(p, rcu); + if (p) + kfree_rcu(p, rcu); } static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a, diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 190570f21b20..7e3fbe9cc936 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -106,6 +106,14 @@ static inline void qdisc_enqueue_skb_bad_txq(struct Qdisc *q, __skb_queue_tail(&q->skb_bad_txq, skb); + if (qdisc_is_percpu_stats(q)) { + qdisc_qstats_cpu_backlog_inc(q, skb); + qdisc_qstats_cpu_qlen_inc(q); + } else { + qdisc_qstats_backlog_inc(q, skb); + q->q.qlen++; + } + if (lock) spin_unlock(lock); } @@ -196,14 +204,6 @@ static void try_bulk_dequeue_skb_slow(struct Qdisc *q, break; if (unlikely(skb_get_queue_mapping(nskb) != mapping)) { qdisc_enqueue_skb_bad_txq(q, nskb); - - if (qdisc_is_percpu_stats(q)) { - qdisc_qstats_cpu_backlog_inc(q, nskb); - qdisc_qstats_cpu_qlen_inc(q); - } else { - qdisc_qstats_backlog_inc(q, nskb); - q->q.qlen++; - } break; } skb->next = nskb; @@ -628,6 +628,7 @@ static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc *qdisc, int band = prio2band[skb->priority & TC_PRIO_MAX]; struct pfifo_fast_priv *priv = qdisc_priv(qdisc); struct skb_array *q = band2list(priv, band); + unsigned int pkt_len = qdisc_pkt_len(skb); int err; err = skb_array_produce(q, skb); @@ -636,7 +637,10 @@ static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc *qdisc, return qdisc_drop_cpu(skb, qdisc, to_free); qdisc_qstats_cpu_qlen_inc(qdisc); - qdisc_qstats_cpu_backlog_inc(qdisc, skb); + /* Note: skb can not be used after skb_array_produce(), + * so we better not use qdisc_qstats_cpu_backlog_inc() + */ + this_cpu_add(qdisc->cpu_qstats->backlog, pkt_len); return NET_XMIT_SUCCESS; } diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 7c179addebcd..7d6801fc5340 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -509,7 +509,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, } if (unlikely(sch->q.qlen >= sch->limit)) - return qdisc_drop(skb, sch, to_free); + return qdisc_drop_all(skb, sch, to_free); qdisc_qstats_backlog_inc(sch, skb); |