int gnet_stats_copy_rate_est(struct gnet_dump *d,
                             const struct gnet_stats_basic_packed *b,
                             struct gnet_stats_rate_est64 *r);
-int gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue *q);
+int gnet_stats_copy_queue(struct gnet_dump *d,
+                         struct gnet_stats_queue *q, __u32 len);
 int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len);
 
 int gnet_stats_finish_copy(struct gnet_dump *d);
 
  * gnet_stats_copy_queue - copy queue statistics into statistics TLV
  * @d: dumping handle
  * @q: queue statistics
+ * @qlen: queue length statistics
  *
  * Appends the queue statistics to the top level TLV created by
  * gnet_stats_start_copy().
  * if the room in the socket buffer was not sufficient.
  */
 int
-gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue *q)
+gnet_stats_copy_queue(struct gnet_dump *d,
+                     struct gnet_stats_queue *q, __u32 qlen)
 {
+       q->qlen = qlen;
+
        if (d->compat_tc_stats) {
                d->tc_stats.drops = q->drops;
                d->tc_stats.qlen = q->qlen;
 
        if (gnet_stats_copy_basic(&d, NULL, &p->tcfc_bstats) < 0 ||
            gnet_stats_copy_rate_est(&d, &p->tcfc_bstats,
                                     &p->tcfc_rate_est) < 0 ||
-           gnet_stats_copy_queue(&d, &p->tcfc_qstats) < 0)
+           gnet_stats_copy_queue(&d,
+                                 &p->tcfc_qstats,
+                                 p->tcfc_qstats.qlen) < 0)
                goto errout;
 
        if (gnet_stats_finish_copy(&d) < 0)
 
        unsigned char *b = skb_tail_pointer(skb);
        struct gnet_dump d;
        struct qdisc_size_table *stab;
+       __u32 qlen;
 
        cond_resched();
        nlh = nlmsg_put(skb, portid, seq, event, sizeof(*tcm), flags);
                goto nla_put_failure;
        if (q->ops->dump && q->ops->dump(q, skb) < 0)
                goto nla_put_failure;
-       q->qstats.qlen = q->q.qlen;
+       qlen = q->q.qlen;
 
        stab = rtnl_dereference(q->stab);
        if (stab && qdisc_dump_stab(skb, stab) < 0)
 
        if (gnet_stats_copy_basic(&d, cpu_bstats, &q->bstats) < 0 ||
            gnet_stats_copy_rate_est(&d, &q->bstats, &q->rate_est) < 0 ||
-           gnet_stats_copy_queue(&d, &q->qstats) < 0)
+           gnet_stats_copy_queue(&d, &q->qstats, qlen) < 0)
                goto nla_put_failure;
 
        if (gnet_stats_finish_copy(&d) < 0)
 
 {
        struct atm_flow_data *flow = (struct atm_flow_data *)arg;
 
-       flow->qstats.qlen = flow->q->q.qlen;
-
        if (gnet_stats_copy_basic(d, NULL, &flow->bstats) < 0 ||
-           gnet_stats_copy_queue(d, &flow->qstats) < 0)
+           gnet_stats_copy_queue(d, &flow->qstats, flow->q->q.qlen) < 0)
                return -1;
 
        return 0;
 
        struct cbq_sched_data *q = qdisc_priv(sch);
        struct cbq_class *cl = (struct cbq_class *)arg;
 
-       cl->qstats.qlen = cl->q->q.qlen;
        cl->xstats.avgidle = cl->avgidle;
        cl->xstats.undertime = 0;
 
 
        if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 ||
            gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
-           gnet_stats_copy_queue(d, &cl->qstats) < 0)
+           gnet_stats_copy_queue(d, &cl->qstats, cl->q->q.qlen) < 0)
                return -1;
 
        return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));
 
                                struct gnet_dump *d)
 {
        struct drr_class *cl = (struct drr_class *)arg;
+       __u32 qlen = cl->qdisc->q.qlen;
        struct tc_drr_stats xstats;
 
        memset(&xstats, 0, sizeof(xstats));
-       if (cl->qdisc->q.qlen) {
+       if (qlen)
                xstats.deficit = cl->deficit;
-               cl->qdisc->qstats.qlen = cl->qdisc->q.qlen;
-       }
 
        if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 ||
            gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
-           gnet_stats_copy_queue(d, &cl->qdisc->qstats) < 0)
+           gnet_stats_copy_queue(d, &cl->qdisc->qstats, qlen) < 0)
                return -1;
 
        return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
 
                qs.backlog = q->backlogs[idx];
                qs.drops = flow->dropped;
        }
-       if (gnet_stats_copy_queue(d, &qs) < 0)
+       if (gnet_stats_copy_queue(d, &qs, 0) < 0)
                return -1;
        if (idx < q->flows_cnt)
                return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
 
        struct hfsc_class *cl = (struct hfsc_class *)arg;
        struct tc_hfsc_stats xstats;
 
-       cl->qstats.qlen = cl->qdisc->q.qlen;
        cl->qstats.backlog = cl->qdisc->qstats.backlog;
        xstats.level   = cl->level;
        xstats.period  = cl->cl_vtperiod;
 
        if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 ||
            gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
-           gnet_stats_copy_queue(d, &cl->qstats) < 0)
+           gnet_stats_copy_queue(d, &cl->qstats, cl->qdisc->q.qlen) < 0)
                return -1;
 
        return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
 
 htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
 {
        struct htb_class *cl = (struct htb_class *)arg;
+       __u32 qlen = 0;
 
        if (!cl->level && cl->un.leaf.q)
-               cl->qstats.qlen = cl->un.leaf.q->q.qlen;
+               qlen = cl->un.leaf.q->q.qlen;
        cl->xstats.tokens = PSCHED_NS2TICKS(cl->tokens);
        cl->xstats.ctokens = PSCHED_NS2TICKS(cl->ctokens);
 
        if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 ||
            gnet_stats_copy_rate_est(d, NULL, &cl->rate_est) < 0 ||
-           gnet_stats_copy_queue(d, &cl->qstats) < 0)
+           gnet_stats_copy_queue(d, &cl->qstats, qlen) < 0)
                return -1;
 
        return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));
 
                sch->q.qlen             += qdisc->q.qlen;
                sch->bstats.bytes       += qdisc->bstats.bytes;
                sch->bstats.packets     += qdisc->bstats.packets;
-               sch->qstats.qlen        += qdisc->qstats.qlen;
                sch->qstats.backlog     += qdisc->qstats.backlog;
                sch->qstats.drops       += qdisc->qstats.drops;
                sch->qstats.requeues    += qdisc->qstats.requeues;
        struct netdev_queue *dev_queue = mq_queue_get(sch, cl);
 
        sch = dev_queue->qdisc_sleeping;
-       sch->qstats.qlen = sch->q.qlen;
        if (gnet_stats_copy_basic(d, NULL, &sch->bstats) < 0 ||
-           gnet_stats_copy_queue(d, &sch->qstats) < 0)
+           gnet_stats_copy_queue(d, &sch->qstats, sch->q.qlen) < 0)
                return -1;
        return 0;
 }
 
                sch->q.qlen             += qdisc->q.qlen;
                sch->bstats.bytes       += qdisc->bstats.bytes;
                sch->bstats.packets     += qdisc->bstats.packets;
-               sch->qstats.qlen        += qdisc->qstats.qlen;
                sch->qstats.backlog     += qdisc->qstats.backlog;
                sch->qstats.drops       += qdisc->qstats.drops;
                sch->qstats.requeues    += qdisc->qstats.requeues;
 
        if (cl <= netdev_get_num_tc(dev)) {
                int i;
+               __u32 qlen = 0;
                struct Qdisc *qdisc;
                struct gnet_stats_queue qstats = {0};
                struct gnet_stats_basic_packed bstats = {0};
 
                        qdisc = rtnl_dereference(q->qdisc);
                        spin_lock_bh(qdisc_lock(qdisc));
+                       qlen              += qdisc->q.qlen;
                        bstats.bytes      += qdisc->bstats.bytes;
                        bstats.packets    += qdisc->bstats.packets;
-                       qstats.qlen       += qdisc->qstats.qlen;
                        qstats.backlog    += qdisc->qstats.backlog;
                        qstats.drops      += qdisc->qstats.drops;
                        qstats.requeues   += qdisc->qstats.requeues;
                /* Reclaim root sleeping lock before completing stats */
                spin_lock_bh(d->lock);
                if (gnet_stats_copy_basic(d, NULL, &bstats) < 0 ||
-                   gnet_stats_copy_queue(d, &qstats) < 0)
+                   gnet_stats_copy_queue(d, &qstats, qlen) < 0)
                        return -1;
        } else {
                struct netdev_queue *dev_queue = mqprio_queue_get(sch, cl);
 
                sch = dev_queue->qdisc_sleeping;
-               sch->qstats.qlen = sch->q.qlen;
                if (gnet_stats_copy_basic(d, NULL, &sch->bstats) < 0 ||
-                   gnet_stats_copy_queue(d, &sch->qstats) < 0)
+                   gnet_stats_copy_queue(d, &sch->qstats, sch->q.qlen) < 0)
                        return -1;
        }
        return 0;
 
        struct Qdisc *cl_q;
 
        cl_q = q->queues[cl - 1];
-       cl_q->qstats.qlen = cl_q->q.qlen;
        if (gnet_stats_copy_basic(d, NULL, &cl_q->bstats) < 0 ||
-           gnet_stats_copy_queue(d, &cl_q->qstats) < 0)
+           gnet_stats_copy_queue(d, &cl_q->qstats, cl_q->q.qlen) < 0)
                return -1;
 
        return 0;
 
        struct Qdisc *cl_q;
 
        cl_q = q->queues[cl - 1];
-       cl_q->qstats.qlen = cl_q->q.qlen;
        if (gnet_stats_copy_basic(d, NULL, &cl_q->bstats) < 0 ||
-           gnet_stats_copy_queue(d, &cl_q->qstats) < 0)
+           gnet_stats_copy_queue(d, &cl_q->qstats, cl_q->q.qlen) < 0)
                return -1;
 
        return 0;
 
        struct tc_qfq_stats xstats;
 
        memset(&xstats, 0, sizeof(xstats));
-       cl->qdisc->qstats.qlen = cl->qdisc->q.qlen;
 
        xstats.weight = cl->agg->class_weight;
        xstats.lmax = cl->agg->lmax;
 
        if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 ||
            gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
-           gnet_stats_copy_queue(d, &cl->qdisc->qstats) < 0)
+           gnet_stats_copy_queue(d, &cl->qdisc->qstats, cl->qdisc->q.qlen) < 0)
                return -1;
 
        return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
 
                qs.qlen = slot->qlen;
                qs.backlog = slot->backlog;
        }
-       if (gnet_stats_copy_queue(d, &qs) < 0)
+       if (gnet_stats_copy_queue(d, &qs, qs.qlen) < 0)
                return -1;
        return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
 }