net: sched: make bstats per cpu and estimator RCU safe
[cascardo/linux.git] / net / sched / sch_multiq.c
index afb050a..4adbf7f 100644 (file)
@@ -31,7 +31,7 @@ struct multiq_sched_data {
        u16 bands;
        u16 max_bands;
        u16 curband;
-       struct tcf_proto *filter_list;
+       struct tcf_proto __rcu *filter_list;
        struct Qdisc **queues;
 };
 
@@ -42,10 +42,11 @@ multiq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
        struct multiq_sched_data *q = qdisc_priv(sch);
        u32 band;
        struct tcf_result res;
+       struct tcf_proto *fl = rcu_dereference_bh(q->filter_list);
        int err;
 
        *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
-       err = tc_classify(skb, q->filter_list, &res);
+       err = tc_classify(skb, fl, &res);
 #ifdef CONFIG_NET_CLS_ACT
        switch (err) {
        case TC_ACT_STOLEN:
@@ -360,7 +361,7 @@ static int multiq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
 
        cl_q = q->queues[cl - 1];
        cl_q->qstats.qlen = cl_q->q.qlen;
-       if (gnet_stats_copy_basic(d, &cl_q->bstats) < 0 ||
+       if (gnet_stats_copy_basic(d, NULL, &cl_q->bstats) < 0 ||
            gnet_stats_copy_queue(d, &cl_q->qstats) < 0)
                return -1;
 
@@ -388,7 +389,8 @@ static void multiq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
        }
 }
 
-static struct tcf_proto **multiq_find_tcf(struct Qdisc *sch, unsigned long cl)
+static struct tcf_proto __rcu **multiq_find_tcf(struct Qdisc *sch,
+                                               unsigned long cl)
 {
        struct multiq_sched_data *q = qdisc_priv(sch);