net/smc: unlock LGR pending lock earlier for SMC-D
authorHans Wippel <hwippel@linux.ibm.com>
Thu, 7 Feb 2019 14:56:17 +0000 (15:56 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 8 Feb 2019 02:06:18 +0000 (18:06 -0800)
If SMC client and server connections are both established at the same
time, smc_connect_ism() cannot send a CLC confirm message while
smc_listen_work() is waiting for one due to lock contention. This can
result in timeouts in smc_clc_wait_msg() and failed SMC connections.

In case of SMC-D, the LGR pending lock is not needed while
smc_listen_work() is waiting for the CLC confirm message. So, this patch
releases the lock earlier for SMC-D to avoid the locking issue.

Signed-off-by: Hans Wippel <hwippel@linux.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/smc/af_smc.c

index 60ccc8f50368f61aa48e4078ef2eceee90257cb5..cf49ed05007bde06221f501db0fabce1af6c1c2b 100644 (file)
@@ -1287,24 +1287,28 @@ static void smc_listen_work(struct work_struct *work)
                return;
        }
 
+       /* SMC-D does not need this lock any more */
+       if (ism_supported)
+               mutex_unlock(&smc_create_lgr_pending);
+
        /* receive SMC Confirm CLC message */
        reason_code = smc_clc_wait_msg(new_smc, &cclc, sizeof(cclc),
                                       SMC_CLC_CONFIRM, CLC_WAIT_TIME);
        if (reason_code) {
-               mutex_unlock(&smc_create_lgr_pending);
+               if (!ism_supported)
+                       mutex_unlock(&smc_create_lgr_pending);
                smc_listen_decline(new_smc, reason_code, local_contact);
                return;
        }
 
        /* finish worker */
        if (!ism_supported) {
-               if (smc_listen_rdma_finish(new_smc, &cclc, local_contact)) {
-                       mutex_unlock(&smc_create_lgr_pending);
+               rc = smc_listen_rdma_finish(new_smc, &cclc, local_contact);
+               mutex_unlock(&smc_create_lgr_pending);
+               if (rc)
                        return;
-               }
        }
        smc_conn_save_peer_info(new_smc, &cclc);
-       mutex_unlock(&smc_create_lgr_pending);
        smc_listen_out_connected(new_smc);
 }