aboutsummaryrefslogtreecommitdiffstats
path: root/main/linux-grsec/net-flow-remove-sleeping-and-deferral-mechanism-from-flow_cache_flush.patch
diff options
context:
space:
mode:
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.patch85
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