Skip to content

Commit 627642f

Browse files
committed
Merge branch 'net-smc-add-failover-processing'
Karsten Graul says: ==================== net/smc: add failover processing This patch series adds the actual SMC-R link failover processing and improved link group termination. There will be one more (very small) series after this which will complete the SMC-R link failover support. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents fc99584 + 649758f commit 627642f

File tree

11 files changed

+514
-75
lines changed

11 files changed

+514
-75
lines changed

net/smc/af_smc.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ static int smcr_clnt_conf_first_link(struct smc_sock *smc)
390390
SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
391391
return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_CL : rc;
392392
}
393+
smc_llc_save_peer_uid(qentry);
393394
rc = smc_llc_eval_conf_link(qentry, SMC_LLC_REQ);
394395
smc_llc_flow_qentry_del(&link->lgr->llc_flow_lcl);
395396
if (rc)
@@ -1056,6 +1057,7 @@ static int smcr_serv_conf_first_link(struct smc_sock *smc)
10561057
SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
10571058
return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_CL : rc;
10581059
}
1060+
smc_llc_save_peer_uid(qentry);
10591061
rc = smc_llc_eval_conf_link(qentry, SMC_LLC_RESP);
10601062
smc_llc_flow_qentry_del(&link->lgr->llc_flow_lcl);
10611063
if (rc)

net/smc/smc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ struct smc_connection {
143143
* .prod cf. TCP snd_nxt
144144
* .cons cf. TCP sends ack
145145
*/
146+
union smc_host_cursor local_tx_ctrl_fin;
147+
/* prod crsr - confirmed by peer
148+
*/
146149
union smc_host_cursor tx_curs_prep; /* tx - prepared data
147150
* snd_max..wmem_alloc
148151
*/
@@ -154,6 +157,7 @@ struct smc_connection {
154157
*/
155158
atomic_t sndbuf_space; /* remaining space in sndbuf */
156159
u16 tx_cdc_seq; /* sequence # for CDC send */
160+
u16 tx_cdc_seq_fin; /* sequence # - tx completed */
157161
spinlock_t send_lock; /* protect wr_sends */
158162
struct delayed_work tx_work; /* retry of smc_cdc_msg_send */
159163
u32 tx_off; /* base offset in peer rmb */
@@ -184,12 +188,14 @@ struct smc_connection {
184188
spinlock_t acurs_lock; /* protect cursors */
185189
#endif
186190
struct work_struct close_work; /* peer sent some closing */
191+
struct work_struct abort_work; /* abort the connection */
187192
struct tasklet_struct rx_tsklet; /* Receiver tasklet for SMC-D */
188193
u8 rx_off; /* receive offset:
189194
* 0 for SMC-R, 32 for SMC-D
190195
*/
191196
u64 peer_token; /* SMC-D token of peer */
192197
u8 killed : 1; /* abnormal termination */
198+
u8 out_of_sync : 1; /* out of sync with peer */
193199
};
194200

195201
struct smc_sock { /* smc sock container */

net/smc/smc_cdc.c

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,20 @@ static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd,
4747
/* guarantee 0 <= sndbuf_space <= sndbuf_desc->len */
4848
smp_mb__after_atomic();
4949
smc_curs_copy(&conn->tx_curs_fin, &cdcpend->cursor, conn);
50+
smc_curs_copy(&conn->local_tx_ctrl_fin, &cdcpend->p_cursor,
51+
conn);
52+
conn->tx_cdc_seq_fin = cdcpend->ctrl_seq;
5053
}
5154
smc_tx_sndbuf_nonfull(smc);
5255
bh_unlock_sock(&smc->sk);
5356
}
5457

5558
int smc_cdc_get_free_slot(struct smc_connection *conn,
59+
struct smc_link *link,
5660
struct smc_wr_buf **wr_buf,
5761
struct smc_rdma_wr **wr_rdma_buf,
5862
struct smc_cdc_tx_pend **pend)
5963
{
60-
struct smc_link *link = conn->lnk;
6164
int rc;
6265

6366
rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf,
@@ -104,22 +107,64 @@ int smc_cdc_msg_send(struct smc_connection *conn,
104107
if (!rc) {
105108
smc_curs_copy(&conn->rx_curs_confirmed, &cfed, conn);
106109
conn->local_rx_ctrl.prod_flags.cons_curs_upd_req = 0;
110+
} else {
111+
conn->tx_cdc_seq--;
112+
conn->local_tx_ctrl.seqno = conn->tx_cdc_seq;
107113
}
108114

109115
return rc;
110116
}
111117

118+
/* send a validation msg indicating the move of a conn to an other QP link */
119+
int smcr_cdc_msg_send_validation(struct smc_connection *conn)
120+
{
121+
struct smc_host_cdc_msg *local = &conn->local_tx_ctrl;
122+
struct smc_link *link = conn->lnk;
123+
struct smc_cdc_tx_pend *pend;
124+
struct smc_wr_buf *wr_buf;
125+
struct smc_cdc_msg *peer;
126+
int rc;
127+
128+
rc = smc_cdc_get_free_slot(conn, link, &wr_buf, NULL, &pend);
129+
if (rc)
130+
return rc;
131+
132+
peer = (struct smc_cdc_msg *)wr_buf;
133+
peer->common.type = local->common.type;
134+
peer->len = local->len;
135+
peer->seqno = htons(conn->tx_cdc_seq_fin); /* seqno last compl. tx */
136+
peer->token = htonl(local->token);
137+
peer->prod_flags.failover_validation = 1;
138+
139+
rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend);
140+
return rc;
141+
}
142+
112143
static int smcr_cdc_get_slot_and_msg_send(struct smc_connection *conn)
113144
{
114145
struct smc_cdc_tx_pend *pend;
115146
struct smc_wr_buf *wr_buf;
147+
struct smc_link *link;
148+
bool again = false;
116149
int rc;
117150

118-
rc = smc_cdc_get_free_slot(conn, &wr_buf, NULL, &pend);
151+
again:
152+
link = conn->lnk;
153+
rc = smc_cdc_get_free_slot(conn, link, &wr_buf, NULL, &pend);
119154
if (rc)
120155
return rc;
121156

122157
spin_lock_bh(&conn->send_lock);
158+
if (link != conn->lnk) {
159+
/* link of connection changed, try again one time*/
160+
spin_unlock_bh(&conn->send_lock);
161+
smc_wr_tx_put_slot(link,
162+
(struct smc_wr_tx_pend_priv *)pend);
163+
if (again)
164+
return -ENOLINK;
165+
again = true;
166+
goto again;
167+
}
123168
rc = smc_cdc_msg_send(conn, wr_buf, pend);
124169
spin_unlock_bh(&conn->send_lock);
125170
return rc;
@@ -237,6 +282,28 @@ static void smc_cdc_handle_urg_data_arrival(struct smc_sock *smc,
237282
sk_send_sigurg(&smc->sk);
238283
}
239284

285+
static void smc_cdc_msg_validate(struct smc_sock *smc, struct smc_cdc_msg *cdc,
286+
struct smc_link *link)
287+
{
288+
struct smc_connection *conn = &smc->conn;
289+
u16 recv_seq = ntohs(cdc->seqno);
290+
s16 diff;
291+
292+
/* check that seqnum was seen before */
293+
diff = conn->local_rx_ctrl.seqno - recv_seq;
294+
if (diff < 0) { /* diff larger than 0x7fff */
295+
/* drop connection */
296+
conn->out_of_sync = 1; /* prevent any further receives */
297+
spin_lock_bh(&conn->send_lock);
298+
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
299+
conn->lnk = link;
300+
spin_unlock_bh(&conn->send_lock);
301+
sock_hold(&smc->sk); /* sock_put in abort_work */
302+
if (!schedule_work(&conn->abort_work))
303+
sock_put(&smc->sk);
304+
}
305+
}
306+
240307
static void smc_cdc_msg_recv_action(struct smc_sock *smc,
241308
struct smc_cdc_msg *cdc)
242309
{
@@ -367,16 +434,19 @@ static void smc_cdc_rx_handler(struct ib_wc *wc, void *buf)
367434
read_lock_bh(&lgr->conns_lock);
368435
conn = smc_lgr_find_conn(ntohl(cdc->token), lgr);
369436
read_unlock_bh(&lgr->conns_lock);
370-
if (!conn)
437+
if (!conn || conn->out_of_sync)
371438
return;
372439
smc = container_of(conn, struct smc_sock, conn);
373440

374-
if (!cdc->prod_flags.failover_validation) {
375-
if (smc_cdc_before(ntohs(cdc->seqno),
376-
conn->local_rx_ctrl.seqno))
377-
/* received seqno is old */
378-
return;
441+
if (cdc->prod_flags.failover_validation) {
442+
smc_cdc_msg_validate(smc, cdc, link);
443+
return;
379444
}
445+
if (smc_cdc_before(ntohs(cdc->seqno),
446+
conn->local_rx_ctrl.seqno))
447+
/* received seqno is old */
448+
return;
449+
380450
smc_cdc_msg_recv(smc, cdc);
381451
}
382452

net/smc/smc_cdc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ struct smc_cdc_tx_pend {
304304
};
305305

306306
int smc_cdc_get_free_slot(struct smc_connection *conn,
307+
struct smc_link *link,
307308
struct smc_wr_buf **wr_buf,
308309
struct smc_rdma_wr **wr_rdma_buf,
309310
struct smc_cdc_tx_pend **pend);
@@ -312,6 +313,7 @@ int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf,
312313
struct smc_cdc_tx_pend *pend);
313314
int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn);
314315
int smcd_cdc_msg_send(struct smc_connection *conn);
316+
int smcr_cdc_msg_send_validation(struct smc_connection *conn);
315317
int smc_cdc_init(void) __init;
316318
void smcd_cdc_rx_init(struct smc_connection *conn);
317319

0 commit comments

Comments
 (0)