diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2011-01-19 22:48:19 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-01-20 19:59:32 -0500 |
commit | a2da570d62fcb9e8816f6920e1ec02c706b289fa (patch) | |
tree | 9a24b76262c40ec2f1be11e29e224c7d7b20fa26 /include/net | |
parent | fd245a4adb5288eac37250875f237c40a20a1944 (diff) |
net_sched: RCU conversion of stab
This patch converts stab qdisc management to RCU, so that we can perform
the qdisc_calculate_pkt_len() call before getting qdisc lock.
This shortens the lock's held time in __dev_xmit_skb().
This permits more qdiscs to get TCQ_F_CAN_BYPASS status, avoiding lot of
cache misses and so reducing latencies.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Patrick McHardy <kaber@trash.net>
CC: Jesper Dangaard Brouer <hawk@diku.dk>
CC: Jarek Poplawski <jarkao2@gmail.com>
CC: Jamal Hadi Salim <hadi@cyberus.ca>
CC: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net')
-rw-r--r-- | include/net/sch_generic.h | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index f6345f55041c..d531baa2506a 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
@@ -36,6 +36,7 @@ enum qdisc___state_t { | |||
36 | }; | 36 | }; |
37 | 37 | ||
38 | struct qdisc_size_table { | 38 | struct qdisc_size_table { |
39 | struct rcu_head rcu; | ||
39 | struct list_head list; | 40 | struct list_head list; |
40 | struct tc_sizespec szopts; | 41 | struct tc_sizespec szopts; |
41 | int refcnt; | 42 | int refcnt; |
@@ -53,7 +54,7 @@ struct Qdisc { | |||
53 | #define TCQ_F_WARN_NONWC (1 << 16) | 54 | #define TCQ_F_WARN_NONWC (1 << 16) |
54 | int padded; | 55 | int padded; |
55 | struct Qdisc_ops *ops; | 56 | struct Qdisc_ops *ops; |
56 | struct qdisc_size_table *stab; | 57 | struct qdisc_size_table __rcu *stab; |
57 | struct list_head list; | 58 | struct list_head list; |
58 | u32 handle; | 59 | u32 handle; |
59 | u32 parent; | 60 | u32 parent; |
@@ -349,8 +350,8 @@ extern struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, | |||
349 | struct Qdisc_ops *ops); | 350 | struct Qdisc_ops *ops); |
350 | extern struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue, | 351 | extern struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue, |
351 | struct Qdisc_ops *ops, u32 parentid); | 352 | struct Qdisc_ops *ops, u32 parentid); |
352 | extern void qdisc_calculate_pkt_len(struct sk_buff *skb, | 353 | extern void __qdisc_calculate_pkt_len(struct sk_buff *skb, |
353 | struct qdisc_size_table *stab); | 354 | const struct qdisc_size_table *stab); |
354 | extern void tcf_destroy(struct tcf_proto *tp); | 355 | extern void tcf_destroy(struct tcf_proto *tp); |
355 | extern void tcf_destroy_chain(struct tcf_proto **fl); | 356 | extern void tcf_destroy_chain(struct tcf_proto **fl); |
356 | 357 | ||
@@ -429,12 +430,20 @@ enum net_xmit_qdisc_t { | |||
429 | #define net_xmit_drop_count(e) (1) | 430 | #define net_xmit_drop_count(e) (1) |
430 | #endif | 431 | #endif |
431 | 432 | ||
432 | static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch) | 433 | static inline void qdisc_calculate_pkt_len(struct sk_buff *skb, |
434 | const struct Qdisc *sch) | ||
433 | { | 435 | { |
434 | #ifdef CONFIG_NET_SCHED | 436 | #ifdef CONFIG_NET_SCHED |
435 | if (sch->stab) | 437 | struct qdisc_size_table *stab = rcu_dereference_bh(sch->stab); |
436 | qdisc_calculate_pkt_len(skb, sch->stab); | 438 | |
439 | if (stab) | ||
440 | __qdisc_calculate_pkt_len(skb, stab); | ||
437 | #endif | 441 | #endif |
442 | } | ||
443 | |||
444 | static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch) | ||
445 | { | ||
446 | qdisc_calculate_pkt_len(skb, sch); | ||
438 | return sch->enqueue(skb, sch); | 447 | return sch->enqueue(skb, sch); |
439 | } | 448 | } |
440 | 449 | ||