diff options
| -rw-r--r-- | include/net/flow.h | 1 | ||||
| -rw-r--r-- | net/core/flow.c | 12 | ||||
| -rw-r--r-- | net/xfrm/xfrm_policy.c | 18 | 
3 files changed, 27 insertions, 4 deletions
diff --git a/include/net/flow.h b/include/net/flow.h index a09447749e2..57f15a7f1cd 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -207,6 +207,7 @@ extern struct flow_cache_object *flow_cache_lookup(  		u8 dir, flow_resolve_t resolver, void *ctx);  extern void flow_cache_flush(void); +extern void flow_cache_flush_deferred(void);  extern atomic_t flow_cache_genid;  #endif diff --git a/net/core/flow.c b/net/core/flow.c index 8ae42de9c79..e318c7e9804 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -358,6 +358,18 @@ void flow_cache_flush(void)  	put_online_cpus();  } +static void flow_cache_flush_task(struct work_struct *work) +{ +	flow_cache_flush(); +} + +static DECLARE_WORK(flow_cache_flush_work, flow_cache_flush_task); + +void flow_cache_flush_deferred(void) +{ +	schedule_work(&flow_cache_flush_work); +} +  static int __cpuinit flow_cache_cpu_prepare(struct flow_cache *fc, int cpu)  {  	struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 2118d644663..9049a5caeb2 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2276,8 +2276,6 @@ static void __xfrm_garbage_collect(struct net *net)  {  	struct dst_entry *head, *next; -	flow_cache_flush(); -  	spin_lock_bh(&xfrm_policy_sk_bundle_lock);  	head = xfrm_policy_sk_bundles;  	xfrm_policy_sk_bundles = NULL; @@ -2290,6 +2288,18 @@ static void __xfrm_garbage_collect(struct net *net)  	}  } +static void xfrm_garbage_collect(struct net *net) +{ +	flow_cache_flush(); +	__xfrm_garbage_collect(net); +} + +static void xfrm_garbage_collect_deferred(struct net *net) +{ +	flow_cache_flush_deferred(); +	__xfrm_garbage_collect(net); +} +  static void xfrm_init_pmtu(struct dst_entry *dst)  {  	do { @@ -2422,7 +2432,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)  		if (likely(dst_ops->neigh_lookup == NULL))  			dst_ops->neigh_lookup = xfrm_neigh_lookup;  		if (likely(afinfo->garbage_collect == NULL)) -			afinfo->garbage_collect = __xfrm_garbage_collect; +			afinfo->garbage_collect = xfrm_garbage_collect_deferred;  		xfrm_policy_afinfo[afinfo->family] = afinfo;  	}  	write_unlock_bh(&xfrm_policy_afinfo_lock); @@ -2516,7 +2526,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void  	switch (event) {  	case NETDEV_DOWN: -		__xfrm_garbage_collect(dev_net(dev)); +		xfrm_garbage_collect(dev_net(dev));  	}  	return NOTIFY_DONE;  }  |