Commit 14ebaf81 authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
Tested-by: default avatarIngo Molnar <mingo@elte.hu>
parent a1870b9c
...@@ -187,7 +187,7 @@ extern int x25_addr_ntoa(unsigned char *, struct x25_address *, ...@@ -187,7 +187,7 @@ extern int x25_addr_ntoa(unsigned char *, struct x25_address *,
extern int x25_addr_aton(unsigned char *, struct x25_address *, extern int x25_addr_aton(unsigned char *, struct x25_address *,
struct x25_address *); struct x25_address *);
extern struct sock *x25_find_socket(unsigned int, struct x25_neigh *); extern struct sock *x25_find_socket(unsigned int, struct x25_neigh *);
extern void x25_destroy_socket(struct sock *); extern void x25_destroy_socket_from_timer(struct sock *);
extern int x25_rx_call_request(struct sk_buff *, struct x25_neigh *, unsigned int); extern int x25_rx_call_request(struct sk_buff *, struct x25_neigh *, unsigned int);
extern void x25_kill_by_neigh(struct x25_neigh *); extern void x25_kill_by_neigh(struct x25_neigh *);
......
...@@ -332,14 +332,14 @@ static unsigned int x25_new_lci(struct x25_neigh *nb) ...@@ -332,14 +332,14 @@ static unsigned int x25_new_lci(struct x25_neigh *nb)
/* /*
* Deferred destroy. * Deferred destroy.
*/ */
void x25_destroy_socket(struct sock *); static void __x25_destroy_socket(struct sock *);
/* /*
* handler for deferred kills. * handler for deferred kills.
*/ */
static void x25_destroy_timer(unsigned long data) static void x25_destroy_timer(unsigned long data)
{ {
x25_destroy_socket((struct sock *)data); x25_destroy_socket_from_timer((struct sock *)data);
} }
/* /*
...@@ -349,12 +349,10 @@ static void x25_destroy_timer(unsigned long data) ...@@ -349,12 +349,10 @@ static void x25_destroy_timer(unsigned long data)
* will touch it and we are (fairly 8-) ) safe. * will touch it and we are (fairly 8-) ) safe.
* Not static as it's used by the timer * Not static as it's used by the timer
*/ */
void x25_destroy_socket(struct sock *sk) static void __x25_destroy_socket(struct sock *sk)
{ {
struct sk_buff *skb; struct sk_buff *skb;
sock_hold(sk);
lock_sock(sk);
x25_stop_heartbeat(sk); x25_stop_heartbeat(sk);
x25_stop_timer(sk); x25_stop_timer(sk);
...@@ -385,7 +383,22 @@ void x25_destroy_socket(struct sock *sk) ...@@ -385,7 +383,22 @@ void x25_destroy_socket(struct sock *sk)
/* drop last reference so sock_put will free */ /* drop last reference so sock_put will free */
__sock_put(sk); __sock_put(sk);
} }
}
void x25_destroy_socket_from_timer(struct sock *sk)
{
sock_hold(sk);
bh_lock_sock(sk);
__x25_destroy_socket(sk);
bh_unlock_sock(sk);
sock_put(sk);
}
static void x25_destroy_socket(struct sock *sk)
{
sock_hold(sk);
lock_sock(sk);
__x25_destroy_socket(sk);
release_sock(sk); release_sock(sk);
sock_put(sk); sock_put(sk);
} }
......
...@@ -113,7 +113,7 @@ static void x25_heartbeat_expiry(unsigned long param) ...@@ -113,7 +113,7 @@ static void x25_heartbeat_expiry(unsigned long param)
(sk->sk_state == TCP_LISTEN && (sk->sk_state == TCP_LISTEN &&
sock_flag(sk, SOCK_DEAD))) { sock_flag(sk, SOCK_DEAD))) {
bh_unlock_sock(sk); bh_unlock_sock(sk);
x25_destroy_socket(sk); x25_destroy_socket_from_timer(sk);
return; return;
} }
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment