diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-06-08 22:09:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-11 21:37:08 -0400 |
commit | c7de2cf053420d63bac85133469c965d4b1083e1 (patch) | |
tree | b56f7c96d01e25f79fe1f9b7e5305265e92214d9 /net/netfilter | |
parent | cbd6890c5987cd7115147e1dd2c10d729afabb08 (diff) |
pkt_sched: gen_kill_estimator() rcu fixes
gen_kill_estimator() API is incomplete or not well documented, since
caller should make sure an RCU grace period is respected before
freeing stats_lock.
This was partially addressed in commit 5d944c640b4
(gen_estimator: deadlock fix), but same problem exist for all
gen_kill_estimator() users, if lock they use is not already RCU
protected.
A code review shows xt_RATEEST.c, act_api.c, act_police.c have this
problem. Other are ok because they use qdisc lock, already RCU
protected.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/xt_RATEEST.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c index 69c01e10f8af..de079abd5bc8 100644 --- a/net/netfilter/xt_RATEEST.c +++ b/net/netfilter/xt_RATEEST.c | |||
@@ -60,13 +60,22 @@ struct xt_rateest *xt_rateest_lookup(const char *name) | |||
60 | } | 60 | } |
61 | EXPORT_SYMBOL_GPL(xt_rateest_lookup); | 61 | EXPORT_SYMBOL_GPL(xt_rateest_lookup); |
62 | 62 | ||
63 | static void xt_rateest_free_rcu(struct rcu_head *head) | ||
64 | { | ||
65 | kfree(container_of(head, struct xt_rateest, rcu)); | ||
66 | } | ||
67 | |||
63 | void xt_rateest_put(struct xt_rateest *est) | 68 | void xt_rateest_put(struct xt_rateest *est) |
64 | { | 69 | { |
65 | mutex_lock(&xt_rateest_mutex); | 70 | mutex_lock(&xt_rateest_mutex); |
66 | if (--est->refcnt == 0) { | 71 | if (--est->refcnt == 0) { |
67 | hlist_del(&est->list); | 72 | hlist_del(&est->list); |
68 | gen_kill_estimator(&est->bstats, &est->rstats); | 73 | gen_kill_estimator(&est->bstats, &est->rstats); |
69 | kfree(est); | 74 | /* |
75 | * gen_estimator est_timer() might access est->lock or bstats, | ||
76 | * wait a RCU grace period before freeing 'est' | ||
77 | */ | ||
78 | call_rcu(&est->rcu, xt_rateest_free_rcu); | ||
70 | } | 79 | } |
71 | mutex_unlock(&xt_rateest_mutex); | 80 | mutex_unlock(&xt_rateest_mutex); |
72 | } | 81 | } |
@@ -179,6 +188,7 @@ static int __init xt_rateest_tg_init(void) | |||
179 | static void __exit xt_rateest_tg_fini(void) | 188 | static void __exit xt_rateest_tg_fini(void) |
180 | { | 189 | { |
181 | xt_unregister_target(&xt_rateest_tg_reg); | 190 | xt_unregister_target(&xt_rateest_tg_reg); |
191 | rcu_barrier(); /* Wait for completion of call_rcu()'s (xt_rateest_free_rcu) */ | ||
182 | } | 192 | } |
183 | 193 | ||
184 | 194 | ||