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>
This commit is contained in:
Родитель
fe28afe23e
Коммит
b290098092
|
@ -188,6 +188,7 @@ struct smc_connection {
|
|||
* 0 for SMC-R, 32 for SMC-D
|
||||
*/
|
||||
u64 peer_token; /* SMC-D token of peer */
|
||||
u8 killed : 1; /* abnormal termination */
|
||||
};
|
||||
|
||||
struct smc_sock { /* smc sock container */
|
||||
|
|
|
@ -63,7 +63,7 @@ int smc_cdc_get_free_slot(struct smc_connection *conn,
|
|||
rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf,
|
||||
wr_rdma_buf,
|
||||
(struct smc_wr_tx_pend_priv **)pend);
|
||||
if (!conn->alert_token_local)
|
||||
if (conn->killed)
|
||||
/* abnormal termination */
|
||||
rc = -EPIPE;
|
||||
return rc;
|
||||
|
@ -328,7 +328,7 @@ static void smcd_cdc_rx_tsklet(unsigned long data)
|
|||
struct smcd_cdc_msg cdc;
|
||||
struct smc_sock *smc;
|
||||
|
||||
if (!conn)
|
||||
if (!conn || conn->killed)
|
||||
return;
|
||||
|
||||
data_cdc = (struct smcd_cdc_msg *)conn->rmb_desc->cpu_addr;
|
||||
|
|
|
@ -66,7 +66,8 @@ static void smc_close_stream_wait(struct smc_sock *smc, long timeout)
|
|||
rc = sk_wait_event(sk, &timeout,
|
||||
!smc_tx_prepared_sends(&smc->conn) ||
|
||||
sk->sk_err == ECONNABORTED ||
|
||||
sk->sk_err == ECONNRESET,
|
||||
sk->sk_err == ECONNRESET ||
|
||||
smc->conn.killed,
|
||||
&wait);
|
||||
if (rc)
|
||||
break;
|
||||
|
@ -95,6 +96,8 @@ static int smc_close_final(struct smc_connection *conn)
|
|||
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
|
||||
else
|
||||
conn->local_tx_ctrl.conn_state_flags.peer_conn_closed = 1;
|
||||
if (conn->killed)
|
||||
return -EPIPE;
|
||||
|
||||
return smc_cdc_get_slot_and_msg_send(conn);
|
||||
}
|
||||
|
@ -326,7 +329,7 @@ static void smc_close_passive_work(struct work_struct *work)
|
|||
lock_sock(sk);
|
||||
old_state = sk->sk_state;
|
||||
|
||||
if (!conn->alert_token_local) {
|
||||
if (conn->killed) {
|
||||
/* abnormal termination */
|
||||
smc_close_active_abort(smc);
|
||||
goto wakeup;
|
||||
|
|
|
@ -500,6 +500,7 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr)
|
|||
conn = rb_entry(node, struct smc_connection, alert_node);
|
||||
smc = container_of(conn, struct smc_sock, conn);
|
||||
sock_hold(&smc->sk); /* sock_put in close work */
|
||||
conn->killed = 1;
|
||||
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
|
||||
__smc_lgr_unregister_conn(conn);
|
||||
conn->lgr = NULL;
|
||||
|
|
|
@ -201,6 +201,8 @@ int smc_rx_wait(struct smc_sock *smc, long *timeo,
|
|||
{
|
||||
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
||||
struct smc_connection *conn = &smc->conn;
|
||||
struct smc_cdc_conn_state_flags *cflags =
|
||||
&conn->local_tx_ctrl.conn_state_flags;
|
||||
struct sock *sk = &smc->sk;
|
||||
int rc;
|
||||
|
||||
|
@ -210,7 +212,9 @@ int smc_rx_wait(struct smc_sock *smc, long *timeo,
|
|||
add_wait_queue(sk_sleep(sk), &wait);
|
||||
rc = sk_wait_event(sk, timeo,
|
||||
sk->sk_err ||
|
||||
cflags->peer_conn_abort ||
|
||||
sk->sk_shutdown & RCV_SHUTDOWN ||
|
||||
conn->killed ||
|
||||
fcrit(conn),
|
||||
&wait);
|
||||
remove_wait_queue(sk_sleep(sk), &wait);
|
||||
|
@ -314,11 +318,13 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg,
|
|||
if (read_done >= target || (pipe && read_done))
|
||||
break;
|
||||
|
||||
if (conn->killed)
|
||||
break;
|
||||
|
||||
if (smc_rx_recvmsg_data_available(smc))
|
||||
goto copy;
|
||||
|
||||
if (sk->sk_shutdown & RCV_SHUTDOWN ||
|
||||
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort) {
|
||||
if (sk->sk_shutdown & RCV_SHUTDOWN) {
|
||||
/* smc_cdc_msg_recv_action() could have run after
|
||||
* above smc_rx_recvmsg_data_available()
|
||||
*/
|
||||
|
|
|
@ -86,6 +86,7 @@ static int smc_tx_wait(struct smc_sock *smc, int flags)
|
|||
sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
|
||||
if (sk->sk_err ||
|
||||
(sk->sk_shutdown & SEND_SHUTDOWN) ||
|
||||
conn->killed ||
|
||||
conn->local_tx_ctrl.conn_state_flags.peer_done_writing) {
|
||||
rc = -EPIPE;
|
||||
break;
|
||||
|
@ -155,7 +156,7 @@ int smc_tx_sendmsg(struct smc_sock *smc, struct msghdr *msg, size_t len)
|
|||
return -ENOTCONN;
|
||||
if (smc->sk.sk_shutdown & SEND_SHUTDOWN ||
|
||||
(smc->sk.sk_err == ECONNABORTED) ||
|
||||
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort)
|
||||
conn->killed)
|
||||
return -EPIPE;
|
||||
if (smc_cdc_rxed_any_close(conn))
|
||||
return send_done ?: -ECONNRESET;
|
||||
|
@ -282,10 +283,8 @@ static int smc_tx_rdma_write(struct smc_connection *conn, int peer_rmbe_offset,
|
|||
peer_rmbe_offset;
|
||||
rdma_wr->rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey;
|
||||
rc = ib_post_send(link->roce_qp, &rdma_wr->wr, NULL);
|
||||
if (rc) {
|
||||
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
|
||||
if (rc)
|
||||
smc_lgr_terminate(lgr);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -495,10 +494,11 @@ static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn)
|
|||
|
||||
if (smc->sk.sk_err == ECONNABORTED)
|
||||
return sock_error(&smc->sk);
|
||||
if (conn->killed)
|
||||
return -EPIPE;
|
||||
rc = 0;
|
||||
if (conn->alert_token_local) /* connection healthy */
|
||||
mod_delayed_work(system_wq, &conn->tx_work,
|
||||
SMC_TX_WORK_DELAY);
|
||||
mod_delayed_work(system_wq, &conn->tx_work,
|
||||
SMC_TX_WORK_DELAY);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -547,6 +547,9 @@ int smc_tx_sndbuf_nonempty(struct smc_connection *conn)
|
|||
{
|
||||
int rc;
|
||||
|
||||
if (conn->killed ||
|
||||
conn->local_rx_ctrl.conn_state_flags.peer_conn_abort)
|
||||
return -EPIPE; /* connection being aborted */
|
||||
if (conn->lgr->is_smcd)
|
||||
rc = smcd_tx_sndbuf_nonempty(conn);
|
||||
else
|
||||
|
@ -573,9 +576,7 @@ void smc_tx_work(struct work_struct *work)
|
|||
int rc;
|
||||
|
||||
lock_sock(&smc->sk);
|
||||
if (smc->sk.sk_err ||
|
||||
!conn->alert_token_local ||
|
||||
conn->local_rx_ctrl.conn_state_flags.peer_conn_abort)
|
||||
if (smc->sk.sk_err)
|
||||
goto out;
|
||||
|
||||
rc = smc_tx_sndbuf_nonempty(conn);
|
||||
|
@ -608,8 +609,11 @@ void smc_tx_consumer_update(struct smc_connection *conn, bool force)
|
|||
((to_confirm > conn->rmbe_update_limit) &&
|
||||
((sender_free <= (conn->rmb_desc->len / 2)) ||
|
||||
conn->local_rx_ctrl.prod_flags.write_blocked))) {
|
||||
if (conn->killed ||
|
||||
conn->local_rx_ctrl.conn_state_flags.peer_conn_abort)
|
||||
return;
|
||||
if ((smc_cdc_get_slot_and_msg_send(conn) < 0) &&
|
||||
conn->alert_token_local) { /* connection healthy */
|
||||
!conn->killed) {
|
||||
schedule_delayed_work(&conn->tx_work,
|
||||
SMC_TX_WORK_DELAY);
|
||||
return;
|
||||
|
|
Загрузка…
Ссылка в новой задаче