aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/core/gen_estimator.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index a89f32fa94f6..57abe8266be1 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -99,7 +99,7 @@ struct gen_estimator_head
99 99
100static struct gen_estimator_head elist[EST_MAX_INTERVAL+1]; 100static struct gen_estimator_head elist[EST_MAX_INTERVAL+1];
101 101
102/* Protects against NULL dereference and RCU write-side */ 102/* Protects against NULL dereference */
103static DEFINE_RWLOCK(est_lock); 103static DEFINE_RWLOCK(est_lock);
104 104
105static void est_timer(unsigned long arg) 105static void est_timer(unsigned long arg)
@@ -185,7 +185,6 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
185 est->last_packets = bstats->packets; 185 est->last_packets = bstats->packets;
186 est->avpps = rate_est->pps<<10; 186 est->avpps = rate_est->pps<<10;
187 187
188 write_lock_bh(&est_lock);
189 if (!elist[idx].timer.function) { 188 if (!elist[idx].timer.function) {
190 INIT_LIST_HEAD(&elist[idx].list); 189 INIT_LIST_HEAD(&elist[idx].list);
191 setup_timer(&elist[idx].timer, est_timer, idx); 190 setup_timer(&elist[idx].timer, est_timer, idx);
@@ -195,7 +194,6 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
195 mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx)); 194 mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx));
196 195
197 list_add_rcu(&est->list, &elist[idx].list); 196 list_add_rcu(&est->list, &elist[idx].list);
198 write_unlock_bh(&est_lock);
199 return 0; 197 return 0;
200} 198}
201 199
@@ -214,6 +212,7 @@ static void __gen_kill_estimator(struct rcu_head *head)
214 * Removes the rate estimator specified by &bstats and &rate_est 212 * Removes the rate estimator specified by &bstats and &rate_est
215 * and deletes the timer. 213 * and deletes the timer.
216 * 214 *
215 * NOTE: Called under rtnl_mutex
217 */ 216 */
218void gen_kill_estimator(struct gnet_stats_basic *bstats, 217void gen_kill_estimator(struct gnet_stats_basic *bstats,
219 struct gnet_stats_rate_est *rate_est) 218 struct gnet_stats_rate_est *rate_est)
@@ -227,17 +226,17 @@ void gen_kill_estimator(struct gnet_stats_basic *bstats,
227 if (!elist[idx].timer.function) 226 if (!elist[idx].timer.function)
228 continue; 227 continue;
229 228
230 write_lock_bh(&est_lock);
231 list_for_each_entry_safe(e, n, &elist[idx].list, list) { 229 list_for_each_entry_safe(e, n, &elist[idx].list, list) {
232 if (e->rate_est != rate_est || e->bstats != bstats) 230 if (e->rate_est != rate_est || e->bstats != bstats)
233 continue; 231 continue;
234 232
233 write_lock_bh(&est_lock);
235 e->bstats = NULL; 234 e->bstats = NULL;
235 write_unlock_bh(&est_lock);
236 236
237 list_del_rcu(&e->list); 237 list_del_rcu(&e->list);
238 call_rcu(&e->e_rcu, __gen_kill_estimator); 238 call_rcu(&e->e_rcu, __gen_kill_estimator);
239 } 239 }
240 write_unlock_bh(&est_lock);
241 } 240 }
242} 241}
243 242