[IPSEC]: Move x->outer_mode->output out of locked section
authorHerbert Xu <herbert@gondor.apana.org.au>
Wed, 14 Nov 2007 05:39:38 +0000 (21:39 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Jan 2008 22:53:44 +0000 (14:53 -0800)
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>
net/ipv6/xfrm6_mode_ro.c
net/xfrm/xfrm_output.c

index a7bc8c62317af220e6ba9ae95842286b4b7925c5..4a01cb3c370b6a365f1497ed57e51a060f8e3c8f 100644 (file)
@@ -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;
 }
index 58d5a746b1c3e07e4d065590aea88ebbf52b6592..b1efdc8850a7413b39aed94b51301a0a85180b9f 100644 (file)
@@ -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++;