Merge branch 'for-3.18/core' of git://git.kernel.dk/linux-block
[firefly-linux-kernel-4.4.55.git] / net / sched / sch_prio.c
index 79359b69ad8d6fcf35b6937673d4ae332bbf5158..8e5cd34aaa74dbaddc4b38be4916bb79526e90fb 100644 (file)
@@ -24,7 +24,7 @@
 
 struct prio_sched_data {
        int bands;
-       struct tcf_proto *filter_list;
+       struct tcf_proto __rcu *filter_list;
        u8  prio2band[TC_PRIO_MAX+1];
        struct Qdisc *queues[TCQ_PRIO_BANDS];
 };
@@ -36,11 +36,13 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
        struct prio_sched_data *q = qdisc_priv(sch);
        u32 band = skb->priority;
        struct tcf_result res;
+       struct tcf_proto *fl;
        int err;
 
        *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
        if (TC_H_MAJ(skb->priority) != sch->handle) {
-               err = tc_classify(skb, q->filter_list, &res);
+               fl = rcu_dereference_bh(q->filter_list);
+               err = tc_classify(skb, fl, &res);
 #ifdef CONFIG_NET_CLS_ACT
                switch (err) {
                case TC_ACT_STOLEN:
@@ -50,7 +52,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
                        return NULL;
                }
 #endif
-               if (!q->filter_list || err < 0) {
+               if (!fl || err < 0) {
                        if (TC_H_MAJ(band))
                                band = 0;
                        return q->queues[q->prio2band[band & TC_PRIO_MAX]];
@@ -75,7 +77,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        if (qdisc == NULL) {
 
                if (ret & __NET_XMIT_BYPASS)
-                       sch->qstats.drops++;
+                       qdisc_qstats_drop(sch);
                kfree_skb(skb);
                return ret;
        }
@@ -87,7 +89,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                return NET_XMIT_SUCCESS;
        }
        if (net_xmit_drop_count(ret))
-               sch->qstats.drops++;
+               qdisc_qstats_drop(sch);
        return ret;
 }
 
@@ -322,9 +324,8 @@ static int prio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
        struct Qdisc *cl_q;
 
        cl_q = q->queues[cl - 1];
-       cl_q->qstats.qlen = cl_q->q.qlen;
-       if (gnet_stats_copy_basic(d, &cl_q->bstats) < 0 ||
-           gnet_stats_copy_queue(d, &cl_q->qstats) < 0)
+       if (gnet_stats_copy_basic(d, NULL, &cl_q->bstats) < 0 ||
+           gnet_stats_copy_queue(d, NULL, &cl_q->qstats, cl_q->q.qlen) < 0)
                return -1;
 
        return 0;
@@ -351,7 +352,8 @@ static void prio_walk(struct Qdisc *sch, struct qdisc_walker *arg)
        }
 }
 
-static struct tcf_proto **prio_find_tcf(struct Qdisc *sch, unsigned long cl)
+static struct tcf_proto __rcu **prio_find_tcf(struct Qdisc *sch,
+                                             unsigned long cl)
 {
        struct prio_sched_data *q = qdisc_priv(sch);