diff options
Diffstat (limited to 'net/sched')
| -rw-r--r-- | net/sched/act_connmark.c | 2 | ||||
| -rw-r--r-- | net/sched/cls_api.c | 12 | ||||
| -rw-r--r-- | net/sched/sch_api.c | 10 | ||||
| -rw-r--r-- | net/sched/sch_codel.c | 2 | ||||
| -rw-r--r-- | net/sched/sch_fq_codel.c | 2 | ||||
| -rw-r--r-- | net/sched/sch_gred.c | 4 | 
6 files changed, 18 insertions, 14 deletions
| diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c index 8e472518f9f6..295d14bd6c67 100644 --- a/net/sched/act_connmark.c +++ b/net/sched/act_connmark.c @@ -63,7 +63,6 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a,  		skb->mark = c->mark;  		/* using overlimits stats to count how many packets marked */  		ca->tcf_qstats.overlimits++; -		nf_ct_put(c);  		goto out;  	} @@ -82,7 +81,6 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a,  	nf_ct_put(c);  out: -	skb->nfct = NULL;  	spin_unlock(&ca->tcf_lock);  	return ca->tcf_action;  } diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 8b0470e418dc..a75864d93142 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -81,6 +81,11 @@ int unregister_tcf_proto_ops(struct tcf_proto_ops *ops)  	struct tcf_proto_ops *t;  	int rc = -ENOENT; +	/* Wait for outstanding call_rcu()s, if any, from a +	 * tcf_proto_ops's destroy() handler. +	 */ +	rcu_barrier(); +  	write_lock(&cls_mod_lock);  	list_for_each_entry(t, &tcf_proto_base, head) {  		if (t == ops) { @@ -308,12 +313,11 @@ replay:  		case RTM_DELTFILTER:  			err = tp->ops->delete(tp, fh);  			if (err == 0) { -				tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); -				if (tcf_destroy(tp, false)) { -					struct tcf_proto *next = rtnl_dereference(tp->next); +				struct tcf_proto *next = rtnl_dereference(tp->next); +				tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); +				if (tcf_destroy(tp, false))  					RCU_INIT_POINTER(*back, next); -				}  			}  			goto errout;  		case RTM_GETTFILTER: diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index ad9eed70bc8f..1e1c89e51a11 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -815,10 +815,8 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,  		if (dev->flags & IFF_UP)  			dev_deactivate(dev); -		if (new && new->ops->attach) { -			new->ops->attach(new); -			num_q = 0; -		} +		if (new && new->ops->attach) +			goto skip;  		for (i = 0; i < num_q; i++) {  			struct netdev_queue *dev_queue = dev_ingress_queue(dev); @@ -834,12 +832,16 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,  				qdisc_destroy(old);  		} +skip:  		if (!ingress) {  			notify_and_destroy(net, skb, n, classid,  					   dev->qdisc, new);  			if (new && !new->ops->attach)  				atomic_inc(&new->refcnt);  			dev->qdisc = new ? : &noop_qdisc; + +			if (new && new->ops->attach) +				new->ops->attach(new);  		} else {  			notify_and_destroy(net, skb, n, classid, old, new);  		} diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c index de28f8e968e8..7a0bdb16ac92 100644 --- a/net/sched/sch_codel.c +++ b/net/sched/sch_codel.c @@ -164,7 +164,7 @@ static int codel_init(struct Qdisc *sch, struct nlattr *opt)  	sch->limit = DEFAULT_CODEL_LIMIT; -	codel_params_init(&q->params); +	codel_params_init(&q->params, sch);  	codel_vars_init(&q->vars);  	codel_stats_init(&q->stats); diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 1e52decb7b59..c244c45b78d7 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -391,7 +391,7 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt)  	q->perturbation = prandom_u32();  	INIT_LIST_HEAD(&q->new_flows);  	INIT_LIST_HEAD(&q->old_flows); -	codel_params_init(&q->cparams); +	codel_params_init(&q->cparams, sch);  	codel_stats_init(&q->cstats);  	q->cparams.ecn = true; diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index a4ca4517cdc8..634529e0ce6b 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -229,7 +229,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch)  		break;  	} -	if (q->backlog + qdisc_pkt_len(skb) <= q->limit) { +	if (gred_backlog(t, q, sch) + qdisc_pkt_len(skb) <= q->limit) {  		q->backlog += qdisc_pkt_len(skb);  		return qdisc_enqueue_tail(skb, sch);  	} @@ -553,7 +553,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)  		opt.limit	= q->limit;  		opt.DP		= q->DP; -		opt.backlog	= q->backlog; +		opt.backlog	= gred_backlog(table, q, sch);  		opt.prio	= q->prio;  		opt.qth_min	= q->parms.qth_min >> q->parms.Wlog;  		opt.qth_max	= q->parms.qth_max >> q->parms.Wlog; |