Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71bcb09a authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller
Browse files

tc: check for errors in gen_rate_estimator creation



The functions gen_new_estimator and gen_replace_estimator can return
errors, but they were being ignored.

Signed-off-by: default avatarStephen Hemminger <shemminger@vyatta.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0e991ec6
Loading
Loading
Loading
Loading
+17 −8
Original line number Diff line number Diff line
@@ -185,14 +185,21 @@ static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est,
		if (parm->peakrate.rate) {
			P_tab = qdisc_get_rtab(&parm->peakrate,
					       tb[TCA_POLICE_PEAKRATE]);
			if (P_tab == NULL) {
				qdisc_put_rtab(R_tab);
			if (P_tab == NULL)
				goto failure;
		}
	}

	spin_lock_bh(&police->tcf_lock);
	if (est) {
		err = gen_replace_estimator(&police->tcf_bstats,
					    &police->tcf_rate_est,
					    &police->tcf_lock, est);
		if (err)
			goto failure_unlock;
	}

	/* No failure allowed after this point */
	spin_lock_bh(&police->tcf_lock);
	if (R_tab != NULL) {
		qdisc_put_rtab(police->tcfp_R_tab);
		police->tcfp_R_tab = R_tab;
@@ -217,10 +224,6 @@ static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est,

	if (tb[TCA_POLICE_AVRATE])
		police->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]);
	if (est)
		gen_replace_estimator(&police->tcf_bstats,
				      &police->tcf_rate_est,
				      &police->tcf_lock, est);

	spin_unlock_bh(&police->tcf_lock);
	if (ret != ACT_P_CREATED)
@@ -238,7 +241,13 @@ static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est,
	a->priv = police;
	return ret;

failure_unlock:
	spin_unlock_bh(&police->tcf_lock);
failure:
	if (P_tab)
		qdisc_put_rtab(P_tab);
	if (R_tab)
		qdisc_put_rtab(R_tab);
	if (ret == ACT_P_CREATED)
		kfree(police);
	return err;
+5 −2
Original line number Diff line number Diff line
@@ -880,9 +880,12 @@ static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
	sch->stab = stab;

	if (tca[TCA_RATE])
		/* NB: ignores errors from replace_estimator
		   because change can't be undone. */
		gen_replace_estimator(&sch->bstats, &sch->rate_est,
					    qdisc_root_sleeping_lock(sch),
					    tca[TCA_RATE]);

	return 0;
}

+24 −9
Original line number Diff line number Diff line
@@ -1765,11 +1765,23 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
		}

		if (tb[TCA_CBQ_RATE]) {
			rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB]);
			rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]),
					      tb[TCA_CBQ_RTAB]);
			if (rtab == NULL)
				return -EINVAL;
		}

		if (tca[TCA_RATE]) {
			err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
						    qdisc_root_sleeping_lock(sch),
						    tca[TCA_RATE]);
			if (err) {
				if (rtab)
					qdisc_put_rtab(rtab);
				return err;
			}
		}

		/* Change class parameters */
		sch_tree_lock(sch);

@@ -1805,10 +1817,6 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t

		sch_tree_unlock(sch);

		if (tca[TCA_RATE])
			gen_replace_estimator(&cl->bstats, &cl->rate_est,
					      qdisc_root_sleeping_lock(sch),
					      tca[TCA_RATE]);
		return 0;
	}

@@ -1855,6 +1863,17 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
	cl = kzalloc(sizeof(*cl), GFP_KERNEL);
	if (cl == NULL)
		goto failure;

	if (tca[TCA_RATE]) {
		err = gen_new_estimator(&cl->bstats, &cl->rate_est,
					qdisc_root_sleeping_lock(sch),
					tca[TCA_RATE]);
		if (err) {
			kfree(cl);
			goto failure;
		}
	}

	cl->R_tab = rtab;
	rtab = NULL;
	cl->refcnt = 1;
@@ -1896,10 +1915,6 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t

	qdisc_class_hash_grow(sch, &q->clhash);

	if (tca[TCA_RATE])
		gen_new_estimator(&cl->bstats, &cl->rate_est,
				  qdisc_root_sleeping_lock(sch), tca[TCA_RATE]);

	*arg = (unsigned long)cl;
	return 0;

+18 −8
Original line number Diff line number Diff line
@@ -82,15 +82,19 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
		quantum = psched_mtu(qdisc_dev(sch));

	if (cl != NULL) {
		if (tca[TCA_RATE]) {
			err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
						    qdisc_root_sleeping_lock(sch),
						    tca[TCA_RATE]);
			if (err)
				return err;
		}

		sch_tree_lock(sch);
		if (tb[TCA_DRR_QUANTUM])
			cl->quantum = quantum;
		sch_tree_unlock(sch);

		if (tca[TCA_RATE])
			gen_replace_estimator(&cl->bstats, &cl->rate_est,
					      qdisc_root_sleeping_lock(sch),
					      tca[TCA_RATE]);
		return 0;
	}

@@ -106,10 +110,16 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
	if (cl->qdisc == NULL)
		cl->qdisc = &noop_qdisc;

	if (tca[TCA_RATE])
		gen_replace_estimator(&cl->bstats, &cl->rate_est,
	if (tca[TCA_RATE]) {
		err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
					    qdisc_root_sleeping_lock(sch),
					    tca[TCA_RATE]);
		if (err) {
			qdisc_destroy(cl->qdisc);
			kfree(cl);
			return err;
		}
	}

	sch_tree_lock(sch);
	qdisc_class_hash_insert(&q->clhash, &cl->common);
+18 −7
Original line number Diff line number Diff line
@@ -1018,6 +1018,14 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
		}
		cur_time = psched_get_time();

		if (tca[TCA_RATE]) {
			err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
					      qdisc_root_sleeping_lock(sch),
					      tca[TCA_RATE]);
			if (err)
				return err;
		}

		sch_tree_lock(sch);
		if (rsc != NULL)
			hfsc_change_rsc(cl, rsc, cur_time);
@@ -1034,10 +1042,6 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
		}
		sch_tree_unlock(sch);

		if (tca[TCA_RATE])
			gen_replace_estimator(&cl->bstats, &cl->rate_est,
					      qdisc_root_sleeping_lock(sch),
					      tca[TCA_RATE]);
		return 0;
	}

@@ -1063,6 +1067,16 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
	if (cl == NULL)
		return -ENOBUFS;

	if (tca[TCA_RATE]) {
		err = gen_new_estimator(&cl->bstats, &cl->rate_est,
					qdisc_root_sleeping_lock(sch),
					tca[TCA_RATE]);
		if (err) {
			kfree(cl);
			return err;
		}
	}

	if (rsc != NULL)
		hfsc_change_rsc(cl, rsc, 0);
	if (fsc != NULL)
@@ -1093,9 +1107,6 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,

	qdisc_class_hash_grow(sch, &q->clhash);

	if (tca[TCA_RATE])
		gen_new_estimator(&cl->bstats, &cl->rate_est,
				  qdisc_root_sleeping_lock(sch), tca[TCA_RATE]);
	*arg = (unsigned long)cl;
	return 0;
}
Loading