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

net/smc: cancel send and receive for terminated socket

The resources for a terminated socket are being cleaned up.
This patch makes sure
* no more data is received for an actively terminated socket
* no more data is sent for an actively or passively terminated socket

Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>

authored by

Ursula Braun and committed by
Jakub Kicinski
b2900980 fe28afe2

+32 -17
+1
net/smc/smc.h
··· 188 188 * 0 for SMC-R, 32 for SMC-D 189 189 */ 190 190 u64 peer_token; /* SMC-D token of peer */ 191 + u8 killed : 1; /* abnormal termination */ 191 192 }; 192 193 193 194 struct smc_sock { /* smc sock container */
+2 -2
net/smc/smc_cdc.c
··· 63 63 rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf, 64 64 wr_rdma_buf, 65 65 (struct smc_wr_tx_pend_priv **)pend); 66 - if (!conn->alert_token_local) 66 + if (conn->killed) 67 67 /* abnormal termination */ 68 68 rc = -EPIPE; 69 69 return rc; ··· 328 328 struct smcd_cdc_msg cdc; 329 329 struct smc_sock *smc; 330 330 331 - if (!conn) 331 + if (!conn || conn->killed) 332 332 return; 333 333 334 334 data_cdc = (struct smcd_cdc_msg *)conn->rmb_desc->cpu_addr;
+5 -2
net/smc/smc_close.c
··· 66 66 rc = sk_wait_event(sk, &timeout, 67 67 !smc_tx_prepared_sends(&smc->conn) || 68 68 sk->sk_err == ECONNABORTED || 69 - sk->sk_err == ECONNRESET, 69 + sk->sk_err == ECONNRESET || 70 + smc->conn.killed, 70 71 &wait); 71 72 if (rc) 72 73 break; ··· 96 95 conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1; 97 96 else 98 97 conn->local_tx_ctrl.conn_state_flags.peer_conn_closed = 1; 98 + if (conn->killed) 99 + return -EPIPE; 99 100 100 101 return smc_cdc_get_slot_and_msg_send(conn); 101 102 } ··· 329 326 lock_sock(sk); 330 327 old_state = sk->sk_state; 331 328 332 - if (!conn->alert_token_local) { 329 + if (conn->killed) { 333 330 /* abnormal termination */ 334 331 smc_close_active_abort(smc); 335 332 goto wakeup;
+1
net/smc/smc_core.c
··· 500 500 conn = rb_entry(node, struct smc_connection, alert_node); 501 501 smc = container_of(conn, struct smc_sock, conn); 502 502 sock_hold(&smc->sk); /* sock_put in close work */ 503 + conn->killed = 1; 503 504 conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1; 504 505 __smc_lgr_unregister_conn(conn); 505 506 conn->lgr = NULL;
+8 -2
net/smc/smc_rx.c
··· 201 201 { 202 202 DEFINE_WAIT_FUNC(wait, woken_wake_function); 203 203 struct smc_connection *conn = &smc->conn; 204 + struct smc_cdc_conn_state_flags *cflags = 205 + &conn->local_tx_ctrl.conn_state_flags; 204 206 struct sock *sk = &smc->sk; 205 207 int rc; 206 208 ··· 212 210 add_wait_queue(sk_sleep(sk), &wait); 213 211 rc = sk_wait_event(sk, timeo, 214 212 sk->sk_err || 213 + cflags->peer_conn_abort || 215 214 sk->sk_shutdown & RCV_SHUTDOWN || 215 + conn->killed || 216 216 fcrit(conn), 217 217 &wait); 218 218 remove_wait_queue(sk_sleep(sk), &wait); ··· 318 314 if (read_done >= target || (pipe && read_done)) 319 315 break; 320 316 317 + if (conn->killed) 318 + break; 319 + 321 320 if (smc_rx_recvmsg_data_available(smc)) 322 321 goto copy; 323 322 324 - if (sk->sk_shutdown & RCV_SHUTDOWN || 325 - conn->local_tx_ctrl.conn_state_flags.peer_conn_abort) { 323 + if (sk->sk_shutdown & RCV_SHUTDOWN) { 326 324 /* smc_cdc_msg_recv_action() could have run after 327 325 * above smc_rx_recvmsg_data_available() 328 326 */
+15 -11
net/smc/smc_tx.c
··· 86 86 sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); 87 87 if (sk->sk_err || 88 88 (sk->sk_shutdown & SEND_SHUTDOWN) || 89 + conn->killed || 89 90 conn->local_tx_ctrl.conn_state_flags.peer_done_writing) { 90 91 rc = -EPIPE; 91 92 break; ··· 156 155 return -ENOTCONN; 157 156 if (smc->sk.sk_shutdown & SEND_SHUTDOWN || 158 157 (smc->sk.sk_err == ECONNABORTED) || 159 - conn->local_tx_ctrl.conn_state_flags.peer_conn_abort) 158 + conn->killed) 160 159 return -EPIPE; 161 160 if (smc_cdc_rxed_any_close(conn)) 162 161 return send_done ?: -ECONNRESET; ··· 283 282 peer_rmbe_offset; 284 283 rdma_wr->rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey; 285 284 rc = ib_post_send(link->roce_qp, &rdma_wr->wr, NULL); 286 - if (rc) { 287 - conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1; 285 + if (rc) 288 286 smc_lgr_terminate(lgr); 289 - } 290 287 return rc; 291 288 } 292 289 ··· 494 495 495 496 if (smc->sk.sk_err == ECONNABORTED) 496 497 return sock_error(&smc->sk); 498 + if (conn->killed) 499 + return -EPIPE; 497 500 rc = 0; 498 - if (conn->alert_token_local) /* connection healthy */ 499 - mod_delayed_work(system_wq, &conn->tx_work, 500 - SMC_TX_WORK_DELAY); 501 + mod_delayed_work(system_wq, &conn->tx_work, 502 + SMC_TX_WORK_DELAY); 501 503 } 502 504 return rc; 503 505 } ··· 547 547 { 548 548 int rc; 549 549 550 + if (conn->killed || 551 + conn->local_rx_ctrl.conn_state_flags.peer_conn_abort) 552 + return -EPIPE; /* connection being aborted */ 550 553 if (conn->lgr->is_smcd) 551 554 rc = smcd_tx_sndbuf_nonempty(conn); 552 555 else ··· 576 573 int rc; 577 574 578 575 lock_sock(&smc->sk); 579 - if (smc->sk.sk_err || 580 - !conn->alert_token_local || 581 - conn->local_rx_ctrl.conn_state_flags.peer_conn_abort) 576 + if (smc->sk.sk_err) 582 577 goto out; 583 578 584 579 rc = smc_tx_sndbuf_nonempty(conn); ··· 609 608 ((to_confirm > conn->rmbe_update_limit) && 610 609 ((sender_free <= (conn->rmb_desc->len / 2)) || 611 610 conn->local_rx_ctrl.prod_flags.write_blocked))) { 611 + if (conn->killed || 612 + conn->local_rx_ctrl.conn_state_flags.peer_conn_abort) 613 + return; 612 614 if ((smc_cdc_get_slot_and_msg_send(conn) < 0) && 613 - conn->alert_token_local) { /* connection healthy */ 615 + !conn->killed) { 614 616 schedule_delayed_work(&conn->tx_work, 615 617 SMC_TX_WORK_DELAY); 616 618 return;