diff options
author | Arnaldo Carvalho de Melo <acme@mandriva.com> | 2006-11-16 11:06:06 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:23:51 -0500 |
commit | 58a5a7b9555ea231b557ebef5cabeaf8e951df0b (patch) | |
tree | 9dac36b3483e9667a967f79982c965abd707e03d | |
parent | e523a1550e877f8a8ff87a50269b7ee7bfb43464 (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.c | 2 | ||||
-rw-r--r-- | include/net/sock.h | 3 | ||||
-rw-r--r-- | net/core/sock.c | 7 | ||||
-rw-r--r-- | net/dccp/ipv4.c | 2 | ||||
-rw-r--r-- | net/dccp/ipv6.c | 2 | ||||
-rw-r--r-- | net/decnet/dn_nsp_in.c | 2 |
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); |
397 | drop: | 397 | drop: |
398 | kfree_skb(skb); | 398 | kfree_skb(skb); |
399 | out: | 399 | out: |
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 | ||
957 | extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb); | 957 | extern 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 | } |
271 | EXPORT_SYMBOL(sock_queue_rcv_skb); | 271 | EXPORT_SYMBOL(sock_queue_rcv_skb); |
272 | 272 | ||
273 | int sk_receive_skb(struct sock *sk, struct sk_buff *skb) | 273 | int 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 | ||
904 | no_dccp_socket: | 904 | no_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 | ||
893 | no_dccp_socket: | 893 | no_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); |