diff options
author | Stephen Hemminger <shemminger@vyatta.com> | 2008-11-26 00:13:31 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-26 00:13:31 -0500 |
commit | 71bcb09a57894fa35591ce93dd972065eeecb63a (patch) | |
tree | 50ca8a43125f0aa89f1444928a209420754a79f3 /net/sched | |
parent | 0e991ec6a0340916d3f29bd5dcb35299069e7226 (diff) |
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: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/act_police.c | 25 | ||||
-rw-r--r-- | net/sched/sch_api.c | 7 | ||||
-rw-r--r-- | net/sched/sch_cbq.c | 33 | ||||
-rw-r--r-- | net/sched/sch_drr.c | 26 | ||||
-rw-r--r-- | net/sched/sch_hfsc.c | 25 | ||||
-rw-r--r-- | net/sched/sch_htb.c | 22 |
6 files changed, 97 insertions, 41 deletions
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 38015b493947..e19a0261144a 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
@@ -185,14 +185,21 @@ override: | |||
185 | if (parm->peakrate.rate) { | 185 | if (parm->peakrate.rate) { |
186 | P_tab = qdisc_get_rtab(&parm->peakrate, | 186 | P_tab = qdisc_get_rtab(&parm->peakrate, |
187 | tb[TCA_POLICE_PEAKRATE]); | 187 | tb[TCA_POLICE_PEAKRATE]); |
188 | if (P_tab == NULL) { | 188 | if (P_tab == NULL) |
189 | qdisc_put_rtab(R_tab); | ||
190 | goto failure; | 189 | goto failure; |
191 | } | ||
192 | } | 190 | } |
193 | } | 191 | } |
194 | /* No failure allowed after this point */ | 192 | |
195 | spin_lock_bh(&police->tcf_lock); | 193 | spin_lock_bh(&police->tcf_lock); |
194 | if (est) { | ||
195 | err = gen_replace_estimator(&police->tcf_bstats, | ||
196 | &police->tcf_rate_est, | ||
197 | &police->tcf_lock, est); | ||
198 | if (err) | ||
199 | goto failure_unlock; | ||
200 | } | ||
201 | |||
202 | /* No failure allowed after this point */ | ||
196 | if (R_tab != NULL) { | 203 | if (R_tab != NULL) { |
197 | qdisc_put_rtab(police->tcfp_R_tab); | 204 | qdisc_put_rtab(police->tcfp_R_tab); |
198 | police->tcfp_R_tab = R_tab; | 205 | police->tcfp_R_tab = R_tab; |
@@ -217,10 +224,6 @@ override: | |||
217 | 224 | ||
218 | if (tb[TCA_POLICE_AVRATE]) | 225 | if (tb[TCA_POLICE_AVRATE]) |
219 | police->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]); | 226 | police->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]); |
220 | if (est) | ||
221 | gen_replace_estimator(&police->tcf_bstats, | ||
222 | &police->tcf_rate_est, | ||
223 | &police->tcf_lock, est); | ||
224 | 227 | ||
225 | spin_unlock_bh(&police->tcf_lock); | 228 | spin_unlock_bh(&police->tcf_lock); |
226 | if (ret != ACT_P_CREATED) | 229 | if (ret != ACT_P_CREATED) |
@@ -238,7 +241,13 @@ override: | |||
238 | a->priv = police; | 241 | a->priv = police; |
239 | return ret; | 242 | return ret; |
240 | 243 | ||
244 | failure_unlock: | ||
245 | spin_unlock_bh(&police->tcf_lock); | ||
241 | failure: | 246 | failure: |
247 | if (P_tab) | ||
248 | qdisc_put_rtab(P_tab); | ||
249 | if (R_tab) | ||
250 | qdisc_put_rtab(R_tab); | ||
242 | if (ret == ACT_P_CREATED) | 251 | if (ret == ACT_P_CREATED) |
243 | kfree(police); | 252 | kfree(police); |
244 | return err; | 253 | return err; |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 3fcfd4ef11d1..f859dd5fabf4 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -880,9 +880,12 @@ static int qdisc_change(struct Qdisc *sch, struct nlattr **tca) | |||
880 | sch->stab = stab; | 880 | sch->stab = stab; |
881 | 881 | ||
882 | if (tca[TCA_RATE]) | 882 | if (tca[TCA_RATE]) |
883 | /* NB: ignores errors from replace_estimator | ||
884 | because change can't be undone. */ | ||
883 | gen_replace_estimator(&sch->bstats, &sch->rate_est, | 885 | gen_replace_estimator(&sch->bstats, &sch->rate_est, |
884 | qdisc_root_sleeping_lock(sch), | 886 | qdisc_root_sleeping_lock(sch), |
885 | tca[TCA_RATE]); | 887 | tca[TCA_RATE]); |
888 | |||
886 | return 0; | 889 | return 0; |
887 | } | 890 | } |
888 | 891 | ||
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 3a9569a3396c..9e43ed949167 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c | |||
@@ -1765,11 +1765,23 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t | |||
1765 | } | 1765 | } |
1766 | 1766 | ||
1767 | if (tb[TCA_CBQ_RATE]) { | 1767 | if (tb[TCA_CBQ_RATE]) { |
1768 | rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB]); | 1768 | rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), |
1769 | tb[TCA_CBQ_RTAB]); | ||
1769 | if (rtab == NULL) | 1770 | if (rtab == NULL) |
1770 | return -EINVAL; | 1771 | return -EINVAL; |
1771 | } | 1772 | } |
1772 | 1773 | ||
1774 | if (tca[TCA_RATE]) { | ||
1775 | err = gen_replace_estimator(&cl->bstats, &cl->rate_est, | ||
1776 | qdisc_root_sleeping_lock(sch), | ||
1777 | tca[TCA_RATE]); | ||
1778 | if (err) { | ||
1779 | if (rtab) | ||
1780 | qdisc_put_rtab(rtab); | ||
1781 | return err; | ||
1782 | } | ||
1783 | } | ||
1784 | |||
1773 | /* Change class parameters */ | 1785 | /* Change class parameters */ |
1774 | sch_tree_lock(sch); | 1786 | sch_tree_lock(sch); |
1775 | 1787 | ||
@@ -1805,10 +1817,6 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t | |||
1805 | 1817 | ||
1806 | sch_tree_unlock(sch); | 1818 | sch_tree_unlock(sch); |
1807 | 1819 | ||
1808 | if (tca[TCA_RATE]) | ||
1809 | gen_replace_estimator(&cl->bstats, &cl->rate_est, | ||
1810 | qdisc_root_sleeping_lock(sch), | ||
1811 | tca[TCA_RATE]); | ||
1812 | return 0; | 1820 | return 0; |
1813 | } | 1821 | } |
1814 | 1822 | ||
@@ -1855,6 +1863,17 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t | |||
1855 | cl = kzalloc(sizeof(*cl), GFP_KERNEL); | 1863 | cl = kzalloc(sizeof(*cl), GFP_KERNEL); |
1856 | if (cl == NULL) | 1864 | if (cl == NULL) |
1857 | goto failure; | 1865 | goto failure; |
1866 | |||
1867 | if (tca[TCA_RATE]) { | ||
1868 | err = gen_new_estimator(&cl->bstats, &cl->rate_est, | ||
1869 | qdisc_root_sleeping_lock(sch), | ||
1870 | tca[TCA_RATE]); | ||
1871 | if (err) { | ||
1872 | kfree(cl); | ||
1873 | goto failure; | ||
1874 | } | ||
1875 | } | ||
1876 | |||
1858 | cl->R_tab = rtab; | 1877 | cl->R_tab = rtab; |
1859 | rtab = NULL; | 1878 | rtab = NULL; |
1860 | cl->refcnt = 1; | 1879 | cl->refcnt = 1; |
@@ -1896,10 +1915,6 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t | |||
1896 | 1915 | ||
1897 | qdisc_class_hash_grow(sch, &q->clhash); | 1916 | qdisc_class_hash_grow(sch, &q->clhash); |
1898 | 1917 | ||
1899 | if (tca[TCA_RATE]) | ||
1900 | gen_new_estimator(&cl->bstats, &cl->rate_est, | ||
1901 | qdisc_root_sleeping_lock(sch), tca[TCA_RATE]); | ||
1902 | |||
1903 | *arg = (unsigned long)cl; | 1918 | *arg = (unsigned long)cl; |
1904 | return 0; | 1919 | return 0; |
1905 | 1920 | ||
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index e7a7e87b141a..f6b4fa97df70 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c | |||
@@ -82,15 +82,19 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
82 | quantum = psched_mtu(qdisc_dev(sch)); | 82 | quantum = psched_mtu(qdisc_dev(sch)); |
83 | 83 | ||
84 | if (cl != NULL) { | 84 | if (cl != NULL) { |
85 | if (tca[TCA_RATE]) { | ||
86 | err = gen_replace_estimator(&cl->bstats, &cl->rate_est, | ||
87 | qdisc_root_sleeping_lock(sch), | ||
88 | tca[TCA_RATE]); | ||
89 | if (err) | ||
90 | return err; | ||
91 | } | ||
92 | |||
85 | sch_tree_lock(sch); | 93 | sch_tree_lock(sch); |
86 | if (tb[TCA_DRR_QUANTUM]) | 94 | if (tb[TCA_DRR_QUANTUM]) |
87 | cl->quantum = quantum; | 95 | cl->quantum = quantum; |
88 | sch_tree_unlock(sch); | 96 | sch_tree_unlock(sch); |
89 | 97 | ||
90 | if (tca[TCA_RATE]) | ||
91 | gen_replace_estimator(&cl->bstats, &cl->rate_est, | ||
92 | qdisc_root_sleeping_lock(sch), | ||
93 | tca[TCA_RATE]); | ||
94 | return 0; | 98 | return 0; |
95 | } | 99 | } |
96 | 100 | ||
@@ -106,10 +110,16 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
106 | if (cl->qdisc == NULL) | 110 | if (cl->qdisc == NULL) |
107 | cl->qdisc = &noop_qdisc; | 111 | cl->qdisc = &noop_qdisc; |
108 | 112 | ||
109 | if (tca[TCA_RATE]) | 113 | if (tca[TCA_RATE]) { |
110 | gen_replace_estimator(&cl->bstats, &cl->rate_est, | 114 | err = gen_replace_estimator(&cl->bstats, &cl->rate_est, |
111 | qdisc_root_sleeping_lock(sch), | 115 | qdisc_root_sleeping_lock(sch), |
112 | tca[TCA_RATE]); | 116 | tca[TCA_RATE]); |
117 | if (err) { | ||
118 | qdisc_destroy(cl->qdisc); | ||
119 | kfree(cl); | ||
120 | return err; | ||
121 | } | ||
122 | } | ||
113 | 123 | ||
114 | sch_tree_lock(sch); | 124 | sch_tree_lock(sch); |
115 | qdisc_class_hash_insert(&q->clhash, &cl->common); | 125 | qdisc_class_hash_insert(&q->clhash, &cl->common); |
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 613179c9969c..45c31b1a4e1d 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
@@ -1018,6 +1018,14 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1018 | } | 1018 | } |
1019 | cur_time = psched_get_time(); | 1019 | cur_time = psched_get_time(); |
1020 | 1020 | ||
1021 | if (tca[TCA_RATE]) { | ||
1022 | err = gen_replace_estimator(&cl->bstats, &cl->rate_est, | ||
1023 | qdisc_root_sleeping_lock(sch), | ||
1024 | tca[TCA_RATE]); | ||
1025 | if (err) | ||
1026 | return err; | ||
1027 | } | ||
1028 | |||
1021 | sch_tree_lock(sch); | 1029 | sch_tree_lock(sch); |
1022 | if (rsc != NULL) | 1030 | if (rsc != NULL) |
1023 | hfsc_change_rsc(cl, rsc, cur_time); | 1031 | hfsc_change_rsc(cl, rsc, cur_time); |
@@ -1034,10 +1042,6 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1034 | } | 1042 | } |
1035 | sch_tree_unlock(sch); | 1043 | sch_tree_unlock(sch); |
1036 | 1044 | ||
1037 | if (tca[TCA_RATE]) | ||
1038 | gen_replace_estimator(&cl->bstats, &cl->rate_est, | ||
1039 | qdisc_root_sleeping_lock(sch), | ||
1040 | tca[TCA_RATE]); | ||
1041 | return 0; | 1045 | return 0; |
1042 | } | 1046 | } |
1043 | 1047 | ||
@@ -1063,6 +1067,16 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1063 | if (cl == NULL) | 1067 | if (cl == NULL) |
1064 | return -ENOBUFS; | 1068 | return -ENOBUFS; |
1065 | 1069 | ||
1070 | if (tca[TCA_RATE]) { | ||
1071 | err = gen_new_estimator(&cl->bstats, &cl->rate_est, | ||
1072 | qdisc_root_sleeping_lock(sch), | ||
1073 | tca[TCA_RATE]); | ||
1074 | if (err) { | ||
1075 | kfree(cl); | ||
1076 | return err; | ||
1077 | } | ||
1078 | } | ||
1079 | |||
1066 | if (rsc != NULL) | 1080 | if (rsc != NULL) |
1067 | hfsc_change_rsc(cl, rsc, 0); | 1081 | hfsc_change_rsc(cl, rsc, 0); |
1068 | if (fsc != NULL) | 1082 | if (fsc != NULL) |
@@ -1093,9 +1107,6 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1093 | 1107 | ||
1094 | qdisc_class_hash_grow(sch, &q->clhash); | 1108 | qdisc_class_hash_grow(sch, &q->clhash); |
1095 | 1109 | ||
1096 | if (tca[TCA_RATE]) | ||
1097 | gen_new_estimator(&cl->bstats, &cl->rate_est, | ||
1098 | qdisc_root_sleeping_lock(sch), tca[TCA_RATE]); | ||
1099 | *arg = (unsigned long)cl; | 1110 | *arg = (unsigned long)cl; |
1100 | return 0; | 1111 | return 0; |
1101 | } | 1112 | } |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 3a119f576bb3..8a4519989732 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -1332,9 +1332,14 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1332 | if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL) | 1332 | if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL) |
1333 | goto failure; | 1333 | goto failure; |
1334 | 1334 | ||
1335 | gen_new_estimator(&cl->bstats, &cl->rate_est, | 1335 | err = gen_new_estimator(&cl->bstats, &cl->rate_est, |
1336 | qdisc_root_sleeping_lock(sch), | 1336 | qdisc_root_sleeping_lock(sch), |
1337 | tca[TCA_RATE] ? : &est.nla); | 1337 | tca[TCA_RATE] ? : &est.nla); |
1338 | if (err) { | ||
1339 | kfree(cl); | ||
1340 | goto failure; | ||
1341 | } | ||
1342 | |||
1338 | cl->refcnt = 1; | 1343 | cl->refcnt = 1; |
1339 | cl->children = 0; | 1344 | cl->children = 0; |
1340 | INIT_LIST_HEAD(&cl->un.leaf.drop_list); | 1345 | INIT_LIST_HEAD(&cl->un.leaf.drop_list); |
@@ -1386,10 +1391,13 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1386 | if (parent) | 1391 | if (parent) |
1387 | parent->children++; | 1392 | parent->children++; |
1388 | } else { | 1393 | } else { |
1389 | if (tca[TCA_RATE]) | 1394 | if (tca[TCA_RATE]) { |
1390 | gen_replace_estimator(&cl->bstats, &cl->rate_est, | 1395 | err = gen_replace_estimator(&cl->bstats, &cl->rate_est, |
1391 | qdisc_root_sleeping_lock(sch), | 1396 | qdisc_root_sleeping_lock(sch), |
1392 | tca[TCA_RATE]); | 1397 | tca[TCA_RATE]); |
1398 | if (err) | ||
1399 | return err; | ||
1400 | } | ||
1393 | sch_tree_lock(sch); | 1401 | sch_tree_lock(sch); |
1394 | } | 1402 | } |
1395 | 1403 | ||