diff options
author | John Fastabend <john.fastabend@gmail.com> | 2014-09-12 23:05:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-13 12:30:25 -0400 |
commit | 25d8c0d55f241ce2d360df1bea48e23a55836ee6 (patch) | |
tree | c0aca67607e7ce560a4a2cebef5fb6d55adf4112 /net/sched/sch_fq_codel.c | |
parent | 46e5da40aec256155cfedee96dd21a75da941f2c (diff) |
net: rcu-ify tcf_proto
rcu'ify tcf_proto this allows calling tc_classify() without holding
any locks. Updaters are protected by RTNL.
This patch prepares the core net_sched infrastracture for running
the classifier/action chains without holding the qdisc lock however
it does nothing to ensure cls_xxx and act_xxx types also work without
locking. Additional patches are required to address the fall out.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/sch_fq_codel.c')
-rw-r--r-- | net/sched/sch_fq_codel.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index cc56c8bb9bed..105cf5557630 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c | |||
@@ -52,7 +52,7 @@ struct fq_codel_flow { | |||
52 | }; /* please try to keep this structure <= 64 bytes */ | 52 | }; /* please try to keep this structure <= 64 bytes */ |
53 | 53 | ||
54 | struct fq_codel_sched_data { | 54 | struct fq_codel_sched_data { |
55 | struct tcf_proto *filter_list; /* optional external classifier */ | 55 | struct tcf_proto __rcu *filter_list; /* optional external classifier */ |
56 | struct fq_codel_flow *flows; /* Flows table [flows_cnt] */ | 56 | struct fq_codel_flow *flows; /* Flows table [flows_cnt] */ |
57 | u32 *backlogs; /* backlog table [flows_cnt] */ | 57 | u32 *backlogs; /* backlog table [flows_cnt] */ |
58 | u32 flows_cnt; /* number of flows */ | 58 | u32 flows_cnt; /* number of flows */ |
@@ -85,6 +85,7 @@ static unsigned int fq_codel_classify(struct sk_buff *skb, struct Qdisc *sch, | |||
85 | int *qerr) | 85 | int *qerr) |
86 | { | 86 | { |
87 | struct fq_codel_sched_data *q = qdisc_priv(sch); | 87 | struct fq_codel_sched_data *q = qdisc_priv(sch); |
88 | struct tcf_proto *filter; | ||
88 | struct tcf_result res; | 89 | struct tcf_result res; |
89 | int result; | 90 | int result; |
90 | 91 | ||
@@ -93,11 +94,12 @@ static unsigned int fq_codel_classify(struct sk_buff *skb, struct Qdisc *sch, | |||
93 | TC_H_MIN(skb->priority) <= q->flows_cnt) | 94 | TC_H_MIN(skb->priority) <= q->flows_cnt) |
94 | return TC_H_MIN(skb->priority); | 95 | return TC_H_MIN(skb->priority); |
95 | 96 | ||
96 | if (!q->filter_list) | 97 | filter = rcu_dereference(q->filter_list); |
98 | if (!filter) | ||
97 | return fq_codel_hash(q, skb) + 1; | 99 | return fq_codel_hash(q, skb) + 1; |
98 | 100 | ||
99 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; | 101 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; |
100 | result = tc_classify(skb, q->filter_list, &res); | 102 | result = tc_classify(skb, filter, &res); |
101 | if (result >= 0) { | 103 | if (result >= 0) { |
102 | #ifdef CONFIG_NET_CLS_ACT | 104 | #ifdef CONFIG_NET_CLS_ACT |
103 | switch (result) { | 105 | switch (result) { |
@@ -496,7 +498,8 @@ static void fq_codel_put(struct Qdisc *q, unsigned long cl) | |||
496 | { | 498 | { |
497 | } | 499 | } |
498 | 500 | ||
499 | static struct tcf_proto **fq_codel_find_tcf(struct Qdisc *sch, unsigned long cl) | 501 | static struct tcf_proto __rcu **fq_codel_find_tcf(struct Qdisc *sch, |
502 | unsigned long cl) | ||
500 | { | 503 | { |
501 | struct fq_codel_sched_data *q = qdisc_priv(sch); | 504 | struct fq_codel_sched_data *q = qdisc_priv(sch); |
502 | 505 | ||