diff options
Diffstat (limited to 'net/sched/cls_u32.c')
| -rw-r--r-- | net/sched/cls_u32.c | 37 | 
1 files changed, 10 insertions, 27 deletions
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index bac47b5d18fd..fb861f90fde6 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -68,10 +68,7 @@ struct tc_u_knode {  	u32 __percpu		*pcpu_success;  #endif  	struct tcf_proto	*tp; -	union { -		struct work_struct	work; -		struct rcu_head		rcu; -	}; +	struct rcu_work		rwork;  	/* The 'sel' field MUST be the last field in structure to allow for  	 * tc_u32_keys allocated at end of structure.  	 */ @@ -436,21 +433,14 @@ static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n,   */  static void u32_delete_key_work(struct work_struct *work)  { -	struct tc_u_knode *key = container_of(work, struct tc_u_knode, work); - +	struct tc_u_knode *key = container_of(to_rcu_work(work), +					      struct tc_u_knode, +					      rwork);  	rtnl_lock();  	u32_destroy_key(key->tp, key, false);  	rtnl_unlock();  } -static void u32_delete_key_rcu(struct rcu_head *rcu) -{ -	struct tc_u_knode *key = container_of(rcu, struct tc_u_knode, rcu); - -	INIT_WORK(&key->work, u32_delete_key_work); -	tcf_queue_work(&key->work); -} -  /* u32_delete_key_freepf_rcu is the rcu callback variant   * that free's the entire structure including the statistics   * percpu variables. Only use this if the key is not a copy @@ -460,21 +450,14 @@ static void u32_delete_key_rcu(struct rcu_head *rcu)   */  static void u32_delete_key_freepf_work(struct work_struct *work)  { -	struct tc_u_knode *key = container_of(work, struct tc_u_knode, work); - +	struct tc_u_knode *key = container_of(to_rcu_work(work), +					      struct tc_u_knode, +					      rwork);  	rtnl_lock();  	u32_destroy_key(key->tp, key, true);  	rtnl_unlock();  } -static void u32_delete_key_freepf_rcu(struct rcu_head *rcu) -{ -	struct tc_u_knode *key = container_of(rcu, struct tc_u_knode, rcu); - -	INIT_WORK(&key->work, u32_delete_key_freepf_work); -	tcf_queue_work(&key->work); -} -  static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)  {  	struct tc_u_knode __rcu **kp; @@ -491,7 +474,7 @@ static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)  				tcf_unbind_filter(tp, &key->res);  				idr_remove(&ht->handle_idr, key->handle);  				tcf_exts_get_net(&key->exts); -				call_rcu(&key->rcu, u32_delete_key_freepf_rcu); +				tcf_queue_work(&key->rwork, u32_delete_key_freepf_work);  				return 0;  			}  		} @@ -611,7 +594,7 @@ static void u32_clear_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht,  			u32_remove_hw_knode(tp, n, extack);  			idr_remove(&ht->handle_idr, n->handle);  			if (tcf_exts_get_net(&n->exts)) -				call_rcu(&n->rcu, u32_delete_key_freepf_rcu); +				tcf_queue_work(&n->rwork, u32_delete_key_freepf_work);  			else  				u32_destroy_key(n->tp, n, true);  		} @@ -995,7 +978,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,  		u32_replace_knode(tp, tp_c, new);  		tcf_unbind_filter(tp, &n->res);  		tcf_exts_get_net(&n->exts); -		call_rcu(&n->rcu, u32_delete_key_rcu); +		tcf_queue_work(&n->rwork, u32_delete_key_work);  		return 0;  	}  | 
