Commit 5b8ef341 authored by Steffen Klassert's avatar Steffen Klassert

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: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent 283bc9f3
...@@ -33,8 +33,6 @@ struct netns_xfrm { ...@@ -33,8 +33,6 @@ struct netns_xfrm {
struct hlist_head state_gc_list; struct hlist_head state_gc_list;
struct work_struct state_gc_work; struct work_struct state_gc_work;
wait_queue_head_t km_waitq;
struct list_head policy_all; struct list_head policy_all;
struct hlist_head *policy_byidx; struct hlist_head *policy_byidx;
unsigned int policy_idx_hmask; unsigned int policy_idx_hmask;
......
...@@ -1380,10 +1380,9 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, const struct sadb ...@@ -1380,10 +1380,9 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, const struct sadb
return 0; return 0;
spin_lock_bh(&x->lock); spin_lock_bh(&x->lock);
if (x->km.state == XFRM_STATE_ACQ) { if (x->km.state == XFRM_STATE_ACQ)
x->km.state = XFRM_STATE_ERROR; x->km.state = XFRM_STATE_ERROR;
wake_up(&net->xfrm.km_waitq);
}
spin_unlock_bh(&x->lock); spin_unlock_bh(&x->lock);
xfrm_state_put(x); xfrm_state_put(x);
return 0; return 0;
......
...@@ -1901,8 +1901,7 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, ...@@ -1901,8 +1901,7 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net,
if (IS_ERR(xdst)) if (IS_ERR(xdst))
return xdst; return xdst;
if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0 || if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0)
(fl->flowi_flags & FLOWI_FLAG_CAN_SLEEP))
return xdst; return xdst;
dst1 = &xdst->u.dst; dst1 = &xdst->u.dst;
...@@ -2077,7 +2076,6 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, ...@@ -2077,7 +2076,6 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
int i, err, num_pols, num_xfrms = 0, drop_pols = 0; int i, err, num_pols, num_xfrms = 0, drop_pols = 0;
restart:
dst = NULL; dst = NULL;
xdst = NULL; xdst = NULL;
route = NULL; route = NULL;
...@@ -2157,23 +2155,8 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, ...@@ -2157,23 +2155,8 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
return make_blackhole(net, family, dst_orig); return make_blackhole(net, family, dst_orig);
} }
if (fl->flowi_flags & FLOWI_FLAG_CAN_SLEEP) {
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&net->xfrm.km_waitq, &wait); err = -EAGAIN;
set_current_state(TASK_INTERRUPTIBLE);
schedule();
set_current_state(TASK_RUNNING);
remove_wait_queue(&net->xfrm.km_waitq, &wait);
if (!signal_pending(current)) {
dst_release(dst);
goto restart;
}
err = -ERESTART;
} else
err = -EAGAIN;
XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
goto error; goto error;
......
...@@ -372,8 +372,6 @@ static void xfrm_state_gc_task(struct work_struct *work) ...@@ -372,8 +372,6 @@ static void xfrm_state_gc_task(struct work_struct *work)
hlist_for_each_entry_safe(x, tmp, &gc_list, gclist) hlist_for_each_entry_safe(x, tmp, &gc_list, gclist)
xfrm_state_gc_destroy(x); xfrm_state_gc_destroy(x);
wake_up(&net->xfrm.km_waitq);
} }
static inline unsigned long make_jiffies(long secs) static inline unsigned long make_jiffies(long secs)
...@@ -388,7 +386,6 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me) ...@@ -388,7 +386,6 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me)
{ {
struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer); struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
struct xfrm_state *x = container_of(thr, struct xfrm_state, mtimer); struct xfrm_state *x = container_of(thr, struct xfrm_state, mtimer);
struct net *net = xs_net(x);
unsigned long now = get_seconds(); unsigned long now = get_seconds();
long next = LONG_MAX; long next = LONG_MAX;
int warn = 0; int warn = 0;
...@@ -458,12 +455,8 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me) ...@@ -458,12 +455,8 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me)
goto out; goto out;
expired: expired:
if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0) { if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0)
x->km.state = XFRM_STATE_EXPIRED; x->km.state = XFRM_STATE_EXPIRED;
wake_up(&net->xfrm.km_waitq);
next = 2;
goto resched;
}
err = __xfrm_state_delete(x); err = __xfrm_state_delete(x);
if (!err) if (!err)
...@@ -635,7 +628,6 @@ int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info) ...@@ -635,7 +628,6 @@ int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info)
out: out:
spin_unlock_bh(&net->xfrm.xfrm_state_lock); spin_unlock_bh(&net->xfrm.xfrm_state_lock);
wake_up(&net->xfrm.km_waitq);
return err; return err;
} }
EXPORT_SYMBOL(xfrm_state_flush); EXPORT_SYMBOL(xfrm_state_flush);
...@@ -948,8 +940,6 @@ static void __xfrm_state_insert(struct xfrm_state *x) ...@@ -948,8 +940,6 @@ static void __xfrm_state_insert(struct xfrm_state *x)
if (x->replay_maxage) if (x->replay_maxage)
mod_timer(&x->rtimer, jiffies + x->replay_maxage); mod_timer(&x->rtimer, jiffies + x->replay_maxage);
wake_up(&net->xfrm.km_waitq);
net->xfrm.state_num++; net->xfrm.state_num++;
xfrm_hash_grow_check(net, x->bydst.next != NULL); xfrm_hash_grow_check(net, x->bydst.next != NULL);
...@@ -1658,16 +1648,12 @@ EXPORT_SYMBOL(km_state_notify); ...@@ -1658,16 +1648,12 @@ EXPORT_SYMBOL(km_state_notify);
void km_state_expired(struct xfrm_state *x, int hard, u32 portid) void km_state_expired(struct xfrm_state *x, int hard, u32 portid)
{ {
struct net *net = xs_net(x);
struct km_event c; struct km_event c;
c.data.hard = hard; c.data.hard = hard;
c.portid = portid; c.portid = portid;
c.event = XFRM_MSG_EXPIRE; c.event = XFRM_MSG_EXPIRE;
km_state_notify(x, &c); km_state_notify(x, &c);
if (hard)
wake_up(&net->xfrm.km_waitq);
} }
EXPORT_SYMBOL(km_state_expired); EXPORT_SYMBOL(km_state_expired);
...@@ -1710,16 +1696,12 @@ EXPORT_SYMBOL(km_new_mapping); ...@@ -1710,16 +1696,12 @@ EXPORT_SYMBOL(km_new_mapping);
void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 portid) void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 portid)
{ {
struct net *net = xp_net(pol);
struct km_event c; struct km_event c;
c.data.hard = hard; c.data.hard = hard;
c.portid = portid; c.portid = portid;
c.event = XFRM_MSG_POLEXPIRE; c.event = XFRM_MSG_POLEXPIRE;
km_policy_notify(pol, dir, &c); km_policy_notify(pol, dir, &c);
if (hard)
wake_up(&net->xfrm.km_waitq);
} }
EXPORT_SYMBOL(km_policy_expired); EXPORT_SYMBOL(km_policy_expired);
...@@ -2028,7 +2010,6 @@ int __net_init xfrm_state_init(struct net *net) ...@@ -2028,7 +2010,6 @@ int __net_init xfrm_state_init(struct net *net)
INIT_WORK(&net->xfrm.state_hash_work, xfrm_hash_resize); INIT_WORK(&net->xfrm.state_hash_work, xfrm_hash_resize);
INIT_HLIST_HEAD(&net->xfrm.state_gc_list); INIT_HLIST_HEAD(&net->xfrm.state_gc_list);
INIT_WORK(&net->xfrm.state_gc_work, xfrm_state_gc_task); INIT_WORK(&net->xfrm.state_gc_work, xfrm_state_gc_task);
init_waitqueue_head(&net->xfrm.km_waitq);
spin_lock_init(&net->xfrm.xfrm_state_lock); spin_lock_init(&net->xfrm.xfrm_state_lock);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment