net: sched: do not acquire qdisc spinlock in qdisc/class stats dump
[deliverable/linux.git] / net / sched / sch_fq_codel.c
index 6883a89715625fc7874780ef962e51dc7773a35b..1daa54237f4e80cdf4427d5ab028ba3afb607f00 100644 (file)
@@ -566,11 +566,13 @@ static int fq_codel_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
        st.qdisc_stats.memory_usage  = q->memory_usage;
        st.qdisc_stats.drop_overmemory = q->drop_overmemory;
 
+       sch_tree_lock(sch);
        list_for_each(pos, &q->new_flows)
                st.qdisc_stats.new_flows_len++;
 
        list_for_each(pos, &q->old_flows)
                st.qdisc_stats.old_flows_len++;
+       sch_tree_unlock(sch);
 
        return gnet_stats_copy_app(d, &st, sizeof(st));
 }
@@ -624,7 +626,7 @@ static int fq_codel_dump_class_stats(struct Qdisc *sch, unsigned long cl,
 
        if (idx < q->flows_cnt) {
                const struct fq_codel_flow *flow = &q->flows[idx];
-               const struct sk_buff *skb = flow->head;
+               const struct sk_buff *skb;
 
                memset(&xstats, 0, sizeof(xstats));
                xstats.type = TCA_FQ_CODEL_XSTATS_CLASS;
@@ -642,9 +644,14 @@ static int fq_codel_dump_class_stats(struct Qdisc *sch, unsigned long cl,
                                codel_time_to_us(delta) :
                                -codel_time_to_us(-delta);
                }
-               while (skb) {
-                       qs.qlen++;
-                       skb = skb->next;
+               if (flow->head) {
+                       sch_tree_lock(sch);
+                       skb = flow->head;
+                       while (skb) {
+                               qs.qlen++;
+                               skb = skb->next;
+                       }
+                       sch_tree_unlock(sch);
                }
                qs.backlog = q->backlogs[idx];
                qs.drops = flow->dropped;
This page took 0.025197 seconds and 5 git commands to generate.