Skip to content

Commit bbb96bf

Browse files
Ursula Braundavem330
authored andcommitted
net/smc: improve state change handling after close wait
When a socket is closed or shutdown, smc waits for data being transmitted in certain states. If the state changes during this wait, the close switch depending on state should be reentered. In addition, state change is avoided if sending of close or shutdown fails. Signed-off-by: Ursula Braun <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 86e780d commit bbb96bf

File tree

1 file changed

+26
-14
lines changed

1 file changed

+26
-14
lines changed

net/smc/smc_close.c

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,9 @@ int smc_close_active(struct smc_sock *smc)
165165
0 : sock_flag(sk, SOCK_LINGER) ?
166166
sk->sk_lingertime : SMC_MAX_STREAM_WAIT_TIMEOUT;
167167

168-
again:
169168
old_state = sk->sk_state;
170-
switch (old_state) {
169+
again:
170+
switch (sk->sk_state) {
171171
case SMC_INIT:
172172
sk->sk_state = SMC_CLOSED;
173173
if (smc->smc_listen_work.func)
@@ -194,6 +194,8 @@ int smc_close_active(struct smc_sock *smc)
194194
if (sk->sk_state == SMC_ACTIVE) {
195195
/* send close request */
196196
rc = smc_close_final(conn);
197+
if (rc)
198+
break;
197199
sk->sk_state = SMC_PEERCLOSEWAIT1;
198200
} else {
199201
/* peer event has changed the state */
@@ -206,6 +208,8 @@ int smc_close_active(struct smc_sock *smc)
206208
!smc_close_sent_any_close(conn)) {
207209
/* just shutdown wr done, send close request */
208210
rc = smc_close_final(conn);
211+
if (rc)
212+
break;
209213
}
210214
sk->sk_state = SMC_CLOSED;
211215
break;
@@ -216,12 +220,13 @@ int smc_close_active(struct smc_sock *smc)
216220
release_sock(sk);
217221
cancel_delayed_work_sync(&conn->tx_work);
218222
lock_sock(sk);
219-
if (sk->sk_err != ECONNABORTED) {
220-
/* confirm close from peer */
221-
rc = smc_close_final(conn);
222-
if (rc)
223-
break;
224-
}
223+
if (sk->sk_state != SMC_APPCLOSEWAIT1 &&
224+
sk->sk_state != SMC_APPCLOSEWAIT2)
225+
goto again;
226+
/* confirm close from peer */
227+
rc = smc_close_final(conn);
228+
if (rc)
229+
break;
225230
if (smc_cdc_rxed_any_close(conn))
226231
/* peer has closed the socket already */
227232
sk->sk_state = SMC_CLOSED;
@@ -235,6 +240,8 @@ int smc_close_active(struct smc_sock *smc)
235240
!smc_close_sent_any_close(conn)) {
236241
/* just shutdown wr done, send close request */
237242
rc = smc_close_final(conn);
243+
if (rc)
244+
break;
238245
}
239246
/* peer sending PeerConnectionClosed will cause transition */
240247
break;
@@ -401,20 +408,21 @@ int smc_close_shutdown_write(struct smc_sock *smc)
401408
0 : sock_flag(sk, SOCK_LINGER) ?
402409
sk->sk_lingertime : SMC_MAX_STREAM_WAIT_TIMEOUT;
403410

404-
again:
405411
old_state = sk->sk_state;
406-
switch (old_state) {
412+
again:
413+
switch (sk->sk_state) {
407414
case SMC_ACTIVE:
408415
smc_close_stream_wait(smc, timeout);
409416
release_sock(sk);
410417
cancel_delayed_work_sync(&conn->tx_work);
411418
lock_sock(sk);
419+
if (sk->sk_state != SMC_ACTIVE)
420+
goto again;
412421
/* send close wr request */
413422
rc = smc_close_wr(conn);
414-
if (sk->sk_state == SMC_ACTIVE)
415-
sk->sk_state = SMC_PEERCLOSEWAIT1;
416-
else
417-
goto again;
423+
if (rc)
424+
break;
425+
sk->sk_state = SMC_PEERCLOSEWAIT1;
418426
break;
419427
case SMC_APPCLOSEWAIT1:
420428
/* passive close */
@@ -423,8 +431,12 @@ int smc_close_shutdown_write(struct smc_sock *smc)
423431
release_sock(sk);
424432
cancel_delayed_work_sync(&conn->tx_work);
425433
lock_sock(sk);
434+
if (sk->sk_state != SMC_APPCLOSEWAIT1)
435+
goto again;
426436
/* confirm close from peer */
427437
rc = smc_close_wr(conn);
438+
if (rc)
439+
break;
428440
sk->sk_state = SMC_APPCLOSEWAIT2;
429441
break;
430442
case SMC_APPCLOSEWAIT2:

0 commit comments

Comments
 (0)