aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-06-16 08:40:30 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-16 08:40:30 -0400
commit14ebaf81e13ce66bff275380b246796fd16cbfa1 (patch)
tree6da2824a42a07f325787130d093e1a986fa29110 /net
parenta1870b9cc280fe16fed13994810f8a1687be3bcf (diff)
x25: Fix sleep from timer on socket destroy.
If socket destuction gets delayed to a timer, we try to lock_sock() from that timer which won't work. Use bh_lock_sock() in that case. Signed-off-by: David S. Miller <davem@davemloft.net> Tested-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'net')
-rw-r--r--net/x25/af_x25.c23
-rw-r--r--net/x25/x25_timer.c2
2 files changed, 19 insertions, 6 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index ed80af8ca5fb..c51f3095739c 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -332,14 +332,14 @@ static unsigned int x25_new_lci(struct x25_neigh *nb)
332/* 332/*
333 * Deferred destroy. 333 * Deferred destroy.
334 */ 334 */
335void x25_destroy_socket(struct sock *); 335static void __x25_destroy_socket(struct sock *);
336 336
337/* 337/*
338 * handler for deferred kills. 338 * handler for deferred kills.
339 */ 339 */
340static void x25_destroy_timer(unsigned long data) 340static void x25_destroy_timer(unsigned long data)
341{ 341{
342 x25_destroy_socket((struct sock *)data); 342 x25_destroy_socket_from_timer((struct sock *)data);
343} 343}
344 344
345/* 345/*
@@ -349,12 +349,10 @@ static void x25_destroy_timer(unsigned long data)
349 * will touch it and we are (fairly 8-) ) safe. 349 * will touch it and we are (fairly 8-) ) safe.
350 * Not static as it's used by the timer 350 * Not static as it's used by the timer
351 */ 351 */
352void x25_destroy_socket(struct sock *sk) 352static void __x25_destroy_socket(struct sock *sk)
353{ 353{
354 struct sk_buff *skb; 354 struct sk_buff *skb;
355 355
356 sock_hold(sk);
357 lock_sock(sk);
358 x25_stop_heartbeat(sk); 356 x25_stop_heartbeat(sk);
359 x25_stop_timer(sk); 357 x25_stop_timer(sk);
360 358
@@ -385,7 +383,22 @@ void x25_destroy_socket(struct sock *sk)
385 /* drop last reference so sock_put will free */ 383 /* drop last reference so sock_put will free */
386 __sock_put(sk); 384 __sock_put(sk);
387 } 385 }
386}
388 387
388void x25_destroy_socket_from_timer(struct sock *sk)
389{
390 sock_hold(sk);
391 bh_lock_sock(sk);
392 __x25_destroy_socket(sk);
393 bh_unlock_sock(sk);
394 sock_put(sk);
395}
396
397static void x25_destroy_socket(struct sock *sk)
398{
399 sock_hold(sk);
400 lock_sock(sk);
401 __x25_destroy_socket(sk);
389 release_sock(sk); 402 release_sock(sk);
390 sock_put(sk); 403 sock_put(sk);
391} 404}
diff --git a/net/x25/x25_timer.c b/net/x25/x25_timer.c
index d3e3e54db936..5c5db1a36399 100644
--- a/net/x25/x25_timer.c
+++ b/net/x25/x25_timer.c
@@ -113,7 +113,7 @@ static void x25_heartbeat_expiry(unsigned long param)
113 (sk->sk_state == TCP_LISTEN && 113 (sk->sk_state == TCP_LISTEN &&
114 sock_flag(sk, SOCK_DEAD))) { 114 sock_flag(sk, SOCK_DEAD))) {
115 bh_unlock_sock(sk); 115 bh_unlock_sock(sk);
116 x25_destroy_socket(sk); 116 x25_destroy_socket_from_timer(sk);
117 return; 117 return;
118 } 118 }
119 break; 119 break;