aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_atm.c
diff options
context:
space:
mode:
authorJohn Fastabend <john.fastabend@gmail.com>2014-09-12 23:05:27 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-13 12:30:25 -0400
commit25d8c0d55f241ce2d360df1bea48e23a55836ee6 (patch)
treec0aca67607e7ce560a4a2cebef5fb6d55adf4112 /net/sched/sch_atm.c
parent46e5da40aec256155cfedee96dd21a75da941f2c (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_atm.c')
-rw-r--r--net/sched/sch_atm.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 8449b337f9e3..c398f9c3dbdd 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -41,7 +41,7 @@
41 41
42struct atm_flow_data { 42struct atm_flow_data {
43 struct Qdisc *q; /* FIFO, TBF, etc. */ 43 struct Qdisc *q; /* FIFO, TBF, etc. */
44 struct tcf_proto *filter_list; 44 struct tcf_proto __rcu *filter_list;
45 struct atm_vcc *vcc; /* VCC; NULL if VCC is closed */ 45 struct atm_vcc *vcc; /* VCC; NULL if VCC is closed */
46 void (*old_pop)(struct atm_vcc *vcc, 46 void (*old_pop)(struct atm_vcc *vcc,
47 struct sk_buff *skb); /* chaining */ 47 struct sk_buff *skb); /* chaining */
@@ -273,7 +273,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
273 error = -ENOBUFS; 273 error = -ENOBUFS;
274 goto err_out; 274 goto err_out;
275 } 275 }
276 flow->filter_list = NULL; 276 RCU_INIT_POINTER(flow->filter_list, NULL);
277 flow->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid); 277 flow->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid);
278 if (!flow->q) 278 if (!flow->q)
279 flow->q = &noop_qdisc; 279 flow->q = &noop_qdisc;
@@ -311,7 +311,7 @@ static int atm_tc_delete(struct Qdisc *sch, unsigned long arg)
311 pr_debug("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n", sch, p, flow); 311 pr_debug("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
312 if (list_empty(&flow->list)) 312 if (list_empty(&flow->list))
313 return -EINVAL; 313 return -EINVAL;
314 if (flow->filter_list || flow == &p->link) 314 if (rcu_access_pointer(flow->filter_list) || flow == &p->link)
315 return -EBUSY; 315 return -EBUSY;
316 /* 316 /*
317 * Reference count must be 2: one for "keepalive" (set at class 317 * Reference count must be 2: one for "keepalive" (set at class
@@ -345,7 +345,8 @@ static void atm_tc_walk(struct Qdisc *sch, struct qdisc_walker *walker)
345 } 345 }
346} 346}
347 347
348static struct tcf_proto **atm_tc_find_tcf(struct Qdisc *sch, unsigned long cl) 348static struct tcf_proto __rcu **atm_tc_find_tcf(struct Qdisc *sch,
349 unsigned long cl)
349{ 350{
350 struct atm_qdisc_data *p = qdisc_priv(sch); 351 struct atm_qdisc_data *p = qdisc_priv(sch);
351 struct atm_flow_data *flow = (struct atm_flow_data *)cl; 352 struct atm_flow_data *flow = (struct atm_flow_data *)cl;
@@ -369,11 +370,12 @@ static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
369 flow = NULL; 370 flow = NULL;
370 if (TC_H_MAJ(skb->priority) != sch->handle || 371 if (TC_H_MAJ(skb->priority) != sch->handle ||
371 !(flow = (struct atm_flow_data *)atm_tc_get(sch, skb->priority))) { 372 !(flow = (struct atm_flow_data *)atm_tc_get(sch, skb->priority))) {
373 struct tcf_proto *fl;
374
372 list_for_each_entry(flow, &p->flows, list) { 375 list_for_each_entry(flow, &p->flows, list) {
373 if (flow->filter_list) { 376 fl = rcu_dereference_bh(flow->filter_list);
374 result = tc_classify_compat(skb, 377 if (fl) {
375 flow->filter_list, 378 result = tc_classify_compat(skb, fl, &res);
376 &res);
377 if (result < 0) 379 if (result < 0)
378 continue; 380 continue;
379 flow = (struct atm_flow_data *)res.class; 381 flow = (struct atm_flow_data *)res.class;
@@ -544,7 +546,7 @@ static int atm_tc_init(struct Qdisc *sch, struct nlattr *opt)
544 if (!p->link.q) 546 if (!p->link.q)
545 p->link.q = &noop_qdisc; 547 p->link.q = &noop_qdisc;
546 pr_debug("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q); 548 pr_debug("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q);
547 p->link.filter_list = NULL; 549 RCU_INIT_POINTER(p->link.filter_list, NULL);
548 p->link.vcc = NULL; 550 p->link.vcc = NULL;
549 p->link.sock = NULL; 551 p->link.sock = NULL;
550 p->link.classid = sch->handle; 552 p->link.classid = sch->handle;