summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-11-14 08:39:38 +0300
committerDavid S. Miller <davem@davemloft.net>2008-01-29 01:53:44 +0300
commita2deb6d26f16ed7bf787dbd6a58c5d7be47d8db3 (patch)
treea8c1ef4007cd8d419aa8d8a218092b00dcd64757
parente40b3286158565909692e5914ea4a11bdbcc68c8 (diff)
downloadlinux-a2deb6d26f16ed7bf787dbd6a58c5d7be47d8db3.tar.xz
[IPSEC]: Move x->outer_mode->output out of locked section
RO mode is the only one that requires a locked output function. So it's easier to move the lock into that function rather than requiring everyone else to run under the lock. In particular, this allows us to move the size check into the output function without causing a potential dead-lock should the ICMP error somehow hit the same SA on transmission. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv6/xfrm6_mode_ro.c3
-rw-r--r--net/xfrm/xfrm_output.c8
2 files changed, 7 insertions, 4 deletions
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c
index a7bc8c62317a..4a01cb3c370b 100644
--- a/net/ipv6/xfrm6_mode_ro.c
+++ b/net/ipv6/xfrm6_mode_ro.c
@@ -28,6 +28,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/skbuff.h>
+#include <linux/spinlock.h>
#include <linux/stringify.h>
#include <linux/time.h>
#include <net/ipv6.h>
@@ -53,7 +54,9 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
__skb_pull(skb, hdr_len);
memmove(ipv6_hdr(skb), iph, hdr_len);
+ spin_lock_bh(&x->lock);
x->lastused = get_seconds();
+ spin_unlock_bh(&x->lock);
return 0;
}
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 58d5a746b1c3..b1efdc8850a7 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -53,6 +53,10 @@ int xfrm_output(struct sk_buff *skb)
}
do {
+ err = x->outer_mode->output(x, skb);
+ if (err)
+ goto error;
+
spin_lock_bh(&x->lock);
err = xfrm_state_check(x, skb);
if (err)
@@ -64,10 +68,6 @@ int xfrm_output(struct sk_buff *skb)
xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
}
- err = x->outer_mode->output(x, skb);
- if (err)
- goto error;
-
x->curlft.bytes += skb->len;
x->curlft.packets++;