aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c33
1 files changed, 16 insertions, 17 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index e16197eb7b9f..c58f66be7e18 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -110,7 +110,7 @@ static void tipc_write_space(struct sock *sk);
static int tipc_release(struct socket *sock);
static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags);
static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p);
-static void tipc_sk_timeout(unsigned long portid);
+static void tipc_sk_timeout(unsigned long data);
static int tipc_sk_publish(struct tipc_sock *tsk, uint scope,
struct tipc_name_seq const *seq);
static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope,
@@ -361,7 +361,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
return -EINVAL;
}
msg_set_origport(msg, tsk->portid);
- setup_timer(&tsk->timer, tipc_sk_timeout, tsk->portid);
+ setup_timer(&tsk->timer, tipc_sk_timeout, (unsigned long)tsk);
sk->sk_backlog_rcv = tipc_backlog_rcv;
sk->sk_rcvbuf = sysctl_tipc_rmem[1];
sk->sk_data_ready = tipc_data_ready;
@@ -475,7 +475,7 @@ static int tipc_release(struct socket *sock)
struct sock *sk = sock->sk;
struct tipc_sock *tsk;
struct sk_buff *skb;
- u32 dnode;
+ u32 dnode, probing_state;
/*
* Exit if socket isn't fully initialized (occurs when a failed accept()
@@ -511,7 +511,9 @@ static int tipc_release(struct socket *sock)
}
tipc_sk_withdraw(tsk, 0, NULL);
- del_timer_sync(&tsk->timer);
+ probing_state = tsk->probing_state;
+ if (del_timer_sync(&tsk->timer) && probing_state != TIPC_CONN_PROBING)
+ sock_put(sk);
tipc_sk_remove(tsk);
if (tsk->connected) {
skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG,
@@ -1141,7 +1143,8 @@ static void tipc_sk_finish_conn(struct tipc_sock *tsk, u32 peer_port,
tsk->probing_intv = CONN_PROBING_INTERVAL;
tsk->probing_state = TIPC_CONN_OK;
tsk->connected = 1;
- mod_timer(&tsk->timer, jiffies + tsk->probing_intv);
+ if (!mod_timer(&tsk->timer, jiffies + tsk->probing_intv))
+ sock_hold(&tsk->sk);
tipc_node_add_conn(peer_node, tsk->portid, peer_port);
tsk->max_pkt = tipc_node_get_mtu(peer_node, tsk->portid);
}
@@ -2096,18 +2099,13 @@ restart:
return res;
}
-static void tipc_sk_timeout(unsigned long portid)
+static void tipc_sk_timeout(unsigned long data)
{
- struct tipc_sock *tsk;
- struct sock *sk;
+ struct tipc_sock *tsk = (struct tipc_sock *)data;
+ struct sock *sk = &tsk->sk;
struct sk_buff *skb = NULL;
u32 peer_port, peer_node;
- tsk = tipc_sk_lookup(portid);
- if (!tsk)
- return;
-
- sk = &tsk->sk;
bh_lock_sock(sk);
if (!tsk->connected) {
bh_unlock_sock(sk);
@@ -2120,18 +2118,19 @@ static void tipc_sk_timeout(unsigned long portid)
/* Previous probe not answered -> self abort */
skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG,
SHORT_H_SIZE, 0, tipc_own_addr,
- peer_node, portid, peer_port,
+ peer_node, tsk->portid, peer_port,
TIPC_ERR_NO_PORT);
} else {
skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE, INT_H_SIZE,
0, peer_node, tipc_own_addr,
- peer_port, portid, TIPC_OK);
+ peer_port, tsk->portid, TIPC_OK);
tsk->probing_state = TIPC_CONN_PROBING;
- mod_timer(&tsk->timer, jiffies + tsk->probing_intv);
+ if (!mod_timer(&tsk->timer, jiffies + tsk->probing_intv))
+ sock_hold(sk);
}
bh_unlock_sock(sk);
if (skb)
- tipc_link_xmit_skb(skb, peer_node, portid);
+ tipc_link_xmit_skb(skb, peer_node, tsk->portid);
exit:
sock_put(sk);
}