Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Ying Xue <ying.xue@windriver.com>
Tested-by: Tero Aho <Tero.Aho@coriant.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ying Xue and committed by
David S. Miller
f2f2a96a 859fc7c0

+16 -17
+16 -17
net/tipc/socket.c
··· 110 110 static int tipc_release(struct socket *sock); 111 111 static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags); 112 112 static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p); 113 - static void tipc_sk_timeout(unsigned long portid); 113 + static void tipc_sk_timeout(unsigned long data); 114 114 static int tipc_sk_publish(struct tipc_sock *tsk, uint scope, 115 115 struct tipc_name_seq const *seq); 116 116 static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, ··· 361 361 return -EINVAL; 362 362 } 363 363 msg_set_origport(msg, tsk->portid); 364 - setup_timer(&tsk->timer, tipc_sk_timeout, tsk->portid); 364 + setup_timer(&tsk->timer, tipc_sk_timeout, (unsigned long)tsk); 365 365 sk->sk_backlog_rcv = tipc_backlog_rcv; 366 366 sk->sk_rcvbuf = sysctl_tipc_rmem[1]; 367 367 sk->sk_data_ready = tipc_data_ready; ··· 475 475 struct sock *sk = sock->sk; 476 476 struct tipc_sock *tsk; 477 477 struct sk_buff *skb; 478 - u32 dnode; 478 + u32 dnode, probing_state; 479 479 480 480 /* 481 481 * Exit if socket isn't fully initialized (occurs when a failed accept() ··· 511 511 } 512 512 513 513 tipc_sk_withdraw(tsk, 0, NULL); 514 - del_timer_sync(&tsk->timer); 514 + probing_state = tsk->probing_state; 515 + if (del_timer_sync(&tsk->timer) && probing_state != TIPC_CONN_PROBING) 516 + sock_put(sk); 515 517 tipc_sk_remove(tsk); 516 518 if (tsk->connected) { 517 519 skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, ··· 1143 1141 tsk->probing_intv = CONN_PROBING_INTERVAL; 1144 1142 tsk->probing_state = TIPC_CONN_OK; 1145 1143 tsk->connected = 1; 1146 - mod_timer(&tsk->timer, jiffies + tsk->probing_intv); 1144 + if (!mod_timer(&tsk->timer, jiffies + tsk->probing_intv)) 1145 + sock_hold(&tsk->sk); 1147 1146 tipc_node_add_conn(peer_node, tsk->portid, peer_port); 1148 1147 tsk->max_pkt = tipc_node_get_mtu(peer_node, tsk->portid); 1149 1148 } ··· 2099 2096 return res; 2100 2097 } 2101 2098 2102 - static void tipc_sk_timeout(unsigned long portid) 2099 + static void tipc_sk_timeout(unsigned long data) 2103 2100 { 2104 - struct tipc_sock *tsk; 2105 - struct sock *sk; 2101 + struct tipc_sock *tsk = (struct tipc_sock *)data; 2102 + struct sock *sk = &tsk->sk; 2106 2103 struct sk_buff *skb = NULL; 2107 2104 u32 peer_port, peer_node; 2108 2105 2109 - tsk = tipc_sk_lookup(portid); 2110 - if (!tsk) 2111 - return; 2112 - 2113 - sk = &tsk->sk; 2114 2106 bh_lock_sock(sk); 2115 2107 if (!tsk->connected) { 2116 2108 bh_unlock_sock(sk); ··· 2118 2120 /* Previous probe not answered -> self abort */ 2119 2121 skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, 2120 2122 SHORT_H_SIZE, 0, tipc_own_addr, 2121 - peer_node, portid, peer_port, 2123 + peer_node, tsk->portid, peer_port, 2122 2124 TIPC_ERR_NO_PORT); 2123 2125 } else { 2124 2126 skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE, INT_H_SIZE, 2125 2127 0, peer_node, tipc_own_addr, 2126 - peer_port, portid, TIPC_OK); 2128 + peer_port, tsk->portid, TIPC_OK); 2127 2129 tsk->probing_state = TIPC_CONN_PROBING; 2128 - mod_timer(&tsk->timer, jiffies + tsk->probing_intv); 2130 + if (!mod_timer(&tsk->timer, jiffies + tsk->probing_intv)) 2131 + sock_hold(sk); 2129 2132 } 2130 2133 bh_unlock_sock(sk); 2131 2134 if (skb) 2132 - tipc_link_xmit_skb(skb, peer_node, portid); 2135 + tipc_link_xmit_skb(skb, peer_node, tsk->portid); 2133 2136 exit: 2134 2137 sock_put(sk); 2135 2138 }