pkt_sched: gen_estimator: Dont report fake rate estimators
[safe/jmp/linux-2.6] / net / sched / sch_hfsc.c
index 51dd3f4..b38b39c 100644 (file)
@@ -77,7 +77,7 @@
  *   The service curve parameters are converted to the internal
  *   representation. The slope values are scaled to avoid overflow.
  *   the inverse slope values as well as the y-projection of the 1st
- *   segment are kept in order to to avoid 64-bit divide operations
+ *   segment are kept in order to avoid 64-bit divide operations
  *   that are expensive on 32-bit architectures.
  */
 
@@ -116,7 +116,7 @@ struct hfsc_class
        struct Qdisc_class_common cl_common;
        unsigned int    refcnt;         /* usage count */
 
-       struct gnet_stats_basic bstats;
+       struct gnet_stats_basic_packed bstats;
        struct gnet_stats_queue qstats;
        struct gnet_stats_rate_est rate_est;
        unsigned int    level;          /* class level in hierarchy */
@@ -372,7 +372,7 @@ cftree_update(struct hfsc_class *cl)
  *     ism: (psched_us/byte) << ISM_SHIFT
  *     dx: psched_us
  *
- * The clock source resolution with ktime is 1.024us.
+ * The clock source resolution with ktime and PSCHED_SHIFT 10 is 1.024us.
  *
  * sm and ism are scaled in order to keep effective digits.
  * SM_SHIFT and ISM_SHIFT are selected to keep at least 4 effective
@@ -383,9 +383,11 @@ cftree_update(struct hfsc_class *cl)
  *  bytes/1.024us 12.8e-3    128e-3     1280e-3    12800e-3   128000e-3
  *
  *  1.024us/byte  78.125     7.8125     0.78125    0.078125   0.0078125
+ *
+ * So, for PSCHED_SHIFT 10 we need: SM_SHIFT 20, ISM_SHIFT 18.
  */
-#define        SM_SHIFT        20
-#define        ISM_SHIFT       18
+#define        SM_SHIFT        (30 - PSCHED_SHIFT)
+#define        ISM_SHIFT       (8 + PSCHED_SHIFT)
 
 #define        SM_MASK         ((1ULL << SM_SHIFT) - 1)
 #define        ISM_MASK        ((1ULL << ISM_SHIFT) - 1)
@@ -887,8 +889,7 @@ qdisc_peek_len(struct Qdisc *sch)
 
        skb = sch->ops->peek(sch);
        if (skb == NULL) {
-               if (net_ratelimit())
-                       printk("qdisc_peek_len: non work-conserving qdisc ?\n");
+               qdisc_warn_nonwc("qdisc_peek_len", sch);
                return 0;
        }
        len = qdisc_pkt_len(skb);
@@ -1018,6 +1019,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 +1043,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 +1068,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 +1108,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;
 }
@@ -1129,8 +1141,11 @@ hfsc_delete_class(struct Qdisc *sch, unsigned long arg)
        hfsc_purge_queue(sch, cl);
        qdisc_class_hash_remove(&q->clhash, &cl->cl_common);
 
-       if (--cl->refcnt == 0)
-               hfsc_destroy_class(sch, cl);
+       BUG_ON(--cl->refcnt == 0);
+       /*
+        * This shouldn't happen: we "hold" one cops->get() when called
+        * from tc_ctl_tclass; the destroy method is done from cops->put().
+        */
 
        sch_tree_unlock(sch);
        return 0;
@@ -1188,8 +1203,6 @@ hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
 {
        struct hfsc_class *cl = (struct hfsc_class *)arg;
 
-       if (cl == NULL)
-               return -ENOENT;
        if (cl->level > 0)
                return -EINVAL;
        if (new == NULL) {
@@ -1213,7 +1226,7 @@ hfsc_class_leaf(struct Qdisc *sch, unsigned long arg)
 {
        struct hfsc_class *cl = (struct hfsc_class *)arg;
 
-       if (cl != NULL && cl->level == 0)
+       if (cl->level == 0)
                return cl->qdisc;
 
        return NULL;
@@ -1362,7 +1375,7 @@ hfsc_dump_class_stats(struct Qdisc *sch, unsigned long arg,
        xstats.rtwork  = cl->cl_cumul;
 
        if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
-           gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
+           gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
            gnet_stats_copy_queue(d, &cl->qstats) < 0)
                return -1;
 
@@ -1563,7 +1576,7 @@ static int
 hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
        struct hfsc_class *cl;
-       int err;
+       int uninitialized_var(err);
 
        cl = hfsc_classify(skb, sch, &err);
        if (cl == NULL) {
@@ -1631,8 +1644,7 @@ hfsc_dequeue(struct Qdisc *sch)
 
        skb = qdisc_dequeue_peeked(cl->qdisc);
        if (skb == NULL) {
-               if (net_ratelimit())
-                       printk("HFSC: Non-work-conserving qdisc ?\n");
+               qdisc_warn_nonwc("HFSC", cl->qdisc);
                return NULL;
        }