diff options
Diffstat (limited to 'net/smc/smc_close.c')
-rw-r--r-- | net/smc/smc_close.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/net/smc/smc_close.c b/net/smc/smc_close.c index 2ad37e998509..fc06720b53c1 100644 --- a/net/smc/smc_close.c +++ b/net/smc/smc_close.c | |||
@@ -21,6 +21,22 @@ | |||
21 | 21 | ||
22 | #define SMC_CLOSE_WAIT_LISTEN_CLCSOCK_TIME (5 * HZ) | 22 | #define SMC_CLOSE_WAIT_LISTEN_CLCSOCK_TIME (5 * HZ) |
23 | 23 | ||
24 | /* release the clcsock that is assigned to the smc_sock */ | ||
25 | void smc_clcsock_release(struct smc_sock *smc) | ||
26 | { | ||
27 | struct socket *tcp; | ||
28 | |||
29 | if (smc->listen_smc && current_work() != &smc->smc_listen_work) | ||
30 | cancel_work_sync(&smc->smc_listen_work); | ||
31 | mutex_lock(&smc->clcsock_release_lock); | ||
32 | if (smc->clcsock) { | ||
33 | tcp = smc->clcsock; | ||
34 | smc->clcsock = NULL; | ||
35 | sock_release(tcp); | ||
36 | } | ||
37 | mutex_unlock(&smc->clcsock_release_lock); | ||
38 | } | ||
39 | |||
24 | static void smc_close_cleanup_listen(struct sock *parent) | 40 | static void smc_close_cleanup_listen(struct sock *parent) |
25 | { | 41 | { |
26 | struct sock *sk; | 42 | struct sock *sk; |
@@ -321,6 +337,7 @@ static void smc_close_passive_work(struct work_struct *work) | |||
321 | close_work); | 337 | close_work); |
322 | struct smc_sock *smc = container_of(conn, struct smc_sock, conn); | 338 | struct smc_sock *smc = container_of(conn, struct smc_sock, conn); |
323 | struct smc_cdc_conn_state_flags *rxflags; | 339 | struct smc_cdc_conn_state_flags *rxflags; |
340 | bool release_clcsock = false; | ||
324 | struct sock *sk = &smc->sk; | 341 | struct sock *sk = &smc->sk; |
325 | int old_state; | 342 | int old_state; |
326 | 343 | ||
@@ -400,13 +417,13 @@ wakeup: | |||
400 | if ((sk->sk_state == SMC_CLOSED) && | 417 | if ((sk->sk_state == SMC_CLOSED) && |
401 | (sock_flag(sk, SOCK_DEAD) || !sk->sk_socket)) { | 418 | (sock_flag(sk, SOCK_DEAD) || !sk->sk_socket)) { |
402 | smc_conn_free(conn); | 419 | smc_conn_free(conn); |
403 | if (smc->clcsock) { | 420 | if (smc->clcsock) |
404 | sock_release(smc->clcsock); | 421 | release_clcsock = true; |
405 | smc->clcsock = NULL; | ||
406 | } | ||
407 | } | 422 | } |
408 | } | 423 | } |
409 | release_sock(sk); | 424 | release_sock(sk); |
425 | if (release_clcsock) | ||
426 | smc_clcsock_release(smc); | ||
410 | sock_put(sk); /* sock_hold done by schedulers of close_work */ | 427 | sock_put(sk); /* sock_hold done by schedulers of close_work */ |
411 | } | 428 | } |
412 | 429 | ||