.. | .. |
---|
13 | 13 | #include <linux/sched/signal.h> |
---|
14 | 14 | |
---|
15 | 15 | #include <net/sock.h> |
---|
| 16 | +#include <net/tcp.h> |
---|
16 | 17 | |
---|
17 | 18 | #include "smc.h" |
---|
18 | 19 | #include "smc_tx.h" |
---|
19 | 20 | #include "smc_cdc.h" |
---|
20 | 21 | #include "smc_close.h" |
---|
21 | 22 | |
---|
22 | | -#define SMC_CLOSE_WAIT_LISTEN_CLCSOCK_TIME (5 * HZ) |
---|
| 23 | +/* release the clcsock that is assigned to the smc_sock */ |
---|
| 24 | +void smc_clcsock_release(struct smc_sock *smc) |
---|
| 25 | +{ |
---|
| 26 | + struct socket *tcp; |
---|
| 27 | + |
---|
| 28 | + if (smc->listen_smc && current_work() != &smc->smc_listen_work) |
---|
| 29 | + cancel_work_sync(&smc->smc_listen_work); |
---|
| 30 | + mutex_lock(&smc->clcsock_release_lock); |
---|
| 31 | + if (smc->clcsock) { |
---|
| 32 | + tcp = smc->clcsock; |
---|
| 33 | + smc->clcsock = NULL; |
---|
| 34 | + sock_release(tcp); |
---|
| 35 | + } |
---|
| 36 | + mutex_unlock(&smc->clcsock_release_lock); |
---|
| 37 | +} |
---|
23 | 38 | |
---|
24 | 39 | static void smc_close_cleanup_listen(struct sock *parent) |
---|
25 | 40 | { |
---|
.. | .. |
---|
49 | 64 | |
---|
50 | 65 | rc = sk_wait_event(sk, &timeout, |
---|
51 | 66 | !smc_tx_prepared_sends(&smc->conn) || |
---|
52 | | - (sk->sk_err == ECONNABORTED) || |
---|
53 | | - (sk->sk_err == ECONNRESET), |
---|
| 67 | + READ_ONCE(sk->sk_err) == ECONNABORTED || |
---|
| 68 | + READ_ONCE(sk->sk_err) == ECONNRESET || |
---|
| 69 | + smc->conn.killed, |
---|
54 | 70 | &wait); |
---|
55 | 71 | if (rc) |
---|
56 | 72 | break; |
---|
.. | .. |
---|
79 | 95 | conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1; |
---|
80 | 96 | else |
---|
81 | 97 | conn->local_tx_ctrl.conn_state_flags.peer_conn_closed = 1; |
---|
| 98 | + if (conn->killed) |
---|
| 99 | + return -EPIPE; |
---|
82 | 100 | |
---|
83 | 101 | return smc_cdc_get_slot_and_msg_send(conn); |
---|
84 | 102 | } |
---|
85 | 103 | |
---|
86 | | -static int smc_close_abort(struct smc_connection *conn) |
---|
| 104 | +int smc_close_abort(struct smc_connection *conn) |
---|
87 | 105 | { |
---|
88 | 106 | conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1; |
---|
89 | 107 | |
---|
90 | 108 | return smc_cdc_get_slot_and_msg_send(conn); |
---|
91 | 109 | } |
---|
92 | 110 | |
---|
93 | | -/* terminate smc socket abnormally - active abort |
---|
94 | | - * link group is terminated, i.e. RDMA communication no longer possible |
---|
95 | | - */ |
---|
96 | | -static void smc_close_active_abort(struct smc_sock *smc) |
---|
| 111 | +static void smc_close_cancel_work(struct smc_sock *smc) |
---|
97 | 112 | { |
---|
98 | 113 | struct sock *sk = &smc->sk; |
---|
99 | 114 | |
---|
100 | | - struct smc_cdc_conn_state_flags *txflags = |
---|
101 | | - &smc->conn.local_tx_ctrl.conn_state_flags; |
---|
| 115 | + release_sock(sk); |
---|
| 116 | + cancel_work_sync(&smc->conn.close_work); |
---|
| 117 | + cancel_delayed_work_sync(&smc->conn.tx_work); |
---|
| 118 | + lock_sock(sk); |
---|
| 119 | +} |
---|
| 120 | + |
---|
| 121 | +/* terminate smc socket abnormally - active abort |
---|
| 122 | + * link group is terminated, i.e. RDMA communication no longer possible |
---|
| 123 | + */ |
---|
| 124 | +void smc_close_active_abort(struct smc_sock *smc) |
---|
| 125 | +{ |
---|
| 126 | + struct sock *sk = &smc->sk; |
---|
| 127 | + bool release_clcsock = false; |
---|
102 | 128 | |
---|
103 | 129 | if (sk->sk_state != SMC_INIT && smc->clcsock && smc->clcsock->sk) { |
---|
104 | 130 | sk->sk_err = ECONNABORTED; |
---|
105 | | - if (smc->clcsock && smc->clcsock->sk) { |
---|
106 | | - smc->clcsock->sk->sk_err = ECONNABORTED; |
---|
107 | | - smc->clcsock->sk->sk_state_change(smc->clcsock->sk); |
---|
108 | | - } |
---|
| 131 | + if (smc->clcsock && smc->clcsock->sk) |
---|
| 132 | + tcp_abort(smc->clcsock->sk, ECONNABORTED); |
---|
109 | 133 | } |
---|
110 | 134 | switch (sk->sk_state) { |
---|
111 | 135 | case SMC_ACTIVE: |
---|
112 | | - sk->sk_state = SMC_PEERABORTWAIT; |
---|
113 | | - release_sock(sk); |
---|
114 | | - cancel_delayed_work_sync(&smc->conn.tx_work); |
---|
115 | | - lock_sock(sk); |
---|
116 | | - sock_put(sk); /* passive closing */ |
---|
117 | | - break; |
---|
118 | 136 | case SMC_APPCLOSEWAIT1: |
---|
119 | 137 | case SMC_APPCLOSEWAIT2: |
---|
120 | | - if (!smc_cdc_rxed_any_close(&smc->conn)) |
---|
121 | | - sk->sk_state = SMC_PEERABORTWAIT; |
---|
122 | | - else |
---|
123 | | - sk->sk_state = SMC_CLOSED; |
---|
124 | | - release_sock(sk); |
---|
125 | | - cancel_delayed_work_sync(&smc->conn.tx_work); |
---|
126 | | - lock_sock(sk); |
---|
| 138 | + sk->sk_state = SMC_PEERABORTWAIT; |
---|
| 139 | + smc_close_cancel_work(smc); |
---|
| 140 | + if (sk->sk_state != SMC_PEERABORTWAIT) |
---|
| 141 | + break; |
---|
| 142 | + sk->sk_state = SMC_CLOSED; |
---|
| 143 | + sock_put(sk); /* (postponed) passive closing */ |
---|
127 | 144 | break; |
---|
128 | 145 | case SMC_PEERCLOSEWAIT1: |
---|
129 | 146 | case SMC_PEERCLOSEWAIT2: |
---|
130 | | - if (!txflags->peer_conn_closed) { |
---|
131 | | - /* just SHUTDOWN_SEND done */ |
---|
132 | | - sk->sk_state = SMC_PEERABORTWAIT; |
---|
133 | | - } else { |
---|
134 | | - sk->sk_state = SMC_CLOSED; |
---|
135 | | - } |
---|
| 147 | + case SMC_PEERFINCLOSEWAIT: |
---|
| 148 | + sk->sk_state = SMC_PEERABORTWAIT; |
---|
| 149 | + smc_close_cancel_work(smc); |
---|
| 150 | + if (sk->sk_state != SMC_PEERABORTWAIT) |
---|
| 151 | + break; |
---|
| 152 | + sk->sk_state = SMC_CLOSED; |
---|
| 153 | + smc_conn_free(&smc->conn); |
---|
| 154 | + release_clcsock = true; |
---|
136 | 155 | sock_put(sk); /* passive closing */ |
---|
137 | 156 | break; |
---|
138 | 157 | case SMC_PROCESSABORT: |
---|
139 | 158 | case SMC_APPFINCLOSEWAIT: |
---|
| 159 | + sk->sk_state = SMC_PEERABORTWAIT; |
---|
| 160 | + smc_close_cancel_work(smc); |
---|
| 161 | + if (sk->sk_state != SMC_PEERABORTWAIT) |
---|
| 162 | + break; |
---|
140 | 163 | sk->sk_state = SMC_CLOSED; |
---|
141 | | - break; |
---|
142 | | - case SMC_PEERFINCLOSEWAIT: |
---|
143 | | - sock_put(sk); /* passive closing */ |
---|
| 164 | + smc_conn_free(&smc->conn); |
---|
| 165 | + release_clcsock = true; |
---|
144 | 166 | break; |
---|
145 | 167 | case SMC_INIT: |
---|
146 | 168 | case SMC_PEERABORTWAIT: |
---|
.. | .. |
---|
150 | 172 | |
---|
151 | 173 | sock_set_flag(sk, SOCK_DEAD); |
---|
152 | 174 | sk->sk_state_change(sk); |
---|
| 175 | + |
---|
| 176 | + if (release_clcsock) { |
---|
| 177 | + release_sock(sk); |
---|
| 178 | + smc_clcsock_release(smc); |
---|
| 179 | + lock_sock(sk); |
---|
| 180 | + } |
---|
153 | 181 | } |
---|
154 | 182 | |
---|
155 | 183 | static inline bool smc_close_sent_any_close(struct smc_connection *conn) |
---|
.. | .. |
---|
183 | 211 | sk->sk_state = SMC_CLOSED; |
---|
184 | 212 | sk->sk_state_change(sk); /* wake up accept */ |
---|
185 | 213 | if (smc->clcsock && smc->clcsock->sk) { |
---|
| 214 | + smc->clcsock->sk->sk_data_ready = smc->clcsk_data_ready; |
---|
| 215 | + smc->clcsock->sk->sk_user_data = NULL; |
---|
186 | 216 | rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR); |
---|
187 | | - /* wake up kernel_accept of smc_tcp_listen_worker */ |
---|
188 | | - smc->clcsock->sk->sk_data_ready(smc->clcsock->sk); |
---|
189 | 217 | } |
---|
190 | 218 | smc_close_cleanup_listen(sk); |
---|
191 | 219 | release_sock(sk); |
---|
.. | .. |
---|
200 | 228 | if (sk->sk_state == SMC_ACTIVE) { |
---|
201 | 229 | /* send close request */ |
---|
202 | 230 | rc = smc_close_final(conn); |
---|
203 | | - if (rc) |
---|
204 | | - break; |
---|
205 | 231 | sk->sk_state = SMC_PEERCLOSEWAIT1; |
---|
206 | 232 | |
---|
207 | 233 | /* actively shutdown clcsock before peer close it, |
---|
.. | .. |
---|
223 | 249 | !smc_close_sent_any_close(conn)) { |
---|
224 | 250 | /* just shutdown wr done, send close request */ |
---|
225 | 251 | rc = smc_close_final(conn); |
---|
226 | | - if (rc) |
---|
227 | | - break; |
---|
228 | 252 | } |
---|
229 | 253 | sk->sk_state = SMC_CLOSED; |
---|
230 | 254 | break; |
---|
.. | .. |
---|
240 | 264 | goto again; |
---|
241 | 265 | /* confirm close from peer */ |
---|
242 | 266 | rc = smc_close_final(conn); |
---|
243 | | - if (rc) |
---|
244 | | - break; |
---|
245 | 267 | if (smc_cdc_rxed_any_close(conn)) { |
---|
246 | 268 | /* peer has closed the socket already */ |
---|
247 | 269 | sk->sk_state = SMC_CLOSED; |
---|
.. | .. |
---|
257 | 279 | !smc_close_sent_any_close(conn)) { |
---|
258 | 280 | /* just shutdown wr done, send close request */ |
---|
259 | 281 | rc = smc_close_final(conn); |
---|
260 | | - if (rc) |
---|
261 | | - break; |
---|
262 | 282 | } |
---|
263 | 283 | /* peer sending PeerConnectionClosed will cause transition */ |
---|
264 | 284 | break; |
---|
.. | .. |
---|
266 | 286 | /* peer sending PeerConnectionClosed will cause transition */ |
---|
267 | 287 | break; |
---|
268 | 288 | case SMC_PROCESSABORT: |
---|
269 | | - smc_close_abort(conn); |
---|
| 289 | + rc = smc_close_abort(conn); |
---|
270 | 290 | sk->sk_state = SMC_CLOSED; |
---|
271 | 291 | break; |
---|
272 | 292 | case SMC_PEERABORTWAIT: |
---|
| 293 | + sk->sk_state = SMC_CLOSED; |
---|
| 294 | + break; |
---|
273 | 295 | case SMC_CLOSED: |
---|
274 | 296 | /* nothing to do, add tracing in future patch */ |
---|
275 | 297 | break; |
---|
.. | .. |
---|
331 | 353 | close_work); |
---|
332 | 354 | struct smc_sock *smc = container_of(conn, struct smc_sock, conn); |
---|
333 | 355 | struct smc_cdc_conn_state_flags *rxflags; |
---|
| 356 | + bool release_clcsock = false; |
---|
334 | 357 | struct sock *sk = &smc->sk; |
---|
335 | 358 | int old_state; |
---|
336 | 359 | |
---|
337 | 360 | lock_sock(sk); |
---|
338 | 361 | old_state = sk->sk_state; |
---|
339 | | - |
---|
340 | | - if (!conn->alert_token_local) { |
---|
341 | | - /* abnormal termination */ |
---|
342 | | - smc_close_active_abort(smc); |
---|
343 | | - goto wakeup; |
---|
344 | | - } |
---|
345 | 362 | |
---|
346 | 363 | rxflags = &conn->local_rx_ctrl.conn_state_flags; |
---|
347 | 364 | if (rxflags->peer_conn_abort) { |
---|
.. | .. |
---|
355 | 372 | |
---|
356 | 373 | switch (sk->sk_state) { |
---|
357 | 374 | case SMC_INIT: |
---|
358 | | - if (atomic_read(&conn->bytes_to_rcv) || |
---|
359 | | - (rxflags->peer_done_writing && |
---|
360 | | - !smc_cdc_rxed_any_close(conn))) { |
---|
361 | | - sk->sk_state = SMC_APPCLOSEWAIT1; |
---|
362 | | - } else { |
---|
363 | | - sk->sk_state = SMC_CLOSED; |
---|
364 | | - sock_put(sk); /* passive closing */ |
---|
365 | | - } |
---|
| 375 | + sk->sk_state = SMC_APPCLOSEWAIT1; |
---|
366 | 376 | break; |
---|
367 | 377 | case SMC_ACTIVE: |
---|
368 | 378 | sk->sk_state = SMC_APPCLOSEWAIT1; |
---|
.. | .. |
---|
373 | 383 | case SMC_PEERCLOSEWAIT1: |
---|
374 | 384 | if (rxflags->peer_done_writing) |
---|
375 | 385 | sk->sk_state = SMC_PEERCLOSEWAIT2; |
---|
376 | | - /* fall through */ |
---|
| 386 | + fallthrough; |
---|
377 | 387 | /* to check for closing */ |
---|
378 | 388 | case SMC_PEERCLOSEWAIT2: |
---|
379 | 389 | if (!smc_cdc_rxed_any_close(conn)) |
---|
.. | .. |
---|
415 | 425 | if (old_state != sk->sk_state) { |
---|
416 | 426 | sk->sk_state_change(sk); |
---|
417 | 427 | if ((sk->sk_state == SMC_CLOSED) && |
---|
418 | | - (sock_flag(sk, SOCK_DEAD) || !sk->sk_socket)) |
---|
| 428 | + (sock_flag(sk, SOCK_DEAD) || !sk->sk_socket)) { |
---|
419 | 429 | smc_conn_free(conn); |
---|
| 430 | + if (smc->clcsock) |
---|
| 431 | + release_clcsock = true; |
---|
| 432 | + } |
---|
420 | 433 | } |
---|
421 | 434 | release_sock(sk); |
---|
| 435 | + if (release_clcsock) |
---|
| 436 | + smc_clcsock_release(smc); |
---|
422 | 437 | sock_put(sk); /* sock_hold done by schedulers of close_work */ |
---|
423 | 438 | } |
---|
424 | 439 | |
---|
.. | .. |
---|
446 | 461 | goto again; |
---|
447 | 462 | /* send close wr request */ |
---|
448 | 463 | rc = smc_close_wr(conn); |
---|
449 | | - if (rc) |
---|
450 | | - break; |
---|
451 | 464 | sk->sk_state = SMC_PEERCLOSEWAIT1; |
---|
452 | 465 | break; |
---|
453 | 466 | case SMC_APPCLOSEWAIT1: |
---|
.. | .. |
---|
461 | 474 | goto again; |
---|
462 | 475 | /* confirm close from peer */ |
---|
463 | 476 | rc = smc_close_wr(conn); |
---|
464 | | - if (rc) |
---|
465 | | - break; |
---|
466 | 477 | sk->sk_state = SMC_APPCLOSEWAIT2; |
---|
467 | 478 | break; |
---|
468 | 479 | case SMC_APPCLOSEWAIT2: |
---|