mirror of https://gitee.com/openkylin/linux.git
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:
parent
fe28afe23e
commit
b290098092
|
@ -188,6 +188,7 @@ struct smc_connection {
|
||||||
* 0 for SMC-R, 32 for SMC-D
|
* 0 for SMC-R, 32 for SMC-D
|
||||||
*/
|
*/
|
||||||
u64 peer_token; /* SMC-D token of peer */
|
u64 peer_token; /* SMC-D token of peer */
|
||||||
|
u8 killed : 1; /* abnormal termination */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smc_sock { /* smc sock container */
|
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,
|
rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf,
|
||||||
wr_rdma_buf,
|
wr_rdma_buf,
|
||||||
(struct smc_wr_tx_pend_priv **)pend);
|
(struct smc_wr_tx_pend_priv **)pend);
|
||||||
if (!conn->alert_token_local)
|
if (conn->killed)
|
||||||
/* abnormal termination */
|
/* abnormal termination */
|
||||||
rc = -EPIPE;
|
rc = -EPIPE;
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -328,7 +328,7 @@ static void smcd_cdc_rx_tsklet(unsigned long data)
|
||||||
struct smcd_cdc_msg cdc;
|
struct smcd_cdc_msg cdc;
|
||||||
struct smc_sock *smc;
|
struct smc_sock *smc;
|
||||||
|
|
||||||
if (!conn)
|
if (!conn || conn->killed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
data_cdc = (struct smcd_cdc_msg *)conn->rmb_desc->cpu_addr;
|
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,
|
rc = sk_wait_event(sk, &timeout,
|
||||||
!smc_tx_prepared_sends(&smc->conn) ||
|
!smc_tx_prepared_sends(&smc->conn) ||
|
||||||
sk->sk_err == ECONNABORTED ||
|
sk->sk_err == ECONNABORTED ||
|
||||||
sk->sk_err == ECONNRESET,
|
sk->sk_err == ECONNRESET ||
|
||||||
|
smc->conn.killed,
|
||||||
&wait);
|
&wait);
|
||||||
if (rc)
|
if (rc)
|
||||||
break;
|
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;
|
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
|
||||||
else
|
else
|
||||||
conn->local_tx_ctrl.conn_state_flags.peer_conn_closed = 1;
|
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);
|
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);
|
lock_sock(sk);
|
||||||
old_state = sk->sk_state;
|
old_state = sk->sk_state;
|
||||||
|
|
||||||
if (!conn->alert_token_local) {
|
if (conn->killed) {
|
||||||
/* abnormal termination */
|
/* abnormal termination */
|
||||||
smc_close_active_abort(smc);
|
smc_close_active_abort(smc);
|
||||||
goto wakeup;
|
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);
|
conn = rb_entry(node, struct smc_connection, alert_node);
|
||||||
smc = container_of(conn, struct smc_sock, conn);
|
smc = container_of(conn, struct smc_sock, conn);
|
||||||
sock_hold(&smc->sk); /* sock_put in close work */
|
sock_hold(&smc->sk); /* sock_put in close work */
|
||||||
|
conn->killed = 1;
|
||||||
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
|
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
|
||||||
__smc_lgr_unregister_conn(conn);
|
__smc_lgr_unregister_conn(conn);
|
||||||
conn->lgr = NULL;
|
conn->lgr = NULL;
|
||||||
|
|
|
@ -201,6 +201,8 @@ int smc_rx_wait(struct smc_sock *smc, long *timeo,
|
||||||
{
|
{
|
||||||
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
||||||
struct smc_connection *conn = &smc->conn;
|
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;
|
struct sock *sk = &smc->sk;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -210,7 +212,9 @@ int smc_rx_wait(struct smc_sock *smc, long *timeo,
|
||||||
add_wait_queue(sk_sleep(sk), &wait);
|
add_wait_queue(sk_sleep(sk), &wait);
|
||||||
rc = sk_wait_event(sk, timeo,
|
rc = sk_wait_event(sk, timeo,
|
||||||
sk->sk_err ||
|
sk->sk_err ||
|
||||||
|
cflags->peer_conn_abort ||
|
||||||
sk->sk_shutdown & RCV_SHUTDOWN ||
|
sk->sk_shutdown & RCV_SHUTDOWN ||
|
||||||
|
conn->killed ||
|
||||||
fcrit(conn),
|
fcrit(conn),
|
||||||
&wait);
|
&wait);
|
||||||
remove_wait_queue(sk_sleep(sk), &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))
|
if (read_done >= target || (pipe && read_done))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (conn->killed)
|
||||||
|
break;
|
||||||
|
|
||||||
if (smc_rx_recvmsg_data_available(smc))
|
if (smc_rx_recvmsg_data_available(smc))
|
||||||
goto copy;
|
goto copy;
|
||||||
|
|
||||||
if (sk->sk_shutdown & RCV_SHUTDOWN ||
|
if (sk->sk_shutdown & RCV_SHUTDOWN) {
|
||||||
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort) {
|
|
||||||
/* smc_cdc_msg_recv_action() could have run after
|
/* smc_cdc_msg_recv_action() could have run after
|
||||||
* above smc_rx_recvmsg_data_available()
|
* 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);
|
sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
|
||||||
if (sk->sk_err ||
|
if (sk->sk_err ||
|
||||||
(sk->sk_shutdown & SEND_SHUTDOWN) ||
|
(sk->sk_shutdown & SEND_SHUTDOWN) ||
|
||||||
|
conn->killed ||
|
||||||
conn->local_tx_ctrl.conn_state_flags.peer_done_writing) {
|
conn->local_tx_ctrl.conn_state_flags.peer_done_writing) {
|
||||||
rc = -EPIPE;
|
rc = -EPIPE;
|
||||||
break;
|
break;
|
||||||
|
@ -155,7 +156,7 @@ int smc_tx_sendmsg(struct smc_sock *smc, struct msghdr *msg, size_t len)
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
if (smc->sk.sk_shutdown & SEND_SHUTDOWN ||
|
if (smc->sk.sk_shutdown & SEND_SHUTDOWN ||
|
||||||
(smc->sk.sk_err == ECONNABORTED) ||
|
(smc->sk.sk_err == ECONNABORTED) ||
|
||||||
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort)
|
conn->killed)
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
if (smc_cdc_rxed_any_close(conn))
|
if (smc_cdc_rxed_any_close(conn))
|
||||||
return send_done ?: -ECONNRESET;
|
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;
|
peer_rmbe_offset;
|
||||||
rdma_wr->rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey;
|
rdma_wr->rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey;
|
||||||
rc = ib_post_send(link->roce_qp, &rdma_wr->wr, NULL);
|
rc = ib_post_send(link->roce_qp, &rdma_wr->wr, NULL);
|
||||||
if (rc) {
|
if (rc)
|
||||||
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
|
|
||||||
smc_lgr_terminate(lgr);
|
smc_lgr_terminate(lgr);
|
||||||
}
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,8 +494,9 @@ static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn)
|
||||||
|
|
||||||
if (smc->sk.sk_err == ECONNABORTED)
|
if (smc->sk.sk_err == ECONNABORTED)
|
||||||
return sock_error(&smc->sk);
|
return sock_error(&smc->sk);
|
||||||
|
if (conn->killed)
|
||||||
|
return -EPIPE;
|
||||||
rc = 0;
|
rc = 0;
|
||||||
if (conn->alert_token_local) /* connection healthy */
|
|
||||||
mod_delayed_work(system_wq, &conn->tx_work,
|
mod_delayed_work(system_wq, &conn->tx_work,
|
||||||
SMC_TX_WORK_DELAY);
|
SMC_TX_WORK_DELAY);
|
||||||
}
|
}
|
||||||
|
@ -547,6 +547,9 @@ int smc_tx_sndbuf_nonempty(struct smc_connection *conn)
|
||||||
{
|
{
|
||||||
int rc;
|
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)
|
if (conn->lgr->is_smcd)
|
||||||
rc = smcd_tx_sndbuf_nonempty(conn);
|
rc = smcd_tx_sndbuf_nonempty(conn);
|
||||||
else
|
else
|
||||||
|
@ -573,9 +576,7 @@ void smc_tx_work(struct work_struct *work)
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
lock_sock(&smc->sk);
|
lock_sock(&smc->sk);
|
||||||
if (smc->sk.sk_err ||
|
if (smc->sk.sk_err)
|
||||||
!conn->alert_token_local ||
|
|
||||||
conn->local_rx_ctrl.conn_state_flags.peer_conn_abort)
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rc = smc_tx_sndbuf_nonempty(conn);
|
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) &&
|
((to_confirm > conn->rmbe_update_limit) &&
|
||||||
((sender_free <= (conn->rmb_desc->len / 2)) ||
|
((sender_free <= (conn->rmb_desc->len / 2)) ||
|
||||||
conn->local_rx_ctrl.prod_flags.write_blocked))) {
|
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) &&
|
if ((smc_cdc_get_slot_and_msg_send(conn) < 0) &&
|
||||||
conn->alert_token_local) { /* connection healthy */
|
!conn->killed) {
|
||||||
schedule_delayed_work(&conn->tx_work,
|
schedule_delayed_work(&conn->tx_work,
|
||||||
SMC_TX_WORK_DELAY);
|
SMC_TX_WORK_DELAY);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue