Merge branch 'net-smc-improve-termination-handling'
Karsten Graul says: ==================== More patches to address abnormal termination processing of sockets and link groups. ==================== Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
This commit is contained in:
Коммит
bd71a35739
|
@ -167,6 +167,7 @@ static int smc_release(struct socket *sock)
|
|||
if (!sk)
|
||||
goto out;
|
||||
|
||||
sock_hold(sk); /* sock_put below */
|
||||
smc = smc_sk(sk);
|
||||
|
||||
/* cleanup for a dangling non-blocking connect */
|
||||
|
@ -189,6 +190,7 @@ static int smc_release(struct socket *sock)
|
|||
sock->sk = NULL;
|
||||
release_sock(sk);
|
||||
|
||||
sock_put(sk); /* sock_hold above */
|
||||
sock_put(sk); /* final sock_put */
|
||||
out:
|
||||
return rc;
|
||||
|
@ -970,12 +972,14 @@ void smc_close_non_accepted(struct sock *sk)
|
|||
{
|
||||
struct smc_sock *smc = smc_sk(sk);
|
||||
|
||||
sock_hold(sk); /* sock_put below */
|
||||
lock_sock(sk);
|
||||
if (!sk->sk_lingertime)
|
||||
/* wait for peer closing */
|
||||
sk->sk_lingertime = SMC_MAX_STREAM_WAIT_TIMEOUT;
|
||||
__smc_release(smc);
|
||||
release_sock(sk);
|
||||
sock_put(sk); /* sock_hold above */
|
||||
sock_put(sk); /* final sock_put */
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/sched/signal.h>
|
||||
|
||||
#include <net/sock.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
#include "smc.h"
|
||||
#include "smc_tx.h"
|
||||
|
@ -66,7 +67,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,11 +97,13 @@ 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);
|
||||
}
|
||||
|
||||
static int smc_close_abort(struct smc_connection *conn)
|
||||
int smc_close_abort(struct smc_connection *conn)
|
||||
{
|
||||
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
|
||||
|
||||
|
@ -109,16 +113,15 @@ static int smc_close_abort(struct smc_connection *conn)
|
|||
/* terminate smc socket abnormally - active abort
|
||||
* link group is terminated, i.e. RDMA communication no longer possible
|
||||
*/
|
||||
static void smc_close_active_abort(struct smc_sock *smc)
|
||||
void smc_close_active_abort(struct smc_sock *smc)
|
||||
{
|
||||
struct sock *sk = &smc->sk;
|
||||
bool release_clcsock = false;
|
||||
|
||||
if (sk->sk_state != SMC_INIT && smc->clcsock && smc->clcsock->sk) {
|
||||
sk->sk_err = ECONNABORTED;
|
||||
if (smc->clcsock && smc->clcsock->sk) {
|
||||
smc->clcsock->sk->sk_err = ECONNABORTED;
|
||||
smc->clcsock->sk->sk_state_change(smc->clcsock->sk);
|
||||
}
|
||||
if (smc->clcsock && smc->clcsock->sk)
|
||||
tcp_abort(smc->clcsock->sk, ECONNABORTED);
|
||||
}
|
||||
switch (sk->sk_state) {
|
||||
case SMC_ACTIVE:
|
||||
|
@ -135,11 +138,14 @@ static void smc_close_active_abort(struct smc_sock *smc)
|
|||
cancel_delayed_work_sync(&smc->conn.tx_work);
|
||||
lock_sock(sk);
|
||||
sk->sk_state = SMC_CLOSED;
|
||||
sock_put(sk); /* postponed passive closing */
|
||||
break;
|
||||
case SMC_PEERCLOSEWAIT1:
|
||||
case SMC_PEERCLOSEWAIT2:
|
||||
case SMC_PEERFINCLOSEWAIT:
|
||||
sk->sk_state = SMC_CLOSED;
|
||||
smc_conn_free(&smc->conn);
|
||||
release_clcsock = true;
|
||||
sock_put(sk); /* passive closing */
|
||||
break;
|
||||
case SMC_PROCESSABORT:
|
||||
|
@ -154,6 +160,12 @@ static void smc_close_active_abort(struct smc_sock *smc)
|
|||
|
||||
sock_set_flag(sk, SOCK_DEAD);
|
||||
sk->sk_state_change(sk);
|
||||
|
||||
if (release_clcsock) {
|
||||
release_sock(sk);
|
||||
smc_clcsock_release(smc);
|
||||
lock_sock(sk);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool smc_close_sent_any_close(struct smc_connection *conn)
|
||||
|
@ -326,12 +338,6 @@ static void smc_close_passive_work(struct work_struct *work)
|
|||
lock_sock(sk);
|
||||
old_state = sk->sk_state;
|
||||
|
||||
if (!conn->alert_token_local) {
|
||||
/* abnormal termination */
|
||||
smc_close_active_abort(smc);
|
||||
goto wakeup;
|
||||
}
|
||||
|
||||
rxflags = &conn->local_rx_ctrl.conn_state_flags;
|
||||
if (rxflags->peer_conn_abort) {
|
||||
/* peer has not received all data */
|
||||
|
|
|
@ -24,5 +24,7 @@ int smc_close_active(struct smc_sock *smc);
|
|||
int smc_close_shutdown_write(struct smc_sock *smc);
|
||||
void smc_close_init(struct smc_sock *smc);
|
||||
void smc_clcsock_release(struct smc_sock *smc);
|
||||
int smc_close_abort(struct smc_connection *conn);
|
||||
void smc_close_active_abort(struct smc_sock *smc);
|
||||
|
||||
#endif /* SMC_CLOSE_H */
|
||||
|
|
|
@ -61,14 +61,21 @@ static void smc_lgr_schedule_free_work(struct smc_link_group *lgr)
|
|||
* creation. For client use a somewhat higher removal delay time,
|
||||
* otherwise there is a risk of out-of-sync link groups.
|
||||
*/
|
||||
mod_delayed_work(system_wq, &lgr->free_work,
|
||||
(!lgr->is_smcd && lgr->role == SMC_CLNT) ?
|
||||
SMC_LGR_FREE_DELAY_CLNT : SMC_LGR_FREE_DELAY_SERV);
|
||||
if (!lgr->freeing && !lgr->freefast) {
|
||||
mod_delayed_work(system_wq, &lgr->free_work,
|
||||
(!lgr->is_smcd && lgr->role == SMC_CLNT) ?
|
||||
SMC_LGR_FREE_DELAY_CLNT :
|
||||
SMC_LGR_FREE_DELAY_SERV);
|
||||
}
|
||||
}
|
||||
|
||||
void smc_lgr_schedule_free_work_fast(struct smc_link_group *lgr)
|
||||
{
|
||||
mod_delayed_work(system_wq, &lgr->free_work, SMC_LGR_FREE_DELAY_FAST);
|
||||
if (!lgr->freeing && !lgr->freefast) {
|
||||
lgr->freefast = 1;
|
||||
mod_delayed_work(system_wq, &lgr->free_work,
|
||||
SMC_LGR_FREE_DELAY_FAST);
|
||||
}
|
||||
}
|
||||
|
||||
/* Register connection's alert token in our lookup structure.
|
||||
|
@ -147,6 +154,7 @@ static void smc_lgr_unregister_conn(struct smc_connection *conn)
|
|||
__smc_lgr_unregister_conn(conn);
|
||||
}
|
||||
write_unlock_bh(&lgr->conns_lock);
|
||||
conn->lgr = NULL;
|
||||
}
|
||||
|
||||
/* Send delete link, either as client to request the initiation
|
||||
|
@ -171,10 +179,15 @@ static void smc_lgr_free_work(struct work_struct *work)
|
|||
struct smc_link_group,
|
||||
free_work);
|
||||
spinlock_t *lgr_lock;
|
||||
struct smc_link *lnk;
|
||||
bool conns;
|
||||
|
||||
smc_lgr_list_head(lgr, &lgr_lock);
|
||||
spin_lock_bh(lgr_lock);
|
||||
if (lgr->freeing) {
|
||||
spin_unlock_bh(lgr_lock);
|
||||
return;
|
||||
}
|
||||
read_lock_bh(&lgr->conns_lock);
|
||||
conns = RB_EMPTY_ROOT(&lgr->conns_all);
|
||||
read_unlock_bh(&lgr->conns_lock);
|
||||
|
@ -182,31 +195,36 @@ static void smc_lgr_free_work(struct work_struct *work)
|
|||
spin_unlock_bh(lgr_lock);
|
||||
return;
|
||||
}
|
||||
if (!list_empty(&lgr->list))
|
||||
list_del_init(&lgr->list); /* remove from smc_lgr_list */
|
||||
spin_unlock_bh(lgr_lock);
|
||||
list_del_init(&lgr->list); /* remove from smc_lgr_list */
|
||||
|
||||
lnk = &lgr->lnk[SMC_SINGLE_LINK];
|
||||
if (!lgr->is_smcd && !lgr->terminating) {
|
||||
struct smc_link *lnk = &lgr->lnk[SMC_SINGLE_LINK];
|
||||
|
||||
/* try to send del link msg, on error free lgr immediately */
|
||||
if (lnk->state == SMC_LNK_ACTIVE &&
|
||||
!smc_link_send_delete(lnk)) {
|
||||
/* reschedule in case we never receive a response */
|
||||
smc_lgr_schedule_free_work(lgr);
|
||||
spin_unlock_bh(lgr_lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
lgr->freeing = 1; /* this instance does the freeing, no new schedule */
|
||||
spin_unlock_bh(lgr_lock);
|
||||
cancel_delayed_work(&lgr->free_work);
|
||||
|
||||
if (!delayed_work_pending(&lgr->free_work)) {
|
||||
struct smc_link *lnk = &lgr->lnk[SMC_SINGLE_LINK];
|
||||
if (!lgr->is_smcd && lnk->state != SMC_LNK_INACTIVE)
|
||||
smc_llc_link_inactive(lnk);
|
||||
if (lgr->is_smcd)
|
||||
smc_ism_signal_shutdown(lgr);
|
||||
smc_lgr_free(lgr);
|
||||
}
|
||||
|
||||
if (!lgr->is_smcd && lnk->state != SMC_LNK_INACTIVE)
|
||||
smc_llc_link_inactive(lnk);
|
||||
if (lgr->is_smcd)
|
||||
smc_ism_signal_shutdown(lgr);
|
||||
smc_lgr_free(lgr);
|
||||
}
|
||||
static void smc_lgr_terminate_work(struct work_struct *work)
|
||||
{
|
||||
struct smc_link_group *lgr = container_of(work, struct smc_link_group,
|
||||
terminate_work);
|
||||
|
||||
smc_lgr_terminate(lgr);
|
||||
}
|
||||
|
||||
/* create a new SMC link group */
|
||||
|
@ -234,6 +252,9 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
|
|||
}
|
||||
lgr->is_smcd = ini->is_smcd;
|
||||
lgr->sync_err = 0;
|
||||
lgr->terminating = 0;
|
||||
lgr->freefast = 0;
|
||||
lgr->freeing = 0;
|
||||
lgr->vlan_id = ini->vlan_id;
|
||||
rwlock_init(&lgr->sndbufs_lock);
|
||||
rwlock_init(&lgr->rmbs_lock);
|
||||
|
@ -245,6 +266,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
|
|||
smc_lgr_list.num += SMC_LGR_NUM_INCR;
|
||||
memcpy(&lgr->id, (u8 *)&smc_lgr_list.num, SMC_LGR_ID_SIZE);
|
||||
INIT_DELAYED_WORK(&lgr->free_work, smc_lgr_free_work);
|
||||
INIT_WORK(&lgr->terminate_work, smc_lgr_terminate_work);
|
||||
lgr->conns_all = RB_ROOT;
|
||||
if (ini->is_smcd) {
|
||||
/* SMC-D specific settings */
|
||||
|
@ -332,7 +354,7 @@ static void smc_buf_unuse(struct smc_connection *conn,
|
|||
conn->sndbuf_desc->used = 0;
|
||||
if (conn->rmb_desc) {
|
||||
if (!conn->rmb_desc->regerr) {
|
||||
if (!lgr->is_smcd) {
|
||||
if (!lgr->is_smcd && !list_empty(&lgr->list)) {
|
||||
/* unregister rmb with peer */
|
||||
smc_llc_do_delete_rkey(
|
||||
&lgr->lnk[SMC_SINGLE_LINK],
|
||||
|
@ -363,9 +385,10 @@ void smc_conn_free(struct smc_connection *conn)
|
|||
} else {
|
||||
smc_cdc_tx_dismiss_slots(conn);
|
||||
}
|
||||
smc_lgr_unregister_conn(conn);
|
||||
smc_buf_unuse(conn, lgr); /* allow buffer reuse */
|
||||
conn->lgr = NULL;
|
||||
if (!list_empty(&lgr->list)) {
|
||||
smc_lgr_unregister_conn(conn);
|
||||
smc_buf_unuse(conn, lgr); /* allow buffer reuse */
|
||||
}
|
||||
|
||||
if (!lgr->conns_num)
|
||||
smc_lgr_schedule_free_work(lgr);
|
||||
|
@ -479,7 +502,27 @@ void smc_lgr_forget(struct smc_link_group *lgr)
|
|||
spin_unlock_bh(lgr_lock);
|
||||
}
|
||||
|
||||
/* terminate linkgroup abnormally */
|
||||
static void smc_sk_wake_ups(struct smc_sock *smc)
|
||||
{
|
||||
smc->sk.sk_write_space(&smc->sk);
|
||||
smc->sk.sk_data_ready(&smc->sk);
|
||||
smc->sk.sk_state_change(&smc->sk);
|
||||
}
|
||||
|
||||
/* kill a connection */
|
||||
static void smc_conn_kill(struct smc_connection *conn)
|
||||
{
|
||||
struct smc_sock *smc = container_of(conn, struct smc_sock, conn);
|
||||
|
||||
smc_close_abort(conn);
|
||||
conn->killed = 1;
|
||||
smc_sk_wake_ups(smc);
|
||||
smc_lgr_unregister_conn(conn);
|
||||
smc->sk.sk_err = ECONNABORTED;
|
||||
smc_close_active_abort(smc);
|
||||
}
|
||||
|
||||
/* terminate link group */
|
||||
static void __smc_lgr_terminate(struct smc_link_group *lgr)
|
||||
{
|
||||
struct smc_connection *conn;
|
||||
|
@ -489,55 +532,65 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr)
|
|||
if (lgr->terminating)
|
||||
return; /* lgr already terminating */
|
||||
lgr->terminating = 1;
|
||||
if (!list_empty(&lgr->list)) /* forget lgr */
|
||||
list_del_init(&lgr->list);
|
||||
if (!lgr->is_smcd)
|
||||
smc_llc_link_inactive(&lgr->lnk[SMC_SINGLE_LINK]);
|
||||
|
||||
write_lock_bh(&lgr->conns_lock);
|
||||
/* kill remaining link group connections */
|
||||
read_lock_bh(&lgr->conns_lock);
|
||||
node = rb_first(&lgr->conns_all);
|
||||
while (node) {
|
||||
read_unlock_bh(&lgr->conns_lock);
|
||||
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->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
|
||||
__smc_lgr_unregister_conn(conn);
|
||||
conn->lgr = NULL;
|
||||
write_unlock_bh(&lgr->conns_lock);
|
||||
if (!schedule_work(&conn->close_work))
|
||||
sock_put(&smc->sk);
|
||||
write_lock_bh(&lgr->conns_lock);
|
||||
sock_hold(&smc->sk); /* sock_put below */
|
||||
lock_sock(&smc->sk);
|
||||
smc_conn_kill(conn);
|
||||
release_sock(&smc->sk);
|
||||
sock_put(&smc->sk); /* sock_hold above */
|
||||
read_lock_bh(&lgr->conns_lock);
|
||||
node = rb_first(&lgr->conns_all);
|
||||
}
|
||||
write_unlock_bh(&lgr->conns_lock);
|
||||
read_unlock_bh(&lgr->conns_lock);
|
||||
if (!lgr->is_smcd)
|
||||
wake_up(&lgr->lnk[SMC_SINGLE_LINK].wr_reg_wait);
|
||||
smc_lgr_schedule_free_work(lgr);
|
||||
smc_lgr_schedule_free_work_fast(lgr);
|
||||
}
|
||||
|
||||
/* unlink and terminate link group */
|
||||
void smc_lgr_terminate(struct smc_link_group *lgr)
|
||||
{
|
||||
spinlock_t *lgr_lock;
|
||||
|
||||
smc_lgr_list_head(lgr, &lgr_lock);
|
||||
spin_lock_bh(lgr_lock);
|
||||
__smc_lgr_terminate(lgr);
|
||||
if (lgr->terminating) {
|
||||
spin_unlock_bh(lgr_lock);
|
||||
return; /* lgr already terminating */
|
||||
}
|
||||
list_del_init(&lgr->list);
|
||||
spin_unlock_bh(lgr_lock);
|
||||
__smc_lgr_terminate(lgr);
|
||||
}
|
||||
|
||||
/* Called when IB port is terminated */
|
||||
void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport)
|
||||
{
|
||||
struct smc_link_group *lgr, *l;
|
||||
LIST_HEAD(lgr_free_list);
|
||||
|
||||
spin_lock_bh(&smc_lgr_list.lock);
|
||||
list_for_each_entry_safe(lgr, l, &smc_lgr_list.list, list) {
|
||||
if (!lgr->is_smcd &&
|
||||
lgr->lnk[SMC_SINGLE_LINK].smcibdev == smcibdev &&
|
||||
lgr->lnk[SMC_SINGLE_LINK].ibport == ibport)
|
||||
__smc_lgr_terminate(lgr);
|
||||
list_move(&lgr->list, &lgr_free_list);
|
||||
}
|
||||
spin_unlock_bh(&smc_lgr_list.lock);
|
||||
|
||||
list_for_each_entry_safe(lgr, l, &lgr_free_list, list) {
|
||||
list_del_init(&lgr->list);
|
||||
__smc_lgr_terminate(lgr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called when SMC-D device is terminated or peer is lost */
|
||||
|
@ -551,7 +604,6 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
|
|||
list_for_each_entry_safe(lgr, l, &dev->lgr_list, list) {
|
||||
if ((!peer_gid || lgr->peer_gid == peer_gid) &&
|
||||
(vlan == VLAN_VID_MASK || lgr->vlan_id == vlan)) {
|
||||
__smc_lgr_terminate(lgr);
|
||||
list_move(&lgr->list, &lgr_free_list);
|
||||
}
|
||||
}
|
||||
|
@ -560,6 +612,7 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
|
|||
/* cancel the regular free workers and actually free lgrs */
|
||||
list_for_each_entry_safe(lgr, l, &lgr_free_list, list) {
|
||||
list_del_init(&lgr->list);
|
||||
__smc_lgr_terminate(lgr);
|
||||
cancel_delayed_work_sync(&lgr->free_work);
|
||||
if (!peer_gid && vlan == VLAN_VID_MASK) /* dev terminated? */
|
||||
smc_ism_signal_shutdown(lgr);
|
||||
|
|
|
@ -202,8 +202,11 @@ struct smc_link_group {
|
|||
|
||||
u8 id[SMC_LGR_ID_SIZE]; /* unique lgr id */
|
||||
struct delayed_work free_work; /* delayed freeing of an lgr */
|
||||
struct work_struct terminate_work; /* abnormal lgr termination */
|
||||
u8 sync_err : 1; /* lgr no longer fits to peer */
|
||||
u8 terminating : 1;/* lgr is terminating */
|
||||
u8 freefast : 1; /* free worker scheduled fast */
|
||||
u8 freeing : 1; /* lgr is being freed */
|
||||
|
||||
bool is_smcd; /* SMC-R or SMC-D */
|
||||
union {
|
||||
|
@ -280,6 +283,12 @@ static inline struct smc_connection *smc_lgr_find_conn(
|
|||
return res;
|
||||
}
|
||||
|
||||
static inline void smc_lgr_terminate_sched(struct smc_link_group *lgr)
|
||||
{
|
||||
if (!lgr->terminating)
|
||||
schedule_work(&lgr->terminate_work);
|
||||
}
|
||||
|
||||
struct smc_sock;
|
||||
struct smc_clc_msg_accept_confirm;
|
||||
struct smc_clc_msg_local;
|
||||
|
|
|
@ -475,7 +475,7 @@ static void smc_llc_rx_delete_link(struct smc_link *link,
|
|||
smc_llc_prep_delete_link(llc, link, SMC_LLC_RESP, true);
|
||||
}
|
||||
smc_llc_send_message(link, llc, sizeof(*llc));
|
||||
smc_lgr_schedule_free_work_fast(lgr);
|
||||
smc_lgr_terminate_sched(lgr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -101,7 +101,7 @@ static inline void smc_wr_tx_process_cqe(struct ib_wc *wc)
|
|||
clear_bit(i, link->wr_tx_mask);
|
||||
}
|
||||
/* terminate connections of this link group abnormally */
|
||||
smc_lgr_terminate(smc_get_lgr(link));
|
||||
smc_lgr_terminate_sched(smc_get_lgr(link));
|
||||
}
|
||||
if (pnd_snd.handler)
|
||||
pnd_snd.handler(&pnd_snd.priv, link, wc->status);
|
||||
|
@ -191,7 +191,7 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
|
|||
SMC_WR_TX_WAIT_FREE_SLOT_TIME);
|
||||
if (!rc) {
|
||||
/* timeout - terminate connections */
|
||||
smc_lgr_terminate(smc_get_lgr(link));
|
||||
smc_lgr_terminate_sched(smc_get_lgr(link));
|
||||
return -EPIPE;
|
||||
}
|
||||
if (idx == link->wr_tx_cnt)
|
||||
|
@ -247,7 +247,7 @@ int smc_wr_tx_send(struct smc_link *link, struct smc_wr_tx_pend_priv *priv)
|
|||
rc = ib_post_send(link->roce_qp, &link->wr_tx_ibs[pend->idx], NULL);
|
||||
if (rc) {
|
||||
smc_wr_tx_put_slot(link, priv);
|
||||
smc_lgr_terminate(smc_get_lgr(link));
|
||||
smc_lgr_terminate_sched(smc_get_lgr(link));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ int smc_wr_reg_send(struct smc_link *link, struct ib_mr *mr)
|
|||
SMC_WR_REG_MR_WAIT_TIME);
|
||||
if (!rc) {
|
||||
/* timeout - terminate connections */
|
||||
smc_lgr_terminate(smc_get_lgr(link));
|
||||
smc_lgr_terminate_sched(smc_get_lgr(link));
|
||||
return -EPIPE;
|
||||
}
|
||||
if (rc == -ERESTARTSYS)
|
||||
|
@ -373,7 +373,7 @@ static inline void smc_wr_rx_process_cqes(struct ib_wc wc[], int num)
|
|||
/* terminate connections of this link group
|
||||
* abnormally
|
||||
*/
|
||||
smc_lgr_terminate(smc_get_lgr(link));
|
||||
smc_lgr_terminate_sched(smc_get_lgr(link));
|
||||
break;
|
||||
default:
|
||||
smc_wr_rx_post(link); /* refill WR RX */
|
||||
|
|
Загрузка…
Ссылка в новой задаче