Skip to content

Commit 2a0674f

Browse files
Ursula BraunJakub Kicinski
authored andcommitted
net/smc: improve abnormal termination of link groups
If a link group and its connections must be terminated, * wake up socket waiters * do not enable buffer reuse A linkgroup might be terminated while normal connection closing is running. Avoid buffer reuse and its related LLC DELETE RKEY call, if linkgroup termination has started. And use the earliest indication of linkgroup termination possible, namely the removal from the linkgroup list. Signed-off-by: Ursula Braun <[email protected]> Signed-off-by: Karsten Graul <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 8317976 commit 2a0674f

File tree

1 file changed

+29
-11
lines changed

1 file changed

+29
-11
lines changed

net/smc/smc_core.c

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ static void smc_lgr_unregister_conn(struct smc_connection *conn)
154154
__smc_lgr_unregister_conn(conn);
155155
}
156156
write_unlock_bh(&lgr->conns_lock);
157+
conn->lgr = NULL;
157158
}
158159

159160
/* Send delete link, either as client to request the initiation
@@ -344,7 +345,7 @@ static void smc_buf_unuse(struct smc_connection *conn,
344345
conn->sndbuf_desc->used = 0;
345346
if (conn->rmb_desc) {
346347
if (!conn->rmb_desc->regerr) {
347-
if (!lgr->is_smcd) {
348+
if (!lgr->is_smcd && !list_empty(&lgr->list)) {
348349
/* unregister rmb with peer */
349350
smc_llc_do_delete_rkey(
350351
&lgr->lnk[SMC_SINGLE_LINK],
@@ -375,9 +376,10 @@ void smc_conn_free(struct smc_connection *conn)
375376
} else {
376377
smc_cdc_tx_dismiss_slots(conn);
377378
}
378-
smc_lgr_unregister_conn(conn);
379-
smc_buf_unuse(conn, lgr); /* allow buffer reuse */
380-
conn->lgr = NULL;
379+
if (!list_empty(&lgr->list)) {
380+
smc_lgr_unregister_conn(conn);
381+
smc_buf_unuse(conn, lgr); /* allow buffer reuse */
382+
}
381383

382384
if (!lgr->conns_num)
383385
smc_lgr_schedule_free_work(lgr);
@@ -491,6 +493,28 @@ void smc_lgr_forget(struct smc_link_group *lgr)
491493
spin_unlock_bh(lgr_lock);
492494
}
493495

496+
static void smc_sk_wake_ups(struct smc_sock *smc)
497+
{
498+
smc->sk.sk_write_space(&smc->sk);
499+
smc->sk.sk_data_ready(&smc->sk);
500+
smc->sk.sk_state_change(&smc->sk);
501+
}
502+
503+
/* kill a connection */
504+
static void smc_conn_kill(struct smc_connection *conn)
505+
{
506+
struct smc_sock *smc = container_of(conn, struct smc_sock, conn);
507+
508+
smc_close_abort(conn);
509+
conn->killed = 1;
510+
smc_sk_wake_ups(smc);
511+
smc_lgr_unregister_conn(conn);
512+
smc->sk.sk_err = ECONNABORTED;
513+
sock_hold(&smc->sk); /* sock_put in close work */
514+
if (!schedule_work(&conn->close_work))
515+
sock_put(&smc->sk);
516+
}
517+
494518
/* terminate link group */
495519
static void __smc_lgr_terminate(struct smc_link_group *lgr)
496520
{
@@ -512,13 +536,7 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr)
512536
conn = rb_entry(node, struct smc_connection, alert_node);
513537
smc = container_of(conn, struct smc_sock, conn);
514538
lock_sock(&smc->sk);
515-
sock_hold(&smc->sk); /* sock_put in close work */
516-
smc_close_abort(conn);
517-
conn->killed = 1;
518-
smc_lgr_unregister_conn(conn);
519-
conn->lgr = NULL;
520-
if (!schedule_work(&conn->close_work))
521-
sock_put(&smc->sk);
539+
smc_conn_kill(conn);
522540
release_sock(&smc->sk);
523541
read_lock_bh(&lgr->conns_lock);
524542
node = rb_first(&lgr->conns_all);

0 commit comments

Comments
 (0)