From 1bd0f7f493e273aff1bdd7551ed959d02927e677 Mon Sep 17 00:00:00 2001 From: James Morris Date: Mon, 31 Mar 2003 17:47:50 -0800 Subject: [PATCH] [IPSEC]: Fix xfrm_state refcounts. --- net/xfrm/xfrm_state.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 6c78d1643ba1f..6f38d9dfb549f 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -176,10 +176,27 @@ static void __xfrm_state_delete(struct xfrm_state *x) spin_unlock(&xfrm_state_lock); if (del_timer(&x->timer)) atomic_dec(&x->refcnt); - if (atomic_read(&x->refcnt) != 1) + + /* The number two in this test is the reference + * mentioned in the comment below plus the reference + * 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(x); } + /* All xfrm_state objects are created by one of two possible + * paths: + * + * 1) xfrm_state_alloc --> xfrm_state_insert + * 2) xfrm_state_lookup --> xfrm_state_insert + * + * The xfrm_state_lookup or xfrm_state_alloc call gives a + * reference, and that is what we are dropping here. + */ + atomic_dec(&x->refcnt); + if (kill && x->type) x->type->destructor(x); wake_up(&km_waitq); -- 2.53.0