Commit 14ebaf81e13ce66bff275380b246796fd16cbfa1

Authored by David S. Miller
1 parent a1870b9cc2

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>

Showing 3 changed files with 20 additions and 7 deletions Side-by-side Diff

... ... @@ -187,7 +187,7 @@
187 187 extern int x25_addr_aton(unsigned char *, struct x25_address *,
188 188 struct x25_address *);
189 189 extern struct sock *x25_find_socket(unsigned int, struct x25_neigh *);
190   -extern void x25_destroy_socket(struct sock *);
  190 +extern void x25_destroy_socket_from_timer(struct sock *);
191 191 extern int x25_rx_call_request(struct sk_buff *, struct x25_neigh *, unsigned int);
192 192 extern void x25_kill_by_neigh(struct x25_neigh *);
193 193  
... ... @@ -332,14 +332,14 @@
332 332 /*
333 333 * Deferred destroy.
334 334 */
335   -void x25_destroy_socket(struct sock *);
  335 +static void __x25_destroy_socket(struct sock *);
336 336  
337 337 /*
338 338 * handler for deferred kills.
339 339 */
340 340 static 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 /*
346 346  
... ... @@ -349,12 +349,10 @@
349 349 * will touch it and we are (fairly 8-) ) safe.
350 350 * Not static as it's used by the timer
351 351 */
352   -void x25_destroy_socket(struct sock *sk)
  352 +static void __x25_destroy_socket(struct sock *sk)
353 353 {
354 354 struct sk_buff *skb;
355 355  
356   - sock_hold(sk);
357   - lock_sock(sk);
358 356 x25_stop_heartbeat(sk);
359 357 x25_stop_timer(sk);
360 358  
361 359  
... ... @@ -385,7 +383,22 @@
385 383 /* drop last reference so sock_put will free */
386 384 __sock_put(sk);
387 385 }
  386 +}
388 387  
  388 +void 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 +
  397 +static void x25_destroy_socket(struct sock *sk)
  398 +{
  399 + sock_hold(sk);
  400 + lock_sock(sk);
  401 + __x25_destroy_socket(sk);
389 402 release_sock(sk);
390 403 sock_put(sk);
391 404 }
... ... @@ -113,7 +113,7 @@
113 113 (sk->sk_state == TCP_LISTEN &&
114 114 sock_flag(sk, SOCK_DEAD))) {
115 115 bh_unlock_sock(sk);
116   - x25_destroy_socket(sk);
  116 + x25_destroy_socket_from_timer(sk);
117 117 return;
118 118 }
119 119 break;