Commit 14ebaf81e13ce66bff275380b246796fd16cbfa1
1 parent
a1870b9cc2
Exists in
master
and in
7 other branches
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
include/net/x25.h
... | ... | @@ -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 |
net/x25/af_x25.c
... | ... | @@ -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 | } |