mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	net_sched: use tcf_queue_work() in tcindex filter
Defer the tcf_exts_destroy() in RCU callback to tc filter workqueue and get RTNL lock. Reported-by: Chris Mi <chrism@mellanox.com> Cc: Daniel Borkmann <daniel@iogearbox.net> Cc: Jiri Pirko <jiri@resnulli.us> Cc: John Fastabend <john.fastabend@gmail.com> Cc: Jamal Hadi Salim <jhs@mojatatu.com> Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									d4f84a41dc
								
							
						
					
					
						commit
						27ce4f05e2
					
				
					 1 changed files with 33 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -27,14 +27,20 @@
 | 
			
		|||
struct tcindex_filter_result {
 | 
			
		||||
	struct tcf_exts		exts;
 | 
			
		||||
	struct tcf_result	res;
 | 
			
		||||
	union {
 | 
			
		||||
		struct work_struct	work;
 | 
			
		||||
		struct rcu_head		rcu;
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct tcindex_filter {
 | 
			
		||||
	u16 key;
 | 
			
		||||
	struct tcindex_filter_result result;
 | 
			
		||||
	struct tcindex_filter __rcu *next;
 | 
			
		||||
	union {
 | 
			
		||||
		struct work_struct work;
 | 
			
		||||
		struct rcu_head rcu;
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -133,12 +139,34 @@ static int tcindex_init(struct tcf_proto *tp)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tcindex_destroy_rexts_work(struct work_struct *work)
 | 
			
		||||
{
 | 
			
		||||
	struct tcindex_filter_result *r;
 | 
			
		||||
 | 
			
		||||
	r = container_of(work, struct tcindex_filter_result, work);
 | 
			
		||||
	rtnl_lock();
 | 
			
		||||
	tcf_exts_destroy(&r->exts);
 | 
			
		||||
	rtnl_unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tcindex_destroy_rexts(struct rcu_head *head)
 | 
			
		||||
{
 | 
			
		||||
	struct tcindex_filter_result *r;
 | 
			
		||||
 | 
			
		||||
	r = container_of(head, struct tcindex_filter_result, rcu);
 | 
			
		||||
	tcf_exts_destroy(&r->exts);
 | 
			
		||||
	INIT_WORK(&r->work, tcindex_destroy_rexts_work);
 | 
			
		||||
	tcf_queue_work(&r->work);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tcindex_destroy_fexts_work(struct work_struct *work)
 | 
			
		||||
{
 | 
			
		||||
	struct tcindex_filter *f = container_of(work, struct tcindex_filter,
 | 
			
		||||
						work);
 | 
			
		||||
 | 
			
		||||
	rtnl_lock();
 | 
			
		||||
	tcf_exts_destroy(&f->result.exts);
 | 
			
		||||
	kfree(f);
 | 
			
		||||
	rtnl_unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tcindex_destroy_fexts(struct rcu_head *head)
 | 
			
		||||
| 
						 | 
				
			
			@ -146,8 +174,8 @@ static void tcindex_destroy_fexts(struct rcu_head *head)
 | 
			
		|||
	struct tcindex_filter *f = container_of(head, struct tcindex_filter,
 | 
			
		||||
						rcu);
 | 
			
		||||
 | 
			
		||||
	tcf_exts_destroy(&f->result.exts);
 | 
			
		||||
	kfree(f);
 | 
			
		||||
	INIT_WORK(&f->work, tcindex_destroy_fexts_work);
 | 
			
		||||
	tcf_queue_work(&f->work);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int tcindex_delete(struct tcf_proto *tp, void *arg, bool *last)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue