diff options
Diffstat (limited to 'main/linux-grsec/net-flow-remove-sleeping-and-deferral-mechanism-from-flow_cache_flush.patch')
-rw-r--r-- | main/linux-grsec/net-flow-remove-sleeping-and-deferral-mechanism-from-flow_cache_flush.patch | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/main/linux-grsec/net-flow-remove-sleeping-and-deferral-mechanism-from-flow_cache_flush.patch b/main/linux-grsec/net-flow-remove-sleeping-and-deferral-mechanism-from-flow_cache_flush.patch new file mode 100644 index 0000000000..8eaadf9429 --- /dev/null +++ b/main/linux-grsec/net-flow-remove-sleeping-and-deferral-mechanism-from-flow_cache_flush.patch @@ -0,0 +1,85 @@ +Based on http://patchwork.ozlabs.org/patch/132353/ + +diff --git a/net/core/flow.c b/net/core/flow.c +index 8ae42de..e318c7e 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 2118d64..9049a5c 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; + } +--- ./include/net/flow.h.orig ++++ ./include/net/flow.h +@@ -207,6 +207,7 @@ + u8 dir, flow_resolve_t resolver, void *ctx); + + extern void flow_cache_flush(void); ++extern void flow_cache_flush_deferred(void); + extern atomic_unchecked_t flow_cache_genid; + + #endif |