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

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

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /net/smc/smc_close.c (Version linux-6.11.5) and /net/smc/smc_close.c (Version linux-6.4.16)


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

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

kernel.org | git.kernel.org | LWN.net | Project Home | 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.

sflogo.php