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 5d944c640b
(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>
Этот коммит содержится в:

коммит произвёл
David S. Miller

родитель
cbd6890c59
Коммит
c7de2cf053
@@ -26,6 +26,11 @@
|
||||
#include <net/act_api.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
static void tcf_common_free_rcu(struct rcu_head *head)
|
||||
{
|
||||
kfree(container_of(head, struct tcf_common, tcfc_rcu));
|
||||
}
|
||||
|
||||
void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo)
|
||||
{
|
||||
unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask);
|
||||
@@ -38,7 +43,11 @@ void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo)
|
||||
write_unlock_bh(hinfo->lock);
|
||||
gen_kill_estimator(&p->tcfc_bstats,
|
||||
&p->tcfc_rate_est);
|
||||
kfree(p);
|
||||
/*
|
||||
* gen_estimator est_timer() might access p->tcfc_lock
|
||||
* or bstats, wait a RCU grace period before freeing p
|
||||
*/
|
||||
call_rcu(&p->tcfc_rcu, tcf_common_free_rcu);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@@ -97,6 +97,11 @@ nla_put_failure:
|
||||
goto done;
|
||||
}
|
||||
|
||||
static void tcf_police_free_rcu(struct rcu_head *head)
|
||||
{
|
||||
kfree(container_of(head, struct tcf_police, tcf_rcu));
|
||||
}
|
||||
|
||||
static void tcf_police_destroy(struct tcf_police *p)
|
||||
{
|
||||
unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK);
|
||||
@@ -113,7 +118,11 @@ static void tcf_police_destroy(struct tcf_police *p)
|
||||
qdisc_put_rtab(p->tcfp_R_tab);
|
||||
if (p->tcfp_P_tab)
|
||||
qdisc_put_rtab(p->tcfp_P_tab);
|
||||
kfree(p);
|
||||
/*
|
||||
* gen_estimator est_timer() might access p->tcf_lock
|
||||
* or bstats, wait a RCU grace period before freeing p
|
||||
*/
|
||||
call_rcu(&p->tcf_rcu, tcf_police_free_rcu);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -397,6 +406,7 @@ static void __exit
|
||||
police_cleanup_module(void)
|
||||
{
|
||||
tcf_unregister_action(&act_police_ops);
|
||||
rcu_barrier(); /* Wait for completion of call_rcu()'s (tcf_police_free_rcu) */
|
||||
}
|
||||
|
||||
module_init(police_init_module);
|
||||
|
Ссылка в новой задаче
Block a user