~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/smc/smc_close.c

Version: ~ [ linux-4.18-rc1 ] ~ [ linux-4.17.2 ] ~ [ linux-4.16.16 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.50 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.109 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.138 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.113 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.57 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.27.62 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  *  Shared Memory Communications over RDMA (SMC-R) and RoCE
  4  *
  5  *  Socket Closing - normal and abnormal
  6  *
  7  *  Copyright IBM Corp. 2016
  8  *
  9  *  Author(s):  Ursula Braun <ubraun@linux.vnet.ibm.com>
 10  */
 11 
 12 #include <linux/workqueue.h>
 13 #include <linux/sched/signal.h>
 14 
 15 #include <net/sock.h>
 16 
 17 #include "smc.h"
 18 #include "smc_tx.h"
 19 #include "smc_cdc.h"
 20 #include "smc_close.h"
 21 
 22 #define SMC_CLOSE_WAIT_LISTEN_CLCSOCK_TIME      (5 * HZ)
 23 
 24 static void smc_close_cleanup_listen(struct sock *parent)
 25 {
 26         struct sock *sk;
 27 
 28         /* Close non-accepted connections */
 29         while ((sk = smc_accept_dequeue(parent, NULL)))
 30                 smc_close_non_accepted(sk);
 31 }
 32 
 33 /* wait for sndbuf data being transmitted */
 34 static void smc_close_stream_wait(struct smc_sock *smc, long timeout)
 35 {
 36         DEFINE_WAIT_FUNC(wait, woken_wake_function);
 37         struct sock *sk = &smc->sk;
 38 
 39         if (!timeout)
 40                 return;
 41 
 42         if (!smc_tx_prepared_sends(&smc->conn))
 43                 return;
 44 
 45         smc->wait_close_tx_prepared = 1;
 46         add_wait_queue(sk_sleep(sk), &wait);
 47         while (!signal_pending(current) && timeout) {
 48                 int rc;
 49 
 50                 rc = sk_wait_event(sk, &timeout,
 51                                    !smc_tx_prepared_sends(&smc->conn) ||
 52                                    (sk->sk_err == ECONNABORTED) ||
 53                                    (sk->sk_err == ECONNRESET),
 54                                    &wait);
 55                 if (rc)
 56                         break;
 57         }
 58         remove_wait_queue(sk_sleep(sk), &wait);
 59         smc->wait_close_tx_prepared = 0;
 60 }
 61 
 62 void smc_close_wake_tx_prepared(struct smc_sock *smc)
 63 {
 64         if (smc->wait_close_tx_prepared)
 65                 /* wake up socket closing */
 66                 smc->sk.sk_state_change(&smc->sk);
 67 }
 68 
 69 static int smc_close_wr(struct smc_connection *conn)
 70 {
 71         conn->local_tx_ctrl.conn_state_flags.peer_done_writing = 1;
 72 
 73         return smc_cdc_get_slot_and_msg_send(conn);
 74 }
 75 
 76 static int smc_close_final(struct smc_connection *conn)
 77 {
 78         if (atomic_read(&conn->bytes_to_rcv))
 79                 conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
 80         else
 81                 conn->local_tx_ctrl.conn_state_flags.peer_conn_closed = 1;
 82 
 83         return smc_cdc_get_slot_and_msg_send(conn);
 84 }
 85 
 86 static int smc_close_abort(struct smc_connection *conn)
 87 {
 88         conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
 89 
 90         return smc_cdc_get_slot_and_msg_send(conn);
 91 }
 92 
 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)
 97 {
 98         struct sock *sk = &smc->sk;
 99 
100         struct smc_cdc_conn_state_flags *txflags =
101                 &smc->conn.local_tx_ctrl.conn_state_flags;
102 
103         sk->sk_err = ECONNABORTED;
104         if (smc->clcsock && smc->clcsock->sk) {
105                 smc->clcsock->sk->sk_err = ECONNABORTED;
106                 smc->clcsock->sk->sk_state_change(smc->clcsock->sk);
107         }
108         switch (sk->sk_state) {
109         case SMC_INIT:
110         case SMC_ACTIVE:
111                 sk->sk_state = SMC_PEERABORTWAIT;
112                 release_sock(sk);
113                 cancel_delayed_work_sync(&smc->conn.tx_work);
114                 lock_sock(sk);
115                 sock_put(sk); /* passive closing */
116                 break;
117         case SMC_APPCLOSEWAIT1:
118         case SMC_APPCLOSEWAIT2:
119                 if (!smc_cdc_rxed_any_close(&smc->conn))
120                         sk->sk_state = SMC_PEERABORTWAIT;
121                 else
122                         sk->sk_state = SMC_CLOSED;
123                 release_sock(sk);
124                 cancel_delayed_work_sync(&smc->conn.tx_work);
125                 lock_sock(sk);
126                 break;
127         case SMC_PEERCLOSEWAIT1:
128         case SMC_PEERCLOSEWAIT2:
129                 if (!txflags->peer_conn_closed) {
130                         /* just SHUTDOWN_SEND done */
131                         sk->sk_state = SMC_PEERABORTWAIT;
132                 } else {
133                         sk->sk_state = SMC_CLOSED;
134                 }
135                 sock_put(sk); /* passive closing */
136                 break;
137         case SMC_PROCESSABORT:
138         case SMC_APPFINCLOSEWAIT:
139                 sk->sk_state = SMC_CLOSED;
140                 break;
141         case SMC_PEERFINCLOSEWAIT:
142                 sock_put(sk); /* passive closing */
143                 break;
144         case SMC_PEERABORTWAIT:
145         case SMC_CLOSED:
146                 break;
147         }
148 
149         sock_set_flag(sk, SOCK_DEAD);
150         sk->sk_state_change(sk);
151 }
152 
153 static inline bool smc_close_sent_any_close(struct smc_connection *conn)
154 {
155         return conn->local_tx_ctrl.conn_state_flags.peer_conn_abort ||
156                conn->local_tx_ctrl.conn_state_flags.peer_conn_closed;
157 }
158 
159 int smc_close_active(struct smc_sock *smc)
160 {
161         struct smc_cdc_conn_state_flags *txflags =
162                 &smc->conn.local_tx_ctrl.conn_state_flags;
163         struct smc_connection *conn = &smc->conn;
164         struct sock *sk = &smc->sk;
165         int old_state;
166         long timeout;
167         int rc = 0;
168 
169         timeout = current->flags & PF_EXITING ?
170                   0 : sock_flag(sk, SOCK_LINGER) ?
171                       sk->sk_lingertime : SMC_MAX_STREAM_WAIT_TIMEOUT;
172 
173         old_state = sk->sk_state;
174 again:
175         switch (sk->sk_state) {
176         case SMC_INIT:
177                 sk->sk_state = SMC_CLOSED;
178                 break;
179         case SMC_LISTEN:
180                 sk->sk_state = SMC_CLOSED;
181                 sk->sk_state_change(sk); /* wake up accept */
182                 if (smc->clcsock && smc->clcsock->sk) {
183                         rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR);
184                         /* wake up kernel_accept of smc_tcp_listen_worker */
185                         smc->clcsock->sk->sk_data_ready(smc->clcsock->sk);
186                 }
187                 smc_close_cleanup_listen(sk);
188                 release_sock(sk);
189                 flush_work(&smc->tcp_listen_work);
190                 lock_sock(sk);
191                 break;
192         case SMC_ACTIVE:
193                 smc_close_stream_wait(smc, timeout);
194                 release_sock(sk);
195                 cancel_delayed_work_sync(&conn->tx_work);
196                 lock_sock(sk);
197                 if (sk->sk_state == SMC_ACTIVE) {
198                         /* send close request */
199                         rc = smc_close_final(conn);
200                         if (rc)
201                                 break;
202                         sk->sk_state = SMC_PEERCLOSEWAIT1;
203                 } else {
204                         /* peer event has changed the state */
205                         goto again;
206                 }
207                 break;
208         case SMC_APPFINCLOSEWAIT:
209                 /* socket already shutdown wr or both (active close) */
210                 if (txflags->peer_done_writing &&
211                     !smc_close_sent_any_close(conn)) {
212                         /* just shutdown wr done, send close request */
213                         rc = smc_close_final(conn);
214                         if (rc)
215                                 break;
216                 }
217                 sk->sk_state = SMC_CLOSED;
218                 break;
219         case SMC_APPCLOSEWAIT1:
220         case SMC_APPCLOSEWAIT2:
221                 if (!smc_cdc_rxed_any_close(conn))
222                         smc_close_stream_wait(smc, timeout);
223                 release_sock(sk);
224                 cancel_delayed_work_sync(&conn->tx_work);
225                 lock_sock(sk);
226                 if (sk->sk_state != SMC_APPCLOSEWAIT1 &&
227                     sk->sk_state != SMC_APPCLOSEWAIT2)
228                         goto again;
229                 /* confirm close from peer */
230                 rc = smc_close_final(conn);
231                 if (rc)
232                         break;
233                 if (smc_cdc_rxed_any_close(conn)) {
234                         /* peer has closed the socket already */
235                         sk->sk_state = SMC_CLOSED;
236                         sock_put(sk); /* postponed passive closing */
237                 } else {
238                         /* peer has just issued a shutdown write */
239                         sk->sk_state = SMC_PEERFINCLOSEWAIT;
240                 }
241                 break;
242         case SMC_PEERCLOSEWAIT1:
243         case SMC_PEERCLOSEWAIT2:
244                 if (txflags->peer_done_writing &&
245                     !smc_close_sent_any_close(conn)) {
246                         /* just shutdown wr done, send close request */
247                         rc = smc_close_final(conn);
248                         if (rc)
249                                 break;
250                 }
251                 /* peer sending PeerConnectionClosed will cause transition */
252                 break;
253         case SMC_PEERFINCLOSEWAIT:
254                 /* peer sending PeerConnectionClosed will cause transition */
255                 break;
256         case SMC_PROCESSABORT:
257                 smc_close_abort(conn);
258                 sk->sk_state = SMC_CLOSED;
259                 break;
260         case SMC_PEERABORTWAIT:
261         case SMC_CLOSED:
262                 /* nothing to do, add tracing in future patch */
263                 break;
264         }
265 
266         if (old_state != sk->sk_state)
267                 sk->sk_state_change(sk);
268         return rc;
269 }
270 
271 static void smc_close_passive_abort_received(struct smc_sock *smc)
272 {
273         struct smc_cdc_conn_state_flags *txflags =
274                 &smc->conn.local_tx_ctrl.conn_state_flags;
275         struct sock *sk = &smc->sk;
276 
277         switch (sk->sk_state) {
278         case SMC_INIT:
279         case SMC_ACTIVE:
280         case SMC_APPCLOSEWAIT1:
281                 sk->sk_state = SMC_PROCESSABORT;
282                 sock_put(sk); /* passive closing */
283                 break;
284         case SMC_APPFINCLOSEWAIT:
285                 sk->sk_state = SMC_PROCESSABORT;
286                 break;
287         case SMC_PEERCLOSEWAIT1:
288         case SMC_PEERCLOSEWAIT2:
289                 if (txflags->peer_done_writing &&
290                     !smc_close_sent_any_close(&smc->conn))
291                         /* just shutdown, but not yet closed locally */
292                         sk->sk_state = SMC_PROCESSABORT;
293                 else
294                         sk->sk_state = SMC_CLOSED;
295                 sock_put(sk); /* passive closing */
296                 break;
297         case SMC_APPCLOSEWAIT2:
298         case SMC_PEERFINCLOSEWAIT:
299                 sk->sk_state = SMC_CLOSED;
300                 sock_put(sk); /* passive closing */
301                 break;
302         case SMC_PEERABORTWAIT:
303                 sk->sk_state = SMC_CLOSED;
304                 break;
305         case SMC_PROCESSABORT:
306         /* nothing to do, add tracing in future patch */
307                 break;
308         }
309 }
310 
311 /* Either some kind of closing has been received: peer_conn_closed,
312  * peer_conn_abort, or peer_done_writing
313  * or the link group of the connection terminates abnormally.
314  */
315 static void smc_close_passive_work(struct work_struct *work)
316 {
317         struct smc_connection *conn = container_of(work,
318                                                    struct smc_connection,
319                                                    close_work);
320         struct smc_sock *smc = container_of(conn, struct smc_sock, conn);
321         struct smc_cdc_conn_state_flags *rxflags;
322         struct sock *sk = &smc->sk;
323         int old_state;
324 
325         lock_sock(sk);
326         old_state = sk->sk_state;
327 
328         if (!conn->alert_token_local) {
329                 /* abnormal termination */
330                 smc_close_active_abort(smc);
331                 goto wakeup;
332         }
333 
334         rxflags = &conn->local_rx_ctrl.conn_state_flags;
335         if (rxflags->peer_conn_abort) {
336                 /* peer has not received all data */
337                 smc_close_passive_abort_received(smc);
338                 release_sock(&smc->sk);
339                 cancel_delayed_work_sync(&conn->tx_work);
340                 lock_sock(&smc->sk);
341                 goto wakeup;
342         }
343 
344         switch (sk->sk_state) {
345         case SMC_INIT:
346                 if (atomic_read(&conn->bytes_to_rcv) ||
347                     (rxflags->peer_done_writing &&
348                      !smc_cdc_rxed_any_close(conn))) {
349                         sk->sk_state = SMC_APPCLOSEWAIT1;
350                 } else {
351                         sk->sk_state = SMC_CLOSED;
352                         sock_put(sk); /* passive closing */
353                 }
354                 break;
355         case SMC_ACTIVE:
356                 sk->sk_state = SMC_APPCLOSEWAIT1;
357                 /* postpone sock_put() for passive closing to cover
358                  * received SEND_SHUTDOWN as well
359                  */
360                 break;
361         case SMC_PEERCLOSEWAIT1:
362                 if (rxflags->peer_done_writing)
363                         sk->sk_state = SMC_PEERCLOSEWAIT2;
364                 /* fall through */
365                 /* to check for closing */
366         case SMC_PEERCLOSEWAIT2:
367                 if (!smc_cdc_rxed_any_close(conn))
368                         break;
369                 if (sock_flag(sk, SOCK_DEAD) &&
370                     smc_close_sent_any_close(conn)) {
371                         /* smc_release has already been called locally */
372                         sk->sk_state = SMC_CLOSED;
373                 } else {
374                         /* just shutdown, but not yet closed locally */
375                         sk->sk_state = SMC_APPFINCLOSEWAIT;
376                 }
377                 sock_put(sk); /* passive closing */
378                 break;
379         case SMC_PEERFINCLOSEWAIT:
380                 if (smc_cdc_rxed_any_close(conn)) {
381                         sk->sk_state = SMC_CLOSED;
382                         sock_put(sk); /* passive closing */
383                 }
384                 break;
385         case SMC_APPCLOSEWAIT1:
386         case SMC_APPCLOSEWAIT2:
387                 /* postpone sock_put() for passive closing to cover
388                  * received SEND_SHUTDOWN as well
389                  */
390                 break;
391         case SMC_APPFINCLOSEWAIT:
392         case SMC_PEERABORTWAIT:
393         case SMC_PROCESSABORT:
394         case SMC_CLOSED:
395                 /* nothing to do, add tracing in future patch */
396                 break;
397         }
398 
399 wakeup:
400         sk->sk_data_ready(sk); /* wakeup blocked rcvbuf consumers */
401         sk->sk_write_space(sk); /* wakeup blocked sndbuf producers */
402 
403         if (old_state != sk->sk_state) {
404                 sk->sk_state_change(sk);
405                 if ((sk->sk_state == SMC_CLOSED) &&
406                     (sock_flag(sk, SOCK_DEAD) || !sk->sk_socket))
407                         smc_conn_free(conn);
408         }
409         release_sock(sk);
410         sock_put(sk); /* sock_hold done by schedulers of close_work */
411 }
412 
413 int smc_close_shutdown_write(struct smc_sock *smc)
414 {
415         struct smc_connection *conn = &smc->conn;
416         struct sock *sk = &smc->sk;
417         int old_state;
418         long timeout;
419         int rc = 0;
420 
421         timeout = current->flags & PF_EXITING ?
422                   0 : sock_flag(sk, SOCK_LINGER) ?
423                       sk->sk_lingertime : SMC_MAX_STREAM_WAIT_TIMEOUT;
424 
425         old_state = sk->sk_state;
426 again:
427         switch (sk->sk_state) {
428         case SMC_ACTIVE:
429                 smc_close_stream_wait(smc, timeout);
430                 release_sock(sk);
431                 cancel_delayed_work_sync(&conn->tx_work);
432                 lock_sock(sk);
433                 if (sk->sk_state != SMC_ACTIVE)
434                         goto again;
435                 /* send close wr request */
436                 rc = smc_close_wr(conn);
437                 if (rc)
438                         break;
439                 sk->sk_state = SMC_PEERCLOSEWAIT1;
440                 break;
441         case SMC_APPCLOSEWAIT1:
442                 /* passive close */
443                 if (!smc_cdc_rxed_any_close(conn))
444                         smc_close_stream_wait(smc, timeout);
445                 release_sock(sk);
446                 cancel_delayed_work_sync(&conn->tx_work);
447                 lock_sock(sk);
448                 if (sk->sk_state != SMC_APPCLOSEWAIT1)
449                         goto again;
450                 /* confirm close from peer */
451                 rc = smc_close_wr(conn);
452                 if (rc)
453                         break;
454                 sk->sk_state = SMC_APPCLOSEWAIT2;
455                 break;
456         case SMC_APPCLOSEWAIT2:
457         case SMC_PEERFINCLOSEWAIT:
458         case SMC_PEERCLOSEWAIT1:
459         case SMC_PEERCLOSEWAIT2:
460         case SMC_APPFINCLOSEWAIT:
461         case SMC_PROCESSABORT:
462         case SMC_PEERABORTWAIT:
463                 /* nothing to do, add tracing in future patch */
464                 break;
465         }
466 
467         if (old_state != sk->sk_state)
468                 sk->sk_state_change(sk);
469         return rc;
470 }
471 
472 /* Initialize close properties on connection establishment. */
473 void smc_close_init(struct smc_sock *smc)
474 {
475         INIT_WORK(&smc->conn.close_work, smc_close_passive_work);
476 }
477 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp