summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-06-16 05:40:30 -0700
committerDavid S. Miller <davem@davemloft.net>2009-06-16 05:40:30 -0700
commit14ebaf81e13ce66bff275380b246796fd16cbfa1 (patch)
tree6da2824a42a07f325787130d093e1a986fa29110
parenta1870b9cc280fe16fed13994810f8a1687be3bcf (diff)
downloadlinux-14ebaf81e13ce66bff275380b246796fd16cbfa1.tar.gz
linux-14ebaf81e13ce66bff275380b246796fd16cbfa1.tar.bz2
linux-14ebaf81e13ce66bff275380b246796fd16cbfa1.zip
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>
-rw-r--r--include/net/x25.h2
-rw-r--r--net/x25/af_x25.c23
-rw-r--r--net/x25/x25_timer.c2
3 files changed, 20 insertions, 7 deletions
diff --git a/include/net/x25.h b/include/net/x25.h
index fc3f03d976f8..2cda04011568 100644
--- a/include/net/x25.h
+++ b/include/net/x25.h
@@ -187,7 +187,7 @@ extern int x25_addr_ntoa(unsigned char *, struct x25_address *,
extern int x25_addr_aton(unsigned char *, struct x25_address *,
struct x25_address *);
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 void x25_kill_by_neigh(struct x25_neigh *);
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)
/*
* Deferred destroy.
*/
-void x25_destroy_socket(struct sock *);
+static void __x25_destroy_socket(struct sock *);
/*
* handler for deferred kills.
*/
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)
* will touch it and we are (fairly 8-) ) safe.
* 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;
- sock_hold(sk);
- lock_sock(sk);
x25_stop_heartbeat(sk);
x25_stop_timer(sk);
@@ -385,7 +383,22 @@ void x25_destroy_socket(struct sock *sk)
/* drop last reference so sock_put will free */
__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);
sock_put(sk);
}
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)
(sk->sk_state == TCP_LISTEN &&
sock_flag(sk, SOCK_DEAD))) {
bh_unlock_sock(sk);
- x25_destroy_socket(sk);
+ x25_destroy_socket_from_timer(sk);
return;
}
break;