aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorSteffen Klassert <steffen.klassert@secunet.com>2013-08-27 07:43:30 -0400
committerSteffen Klassert <steffen.klassert@secunet.com>2013-12-06 01:24:31 -0500
commit5b8ef3415a21f173ab115e90ec92c071a03f22d7 (patch)
treebb78d47430f22c24030375aeb2b358d8e38ddd18 /net
parent283bc9f35bbbcb0e9ab4e6d2427da7f9f710d52d (diff)
xfrm: Remove ancient sleeping when the SA is in acquire state
We now queue packets to the policy if the states are not yet resolved, this replaces the ancient sleeping code. Also the sleeping can cause indefinite task hangs if the needed state does not get resolved. Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net')
-rw-r--r--net/key/af_key.c5
-rw-r--r--net/xfrm/xfrm_policy.c21
-rw-r--r--net/xfrm/xfrm_state.c21
3 files changed, 5 insertions, 42 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 9a039acf37e8..5beabd8ba772 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1380,10 +1380,9 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, const struct sadb
1380 return 0; 1380 return 0;
1381 1381
1382 spin_lock_bh(&x->lock); 1382 spin_lock_bh(&x->lock);
1383 if (x->km.state == XFRM_STATE_ACQ) { 1383 if (x->km.state == XFRM_STATE_ACQ)
1384 x->km.state = XFRM_STATE_ERROR; 1384 x->km.state = XFRM_STATE_ERROR;
1385 wake_up(&net->xfrm.km_waitq); 1385
1386 }
1387 spin_unlock_bh(&x->lock); 1386 spin_unlock_bh(&x->lock);
1388 xfrm_state_put(x); 1387 xfrm_state_put(x);
1389 return 0; 1388 return 0;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 73b04d3df44e..a7487f34e813 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1901,8 +1901,7 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net,
1901 if (IS_ERR(xdst)) 1901 if (IS_ERR(xdst))
1902 return xdst; 1902 return xdst;
1903 1903
1904 if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0 || 1904 if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0)
1905 (fl->flowi_flags & FLOWI_FLAG_CAN_SLEEP))
1906 return xdst; 1905 return xdst;
1907 1906
1908 dst1 = &xdst->u.dst; 1907 dst1 = &xdst->u.dst;
@@ -2077,7 +2076,6 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
2077 u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); 2076 u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
2078 int i, err, num_pols, num_xfrms = 0, drop_pols = 0; 2077 int i, err, num_pols, num_xfrms = 0, drop_pols = 0;
2079 2078
2080restart:
2081 dst = NULL; 2079 dst = NULL;
2082 xdst = NULL; 2080 xdst = NULL;
2083 route = NULL; 2081 route = NULL;
@@ -2157,23 +2155,8 @@ restart:
2157 2155
2158 return make_blackhole(net, family, dst_orig); 2156 return make_blackhole(net, family, dst_orig);
2159 } 2157 }
2160 if (fl->flowi_flags & FLOWI_FLAG_CAN_SLEEP) {
2161 DECLARE_WAITQUEUE(wait, current);
2162 2158
2163 add_wait_queue(&net->xfrm.km_waitq, &wait); 2159 err = -EAGAIN;
2164 set_current_state(TASK_INTERRUPTIBLE);
2165 schedule();
2166 set_current_state(TASK_RUNNING);
2167 remove_wait_queue(&net->xfrm.km_waitq, &wait);
2168
2169 if (!signal_pending(current)) {
2170 dst_release(dst);
2171 goto restart;
2172 }
2173
2174 err = -ERESTART;
2175 } else
2176 err = -EAGAIN;
2177 2160
2178 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); 2161 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
2179 goto error; 2162 goto error;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 290479d0746d..e845066547c4 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -372,8 +372,6 @@ static void xfrm_state_gc_task(struct work_struct *work)
372 372
373 hlist_for_each_entry_safe(x, tmp, &gc_list, gclist) 373 hlist_for_each_entry_safe(x, tmp, &gc_list, gclist)
374 xfrm_state_gc_destroy(x); 374 xfrm_state_gc_destroy(x);
375
376 wake_up(&net->xfrm.km_waitq);
377} 375}
378 376
379static inline unsigned long make_jiffies(long secs) 377static inline unsigned long make_jiffies(long secs)
@@ -388,7 +386,6 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me)
388{ 386{
389 struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer); 387 struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
390 struct xfrm_state *x = container_of(thr, struct xfrm_state, mtimer); 388 struct xfrm_state *x = container_of(thr, struct xfrm_state, mtimer);
391 struct net *net = xs_net(x);
392 unsigned long now = get_seconds(); 389 unsigned long now = get_seconds();
393 long next = LONG_MAX; 390 long next = LONG_MAX;
394 int warn = 0; 391 int warn = 0;
@@ -458,12 +455,8 @@ resched:
458 goto out; 455 goto out;
459 456
460expired: 457expired:
461 if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0) { 458 if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0)
462 x->km.state = XFRM_STATE_EXPIRED; 459 x->km.state = XFRM_STATE_EXPIRED;
463 wake_up(&net->xfrm.km_waitq);
464 next = 2;
465 goto resched;
466 }
467 460
468 err = __xfrm_state_delete(x); 461 err = __xfrm_state_delete(x);
469 if (!err) 462 if (!err)
@@ -635,7 +628,6 @@ restart:
635 628
636out: 629out:
637 spin_unlock_bh(&net->xfrm.xfrm_state_lock); 630 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
638 wake_up(&net->xfrm.km_waitq);
639 return err; 631 return err;
640} 632}
641EXPORT_SYMBOL(xfrm_state_flush); 633EXPORT_SYMBOL(xfrm_state_flush);
@@ -948,8 +940,6 @@ static void __xfrm_state_insert(struct xfrm_state *x)
948 if (x->replay_maxage) 940 if (x->replay_maxage)
949 mod_timer(&x->rtimer, jiffies + x->replay_maxage); 941 mod_timer(&x->rtimer, jiffies + x->replay_maxage);
950 942
951 wake_up(&net->xfrm.km_waitq);
952
953 net->xfrm.state_num++; 943 net->xfrm.state_num++;
954 944
955 xfrm_hash_grow_check(net, x->bydst.next != NULL); 945 xfrm_hash_grow_check(net, x->bydst.next != NULL);
@@ -1658,16 +1648,12 @@ EXPORT_SYMBOL(km_state_notify);
1658 1648
1659void km_state_expired(struct xfrm_state *x, int hard, u32 portid) 1649void km_state_expired(struct xfrm_state *x, int hard, u32 portid)
1660{ 1650{
1661 struct net *net = xs_net(x);
1662 struct km_event c; 1651 struct km_event c;
1663 1652
1664 c.data.hard = hard; 1653 c.data.hard = hard;
1665 c.portid = portid; 1654 c.portid = portid;
1666 c.event = XFRM_MSG_EXPIRE; 1655 c.event = XFRM_MSG_EXPIRE;
1667 km_state_notify(x, &c); 1656 km_state_notify(x, &c);
1668
1669 if (hard)
1670 wake_up(&net->xfrm.km_waitq);
1671} 1657}
1672 1658
1673EXPORT_SYMBOL(km_state_expired); 1659EXPORT_SYMBOL(km_state_expired);
@@ -1710,16 +1696,12 @@ EXPORT_SYMBOL(km_new_mapping);
1710 1696
1711void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 portid) 1697void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 portid)
1712{ 1698{
1713 struct net *net = xp_net(pol);
1714 struct km_event c; 1699 struct km_event c;
1715 1700
1716 c.data.hard = hard; 1701 c.data.hard = hard;
1717 c.portid = portid; 1702 c.portid = portid;
1718 c.event = XFRM_MSG_POLEXPIRE; 1703 c.event = XFRM_MSG_POLEXPIRE;
1719 km_policy_notify(pol, dir, &c); 1704 km_policy_notify(pol, dir, &c);
1720
1721 if (hard)
1722 wake_up(&net->xfrm.km_waitq);
1723} 1705}
1724EXPORT_SYMBOL(km_policy_expired); 1706EXPORT_SYMBOL(km_policy_expired);
1725 1707
@@ -2028,7 +2010,6 @@ int __net_init xfrm_state_init(struct net *net)
2028 INIT_WORK(&net->xfrm.state_hash_work, xfrm_hash_resize); 2010 INIT_WORK(&net->xfrm.state_hash_work, xfrm_hash_resize);
2029 INIT_HLIST_HEAD(&net->xfrm.state_gc_list); 2011 INIT_HLIST_HEAD(&net->xfrm.state_gc_list);
2030 INIT_WORK(&net->xfrm.state_gc_work, xfrm_state_gc_task); 2012 INIT_WORK(&net->xfrm.state_gc_work, xfrm_state_gc_task);
2031 init_waitqueue_head(&net->xfrm.km_waitq);
2032 spin_lock_init(&net->xfrm.xfrm_state_lock); 2013 spin_lock_init(&net->xfrm.xfrm_state_lock);
2033 return 0; 2014 return 0;
2034 2015