aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/xfrm/xfrm_policy.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 54a4be6a7d26..d19e274b9c4a 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -346,6 +346,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
346 struct xfrm_policy *pol, **p; 346 struct xfrm_policy *pol, **p;
347 struct xfrm_policy *delpol = NULL; 347 struct xfrm_policy *delpol = NULL;
348 struct xfrm_policy **newpos = NULL; 348 struct xfrm_policy **newpos = NULL;
349 struct dst_entry *gc_list;
349 350
350 write_lock_bh(&xfrm_policy_lock); 351 write_lock_bh(&xfrm_policy_lock);
351 for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) { 352 for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) {
@@ -381,9 +382,36 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
381 xfrm_pol_hold(policy); 382 xfrm_pol_hold(policy);
382 write_unlock_bh(&xfrm_policy_lock); 383 write_unlock_bh(&xfrm_policy_lock);
383 384
384 if (delpol) { 385 if (delpol)
385 xfrm_policy_kill(delpol); 386 xfrm_policy_kill(delpol);
387
388 read_lock_bh(&xfrm_policy_lock);
389 gc_list = NULL;
390 for (policy = policy->next; policy; policy = policy->next) {
391 struct dst_entry *dst;
392
393 write_lock(&policy->lock);
394 dst = policy->bundles;
395 if (dst) {
396 struct dst_entry *tail = dst;
397 while (tail->next)
398 tail = tail->next;
399 tail->next = gc_list;
400 gc_list = dst;
401
402 policy->bundles = NULL;
403 }
404 write_unlock(&policy->lock);
386 } 405 }
406 read_unlock_bh(&xfrm_policy_lock);
407
408 while (gc_list) {
409 struct dst_entry *dst = gc_list;
410
411 gc_list = dst->next;
412 dst_free(dst);
413 }
414
387 return 0; 415 return 0;
388} 416}
389EXPORT_SYMBOL(xfrm_policy_insert); 417EXPORT_SYMBOL(xfrm_policy_insert);