net: sched: do not acquire qdisc spinlock in qdisc/class stats dump
[deliverable/linux.git] / include / net / sch_generic.h
index 46e55f0202a61b9be253422b4c32cee4f9f6d911..c4f5749342ecc5554f70a2971832ab5ba88da1a1 100644 (file)
@@ -29,13 +29,6 @@ enum qdisc_state_t {
        __QDISC_STATE_THROTTLED,
 };
 
-/*
- * following bits are only changed while qdisc lock is held
- */
-enum qdisc___state_t {
-       __QDISC___STATE_RUNNING = 1,
-};
-
 struct qdisc_size_table {
        struct rcu_head         rcu;
        struct list_head        list;
@@ -93,7 +86,7 @@ struct Qdisc {
        unsigned long           state;
        struct sk_buff_head     q;
        struct gnet_stats_basic_packed bstats;
-       unsigned int            __state;
+       seqcount_t              running;
        struct gnet_stats_queue qstats;
        struct rcu_head         rcu_head;
        int                     padded;
@@ -104,20 +97,20 @@ struct Qdisc {
 
 static inline bool qdisc_is_running(const struct Qdisc *qdisc)
 {
-       return (qdisc->__state & __QDISC___STATE_RUNNING) ? true : false;
+       return (raw_read_seqcount(&qdisc->running) & 1) ? true : false;
 }
 
 static inline bool qdisc_run_begin(struct Qdisc *qdisc)
 {
        if (qdisc_is_running(qdisc))
                return false;
-       qdisc->__state |= __QDISC___STATE_RUNNING;
+       write_seqcount_begin(&qdisc->running);
        return true;
 }
 
 static inline void qdisc_run_end(struct Qdisc *qdisc)
 {
-       qdisc->__state &= ~__QDISC___STATE_RUNNING;
+       write_seqcount_end(&qdisc->running);
 }
 
 static inline bool qdisc_may_bulk(const struct Qdisc *qdisc)
@@ -321,6 +314,14 @@ static inline spinlock_t *qdisc_root_sleeping_lock(const struct Qdisc *qdisc)
        return qdisc_lock(root);
 }
 
+static inline seqcount_t *qdisc_root_sleeping_running(const struct Qdisc *qdisc)
+{
+       struct Qdisc *root = qdisc_root_sleeping(qdisc);
+
+       ASSERT_RTNL();
+       return &root->running;
+}
+
 static inline struct net_device *qdisc_dev(const struct Qdisc *qdisc)
 {
        return qdisc->dev_queue->dev;
@@ -527,11 +528,27 @@ static inline bool qdisc_is_percpu_stats(const struct Qdisc *q)
        return q->flags & TCQ_F_CPUSTATS;
 }
 
+static inline void _bstats_update(struct gnet_stats_basic_packed *bstats,
+                                 __u64 bytes, __u32 packets)
+{
+       bstats->bytes += bytes;
+       bstats->packets += packets;
+}
+
 static inline void bstats_update(struct gnet_stats_basic_packed *bstats,
                                 const struct sk_buff *skb)
 {
-       bstats->bytes += qdisc_pkt_len(skb);
-       bstats->packets += skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1;
+       _bstats_update(bstats,
+                      qdisc_pkt_len(skb),
+                      skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1);
+}
+
+static inline void _bstats_cpu_update(struct gnet_stats_basic_cpu *bstats,
+                                     __u64 bytes, __u32 packets)
+{
+       u64_stats_update_begin(&bstats->syncp);
+       _bstats_update(&bstats->bstats, bytes, packets);
+       u64_stats_update_end(&bstats->syncp);
 }
 
 static inline void bstats_cpu_update(struct gnet_stats_basic_cpu *bstats,
This page took 0.025868 seconds and 5 git commands to generate.