diff options
Diffstat (limited to 'net/sched/sch_prio.c')
-rw-r--r-- | net/sched/sch_prio.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index 79359b69ad8d..8e5cd34aaa74 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | struct prio_sched_data { | 25 | struct prio_sched_data { |
26 | int bands; | 26 | int bands; |
27 | struct tcf_proto *filter_list; | 27 | struct tcf_proto __rcu *filter_list; |
28 | u8 prio2band[TC_PRIO_MAX+1]; | 28 | u8 prio2band[TC_PRIO_MAX+1]; |
29 | struct Qdisc *queues[TCQ_PRIO_BANDS]; | 29 | struct Qdisc *queues[TCQ_PRIO_BANDS]; |
30 | }; | 30 | }; |
@@ -36,11 +36,13 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
36 | struct prio_sched_data *q = qdisc_priv(sch); | 36 | struct prio_sched_data *q = qdisc_priv(sch); |
37 | u32 band = skb->priority; | 37 | u32 band = skb->priority; |
38 | struct tcf_result res; | 38 | struct tcf_result res; |
39 | struct tcf_proto *fl; | ||
39 | int err; | 40 | int err; |
40 | 41 | ||
41 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; | 42 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; |
42 | if (TC_H_MAJ(skb->priority) != sch->handle) { | 43 | if (TC_H_MAJ(skb->priority) != sch->handle) { |
43 | err = tc_classify(skb, q->filter_list, &res); | 44 | fl = rcu_dereference_bh(q->filter_list); |
45 | err = tc_classify(skb, fl, &res); | ||
44 | #ifdef CONFIG_NET_CLS_ACT | 46 | #ifdef CONFIG_NET_CLS_ACT |
45 | switch (err) { | 47 | switch (err) { |
46 | case TC_ACT_STOLEN: | 48 | case TC_ACT_STOLEN: |
@@ -50,7 +52,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
50 | return NULL; | 52 | return NULL; |
51 | } | 53 | } |
52 | #endif | 54 | #endif |
53 | if (!q->filter_list || err < 0) { | 55 | if (!fl || err < 0) { |
54 | if (TC_H_MAJ(band)) | 56 | if (TC_H_MAJ(band)) |
55 | band = 0; | 57 | band = 0; |
56 | return q->queues[q->prio2band[band & TC_PRIO_MAX]]; | 58 | return q->queues[q->prio2band[band & TC_PRIO_MAX]]; |
@@ -75,7 +77,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
75 | if (qdisc == NULL) { | 77 | if (qdisc == NULL) { |
76 | 78 | ||
77 | if (ret & __NET_XMIT_BYPASS) | 79 | if (ret & __NET_XMIT_BYPASS) |
78 | sch->qstats.drops++; | 80 | qdisc_qstats_drop(sch); |
79 | kfree_skb(skb); | 81 | kfree_skb(skb); |
80 | return ret; | 82 | return ret; |
81 | } | 83 | } |
@@ -87,7 +89,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
87 | return NET_XMIT_SUCCESS; | 89 | return NET_XMIT_SUCCESS; |
88 | } | 90 | } |
89 | if (net_xmit_drop_count(ret)) | 91 | if (net_xmit_drop_count(ret)) |
90 | sch->qstats.drops++; | 92 | qdisc_qstats_drop(sch); |
91 | return ret; | 93 | return ret; |
92 | } | 94 | } |
93 | 95 | ||
@@ -322,9 +324,8 @@ static int prio_dump_class_stats(struct Qdisc *sch, unsigned long cl, | |||
322 | struct Qdisc *cl_q; | 324 | struct Qdisc *cl_q; |
323 | 325 | ||
324 | cl_q = q->queues[cl - 1]; | 326 | cl_q = q->queues[cl - 1]; |
325 | cl_q->qstats.qlen = cl_q->q.qlen; | 327 | if (gnet_stats_copy_basic(d, NULL, &cl_q->bstats) < 0 || |
326 | if (gnet_stats_copy_basic(d, &cl_q->bstats) < 0 || | 328 | gnet_stats_copy_queue(d, NULL, &cl_q->qstats, cl_q->q.qlen) < 0) |
327 | gnet_stats_copy_queue(d, &cl_q->qstats) < 0) | ||
328 | return -1; | 329 | return -1; |
329 | 330 | ||
330 | return 0; | 331 | return 0; |
@@ -351,7 +352,8 @@ static void prio_walk(struct Qdisc *sch, struct qdisc_walker *arg) | |||
351 | } | 352 | } |
352 | } | 353 | } |
353 | 354 | ||
354 | static struct tcf_proto **prio_find_tcf(struct Qdisc *sch, unsigned long cl) | 355 | static struct tcf_proto __rcu **prio_find_tcf(struct Qdisc *sch, |
356 | unsigned long cl) | ||
355 | { | 357 | { |
356 | struct prio_sched_data *q = qdisc_priv(sch); | 358 | struct prio_sched_data *q = qdisc_priv(sch); |
357 | 359 | ||