Commit f2f2a96a authored by Ying Xue's avatar Ying Xue Committed by David S. Miller

tipc: feed tipc sock pointer to tipc_sk_timeout routine

In order to make tipc socket table aware of namespace, a networking
namespace instance must be passed to tipc_sk_lookup(), allowing it
to look up tipc socket instance with a given port ID from a concrete
socket table. However, as now tipc_sk_timeout() only has one port ID
parameter and is not namespace aware, it's unable to obtain a correct
socket instance through tipc_sk_lookup() just with a port ID,
especially after namespace is completely supported.

If port ID is replaced with socket instance as tipc_sk_timeout()'s
parameter, it's unnecessary to look up socket table. But as the timer
handler - tipc_sk_timeout() is run asynchronously, socket reference
must be held before its timer is launched, and must be carefully
checked to identify whether the socket reference needs to be put or
not when its timer is terminated.
Signed-off-by: default avatarYing Xue <ying.xue@windriver.com>
Tested-by: default avatarTero Aho <Tero.Aho@coriant.com>
Reviewed-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 859fc7c0
...@@ -110,7 +110,7 @@ static void tipc_write_space(struct sock *sk); ...@@ -110,7 +110,7 @@ static void tipc_write_space(struct sock *sk);
static int tipc_release(struct socket *sock); static int tipc_release(struct socket *sock);
static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags); 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 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, static int tipc_sk_publish(struct tipc_sock *tsk, uint scope,
struct tipc_name_seq const *seq); struct tipc_name_seq const *seq);
static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, 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, ...@@ -361,7 +361,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
return -EINVAL; return -EINVAL;
} }
msg_set_origport(msg, tsk->portid); 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_backlog_rcv = tipc_backlog_rcv;
sk->sk_rcvbuf = sysctl_tipc_rmem[1]; sk->sk_rcvbuf = sysctl_tipc_rmem[1];
sk->sk_data_ready = tipc_data_ready; sk->sk_data_ready = tipc_data_ready;
...@@ -475,7 +475,7 @@ static int tipc_release(struct socket *sock) ...@@ -475,7 +475,7 @@ static int tipc_release(struct socket *sock)
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct tipc_sock *tsk; struct tipc_sock *tsk;
struct sk_buff *skb; struct sk_buff *skb;
u32 dnode; u32 dnode, probing_state;
/* /*
* Exit if socket isn't fully initialized (occurs when a failed accept() * Exit if socket isn't fully initialized (occurs when a failed accept()
...@@ -511,7 +511,9 @@ static int tipc_release(struct socket *sock) ...@@ -511,7 +511,9 @@ static int tipc_release(struct socket *sock)
} }
tipc_sk_withdraw(tsk, 0, NULL); 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); tipc_sk_remove(tsk);
if (tsk->connected) { if (tsk->connected) {
skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, 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, ...@@ -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_intv = CONN_PROBING_INTERVAL;
tsk->probing_state = TIPC_CONN_OK; tsk->probing_state = TIPC_CONN_OK;
tsk->connected = 1; 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); tipc_node_add_conn(peer_node, tsk->portid, peer_port);
tsk->max_pkt = tipc_node_get_mtu(peer_node, tsk->portid); tsk->max_pkt = tipc_node_get_mtu(peer_node, tsk->portid);
} }
...@@ -2096,18 +2099,13 @@ static int tipc_shutdown(struct socket *sock, int how) ...@@ -2096,18 +2099,13 @@ static int tipc_shutdown(struct socket *sock, int how)
return res; return res;
} }
static void tipc_sk_timeout(unsigned long portid) static void tipc_sk_timeout(unsigned long data)
{ {
struct tipc_sock *tsk; struct tipc_sock *tsk = (struct tipc_sock *)data;
struct sock *sk; struct sock *sk = &tsk->sk;
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
u32 peer_port, peer_node; u32 peer_port, peer_node;
tsk = tipc_sk_lookup(portid);
if (!tsk)
return;
sk = &tsk->sk;
bh_lock_sock(sk); bh_lock_sock(sk);
if (!tsk->connected) { if (!tsk->connected) {
bh_unlock_sock(sk); bh_unlock_sock(sk);
...@@ -2120,18 +2118,19 @@ static void tipc_sk_timeout(unsigned long portid) ...@@ -2120,18 +2118,19 @@ static void tipc_sk_timeout(unsigned long portid)
/* Previous probe not answered -> self abort */ /* Previous probe not answered -> self abort */
skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG,
SHORT_H_SIZE, 0, tipc_own_addr, SHORT_H_SIZE, 0, tipc_own_addr,
peer_node, portid, peer_port, peer_node, tsk->portid, peer_port,
TIPC_ERR_NO_PORT); TIPC_ERR_NO_PORT);
} else { } else {
skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE, INT_H_SIZE, skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE, INT_H_SIZE,
0, peer_node, tipc_own_addr, 0, peer_node, tipc_own_addr,
peer_port, portid, TIPC_OK); peer_port, tsk->portid, TIPC_OK);
tsk->probing_state = TIPC_CONN_PROBING; 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); bh_unlock_sock(sk);
if (skb) if (skb)
tipc_link_xmit_skb(skb, peer_node, portid); tipc_link_xmit_skb(skb, peer_node, tsk->portid);
exit: exit:
sock_put(sk); sock_put(sk);
} }
......
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