Skip to content

Commit a98bf8c

Browse files
Ursula Braundavem330
authored andcommitted
net/smc: guarantee ConnClosed send after shutdown SHUT_WR
State SMC_CLOSED should be reached only, if ConnClosed has been sent to the peer. If ConnClosed is received from the peer, a socket with shutdown SHUT_WR done, switches errorneously to state SMC_CLOSED, which means the peer socket is dangling. The local SMC socket is supposed to switch to state APPFINCLOSEWAIT to make sure smc_close_final() is called during socket close. Signed-off-by: Ursula Braun <[email protected]> Reviewed-by: Thomas Richter <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 46c28db commit a98bf8c

File tree

1 file changed

+25
-11
lines changed

1 file changed

+25
-11
lines changed

net/smc/smc_close.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,12 @@ void smc_close_active_abort(struct smc_sock *smc)
164164
smc->sk.sk_state_change(&smc->sk);
165165
}
166166

167+
static inline bool smc_close_sent_any_close(struct smc_connection *conn)
168+
{
169+
return conn->local_tx_ctrl.conn_state_flags.peer_conn_abort ||
170+
conn->local_tx_ctrl.conn_state_flags.peer_conn_closed;
171+
}
172+
167173
int smc_close_active(struct smc_sock *smc)
168174
{
169175
struct smc_cdc_conn_state_flags *txflags =
@@ -217,7 +223,7 @@ int smc_close_active(struct smc_sock *smc)
217223
case SMC_APPFINCLOSEWAIT:
218224
/* socket already shutdown wr or both (active close) */
219225
if (txflags->peer_done_writing &&
220-
!txflags->peer_conn_closed) {
226+
!smc_close_sent_any_close(conn)) {
221227
/* just shutdown wr done, send close request */
222228
rc = smc_close_final(conn);
223229
}
@@ -247,6 +253,13 @@ int smc_close_active(struct smc_sock *smc)
247253
break;
248254
case SMC_PEERCLOSEWAIT1:
249255
case SMC_PEERCLOSEWAIT2:
256+
if (txflags->peer_done_writing &&
257+
!smc_close_sent_any_close(conn)) {
258+
/* just shutdown wr done, send close request */
259+
rc = smc_close_final(conn);
260+
}
261+
/* peer sending PeerConnectionClosed will cause transition */
262+
break;
250263
case SMC_PEERFINCLOSEWAIT:
251264
/* peer sending PeerConnectionClosed will cause transition */
252265
break;
@@ -284,7 +297,7 @@ static void smc_close_passive_abort_received(struct smc_sock *smc)
284297
case SMC_PEERCLOSEWAIT1:
285298
case SMC_PEERCLOSEWAIT2:
286299
if (txflags->peer_done_writing &&
287-
!txflags->peer_conn_closed) {
300+
!smc_close_sent_any_close(&smc->conn)) {
288301
/* just shutdown, but not yet closed locally */
289302
smc_close_abort(&smc->conn);
290303
sk->sk_state = SMC_PROCESSABORT;
@@ -335,7 +348,7 @@ static void smc_close_passive_work(struct work_struct *work)
335348
case SMC_INIT:
336349
if (atomic_read(&smc->conn.bytes_to_rcv) ||
337350
(rxflags->peer_done_writing &&
338-
!rxflags->peer_conn_closed))
351+
!smc_cdc_rxed_any_close(conn)))
339352
sk->sk_state = SMC_APPCLOSEWAIT1;
340353
else
341354
sk->sk_state = SMC_CLOSED;
@@ -352,7 +365,7 @@ static void smc_close_passive_work(struct work_struct *work)
352365
if (!smc_cdc_rxed_any_close(&smc->conn))
353366
break;
354367
if (sock_flag(sk, SOCK_DEAD) &&
355-
(sk->sk_shutdown == SHUTDOWN_MASK)) {
368+
smc_close_sent_any_close(conn)) {
356369
/* smc_release has already been called locally */
357370
sk->sk_state = SMC_CLOSED;
358371
} else {
@@ -371,16 +384,17 @@ static void smc_close_passive_work(struct work_struct *work)
371384
}
372385

373386
wakeup:
374-
if (old_state != sk->sk_state)
375-
sk->sk_state_change(sk);
376387
sk->sk_data_ready(sk); /* wakeup blocked rcvbuf consumers */
377388
sk->sk_write_space(sk); /* wakeup blocked sndbuf producers */
378389

379-
if ((sk->sk_state == SMC_CLOSED) &&
380-
(sock_flag(sk, SOCK_DEAD) || !sk->sk_socket)) {
381-
smc_conn_free(&smc->conn);
382-
schedule_delayed_work(&smc->sock_put_work,
383-
SMC_CLOSE_SOCK_PUT_DELAY);
390+
if (old_state != sk->sk_state) {
391+
sk->sk_state_change(sk);
392+
if ((sk->sk_state == SMC_CLOSED) &&
393+
(sock_flag(sk, SOCK_DEAD) || !sk->sk_socket)) {
394+
smc_conn_free(&smc->conn);
395+
schedule_delayed_work(&smc->sock_put_work,
396+
SMC_CLOSE_SOCK_PUT_DELAY);
397+
}
384398
}
385399
release_sock(&smc->sk);
386400
}

0 commit comments

Comments
 (0)