Commit 50a30657 authored by Alexey Dobriyan's avatar Alexey Dobriyan Committed by David S. Miller

netns xfrm: per-netns km_waitq

Disallow spurious wakeups in __xfrm_lookup().
Signed-off-by: default avatarAlexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c7837144
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define __NETNS_XFRM_H #define __NETNS_XFRM_H
#include <linux/list.h> #include <linux/list.h>
#include <linux/wait.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
struct netns_xfrm { struct netns_xfrm {
...@@ -22,6 +23,8 @@ struct netns_xfrm { ...@@ -22,6 +23,8 @@ struct netns_xfrm {
struct work_struct state_hash_work; struct work_struct state_hash_work;
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;
}; };
#endif #endif
...@@ -1459,7 +1459,6 @@ extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, ...@@ -1459,7 +1459,6 @@ extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
struct xfrm_kmaddress *k); struct xfrm_kmaddress *k);
#endif #endif
extern wait_queue_head_t km_waitq;
extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid); extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid);
extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
......
...@@ -1411,7 +1411,7 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg * ...@@ -1411,7 +1411,7 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg *
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(&km_waitq); wake_up(&init_net.xfrm.km_waitq);
} }
spin_unlock_bh(&x->lock); spin_unlock_bh(&x->lock);
xfrm_state_put(x); xfrm_state_put(x);
......
...@@ -1691,11 +1691,11 @@ int __xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, ...@@ -1691,11 +1691,11 @@ int __xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
if (err == -EAGAIN && (flags & XFRM_LOOKUP_WAIT)) { if (err == -EAGAIN && (flags & XFRM_LOOKUP_WAIT)) {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&km_waitq, &wait); add_wait_queue(&init_net.xfrm.km_waitq, &wait);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
schedule(); schedule();
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
remove_wait_queue(&km_waitq, &wait); remove_wait_queue(&init_net.xfrm.km_waitq, &wait);
nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family); nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family);
......
...@@ -170,9 +170,6 @@ static void xfrm_hash_resize(struct work_struct *work) ...@@ -170,9 +170,6 @@ static void xfrm_hash_resize(struct work_struct *work)
mutex_unlock(&hash_resize_mutex); mutex_unlock(&hash_resize_mutex);
} }
DECLARE_WAIT_QUEUE_HEAD(km_waitq);
EXPORT_SYMBOL(km_waitq);
static DEFINE_RWLOCK(xfrm_state_afinfo_lock); static DEFINE_RWLOCK(xfrm_state_afinfo_lock);
static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
...@@ -399,7 +396,7 @@ static void xfrm_state_gc_task(struct work_struct *work) ...@@ -399,7 +396,7 @@ static void xfrm_state_gc_task(struct work_struct *work)
hlist_for_each_entry_safe(x, entry, tmp, &gc_list, gclist) hlist_for_each_entry_safe(x, entry, tmp, &gc_list, gclist)
xfrm_state_gc_destroy(x); xfrm_state_gc_destroy(x);
wake_up(&km_waitq); wake_up(&net->xfrm.km_waitq);
} }
static inline unsigned long make_jiffies(long secs) static inline unsigned long make_jiffies(long secs)
...@@ -470,7 +467,7 @@ static void xfrm_timer_handler(unsigned long data) ...@@ -470,7 +467,7 @@ static void xfrm_timer_handler(unsigned long data)
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(&km_waitq); wake_up(&init_net.xfrm.km_waitq);
next = 2; next = 2;
goto resched; goto resched;
} }
...@@ -638,7 +635,7 @@ int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info) ...@@ -638,7 +635,7 @@ int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
out: out:
spin_unlock_bh(&xfrm_state_lock); spin_unlock_bh(&xfrm_state_lock);
wake_up(&km_waitq); wake_up(&init_net.xfrm.km_waitq);
return err; return err;
} }
EXPORT_SYMBOL(xfrm_state_flush); EXPORT_SYMBOL(xfrm_state_flush);
...@@ -929,7 +926,7 @@ static void __xfrm_state_insert(struct xfrm_state *x) ...@@ -929,7 +926,7 @@ 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(&km_waitq); wake_up(&init_net.xfrm.km_waitq);
init_net.xfrm.state_num++; init_net.xfrm.state_num++;
...@@ -1743,7 +1740,7 @@ void km_state_expired(struct xfrm_state *x, int hard, u32 pid) ...@@ -1743,7 +1740,7 @@ void km_state_expired(struct xfrm_state *x, int hard, u32 pid)
km_state_notify(x, &c); km_state_notify(x, &c);
if (hard) if (hard)
wake_up(&km_waitq); wake_up(&init_net.xfrm.km_waitq);
} }
EXPORT_SYMBOL(km_state_expired); EXPORT_SYMBOL(km_state_expired);
...@@ -1794,7 +1791,7 @@ void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid) ...@@ -1794,7 +1791,7 @@ void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid)
km_policy_notify(pol, dir, &c); km_policy_notify(pol, dir, &c);
if (hard) if (hard)
wake_up(&km_waitq); wake_up(&init_net.xfrm.km_waitq);
} }
EXPORT_SYMBOL(km_policy_expired); EXPORT_SYMBOL(km_policy_expired);
...@@ -2089,6 +2086,7 @@ int __net_init xfrm_state_init(struct net *net) ...@@ -2089,6 +2086,7 @@ 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);
return 0; return 0;
out_byspi: out_byspi:
......
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