diff options
author | Jon Paul Maloy <jon.maloy@ericsson.com> | 2014-08-22 18:09:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-08-23 14:18:33 -0400 |
commit | 5728901581139e68e6cf53b36590f64829c37453 (patch) | |
tree | 3c0aa4250f7b4528d8997a18d757bd36d45034ee | |
parent | 02be61a981fb5ca5f1526323336198ee92cadf95 (diff) |
tipc: clean up socket timer function
The last remaining BH upcall to the socket, apart for the message
reception function tipc_sk_rcv(), is the timer function.
We prefer to let this function continue executing in BH, since it only
does read-acces to semi-permanent data, but we make three changes to it:
1) We introduce a bh_lock_sock()/bh_unlock_sock() inside the scope
of port_lock. This is a preparation for replacing port_lock with
bh_lock_sock() at the locations where it is still used.
2) We move the function from port.c to socket.c, as a further step
of eliminating the port code level altogether.
3) We let it make use of the newly introduced tipc_msg_create()
function. This enables us to get rid of three context specific
functions (port_create_self_abort_msg() etc.) in port.c
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/tipc/port.c | 126 | ||||
-rw-r--r-- | net/tipc/socket.c | 46 |
2 files changed, 69 insertions, 103 deletions
diff --git a/net/tipc/port.c b/net/tipc/port.c index edbd83d223c5..6de79f26981e 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c | |||
@@ -48,9 +48,6 @@ | |||
48 | DEFINE_SPINLOCK(tipc_port_list_lock); | 48 | DEFINE_SPINLOCK(tipc_port_list_lock); |
49 | 49 | ||
50 | static LIST_HEAD(ports); | 50 | static LIST_HEAD(ports); |
51 | static struct sk_buff *port_build_self_abort_msg(struct tipc_port *, u32 err); | ||
52 | static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *, u32 err); | ||
53 | static void port_timeout(unsigned long ref); | ||
54 | 51 | ||
55 | /** | 52 | /** |
56 | * tipc_port_peer_msg - verify message was sent by connected port's peer | 53 | * tipc_port_peer_msg - verify message was sent by connected port's peer |
@@ -92,7 +89,6 @@ u32 tipc_port_init(struct tipc_port *p_ptr, | |||
92 | p_ptr->max_pkt = MAX_PKT_DEFAULT; | 89 | p_ptr->max_pkt = MAX_PKT_DEFAULT; |
93 | p_ptr->ref = ref; | 90 | p_ptr->ref = ref; |
94 | INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); | 91 | INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); |
95 | k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref); | ||
96 | INIT_LIST_HEAD(&p_ptr->publications); | 92 | INIT_LIST_HEAD(&p_ptr->publications); |
97 | INIT_LIST_HEAD(&p_ptr->port_list); | 93 | INIT_LIST_HEAD(&p_ptr->port_list); |
98 | 94 | ||
@@ -114,7 +110,7 @@ void tipc_port_destroy(struct tipc_port *p_ptr) | |||
114 | { | 110 | { |
115 | struct sk_buff *buf = NULL; | 111 | struct sk_buff *buf = NULL; |
116 | struct tipc_msg *msg = NULL; | 112 | struct tipc_msg *msg = NULL; |
117 | u32 peer; | 113 | u32 peer_node; |
118 | 114 | ||
119 | tipc_withdraw(p_ptr, 0, NULL); | 115 | tipc_withdraw(p_ptr, 0, NULL); |
120 | 116 | ||
@@ -124,11 +120,16 @@ void tipc_port_destroy(struct tipc_port *p_ptr) | |||
124 | 120 | ||
125 | k_cancel_timer(&p_ptr->timer); | 121 | k_cancel_timer(&p_ptr->timer); |
126 | if (p_ptr->connected) { | 122 | if (p_ptr->connected) { |
127 | buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT); | 123 | peer_node = tipc_port_peernode(p_ptr); |
128 | msg = buf_msg(buf); | 124 | buf = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, |
129 | peer = msg_destnode(msg); | 125 | SHORT_H_SIZE, 0, peer_node, |
130 | tipc_link_xmit(buf, peer, msg_link_selector(msg)); | 126 | tipc_own_addr, tipc_port_peerport(p_ptr), |
131 | tipc_node_remove_conn(peer, p_ptr->ref); | 127 | p_ptr->ref, TIPC_ERR_NO_PORT); |
128 | if (buf) { | ||
129 | msg = buf_msg(buf); | ||
130 | tipc_link_xmit(buf, peer_node, msg_link_selector(msg)); | ||
131 | } | ||
132 | tipc_node_remove_conn(peer_node, p_ptr->ref); | ||
132 | } | 133 | } |
133 | spin_lock_bh(&tipc_port_list_lock); | 134 | spin_lock_bh(&tipc_port_list_lock); |
134 | list_del(&p_ptr->port_list); | 135 | list_del(&p_ptr->port_list); |
@@ -136,94 +137,6 @@ void tipc_port_destroy(struct tipc_port *p_ptr) | |||
136 | k_term_timer(&p_ptr->timer); | 137 | k_term_timer(&p_ptr->timer); |
137 | } | 138 | } |
138 | 139 | ||
139 | /* | ||
140 | * port_build_proto_msg(): create connection protocol message for port | ||
141 | * | ||
142 | * On entry the port must be locked and connected. | ||
143 | */ | ||
144 | static struct sk_buff *port_build_proto_msg(struct tipc_port *p_ptr, | ||
145 | u32 type, u32 ack) | ||
146 | { | ||
147 | struct sk_buff *buf; | ||
148 | struct tipc_msg *msg; | ||
149 | |||
150 | buf = tipc_buf_acquire(INT_H_SIZE); | ||
151 | if (buf) { | ||
152 | msg = buf_msg(buf); | ||
153 | tipc_msg_init(msg, CONN_MANAGER, type, INT_H_SIZE, | ||
154 | tipc_port_peernode(p_ptr)); | ||
155 | msg_set_destport(msg, tipc_port_peerport(p_ptr)); | ||
156 | msg_set_origport(msg, p_ptr->ref); | ||
157 | msg_set_msgcnt(msg, ack); | ||
158 | buf->next = NULL; | ||
159 | } | ||
160 | return buf; | ||
161 | } | ||
162 | |||
163 | static void port_timeout(unsigned long ref) | ||
164 | { | ||
165 | struct tipc_port *p_ptr = tipc_port_lock(ref); | ||
166 | struct sk_buff *buf = NULL; | ||
167 | struct tipc_msg *msg = NULL; | ||
168 | |||
169 | if (!p_ptr) | ||
170 | return; | ||
171 | |||
172 | if (!p_ptr->connected) { | ||
173 | tipc_port_unlock(p_ptr); | ||
174 | return; | ||
175 | } | ||
176 | |||
177 | /* Last probe answered ? */ | ||
178 | if (p_ptr->probing_state == TIPC_CONN_PROBING) { | ||
179 | buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT); | ||
180 | } else { | ||
181 | buf = port_build_proto_msg(p_ptr, CONN_PROBE, 0); | ||
182 | p_ptr->probing_state = TIPC_CONN_PROBING; | ||
183 | k_start_timer(&p_ptr->timer, p_ptr->probing_interval); | ||
184 | } | ||
185 | tipc_port_unlock(p_ptr); | ||
186 | msg = buf_msg(buf); | ||
187 | tipc_link_xmit(buf, msg_destnode(msg), msg_link_selector(msg)); | ||
188 | } | ||
189 | |||
190 | static struct sk_buff *port_build_self_abort_msg(struct tipc_port *p_ptr, u32 err) | ||
191 | { | ||
192 | struct sk_buff *buf = port_build_peer_abort_msg(p_ptr, err); | ||
193 | |||
194 | if (buf) { | ||
195 | struct tipc_msg *msg = buf_msg(buf); | ||
196 | msg_swap_words(msg, 4, 5); | ||
197 | msg_swap_words(msg, 6, 7); | ||
198 | buf->next = NULL; | ||
199 | } | ||
200 | return buf; | ||
201 | } | ||
202 | |||
203 | static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 err) | ||
204 | { | ||
205 | struct sk_buff *buf; | ||
206 | struct tipc_msg *msg; | ||
207 | u32 imp; | ||
208 | |||
209 | if (!p_ptr->connected) | ||
210 | return NULL; | ||
211 | |||
212 | buf = tipc_buf_acquire(BASIC_H_SIZE); | ||
213 | if (buf) { | ||
214 | msg = buf_msg(buf); | ||
215 | memcpy(msg, &p_ptr->phdr, BASIC_H_SIZE); | ||
216 | msg_set_hdr_sz(msg, BASIC_H_SIZE); | ||
217 | msg_set_size(msg, BASIC_H_SIZE); | ||
218 | imp = msg_importance(msg); | ||
219 | if (imp < TIPC_CRITICAL_IMPORTANCE) | ||
220 | msg_set_importance(msg, ++imp); | ||
221 | msg_set_errcode(msg, err); | ||
222 | buf->next = NULL; | ||
223 | } | ||
224 | return buf; | ||
225 | } | ||
226 | |||
227 | static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id) | 140 | static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id) |
228 | { | 141 | { |
229 | struct publication *publ; | 142 | struct publication *publ; |
@@ -321,12 +234,15 @@ void tipc_acknowledge(u32 ref, u32 ack) | |||
321 | if (!p_ptr) | 234 | if (!p_ptr) |
322 | return; | 235 | return; |
323 | if (p_ptr->connected) | 236 | if (p_ptr->connected) |
324 | buf = port_build_proto_msg(p_ptr, CONN_ACK, ack); | 237 | buf = tipc_msg_create(CONN_MANAGER, CONN_ACK, INT_H_SIZE, |
325 | 238 | 0, tipc_port_peernode(p_ptr), | |
239 | tipc_own_addr, tipc_port_peerport(p_ptr), | ||
240 | p_ptr->ref, TIPC_OK); | ||
326 | tipc_port_unlock(p_ptr); | 241 | tipc_port_unlock(p_ptr); |
327 | if (!buf) | 242 | if (!buf) |
328 | return; | 243 | return; |
329 | msg = buf_msg(buf); | 244 | msg = buf_msg(buf); |
245 | msg_set_msgcnt(msg, ack); | ||
330 | tipc_link_xmit(buf, msg_destnode(msg), msg_link_selector(msg)); | 246 | tipc_link_xmit(buf, msg_destnode(msg), msg_link_selector(msg)); |
331 | } | 247 | } |
332 | 248 | ||
@@ -478,14 +394,18 @@ int tipc_port_shutdown(u32 ref) | |||
478 | struct tipc_msg *msg; | 394 | struct tipc_msg *msg; |
479 | struct tipc_port *p_ptr; | 395 | struct tipc_port *p_ptr; |
480 | struct sk_buff *buf = NULL; | 396 | struct sk_buff *buf = NULL; |
397 | u32 peer_node; | ||
481 | 398 | ||
482 | p_ptr = tipc_port_lock(ref); | 399 | p_ptr = tipc_port_lock(ref); |
483 | if (!p_ptr) | 400 | if (!p_ptr) |
484 | return -EINVAL; | 401 | return -EINVAL; |
485 | 402 | peer_node = tipc_port_peernode(p_ptr); | |
486 | buf = port_build_peer_abort_msg(p_ptr, TIPC_CONN_SHUTDOWN); | 403 | buf = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, |
404 | SHORT_H_SIZE, 0, peer_node, | ||
405 | tipc_own_addr, tipc_port_peerport(p_ptr), | ||
406 | p_ptr->ref, TIPC_CONN_SHUTDOWN); | ||
487 | tipc_port_unlock(p_ptr); | 407 | tipc_port_unlock(p_ptr); |
488 | msg = buf_msg(buf); | 408 | msg = buf_msg(buf); |
489 | tipc_link_xmit(buf, msg_destnode(msg), msg_link_selector(msg)); | 409 | tipc_link_xmit(buf, peer_node, msg_link_selector(msg)); |
490 | return tipc_port_disconnect(ref); | 410 | return tipc_port_disconnect(ref); |
491 | } | 411 | } |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index a8be4d2001f7..5f8376e8da2a 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -53,6 +53,7 @@ static void tipc_write_space(struct sock *sk); | |||
53 | static int tipc_release(struct socket *sock); | 53 | static int tipc_release(struct socket *sock); |
54 | static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags); | 54 | static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags); |
55 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p); | 55 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p); |
56 | static void tipc_sk_timeout(unsigned long ref); | ||
56 | 57 | ||
57 | static const struct proto_ops packet_ops; | 58 | static const struct proto_ops packet_ops; |
58 | static const struct proto_ops stream_ops; | 59 | static const struct proto_ops stream_ops; |
@@ -202,6 +203,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock, | |||
202 | sock->state = state; | 203 | sock->state = state; |
203 | 204 | ||
204 | sock_init_data(sock, sk); | 205 | sock_init_data(sock, sk); |
206 | k_init_timer(&port->timer, (Handler)tipc_sk_timeout, ref); | ||
205 | sk->sk_backlog_rcv = tipc_backlog_rcv; | 207 | sk->sk_backlog_rcv = tipc_backlog_rcv; |
206 | sk->sk_rcvbuf = sysctl_tipc_rmem[1]; | 208 | sk->sk_rcvbuf = sysctl_tipc_rmem[1]; |
207 | sk->sk_data_ready = tipc_data_ready; | 209 | sk->sk_data_ready = tipc_data_ready; |
@@ -1946,6 +1948,50 @@ restart: | |||
1946 | return res; | 1948 | return res; |
1947 | } | 1949 | } |
1948 | 1950 | ||
1951 | static void tipc_sk_timeout(unsigned long ref) | ||
1952 | { | ||
1953 | struct tipc_port *port = tipc_port_lock(ref); | ||
1954 | struct tipc_sock *tsk; | ||
1955 | struct sock *sk; | ||
1956 | struct sk_buff *buf = NULL; | ||
1957 | struct tipc_msg *msg = NULL; | ||
1958 | u32 peer_port, peer_node; | ||
1959 | |||
1960 | if (!port) | ||
1961 | return; | ||
1962 | |||
1963 | if (!port->connected) { | ||
1964 | tipc_port_unlock(port); | ||
1965 | return; | ||
1966 | } | ||
1967 | tsk = tipc_port_to_sock(port); | ||
1968 | sk = &tsk->sk; | ||
1969 | bh_lock_sock(sk); | ||
1970 | peer_port = tipc_port_peerport(port); | ||
1971 | peer_node = tipc_port_peernode(port); | ||
1972 | |||
1973 | if (port->probing_state == TIPC_CONN_PROBING) { | ||
1974 | /* Previous probe not answered -> self abort */ | ||
1975 | buf = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, | ||
1976 | SHORT_H_SIZE, 0, tipc_own_addr, | ||
1977 | peer_node, ref, peer_port, | ||
1978 | TIPC_ERR_NO_PORT); | ||
1979 | } else { | ||
1980 | buf = tipc_msg_create(CONN_MANAGER, CONN_PROBE, INT_H_SIZE, | ||
1981 | 0, peer_node, tipc_own_addr, | ||
1982 | peer_port, ref, TIPC_OK); | ||
1983 | port->probing_state = TIPC_CONN_PROBING; | ||
1984 | k_start_timer(&port->timer, port->probing_interval); | ||
1985 | } | ||
1986 | bh_unlock_sock(sk); | ||
1987 | tipc_port_unlock(port); | ||
1988 | if (!buf) | ||
1989 | return; | ||
1990 | |||
1991 | msg = buf_msg(buf); | ||
1992 | tipc_link_xmit(buf, msg_destnode(msg), msg_link_selector(msg)); | ||
1993 | } | ||
1994 | |||
1949 | /** | 1995 | /** |
1950 | * tipc_setsockopt - set socket option | 1996 | * tipc_setsockopt - set socket option |
1951 | * @sock: socket structure | 1997 | * @sock: socket structure |