diff options
Diffstat (limited to 'net/sched/act_police.c')
-rw-r--r-- | net/sched/act_police.c | 45 |
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 { | |||
60 | static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb, | 60 | static 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 | } |
96 | done: | 97 | done: |
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 | ||
107 | static void tcf_police_destroy(struct tcf_police *p) | 108 | static 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 | ||
130 | static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = { | 122 | static 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; |