aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@mandriva.com>2006-11-16 11:06:06 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:23:51 -0500
commit58a5a7b9555ea231b557ebef5cabeaf8e951df0b (patch)
tree9dac36b3483e9667a967f79982c965abd707e03d
parente523a1550e877f8a8ff87a50269b7ee7bfb43464 (diff)
[NET]: Conditionally use bh_lock_sock_nested in sk_receive_skb
Spotted by Ian McDonald, tentatively fixed by Gerrit Renker: http://www.mail-archive.com/dccp%40vger.kernel.org/msg00599.html Rewritten not to unroll sk_receive_skb, in the common case, i.e. no lock debugging, its optimized away. Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
-rw-r--r--drivers/net/pppoe.c2
-rw-r--r--include/net/sock.h3
-rw-r--r--net/core/sock.c7
-rw-r--r--net/dccp/ipv4.c2
-rw-r--r--net/dccp/ipv6.c2
-rw-r--r--net/decnet/dn_nsp_in.c2
6 files changed, 11 insertions, 7 deletions
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 0adee733b761..315d5c3fc66a 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -393,7 +393,7 @@ static int pppoe_rcv(struct sk_buff *skb,
393 393
394 po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source); 394 po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source);
395 if (po != NULL) 395 if (po != NULL)
396 return sk_receive_skb(sk_pppox(po), skb); 396 return sk_receive_skb(sk_pppox(po), skb, 0);
397drop: 397drop:
398 kfree_skb(skb); 398 kfree_skb(skb);
399out: 399out:
diff --git a/include/net/sock.h b/include/net/sock.h
index dc4b92b8abea..26fc0b16bc0c 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -954,7 +954,8 @@ static inline void sock_put(struct sock *sk)
954 sk_free(sk); 954 sk_free(sk);
955} 955}
956 956
957extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb); 957extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb,
958 const int nested);
958 959
959/* Detach socket from process context. 960/* Detach socket from process context.
960 * Announce socket dead, detach it from wait queue and inode. 961 * Announce socket dead, detach it from wait queue and inode.
diff --git a/net/core/sock.c b/net/core/sock.c
index 32ff1c551d69..ab8fafadb4ba 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -270,7 +270,7 @@ out:
270} 270}
271EXPORT_SYMBOL(sock_queue_rcv_skb); 271EXPORT_SYMBOL(sock_queue_rcv_skb);
272 272
273int sk_receive_skb(struct sock *sk, struct sk_buff *skb) 273int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested)
274{ 274{
275 int rc = NET_RX_SUCCESS; 275 int rc = NET_RX_SUCCESS;
276 276
@@ -279,7 +279,10 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb)
279 279
280 skb->dev = NULL; 280 skb->dev = NULL;
281 281
282 bh_lock_sock(sk); 282 if (nested)
283 bh_lock_sock_nested(sk);
284 else
285 bh_lock_sock(sk);
283 if (!sock_owned_by_user(sk)) { 286 if (!sock_owned_by_user(sk)) {
284 /* 287 /*
285 * trylock + unlock semantics: 288 * trylock + unlock semantics:
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index a20eb71d45db..7114befe7d50 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -899,7 +899,7 @@ static int dccp_v4_rcv(struct sk_buff *skb)
899 goto discard_and_relse; 899 goto discard_and_relse;
900 nf_reset(skb); 900 nf_reset(skb);
901 901
902 return sk_receive_skb(sk, skb); 902 return sk_receive_skb(sk, skb, 1);
903 903
904no_dccp_socket: 904no_dccp_socket:
905 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) 905 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 6eda430ae929..03bb8298250a 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -888,7 +888,7 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
888 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) 888 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
889 goto discard_and_relse; 889 goto discard_and_relse;
890 890
891 return sk_receive_skb(sk, skb) ? -1 : 0; 891 return sk_receive_skb(sk, skb, 1) ? -1 : 0;
892 892
893no_dccp_socket: 893no_dccp_socket:
894 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) 894 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 7683d4f754d2..39a6cf7fb566 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -804,7 +804,7 @@ got_it:
804 goto free_out; 804 goto free_out;
805 } 805 }
806 806
807 return sk_receive_skb(sk, skb); 807 return sk_receive_skb(sk, skb, 0);
808 } 808 }
809 809
810 return dn_nsp_no_socket(skb, reason); 810 return dn_nsp_no_socket(skb, reason);