* [PATCH 1/2] tc: check for errors from gen_replace_estimator
@ 2008-11-25 18:16 Stephen Hemminger
2008-11-25 18:21 ` [PATCH 2/2] tc: policing requires a rate estimator Stephen Hemminger
2008-11-25 18:28 ` [PATCH 1/2] tc: check for errors from gen_replace_estimator Patrick McHardy
0 siblings, 2 replies; 18+ messages in thread
From: Stephen Hemminger @ 2008-11-25 18:16 UTC (permalink / raw)
To: David Miller, Patrick McHardy; +Cc: netdev
gen_replace_estimator can return errors, but they were being ignored.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/net/sched/act_police.c 2008-11-25 10:02:05.000000000 -0800
+++ b/net/sched/act_police.c 2008-11-25 10:15:50.000000000 -0800
@@ -185,14 +185,21 @@ override:
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;
- }
}
}
- /* No failure allowed after this point */
+
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 */
if (R_tab != NULL) {
qdisc_put_rtab(police->tcfp_R_tab);
police->tcfp_R_tab = R_tab;
@@ -217,10 +224,6 @@ override:
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 @@ override:
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;
--- a/net/sched/sch_api.c 2008-11-25 10:02:05.000000000 -0800
+++ b/net/sched/sch_api.c 2008-11-25 10:07:21.000000000 -0800
@@ -897,10 +897,10 @@ static int qdisc_change(struct Qdisc *sc
sch->stab = stab;
if (tca[TCA_RATE])
- gen_replace_estimator(&sch->bstats, &sch->rate_est,
- qdisc_root_sleeping_lock(sch),
- tca[TCA_RATE]);
- return 0;
+ err = gen_replace_estimator(&sch->bstats, &sch->rate_est,
+ qdisc_root_sleeping_lock(sch),
+ tca[TCA_RATE]);
+ return err;
}
struct check_loop_arg
--- a/net/sched/sch_cbq.c 2008-11-25 10:02:05.000000000 -0800
+++ b/net/sched/sch_cbq.c 2008-11-25 10:07:21.000000000 -0800
@@ -1806,10 +1806,10 @@ cbq_change_class(struct Qdisc *sch, u32
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;
+ err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
+ qdisc_root_sleeping_lock(sch),
+ tca[TCA_RATE]);
+ return err;
}
if (parentid == TC_H_ROOT)
--- a/net/sched/sch_drr.c 2008-11-25 10:02:05.000000000 -0800
+++ b/net/sched/sch_drr.c 2008-11-25 10:07:21.000000000 -0800
@@ -88,10 +88,10 @@ static int drr_change_class(struct Qdisc
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;
+ err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
+ qdisc_root_sleeping_lock(sch),
+ tca[TCA_RATE]);
+ return err;
}
cl = kzalloc(sizeof(struct drr_class), GFP_KERNEL);
@@ -106,10 +106,15 @@ static int drr_change_class(struct Qdisc
if (cl->qdisc == NULL)
cl->qdisc = &noop_qdisc;
- if (tca[TCA_RATE])
- gen_replace_estimator(&cl->bstats, &cl->rate_est,
- qdisc_root_sleeping_lock(sch),
- tca[TCA_RATE]);
+ if (tca[TCA_RATE]) {
+ err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
+ qdisc_root_sleeping_lock(sch),
+ tca[TCA_RATE]);
+ if (err) {
+ kfree(cl);
+ return err;
+ }
+ }
sch_tree_lock(sch);
qdisc_class_hash_insert(&q->clhash, &cl->common);
--- a/net/sched/sch_hfsc.c 2008-11-25 10:02:05.000000000 -0800
+++ b/net/sched/sch_hfsc.c 2008-11-25 10:07:21.000000000 -0800
@@ -1035,10 +1035,10 @@ hfsc_change_class(struct Qdisc *sch, u32
sch_tree_unlock(sch);
if (tca[TCA_RATE])
- gen_replace_estimator(&cl->bstats, &cl->rate_est,
+ err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
qdisc_root_sleeping_lock(sch),
tca[TCA_RATE]);
- return 0;
+ return err;
}
if (parentid == TC_H_ROOT)
^ permalink raw reply [flat|nested] 18+ messages in thread* [PATCH 2/2] tc: policing requires a rate estimator 2008-11-25 18:16 [PATCH 1/2] tc: check for errors from gen_replace_estimator Stephen Hemminger @ 2008-11-25 18:21 ` Stephen Hemminger 2008-11-25 18:32 ` Patrick McHardy ` (2 more replies) 2008-11-25 18:28 ` [PATCH 1/2] tc: check for errors from gen_replace_estimator Patrick McHardy 1 sibling, 3 replies; 18+ messages in thread From: Stephen Hemminger @ 2008-11-25 18:21 UTC (permalink / raw) To: David Miller, Patrick McHardy; +Cc: netdev Found that while trying average rate policing, it was possible to request average rate policing without a rate estimator. This results in no policing which is harmless but incorrect. Since policing could be setup in two steps, need to check in the kernel. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> --- include/net/gen_stats.h | 1 + net/core/gen_estimator.c | 30 +++++++++++++++++++++++++++--- net/sched/act_police.c | 16 ++++++++++++---- 3 files changed, 40 insertions(+), 7 deletions(-) --- a/net/sched/act_police.c 2008-11-25 10:15:50.000000000 -0800 +++ b/net/sched/act_police.c 2008-11-25 10:17:54.000000000 -0800 @@ -182,6 +182,12 @@ override: R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]); if (R_tab == NULL) goto failure; + + if (!est && !gen_estimator_active(&police->tcf_rate_est)) { + err = -EINVAL; + goto failure; + } + if (parm->peakrate.rate) { P_tab = qdisc_get_rtab(&parm->peakrate, tb[TCA_POLICE_PEAKRATE]); --- a/include/net/gen_stats.h 2008-11-25 10:14:52.000000000 -0800 +++ b/include/net/gen_stats.h 2008-11-25 10:16:52.000000000 -0800 @@ -45,5 +45,6 @@ extern void gen_kill_estimator(struct gn extern int gen_replace_estimator(struct gnet_stats_basic *bstats, struct gnet_stats_rate_est *rate_est, spinlock_t *stats_lock, struct nlattr *opt); +extern int gen_estimator_active(const struct gnet_stats_rate_est *rate_est); #endif --- a/net/core/gen_estimator.c 2008-11-25 10:14:52.000000000 -0800 +++ b/net/core/gen_estimator.c 2008-11-25 10:16:52.000000000 -0800 @@ -242,6 +242,7 @@ int gen_new_estimator(struct gnet_stats_ return 0; } +EXPORT_SYMBOL(gen_new_estimator); static void __gen_kill_estimator(struct rcu_head *head) { @@ -275,6 +276,7 @@ void gen_kill_estimator(struct gnet_stat call_rcu(&e->e_rcu, __gen_kill_estimator); } } +EXPORT_SYMBOL(gen_kill_estimator); /** * gen_replace_estimator - replace rate estimator configuration @@ -295,8 +297,30 @@ int gen_replace_estimator(struct gnet_st gen_kill_estimator(bstats, rate_est); return gen_new_estimator(bstats, rate_est, stats_lock, opt); } +EXPORT_SYMBOL(gen_replace_estimator); + +/** + * gen_estimator_active - test if estimator is currently in use + * @rate_est: rate estimator statistics + * + * Returns 1 if estimator is active, and 0 if not. + */ +int gen_estimator_active(const struct gnet_stats_rate_est *rate_est) +{ + int idx; + struct gen_estimator *e; + ASSERT_RTNL(); -EXPORT_SYMBOL(gen_kill_estimator); -EXPORT_SYMBOL(gen_new_estimator); -EXPORT_SYMBOL(gen_replace_estimator); + for (idx=0; idx <= EST_MAX_INTERVAL; idx++) { + if (!elist[idx].timer.function) + continue; + + list_for_each_entry(e, &elist[idx].list, list) { + if (e->rate_est == rate_est) + return 1; + } + } + return 0; +} +EXPORT_SYMBOL(gen_estimator_active); ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] tc: policing requires a rate estimator 2008-11-25 18:21 ` [PATCH 2/2] tc: policing requires a rate estimator Stephen Hemminger @ 2008-11-25 18:32 ` Patrick McHardy 2008-11-25 18:33 ` Stephen Hemminger 2008-11-26 5:14 ` David Miller 2008-11-26 11:10 ` [PATCH] pkt_sched: gen_estimator: Optimize gen_estimator_active() Jarek Poplawski 2 siblings, 1 reply; 18+ messages in thread From: Patrick McHardy @ 2008-11-25 18:32 UTC (permalink / raw) To: Stephen Hemminger; +Cc: David Miller, netdev Stephen Hemminger wrote: > Found that while trying average rate policing, it was possible to > request average rate policing without a rate estimator. This results > in no policing which is harmless but incorrect. > > Since policing could be setup in two steps, need to check > in the kernel. > > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> > > > --- > include/net/gen_stats.h | 1 + > net/core/gen_estimator.c | 30 +++++++++++++++++++++++++++--- > net/sched/act_police.c | 16 ++++++++++++---- > 3 files changed, 40 insertions(+), 7 deletions(-) > > --- a/net/sched/act_police.c 2008-11-25 10:15:50.000000000 -0800 > +++ b/net/sched/act_police.c 2008-11-25 10:17:54.000000000 -0800 > @@ -182,6 +182,12 @@ override: > R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]); > if (R_tab == NULL) > goto failure; > + > + if (!est && !gen_estimator_active(&police->tcf_rate_est)) { > + err = -EINVAL; > + goto failure; This leaks the R_tab reference. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] tc: policing requires a rate estimator 2008-11-25 18:32 ` Patrick McHardy @ 2008-11-25 18:33 ` Stephen Hemminger 2008-11-25 18:38 ` Patrick McHardy 0 siblings, 1 reply; 18+ messages in thread From: Stephen Hemminger @ 2008-11-25 18:33 UTC (permalink / raw) To: Patrick McHardy; +Cc: David Miller, netdev On Tue, 25 Nov 2008 19:32:13 +0100 Patrick McHardy <kaber@trash.net> wrote: > Stephen Hemminger wrote: > > Found that while trying average rate policing, it was possible to > > request average rate policing without a rate estimator. This results > > in no policing which is harmless but incorrect. > > > > Since policing could be setup in two steps, need to check > > in the kernel. > > > > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> > > > > > > --- > > include/net/gen_stats.h | 1 + > > net/core/gen_estimator.c | 30 +++++++++++++++++++++++++++--- > > net/sched/act_police.c | 16 ++++++++++++---- > > 3 files changed, 40 insertions(+), 7 deletions(-) > > > > --- a/net/sched/act_police.c 2008-11-25 10:15:50.000000000 -0800 > > +++ b/net/sched/act_police.c 2008-11-25 10:17:54.000000000 -0800 > > @@ -182,6 +182,12 @@ override: > > R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]); > > if (R_tab == NULL) > > goto failure; > > + > > + if (!est && !gen_estimator_active(&police->tcf_rate_est)) { > > + err = -EINVAL; > > + goto failure; > > This leaks the R_tab reference. The previous patch added a put at the failure: tag. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] tc: policing requires a rate estimator 2008-11-25 18:33 ` Stephen Hemminger @ 2008-11-25 18:38 ` Patrick McHardy 0 siblings, 0 replies; 18+ messages in thread From: Patrick McHardy @ 2008-11-25 18:38 UTC (permalink / raw) To: Stephen Hemminger; +Cc: David Miller, netdev Stephen Hemminger wrote: > On Tue, 25 Nov 2008 19:32:13 +0100 > Patrick McHardy <kaber@trash.net> wrote: > >>> >>> --- a/net/sched/act_police.c 2008-11-25 10:15:50.000000000 -0800 >>> +++ b/net/sched/act_police.c 2008-11-25 10:17:54.000000000 -0800 >>> @@ -182,6 +182,12 @@ override: >>> R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]); >>> if (R_tab == NULL) >>> goto failure; >>> + >>> + if (!est && !gen_estimator_active(&police->tcf_rate_est)) { >>> + err = -EINVAL; >>> + goto failure; >> This leaks the R_tab reference. > > The previous patch added a put at the failure: tag. I missed that, sorry. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] tc: policing requires a rate estimator 2008-11-25 18:21 ` [PATCH 2/2] tc: policing requires a rate estimator Stephen Hemminger 2008-11-25 18:32 ` Patrick McHardy @ 2008-11-26 5:14 ` David Miller 2008-11-26 11:10 ` [PATCH] pkt_sched: gen_estimator: Optimize gen_estimator_active() Jarek Poplawski 2 siblings, 0 replies; 18+ messages in thread From: David Miller @ 2008-11-26 5:14 UTC (permalink / raw) To: shemminger; +Cc: kaber, netdev From: Stephen Hemminger <shemminger@vyatta.com> Date: Tue, 25 Nov 2008 10:21:13 -0800 > Found that while trying average rate policing, it was possible to > request average rate policing without a rate estimator. This results > in no policing which is harmless but incorrect. > > Since policing could be setup in two steps, need to check > in the kernel. > > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Applied. ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH] pkt_sched: gen_estimator: Optimize gen_estimator_active() 2008-11-25 18:21 ` [PATCH 2/2] tc: policing requires a rate estimator Stephen Hemminger 2008-11-25 18:32 ` Patrick McHardy 2008-11-26 5:14 ` David Miller @ 2008-11-26 11:10 ` Jarek Poplawski 2008-11-26 16:29 ` Stephen Hemminger 2008-11-26 23:24 ` David Miller 2 siblings, 2 replies; 18+ messages in thread From: Jarek Poplawski @ 2008-11-26 11:10 UTC (permalink / raw) To: Stephen Hemminger; +Cc: David Miller, Patrick McHardy, netdev pkt_sched: gen_estimator: Optimize gen_estimator_active() Since all other gen_estimator functions use bstats and rate_est params together, and searching for them is optimized now, let's use this also in gen_estimator_active(). The return type of gen_estimator_active() is changed to bool, and gen_find_node() parameters to const, btw. In tcf_act_police_locate() a check for ACT_P_CREATED is added before calling gen_estimator_active(). Signed-off-by: Jarek Poplawski <jarkao2@gmail.com> --- include/net/gen_stats.h | 4 ++-- net/core/gen_estimator.c | 25 ++++++++----------------- net/sched/act_police.c | 4 +++- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h index dcf5bfa..d136b52 100644 --- a/include/net/gen_stats.h +++ b/include/net/gen_stats.h @@ -45,6 +45,6 @@ extern void gen_kill_estimator(struct gnet_stats_basic *bstats, extern int gen_replace_estimator(struct gnet_stats_basic *bstats, struct gnet_stats_rate_est *rate_est, spinlock_t *stats_lock, struct nlattr *opt); -extern int gen_estimator_active(const struct gnet_stats_rate_est *rate_est); - +extern bool gen_estimator_active(const struct gnet_stats_basic *bstats, + const struct gnet_stats_rate_est *rate_est); #endif diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 3885550..9cc9f95 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -163,8 +163,9 @@ static void gen_add_node(struct gen_estimator *est) rb_insert_color(&est->node, &est_root); } -static struct gen_estimator *gen_find_node(struct gnet_stats_basic *bstats, - struct gnet_stats_rate_est *rate_est) +static +struct gen_estimator *gen_find_node(const struct gnet_stats_basic *bstats, + const struct gnet_stats_rate_est *rate_est) { struct rb_node *p = est_root.rb_node; @@ -301,26 +302,16 @@ EXPORT_SYMBOL(gen_replace_estimator); /** * gen_estimator_active - test if estimator is currently in use + * @bstats: basic statistics * @rate_est: rate estimator statistics * - * Returns 1 if estimator is active, and 0 if not. + * Returns true if estimator is active, and false if not. */ -int gen_estimator_active(const struct gnet_stats_rate_est *rate_est) +bool gen_estimator_active(const struct gnet_stats_basic *bstats, + const struct gnet_stats_rate_est *rate_est) { - int idx; - struct gen_estimator *e; - ASSERT_RTNL(); - for (idx=0; idx <= EST_MAX_INTERVAL; idx++) { - if (!elist[idx].timer.function) - continue; - - list_for_each_entry(e, &elist[idx].list, list) { - if (e->rate_est == rate_est) - return 1; - } - } - return 0; + return gen_find_node(bstats, rate_est) != NULL; } EXPORT_SYMBOL(gen_estimator_active); diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 40df1d0..40f9a81 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c @@ -183,7 +183,9 @@ override: if (R_tab == NULL) goto failure; - if (!est && !gen_estimator_active(&police->tcf_rate_est)) { + if (!est && (ret == ACT_P_CREATED || + !gen_estimator_active(&police->tcf_bstats, + &police->tcf_rate_est))) { err = -EINVAL; goto failure; } ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH] pkt_sched: gen_estimator: Optimize gen_estimator_active() 2008-11-26 11:10 ` [PATCH] pkt_sched: gen_estimator: Optimize gen_estimator_active() Jarek Poplawski @ 2008-11-26 16:29 ` Stephen Hemminger 2008-11-26 23:24 ` David Miller 1 sibling, 0 replies; 18+ messages in thread From: Stephen Hemminger @ 2008-11-26 16:29 UTC (permalink / raw) To: Jarek Poplawski; +Cc: David Miller, Patrick McHardy, netdev On Wed, 26 Nov 2008 11:10:22 +0000 Jarek Poplawski <jarkao2@gmail.com> wrote: > pkt_sched: gen_estimator: Optimize gen_estimator_active() > > Since all other gen_estimator functions use bstats and rate_est params > together, and searching for them is optimized now, let's use this also > in gen_estimator_active(). The return type of gen_estimator_active() > is changed to bool, and gen_find_node() parameters to const, btw. > > In tcf_act_police_locate() a check for ACT_P_CREATED is added before > calling gen_estimator_active(). > > Signed-off-by: Jarek Poplawski <jarkao2@gmail.com> yeah sure, i just coded the obvious way. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] pkt_sched: gen_estimator: Optimize gen_estimator_active() 2008-11-26 11:10 ` [PATCH] pkt_sched: gen_estimator: Optimize gen_estimator_active() Jarek Poplawski 2008-11-26 16:29 ` Stephen Hemminger @ 2008-11-26 23:24 ` David Miller 1 sibling, 0 replies; 18+ messages in thread From: David Miller @ 2008-11-26 23:24 UTC (permalink / raw) To: jarkao2; +Cc: shemminger, kaber, netdev From: Jarek Poplawski <jarkao2@gmail.com> Date: Wed, 26 Nov 2008 11:10:22 +0000 > pkt_sched: gen_estimator: Optimize gen_estimator_active() > > Since all other gen_estimator functions use bstats and rate_est params > together, and searching for them is optimized now, let's use this also > in gen_estimator_active(). The return type of gen_estimator_active() > is changed to bool, and gen_find_node() parameters to const, btw. > > In tcf_act_police_locate() a check for ACT_P_CREATED is added before > calling gen_estimator_active(). > > Signed-off-by: Jarek Poplawski <jarkao2@gmail.com> Applied, thanks Jarek. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/2] tc: check for errors from gen_replace_estimator 2008-11-25 18:16 [PATCH 1/2] tc: check for errors from gen_replace_estimator Stephen Hemminger 2008-11-25 18:21 ` [PATCH 2/2] tc: policing requires a rate estimator Stephen Hemminger @ 2008-11-25 18:28 ` Patrick McHardy 2008-11-25 18:57 ` [PATCH 1a/2] tc: propogate errors from tcf_hash_create Stephen Hemminger 2008-11-25 18:58 ` [PATCH 1b/2] tc: check for errors in gen_rate_estimator creation Stephen Hemminger 1 sibling, 2 replies; 18+ messages in thread From: Patrick McHardy @ 2008-11-25 18:28 UTC (permalink / raw) To: Stephen Hemminger; +Cc: David Miller, netdev Stephen Hemminger wrote: > gen_replace_estimator can return errors, but they were being ignored. > > --- a/net/sched/sch_hfsc.c 2008-11-25 10:02:05.000000000 -0800 > +++ b/net/sched/sch_hfsc.c 2008-11-25 10:07:21.000000000 -0800 > @@ -1035,10 +1035,10 @@ hfsc_change_class(struct Qdisc *sch, u32 > sch_tree_unlock(sch); > > if (tca[TCA_RATE]) > - gen_replace_estimator(&cl->bstats, &cl->rate_est, > + err = gen_replace_estimator(&cl->bstats, &cl->rate_est, > qdisc_root_sleeping_lock(sch), > tca[TCA_RATE]); > - return 0; > + return err; At this point we've already made changes to the class, so returning an error without undoing them is wrong. I'd suggest to move the estimator replacement up a bit, the other changes can't fail. There's also gen_new_estimator() that should be treated similary for consistency. ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 1a/2] tc: propogate errors from tcf_hash_create 2008-11-25 18:28 ` [PATCH 1/2] tc: check for errors from gen_replace_estimator Patrick McHardy @ 2008-11-25 18:57 ` Stephen Hemminger 2008-11-26 5:12 ` David Miller 2008-11-25 18:58 ` [PATCH 1b/2] tc: check for errors in gen_rate_estimator creation Stephen Hemminger 1 sibling, 1 reply; 18+ messages in thread From: Stephen Hemminger @ 2008-11-25 18:57 UTC (permalink / raw) To: Patrick McHardy; +Cc: David Miller, netdev Allow tcf_hash_create to return different errors on estimator failure. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> --- net/sched/act_api.c | 18 +++++++++++++----- net/sched/act_gact.c | 4 ++-- net/sched/act_ipt.c | 4 ++-- net/sched/act_mirred.c | 4 ++-- net/sched/act_nat.c | 4 ++-- net/sched/act_pedit.c | 4 ++-- net/sched/act_simple.c | 4 ++-- net/sched/act_skbedit.c | 4 ++-- 8 files changed, 27 insertions(+), 19 deletions(-) --- a/net/sched/act_api.c 2008-11-25 10:47:48.000000000 -0800 +++ b/net/sched/act_api.c 2008-11-25 10:50:56.000000000 -0800 @@ -214,12 +214,14 @@ struct tcf_common *tcf_hash_check(u32 in } EXPORT_SYMBOL(tcf_hash_check); -struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a, int size, int bind, u32 *idx_gen, struct tcf_hashinfo *hinfo) +struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est, + struct tc_action *a, int size, int bind, + u32 *idx_gen, struct tcf_hashinfo *hinfo) { struct tcf_common *p = kzalloc(size, GFP_KERNEL); if (unlikely(!p)) - return p; + return ERR_PTR(-ENOMEM); p->tcfc_refcnt = 1; if (bind) p->tcfc_bindcnt = 1; @@ -228,9 +230,15 @@ struct tcf_common *tcf_hash_create(u32 i p->tcfc_index = index ? index : tcf_hash_new_index(idx_gen, hinfo); p->tcfc_tm.install = jiffies; p->tcfc_tm.lastuse = jiffies; - if (est) - gen_new_estimator(&p->tcfc_bstats, &p->tcfc_rate_est, - &p->tcfc_lock, est); + if (est) { + int err = gen_new_estimator(&p->tcfc_bstats, &p->tcfc_rate_est, + &p->tcfc_lock, est); + if (err) { + kfree(p); + return ERR_PTR(err); + } + } + a->priv = (void *) p; return p; } --- a/net/sched/act_gact.c 2008-11-25 10:47:48.000000000 -0800 +++ b/net/sched/act_gact.c 2008-11-25 10:52:19.000000000 -0800 @@ -88,8 +88,8 @@ static int tcf_gact_init(struct nlattr * if (!pc) { pc = tcf_hash_create(parm->index, est, a, sizeof(*gact), bind, &gact_idx_gen, &gact_hash_info); - if (unlikely(!pc)) - return -ENOMEM; + if (IS_ERR(pc)) + return PTR_ERR(pc); ret = ACT_P_CREATED; } else { if (!ovr) { --- a/net/sched/act_ipt.c 2008-11-25 10:47:48.000000000 -0800 +++ b/net/sched/act_ipt.c 2008-11-25 10:52:31.000000000 -0800 @@ -136,8 +136,8 @@ static int tcf_ipt_init(struct nlattr *n if (!pc) { pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind, &ipt_idx_gen, &ipt_hash_info); - if (unlikely(!pc)) - return -ENOMEM; + if (IS_ERR(pc)) + return PTR_ERR(pc); ret = ACT_P_CREATED; } else { if (!ovr) { --- a/net/sched/act_mirred.c 2008-11-25 10:47:48.000000000 -0800 +++ b/net/sched/act_mirred.c 2008-11-25 10:52:25.000000000 -0800 @@ -105,8 +105,8 @@ static int tcf_mirred_init(struct nlattr return -EINVAL; pc = tcf_hash_create(parm->index, est, a, sizeof(*m), bind, &mirred_idx_gen, &mirred_hash_info); - if (unlikely(!pc)) - return -ENOMEM; + if (IS_ERR(pc)) + return PTR_ERR(pc); ret = ACT_P_CREATED; } else { if (!ovr) { --- a/net/sched/act_nat.c 2008-11-25 10:47:48.000000000 -0800 +++ b/net/sched/act_nat.c 2008-11-25 10:52:37.000000000 -0800 @@ -68,8 +68,8 @@ static int tcf_nat_init(struct nlattr *n if (!pc) { pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind, &nat_idx_gen, &nat_hash_info); - if (unlikely(!pc)) - return -ENOMEM; + if (IS_ERR(pc)) + return PTR_ERR(pc); p = to_tcf_nat(pc); ret = ACT_P_CREATED; } else { --- a/net/sched/act_pedit.c 2008-11-25 10:47:48.000000000 -0800 +++ b/net/sched/act_pedit.c 2008-11-25 10:52:44.000000000 -0800 @@ -68,8 +68,8 @@ static int tcf_pedit_init(struct nlattr return -EINVAL; pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind, &pedit_idx_gen, &pedit_hash_info); - if (unlikely(!pc)) - return -ENOMEM; + if (IS_ERR(pc)) + return PTR_ERR(pc); p = to_pedit(pc); keys = kmalloc(ksize, GFP_KERNEL); if (keys == NULL) { --- a/net/sched/act_simple.c 2008-11-25 10:47:48.000000000 -0800 +++ b/net/sched/act_simple.c 2008-11-25 10:52:51.000000000 -0800 @@ -124,8 +124,8 @@ static int tcf_simp_init(struct nlattr * if (!pc) { pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind, &simp_idx_gen, &simp_hash_info); - if (unlikely(!pc)) - return -ENOMEM; + if (IS_ERR(pc)) + return PTR_ERR(pc); d = to_defact(pc); ret = alloc_defdata(d, defdata); --- a/net/sched/act_skbedit.c 2008-11-25 10:47:48.000000000 -0800 +++ b/net/sched/act_skbedit.c 2008-11-25 10:53:11.000000000 -0800 @@ -104,8 +104,8 @@ static int tcf_skbedit_init(struct nlatt if (!pc) { pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind, &skbedit_idx_gen, &skbedit_hash_info); - if (unlikely(!pc)) - return -ENOMEM; + if (IS_ERR(pc)) + return PTR_ERR(pc); d = to_skbedit(pc); ret = ACT_P_CREATED; ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1a/2] tc: propogate errors from tcf_hash_create 2008-11-25 18:57 ` [PATCH 1a/2] tc: propogate errors from tcf_hash_create Stephen Hemminger @ 2008-11-26 5:12 ` David Miller 0 siblings, 0 replies; 18+ messages in thread From: David Miller @ 2008-11-26 5:12 UTC (permalink / raw) To: shemminger; +Cc: kaber, netdev From: Stephen Hemminger <shemminger@vyatta.com> Date: Tue, 25 Nov 2008 10:57:27 -0800 > Allow tcf_hash_create to return different errors on estimator failure. > > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Applied. ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 1b/2] tc: check for errors in gen_rate_estimator creation 2008-11-25 18:28 ` [PATCH 1/2] tc: check for errors from gen_replace_estimator Patrick McHardy 2008-11-25 18:57 ` [PATCH 1a/2] tc: propogate errors from tcf_hash_create Stephen Hemminger @ 2008-11-25 18:58 ` Stephen Hemminger 2008-11-25 19:05 ` Patrick McHardy 1 sibling, 1 reply; 18+ messages in thread From: Stephen Hemminger @ 2008-11-25 18:58 UTC (permalink / raw) To: Patrick McHardy; +Cc: David Miller, netdev The functions gen_new_estimator and gen_replace_estimator can return errors, but they were being ignored. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> --- net/sched/act_police.c | 25 +++++++++++++++++-------- net/sched/sch_api.c | 12 ++++++++---- net/sched/sch_cbq.c | 33 ++++++++++++++++++++++++--------- net/sched/sch_drr.c | 26 ++++++++++++++++++-------- net/sched/sch_hfsc.c | 12 ++++++++---- net/sched/sch_htb.c | 22 +++++++++++++++------- 6 files changed, 90 insertions(+), 40 deletions(-) --- a/net/sched/act_police.c 2008-11-25 10:51:47.000000000 -0800 +++ b/net/sched/act_police.c 2008-11-25 10:54:16.000000000 -0800 @@ -185,14 +185,21 @@ override: 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; - } } } - /* No failure allowed after this point */ + 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 */ if (R_tab != NULL) { qdisc_put_rtab(police->tcfp_R_tab); police->tcfp_R_tab = R_tab; @@ -217,10 +224,6 @@ override: 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 @@ override: 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; --- a/net/sched/sch_api.c 2008-11-25 10:51:47.000000000 -0800 +++ b/net/sched/sch_api.c 2008-11-25 10:54:16.000000000 -0800 @@ -887,6 +887,14 @@ static int qdisc_change(struct Qdisc *sc return err; } + if (tca[TCA_RATE]) { + err = gen_replace_estimator(&sch->bstats, &sch->rate_est, + qdisc_root_sleeping_lock(sch), + tca[TCA_RATE]); + if (err) + return err; + } + if (tca[TCA_STAB]) { stab = qdisc_get_stab(tca[TCA_STAB]); if (IS_ERR(stab)) @@ -896,10 +904,6 @@ static int qdisc_change(struct Qdisc *sc qdisc_put_stab(sch->stab); sch->stab = stab; - if (tca[TCA_RATE]) - gen_replace_estimator(&sch->bstats, &sch->rate_est, - qdisc_root_sleeping_lock(sch), - tca[TCA_RATE]); return 0; } --- a/net/sched/sch_cbq.c 2008-11-25 10:51:47.000000000 -0800 +++ b/net/sched/sch_cbq.c 2008-11-25 10:56:15.000000000 -0800 @@ -1765,11 +1765,23 @@ cbq_change_class(struct Qdisc *sch, u32 } 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 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 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 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; --- a/net/sched/sch_drr.c 2008-11-25 10:51:47.000000000 -0800 +++ b/net/sched/sch_drr.c 2008-11-25 10:54:16.000000000 -0800 @@ -82,15 +82,19 @@ static int drr_change_class(struct Qdisc 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 if (cl->qdisc == NULL) cl->qdisc = &noop_qdisc; - if (tca[TCA_RATE]) - gen_replace_estimator(&cl->bstats, &cl->rate_est, - qdisc_root_sleeping_lock(sch), - tca[TCA_RATE]); + 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); --- a/net/sched/sch_hfsc.c 2008-11-25 10:51:47.000000000 -0800 +++ b/net/sched/sch_hfsc.c 2008-11-25 10:54:16.000000000 -0800 @@ -1018,6 +1018,14 @@ hfsc_change_class(struct Qdisc *sch, u32 } 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 } 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; } --- a/net/sched/sch_htb.c 2008-11-25 10:51:47.000000000 -0800 +++ b/net/sched/sch_htb.c 2008-11-25 10:54:16.000000000 -0800 @@ -1332,9 +1332,14 @@ static int htb_change_class(struct Qdisc if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL) goto failure; - gen_new_estimator(&cl->bstats, &cl->rate_est, - qdisc_root_sleeping_lock(sch), - tca[TCA_RATE] ? : &est.nla); + err = gen_new_estimator(&cl->bstats, &cl->rate_est, + qdisc_root_sleeping_lock(sch), + tca[TCA_RATE] ? : &est.nla); + if (err) { + kfree(cl); + goto failure; + } + cl->refcnt = 1; cl->children = 0; INIT_LIST_HEAD(&cl->un.leaf.drop_list); @@ -1386,10 +1391,13 @@ static int htb_change_class(struct Qdisc if (parent) parent->children++; } else { - if (tca[TCA_RATE]) - gen_replace_estimator(&cl->bstats, &cl->rate_est, - qdisc_root_sleeping_lock(sch), - tca[TCA_RATE]); + 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); } ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1b/2] tc: check for errors in gen_rate_estimator creation 2008-11-25 18:58 ` [PATCH 1b/2] tc: check for errors in gen_rate_estimator creation Stephen Hemminger @ 2008-11-25 19:05 ` Patrick McHardy 2008-11-25 19:14 ` Stephen Hemminger 0 siblings, 1 reply; 18+ messages in thread From: Patrick McHardy @ 2008-11-25 19:05 UTC (permalink / raw) To: Stephen Hemminger; +Cc: David Miller, netdev Stephen Hemminger wrote: > The functions gen_new_estimator and gen_replace_estimator can return errors, > but they were being ignored. > > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> > > > --- > --- a/net/sched/sch_api.c 2008-11-25 10:51:47.000000000 -0800 > +++ b/net/sched/sch_api.c 2008-11-25 10:54:16.000000000 -0800 > @@ -887,6 +887,14 @@ static int qdisc_change(struct Qdisc *sc > return err; > } > > + if (tca[TCA_RATE]) { > + err = gen_replace_estimator(&sch->bstats, &sch->rate_est, > + qdisc_root_sleeping_lock(sch), > + tca[TCA_RATE]); > + if (err) > + return err; This appears to have the same problem as in HFSC unless I missed more code movement - changes to the qdisc have already been performed. > --- a/net/sched/sch_hfsc.c 2008-11-25 10:51:47.000000000 -0800 > +++ b/net/sched/sch_hfsc.c 2008-11-25 10:54:16.000000000 -0800 > @@ -1018,6 +1018,14 @@ hfsc_change_class(struct Qdisc *sch, u32 > } > 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 > } > 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; > } There's a gen_new_estimator() a few lines below that is still unchecked. The remaining ones look fine. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1b/2] tc: check for errors in gen_rate_estimator creation 2008-11-25 19:05 ` Patrick McHardy @ 2008-11-25 19:14 ` Stephen Hemminger 2008-11-25 19:19 ` Patrick McHardy 0 siblings, 1 reply; 18+ messages in thread From: Stephen Hemminger @ 2008-11-25 19:14 UTC (permalink / raw) To: Patrick McHardy; +Cc: David Miller, netdev On Tue, 25 Nov 2008 20:05:46 +0100 Patrick McHardy <kaber@trash.net> wrote: > Stephen Hemminger wrote: > > The functions gen_new_estimator and gen_replace_estimator can return errors, > > but they were being ignored. > > > > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> > > > > > > --- > > --- a/net/sched/sch_api.c 2008-11-25 10:51:47.000000000 -0800 > > +++ b/net/sched/sch_api.c 2008-11-25 10:54:16.000000000 -0800 > > @@ -887,6 +887,14 @@ static int qdisc_change(struct Qdisc *sc > > return err; > > } > > > > + if (tca[TCA_RATE]) { > > + err = gen_replace_estimator(&sch->bstats, &sch->rate_est, > > + qdisc_root_sleeping_lock(sch), > > + tca[TCA_RATE]); > > + if (err) > > + return err; > > This appears to have the same problem as in HFSC unless I missed more > code movement - changes to the qdisc have already been performed. That is not fixable since both change and replace_estimator are non-unwindable, and either one could fail. Could split checking and initialization out of gen_new_estimator, but is it worth it?? ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1b/2] tc: check for errors in gen_rate_estimator creation 2008-11-25 19:14 ` Stephen Hemminger @ 2008-11-25 19:19 ` Patrick McHardy 2008-11-25 19:25 ` Stephen Hemminger 0 siblings, 1 reply; 18+ messages in thread From: Patrick McHardy @ 2008-11-25 19:19 UTC (permalink / raw) To: Stephen Hemminger; +Cc: David Miller, netdev Stephen Hemminger wrote: > On Tue, 25 Nov 2008 20:05:46 +0100 > Patrick McHardy <kaber@trash.net> wrote: > >> Stephen Hemminger wrote: >>> The functions gen_new_estimator and gen_replace_estimator can return errors, >>> but they were being ignored. >>> >>> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> >>> >>> >>> --- >>> --- a/net/sched/sch_api.c 2008-11-25 10:51:47.000000000 -0800 >>> +++ b/net/sched/sch_api.c 2008-11-25 10:54:16.000000000 -0800 >>> @@ -887,6 +887,14 @@ static int qdisc_change(struct Qdisc *sc >>> return err; >>> } >>> >>> + if (tca[TCA_RATE]) { >>> + err = gen_replace_estimator(&sch->bstats, &sch->rate_est, >>> + qdisc_root_sleeping_lock(sch), >>> + tca[TCA_RATE]); >>> + if (err) >>> + return err; >> This appears to have the same problem as in HFSC unless I missed more >> code movement - changes to the qdisc have already been performed. > > That is not fixable since both change and replace_estimator are non-unwindable, > and either one could fail. Could split checking and initialization out of gen_new_estimator, > but is it worth it?? Probably not. I'd suggest to not return the estimator error in this spot instead. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1b/2] tc: check for errors in gen_rate_estimator creation 2008-11-25 19:19 ` Patrick McHardy @ 2008-11-25 19:25 ` Stephen Hemminger 2008-11-26 5:13 ` David Miller 0 siblings, 1 reply; 18+ messages in thread From: Stephen Hemminger @ 2008-11-25 19:25 UTC (permalink / raw) To: Patrick McHardy; +Cc: David Miller, netdev The functions gen_new_estimator and gen_replace_estimator can return errors, but they were being ignored. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> --- net/sched/act_police.c | 25 +++++++++++++++++-------- net/sched/sch_api.c | 7 +++++-- net/sched/sch_cbq.c | 33 ++++++++++++++++++++++++--------- net/sched/sch_drr.c | 26 ++++++++++++++++++-------- net/sched/sch_hfsc.c | 25 ++++++++++++++++++------- net/sched/sch_htb.c | 22 +++++++++++++++------- 6 files changed, 97 insertions(+), 41 deletions(-) --- a/net/sched/act_police.c 2008-11-25 10:51:47.000000000 -0800 +++ b/net/sched/act_police.c 2008-11-25 10:54:16.000000000 -0800 @@ -185,14 +185,21 @@ override: 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; - } } } - /* No failure allowed after this point */ + 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 */ if (R_tab != NULL) { qdisc_put_rtab(police->tcfp_R_tab); police->tcfp_R_tab = R_tab; @@ -217,10 +224,6 @@ override: 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 @@ override: 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; --- a/net/sched/sch_api.c 2008-11-25 10:51:47.000000000 -0800 +++ b/net/sched/sch_api.c 2008-11-25 11:23:19.000000000 -0800 @@ -897,9 +897,12 @@ static int qdisc_change(struct Qdisc *sc 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]); + qdisc_root_sleeping_lock(sch), + tca[TCA_RATE]); + return 0; } --- a/net/sched/sch_cbq.c 2008-11-25 10:51:47.000000000 -0800 +++ b/net/sched/sch_cbq.c 2008-11-25 10:56:15.000000000 -0800 @@ -1765,11 +1765,23 @@ cbq_change_class(struct Qdisc *sch, u32 } 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 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 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 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; --- a/net/sched/sch_drr.c 2008-11-25 10:51:47.000000000 -0800 +++ b/net/sched/sch_drr.c 2008-11-25 10:54:16.000000000 -0800 @@ -82,15 +82,19 @@ static int drr_change_class(struct Qdisc 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 if (cl->qdisc == NULL) cl->qdisc = &noop_qdisc; - if (tca[TCA_RATE]) - gen_replace_estimator(&cl->bstats, &cl->rate_est, - qdisc_root_sleeping_lock(sch), - tca[TCA_RATE]); + 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); --- a/net/sched/sch_hfsc.c 2008-11-25 10:51:47.000000000 -0800 +++ b/net/sched/sch_hfsc.c 2008-11-25 11:08:27.000000000 -0800 @@ -1018,6 +1018,14 @@ hfsc_change_class(struct Qdisc *sch, u32 } 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 } 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 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 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; } --- a/net/sched/sch_htb.c 2008-11-25 10:51:47.000000000 -0800 +++ b/net/sched/sch_htb.c 2008-11-25 10:54:16.000000000 -0800 @@ -1332,9 +1332,14 @@ static int htb_change_class(struct Qdisc if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL) goto failure; - gen_new_estimator(&cl->bstats, &cl->rate_est, - qdisc_root_sleeping_lock(sch), - tca[TCA_RATE] ? : &est.nla); + err = gen_new_estimator(&cl->bstats, &cl->rate_est, + qdisc_root_sleeping_lock(sch), + tca[TCA_RATE] ? : &est.nla); + if (err) { + kfree(cl); + goto failure; + } + cl->refcnt = 1; cl->children = 0; INIT_LIST_HEAD(&cl->un.leaf.drop_list); @@ -1386,10 +1391,13 @@ static int htb_change_class(struct Qdisc if (parent) parent->children++; } else { - if (tca[TCA_RATE]) - gen_replace_estimator(&cl->bstats, &cl->rate_est, - qdisc_root_sleeping_lock(sch), - tca[TCA_RATE]); + 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); } ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1b/2] tc: check for errors in gen_rate_estimator creation 2008-11-25 19:25 ` Stephen Hemminger @ 2008-11-26 5:13 ` David Miller 0 siblings, 0 replies; 18+ messages in thread From: David Miller @ 2008-11-26 5:13 UTC (permalink / raw) To: shemminger; +Cc: kaber, netdev From: Stephen Hemminger <shemminger@vyatta.com> Date: Tue, 25 Nov 2008 11:25:37 -0800 > The functions gen_new_estimator and gen_replace_estimator can return errors, > but they were being ignored. > > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Applied. ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2008-11-26 23:24 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-11-25 18:16 [PATCH 1/2] tc: check for errors from gen_replace_estimator Stephen Hemminger 2008-11-25 18:21 ` [PATCH 2/2] tc: policing requires a rate estimator Stephen Hemminger 2008-11-25 18:32 ` Patrick McHardy 2008-11-25 18:33 ` Stephen Hemminger 2008-11-25 18:38 ` Patrick McHardy 2008-11-26 5:14 ` David Miller 2008-11-26 11:10 ` [PATCH] pkt_sched: gen_estimator: Optimize gen_estimator_active() Jarek Poplawski 2008-11-26 16:29 ` Stephen Hemminger 2008-11-26 23:24 ` David Miller 2008-11-25 18:28 ` [PATCH 1/2] tc: check for errors from gen_replace_estimator Patrick McHardy 2008-11-25 18:57 ` [PATCH 1a/2] tc: propogate errors from tcf_hash_create Stephen Hemminger 2008-11-26 5:12 ` David Miller 2008-11-25 18:58 ` [PATCH 1b/2] tc: check for errors in gen_rate_estimator creation Stephen Hemminger 2008-11-25 19:05 ` Patrick McHardy 2008-11-25 19:14 ` Stephen Hemminger 2008-11-25 19:19 ` Patrick McHardy 2008-11-25 19:25 ` Stephen Hemminger 2008-11-26 5:13 ` David Miller
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).