summaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_user.c
diff options
context:
space:
mode:
authorFan Du <fan.du@windriver.com>2013-11-07 17:47:50 +0800
committerSteffen Klassert <steffen.klassert@secunet.com>2013-12-06 06:45:06 +0100
commit283bc9f35bbbcb0e9ab4e6d2427da7f9f710d52d (patch)
tree8b580340bdc0d1f25f4a76dfc39c48760f3f307a /net/xfrm/xfrm_user.c
parent8d549c4f5d92d80fc6f888fd314e10972ae0ec37 (diff)
xfrm: Namespacify xfrm state/policy locks
By semantics, xfrm layer is fully name space aware, so will the locks, e.g. xfrm_state/pocliy_lock. Ensure exclusive access into state/policy link list for different name space with one global lock is not right in terms of semantics aspect at first place, as they are indeed mutually independent with each other, but also more seriously causes scalability problem. One practical scenario is on a Open Network Stack, more than hundreds of lxc tenants acts as routers within one host, a global xfrm_state/policy_lock becomes the bottleneck. But onces those locks are decoupled in a per-namespace fashion, locks contend is just with in specific name space scope, without causing additional SPD/SAD access delay for other name space. Also this patch improve scalability while as without changing original xfrm behavior. Signed-off-by: Fan Du <fan.du@windriver.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r--net/xfrm/xfrm_user.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 840cc8d9fbe..16c84608e81 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -877,7 +877,10 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
static int xfrm_dump_sa_done(struct netlink_callback *cb)
{
struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
- xfrm_state_walk_done(walk);
+ struct sock *sk = cb->skb->sk;
+ struct net *net = sock_net(sk);
+
+ xfrm_state_walk_done(walk, net);
return 0;
}
@@ -1555,8 +1558,9 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
static int xfrm_dump_policy_done(struct netlink_callback *cb)
{
struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
+ struct net *net = sock_net(cb->skb->sk);
- xfrm_policy_walk_done(walk);
+ xfrm_policy_walk_done(walk, net);
return 0;
}
@@ -2403,9 +2407,11 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
static void xfrm_netlink_rcv(struct sk_buff *skb)
{
- mutex_lock(&xfrm_cfg_mutex);
+ struct net *net = sock_net(skb->sk);
+
+ mutex_lock(&net->xfrm.xfrm_cfg_mutex);
netlink_rcv_skb(skb, &xfrm_user_rcv_msg);
- mutex_unlock(&xfrm_cfg_mutex);
+ mutex_unlock(&net->xfrm.xfrm_cfg_mutex);
}
static inline size_t xfrm_expire_msgsize(void)