diff options
-rw-r--r-- | net/xfrm/xfrm_policy.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index fbf8270619255..80828078733dd 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -13,6 +13,7 @@ * */ +#include <asm/bug.h> #include <linux/config.h> #include <linux/slab.h> #include <linux/kmod.h> @@ -300,20 +301,20 @@ static void xfrm_policy_gc_task(void *data) static void xfrm_policy_kill(struct xfrm_policy *policy) { + int dead; + write_lock_bh(&policy->lock); - if (policy->dead) { - write_unlock_bh(&policy->lock); + dead = policy->dead; + policy->dead = 1; + write_unlock_bh(&policy->lock); + + if (unlikely(dead)) { + WARN_ON(1); return; } - policy->dead = 1; spin_lock(&xfrm_policy_gc_lock); list_add(&policy->list, &xfrm_policy_gc_list); - /* - * Unlock the policy (out of order unlocking), to make sure - * the GC context does not free it with an active lock: - */ - write_unlock_bh(&policy->lock); spin_unlock(&xfrm_policy_gc_lock); schedule_work(&xfrm_policy_gc_work); |