@@ -47,17 +47,20 @@ static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd,
47
47
/* guarantee 0 <= sndbuf_space <= sndbuf_desc->len */
48
48
smp_mb__after_atomic ();
49
49
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 ;
50
53
}
51
54
smc_tx_sndbuf_nonfull (smc );
52
55
bh_unlock_sock (& smc -> sk );
53
56
}
54
57
55
58
int smc_cdc_get_free_slot (struct smc_connection * conn ,
59
+ struct smc_link * link ,
56
60
struct smc_wr_buf * * wr_buf ,
57
61
struct smc_rdma_wr * * wr_rdma_buf ,
58
62
struct smc_cdc_tx_pend * * pend )
59
63
{
60
- struct smc_link * link = conn -> lnk ;
61
64
int rc ;
62
65
63
66
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,
104
107
if (!rc ) {
105
108
smc_curs_copy (& conn -> rx_curs_confirmed , & cfed , conn );
106
109
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 ;
107
113
}
108
114
109
115
return rc ;
110
116
}
111
117
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
+
112
143
static int smcr_cdc_get_slot_and_msg_send (struct smc_connection * conn )
113
144
{
114
145
struct smc_cdc_tx_pend * pend ;
115
146
struct smc_wr_buf * wr_buf ;
147
+ struct smc_link * link ;
148
+ bool again = false;
116
149
int rc ;
117
150
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 );
119
154
if (rc )
120
155
return rc ;
121
156
122
157
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
+ }
123
168
rc = smc_cdc_msg_send (conn , wr_buf , pend );
124
169
spin_unlock_bh (& conn -> send_lock );
125
170
return rc ;
@@ -237,6 +282,28 @@ static void smc_cdc_handle_urg_data_arrival(struct smc_sock *smc,
237
282
sk_send_sigurg (& smc -> sk );
238
283
}
239
284
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
+
240
307
static void smc_cdc_msg_recv_action (struct smc_sock * smc ,
241
308
struct smc_cdc_msg * cdc )
242
309
{
@@ -367,16 +434,19 @@ static void smc_cdc_rx_handler(struct ib_wc *wc, void *buf)
367
434
read_lock_bh (& lgr -> conns_lock );
368
435
conn = smc_lgr_find_conn (ntohl (cdc -> token ), lgr );
369
436
read_unlock_bh (& lgr -> conns_lock );
370
- if (!conn )
437
+ if (!conn || conn -> out_of_sync )
371
438
return ;
372
439
smc = container_of (conn , struct smc_sock , conn );
373
440
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 ;
379
444
}
445
+ if (smc_cdc_before (ntohs (cdc -> seqno ),
446
+ conn -> local_rx_ctrl .seqno ))
447
+ /* received seqno is old */
448
+ return ;
449
+
380
450
smc_cdc_msg_recv (smc , cdc );
381
451
}
382
452
0 commit comments