diff options
Diffstat (limited to 'net/sched/act_api.c')
| -rw-r--r-- | net/sched/act_api.c | 11 | 
1 files changed, 10 insertions, 1 deletions
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 972378f47f3..23b25f89e7e 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -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;  		}  	}  |