aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/act_police.c
diff options
context:
space:
mode:
authorWANG Cong <xiyou.wangcong@gmail.com>2013-12-15 23:15:09 -0500
committerDavid S. Miller <davem@davemloft.net>2013-12-18 12:52:07 -0500
commit89819dc01f4c5920783f561597a48d9d75220e9e (patch)
tree2c37980c3b2cc34fece254b4e15b8fb56a24cead /net/sched/act_police.c
parent369ba56787d7469c0afda70bb9ff76ad5faaead5 (diff)
net_sched: convert tcf_hashinfo to hlist and use spinlock
So that we don't need to play with singly linked list, and since the code is not on hot path, we can use spinlock instead of rwlock. Cc: Jamal Hadi Salim <jhs@mojatatu.com> Cc: David S. Miller <davem@davemloft.net> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/act_police.c')
-rw-r--r--net/sched/act_police.c45
1 files changed, 18 insertions, 27 deletions
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index f201576d25c2..0cc305e7e469 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -60,18 +60,19 @@ struct tc_police_compat {
60static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb, 60static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb,
61 int type, struct tc_action *a) 61 int type, struct tc_action *a)
62{ 62{
63 struct hlist_head *head;
63 struct tcf_common *p; 64 struct tcf_common *p;
64 int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; 65 int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
65 struct nlattr *nest; 66 struct nlattr *nest;
66 67
67 read_lock_bh(&police_hash_info.lock); 68 spin_lock_bh(&police_hash_info.lock);
68 69
69 s_i = cb->args[0]; 70 s_i = cb->args[0];
70 71
71 for (i = 0; i < (POL_TAB_MASK + 1); i++) { 72 for (i = 0; i < (POL_TAB_MASK + 1); i++) {
72 p = police_hash_info.htab[tcf_hash(i, POL_TAB_MASK)]; 73 head = &police_hash_info.htab[tcf_hash(i, POL_TAB_MASK)];
73 74
74 for (; p; p = p->tcfc_next) { 75 hlist_for_each_entry_rcu(p, head, tcfc_head) {
75 index++; 76 index++;
76 if (index < s_i) 77 if (index < s_i)
77 continue; 78 continue;
@@ -94,7 +95,7 @@ static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *c
94 } 95 }
95 } 96 }
96done: 97done:
97 read_unlock_bh(&police_hash_info.lock); 98 spin_unlock_bh(&police_hash_info.lock);
98 if (n_i) 99 if (n_i)
99 cb->args[0] += n_i; 100 cb->args[0] += n_i;
100 return n_i; 101 return n_i;
@@ -106,25 +107,16 @@ nla_put_failure:
106 107
107static void tcf_police_destroy(struct tcf_police *p) 108static void tcf_police_destroy(struct tcf_police *p)
108{ 109{
109 unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK); 110 spin_lock_bh(&police_hash_info.lock);
110 struct tcf_common **p1p; 111 hlist_del(&p->tcf_head);
111 112 spin_unlock_bh(&police_hash_info.lock);
112 for (p1p = &police_hash_info.htab[h]; *p1p; p1p = &(*p1p)->tcfc_next) { 113 gen_kill_estimator(&p->tcf_bstats,
113 if (*p1p == &p->common) { 114 &p->tcf_rate_est);
114 write_lock_bh(&police_hash_info.lock); 115 /*
115 *p1p = p->tcf_next; 116 * gen_estimator est_timer() might access p->tcf_lock
116 write_unlock_bh(&police_hash_info.lock); 117 * or bstats, wait a RCU grace period before freeing p
117 gen_kill_estimator(&p->tcf_bstats, 118 */
118 &p->tcf_rate_est); 119 kfree_rcu(p, tcf_rcu);
119 /*
120 * gen_estimator est_timer() might access p->tcf_lock
121 * or bstats, wait a RCU grace period before freeing p
122 */
123 kfree_rcu(p, tcf_rcu);
124 return;
125 }
126 }
127 WARN_ON(1);
128} 120}
129 121
130static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = { 122static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
@@ -259,10 +251,9 @@ override:
259 police->tcf_index = parm->index ? parm->index : 251 police->tcf_index = parm->index ? parm->index :
260 tcf_hash_new_index(&police_idx_gen, &police_hash_info); 252 tcf_hash_new_index(&police_idx_gen, &police_hash_info);
261 h = tcf_hash(police->tcf_index, POL_TAB_MASK); 253 h = tcf_hash(police->tcf_index, POL_TAB_MASK);
262 write_lock_bh(&police_hash_info.lock); 254 spin_lock_bh(&police_hash_info.lock);
263 police->tcf_next = police_hash_info.htab[h]; 255 hlist_add_head(&police->tcf_head, &police_hash_info.htab[h]);
264 police_hash_info.htab[h] = &police->common; 256 spin_unlock_bh(&police_hash_info.lock);
265 write_unlock_bh(&police_hash_info.lock);
266 257
267 a->priv = police; 258 a->priv = police;
268 return ret; 259 return ret;