diff options
| -rw-r--r-- | net/xfrm/xfrm_state.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 78d6c52a65cc..102bb826e273 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -48,6 +48,8 @@ static struct work_struct xfrm_state_gc_work; static struct list_head xfrm_state_gc_list = LIST_HEAD_INIT(xfrm_state_gc_list); static DEFINE_SPINLOCK(xfrm_state_gc_lock); +static int xfrm_state_gc_flush_bundles; + static void __xfrm_state_delete(struct xfrm_state *x); static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); @@ -81,6 +83,11 @@ static void xfrm_state_gc_task(void *data) struct list_head *entry, *tmp; struct list_head gc_list = LIST_HEAD_INIT(gc_list); + if (xfrm_state_gc_flush_bundles) { + xfrm_state_gc_flush_bundles = 0; + xfrm_flush_bundles(); + } + spin_lock_bh(&xfrm_state_gc_lock); list_splice_init(&xfrm_state_gc_list, &gc_list); spin_unlock_bh(&xfrm_state_gc_lock); @@ -228,8 +235,10 @@ static void __xfrm_state_delete(struct xfrm_state *x) * our caller holds. A larger value means that * there are DSTs attached to this xfrm_state. */ - if (atomic_read(&x->refcnt) > 2) - xfrm_flush_bundles(); + if (atomic_read(&x->refcnt) > 2) { + xfrm_state_gc_flush_bundles = 1; + schedule_work(&xfrm_state_gc_work); + } /* All xfrm_state objects are created by xfrm_state_alloc. * The xfrm_state_alloc call gives a reference, and that |
