aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2008-11-25 20:21:01 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-25 20:21:01 -0500
commit50a30657fd7ee77a94a6bf0ad86eba7c37c3032e (patch)
tree7eb9165881b9082588eb2c373e9ed2ebc013321e
parentc78371441c0d957f54c9f8a35b3ee5a378d14808 (diff)
netns xfrm: per-netns km_waitq
Disallow spurious wakeups in __xfrm_lookup(). Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/netns/xfrm.h3
-rw-r--r--include/net/xfrm.h1
-rw-r--r--net/key/af_key.c2
-rw-r--r--net/xfrm/xfrm_policy.c4
-rw-r--r--net/xfrm/xfrm_state.c16
5 files changed, 13 insertions, 13 deletions
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 80555351fe5e..2a383c8ba1af 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -2,6 +2,7 @@
2#define __NETNS_XFRM_H 2#define __NETNS_XFRM_H
3 3
4#include <linux/list.h> 4#include <linux/list.h>
5#include <linux/wait.h>
5#include <linux/workqueue.h> 6#include <linux/workqueue.h>
6 7
7struct netns_xfrm { 8struct netns_xfrm {
@@ -22,6 +23,8 @@ struct netns_xfrm {
22 struct work_struct state_hash_work; 23 struct work_struct state_hash_work;
23 struct hlist_head state_gc_list; 24 struct hlist_head state_gc_list;
24 struct work_struct state_gc_work; 25 struct work_struct state_gc_work;
26
27 wait_queue_head_t km_waitq;
25}; 28};
26 29
27#endif 30#endif
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 9da89039832c..0d4353c11093 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1459,7 +1459,6 @@ extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
1459 struct xfrm_kmaddress *k); 1459 struct xfrm_kmaddress *k);
1460#endif 1460#endif
1461 1461
1462extern wait_queue_head_t km_waitq;
1463extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); 1462extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
1464extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid); 1463extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid);
1465extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); 1464extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index bde8aad4cc93..f202ba6c8dcb 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1411,7 +1411,7 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg *
1411 spin_lock_bh(&x->lock); 1411 spin_lock_bh(&x->lock);
1412 if (x->km.state == XFRM_STATE_ACQ) { 1412 if (x->km.state == XFRM_STATE_ACQ) {
1413 x->km.state = XFRM_STATE_ERROR; 1413 x->km.state = XFRM_STATE_ERROR;
1414 wake_up(&km_waitq); 1414 wake_up(&init_net.xfrm.km_waitq);
1415 } 1415 }
1416 spin_unlock_bh(&x->lock); 1416 spin_unlock_bh(&x->lock);
1417 xfrm_state_put(x); 1417 xfrm_state_put(x);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 8e7671b9e76e..cf2bf3aa7ab4 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1691,11 +1691,11 @@ restart:
1691 if (err == -EAGAIN && (flags & XFRM_LOOKUP_WAIT)) { 1691 if (err == -EAGAIN && (flags & XFRM_LOOKUP_WAIT)) {
1692 DECLARE_WAITQUEUE(wait, current); 1692 DECLARE_WAITQUEUE(wait, current);
1693 1693
1694 add_wait_queue(&km_waitq, &wait); 1694 add_wait_queue(&init_net.xfrm.km_waitq, &wait);
1695 set_current_state(TASK_INTERRUPTIBLE); 1695 set_current_state(TASK_INTERRUPTIBLE);
1696 schedule(); 1696 schedule();
1697 set_current_state(TASK_RUNNING); 1697 set_current_state(TASK_RUNNING);
1698 remove_wait_queue(&km_waitq, &wait); 1698 remove_wait_queue(&init_net.xfrm.km_waitq, &wait);
1699 1699
1700 nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family); 1700 nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family);
1701 1701
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 69c0b06bf756..24bd89e76236 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -170,9 +170,6 @@ out_unlock:
170 mutex_unlock(&hash_resize_mutex); 170 mutex_unlock(&hash_resize_mutex);
171} 171}
172 172
173DECLARE_WAIT_QUEUE_HEAD(km_waitq);
174EXPORT_SYMBOL(km_waitq);
175
176static DEFINE_RWLOCK(xfrm_state_afinfo_lock); 173static DEFINE_RWLOCK(xfrm_state_afinfo_lock);
177static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; 174static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
178 175
@@ -399,7 +396,7 @@ static void xfrm_state_gc_task(struct work_struct *work)
399 hlist_for_each_entry_safe(x, entry, tmp, &gc_list, gclist) 396 hlist_for_each_entry_safe(x, entry, tmp, &gc_list, gclist)
400 xfrm_state_gc_destroy(x); 397 xfrm_state_gc_destroy(x);
401 398
402 wake_up(&km_waitq); 399 wake_up(&net->xfrm.km_waitq);
403} 400}
404 401
405static inline unsigned long make_jiffies(long secs) 402static inline unsigned long make_jiffies(long secs)
@@ -470,7 +467,7 @@ resched:
470expired: 467expired:
471 if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0) { 468 if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0) {
472 x->km.state = XFRM_STATE_EXPIRED; 469 x->km.state = XFRM_STATE_EXPIRED;
473 wake_up(&km_waitq); 470 wake_up(&init_net.xfrm.km_waitq);
474 next = 2; 471 next = 2;
475 goto resched; 472 goto resched;
476 } 473 }
@@ -638,7 +635,7 @@ restart:
638 635
639out: 636out:
640 spin_unlock_bh(&xfrm_state_lock); 637 spin_unlock_bh(&xfrm_state_lock);
641 wake_up(&km_waitq); 638 wake_up(&init_net.xfrm.km_waitq);
642 return err; 639 return err;
643} 640}
644EXPORT_SYMBOL(xfrm_state_flush); 641EXPORT_SYMBOL(xfrm_state_flush);
@@ -929,7 +926,7 @@ static void __xfrm_state_insert(struct xfrm_state *x)
929 if (x->replay_maxage) 926 if (x->replay_maxage)
930 mod_timer(&x->rtimer, jiffies + x->replay_maxage); 927 mod_timer(&x->rtimer, jiffies + x->replay_maxage);
931 928
932 wake_up(&km_waitq); 929 wake_up(&init_net.xfrm.km_waitq);
933 930
934 init_net.xfrm.state_num++; 931 init_net.xfrm.state_num++;
935 932
@@ -1743,7 +1740,7 @@ void km_state_expired(struct xfrm_state *x, int hard, u32 pid)
1743 km_state_notify(x, &c); 1740 km_state_notify(x, &c);
1744 1741
1745 if (hard) 1742 if (hard)
1746 wake_up(&km_waitq); 1743 wake_up(&init_net.xfrm.km_waitq);
1747} 1744}
1748 1745
1749EXPORT_SYMBOL(km_state_expired); 1746EXPORT_SYMBOL(km_state_expired);
@@ -1794,7 +1791,7 @@ void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid)
1794 km_policy_notify(pol, dir, &c); 1791 km_policy_notify(pol, dir, &c);
1795 1792
1796 if (hard) 1793 if (hard)
1797 wake_up(&km_waitq); 1794 wake_up(&init_net.xfrm.km_waitq);
1798} 1795}
1799EXPORT_SYMBOL(km_policy_expired); 1796EXPORT_SYMBOL(km_policy_expired);
1800 1797
@@ -2089,6 +2086,7 @@ int __net_init xfrm_state_init(struct net *net)
2089 INIT_WORK(&net->xfrm.state_hash_work, xfrm_hash_resize); 2086 INIT_WORK(&net->xfrm.state_hash_work, xfrm_hash_resize);
2090 INIT_HLIST_HEAD(&net->xfrm.state_gc_list); 2087 INIT_HLIST_HEAD(&net->xfrm.state_gc_list);
2091 INIT_WORK(&net->xfrm.state_gc_work, xfrm_state_gc_task); 2088 INIT_WORK(&net->xfrm.state_gc_work, xfrm_state_gc_task);
2089 init_waitqueue_head(&net->xfrm.km_waitq);
2092 return 0; 2090 return 0;
2093 2091
2094out_byspi: 2092out_byspi: