From: Stefan Raspl <raspl@linux.ibm.com>
Subject: net/smc: lock smc_lgr_list in port_terminate()
Patch-mainline: v4.18-rc1
Git-commit: b9f227c37071d1115cec791b328b684e2c4ba414
References: FATE#325694, LTC#167874, bsc#1113480
Summary: net/smc: SMC-R MVP
Description: Add latest upstream patches to push SMC-R to the MVP level
Upstream-Description:
net/smc: lock smc_lgr_list in port_terminate()
Currently, smc_port_terminate() is not holding the lock of the lgr list
while it is traversing the list. This patch adds locking to this
function and changes smc_lgr_terminate() accordingly.
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>
Signed-off-by: Stefan Raspl <raspl@linux.ibm.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
net/smc/smc_core.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
--- a/net/smc/smc_core.c
+++ b/net/smc/smc_core.c
@@ -345,7 +345,7 @@ void smc_lgr_forget(struct smc_link_grou
}
/* terminate linkgroup abnormally */
-void smc_lgr_terminate(struct smc_link_group *lgr)
+static void __smc_lgr_terminate(struct smc_link_group *lgr)
{
struct smc_connection *conn;
struct smc_sock *smc;
@@ -354,7 +354,8 @@ void smc_lgr_terminate(struct smc_link_g
if (lgr->terminating)
return; /* lgr already terminating */
lgr->terminating = 1;
- smc_lgr_forget(lgr);
+ if (!list_empty(&lgr->list)) /* forget lgr */
+ list_del_init(&lgr->list);
smc_llc_link_inactive(&lgr->lnk[SMC_SINGLE_LINK]);
write_lock_bh(&lgr->conns_lock);
@@ -376,16 +377,25 @@ void smc_lgr_terminate(struct smc_link_g
smc_lgr_schedule_free_work(lgr);
}
+void smc_lgr_terminate(struct smc_link_group *lgr)
+{
+ spin_lock_bh(&smc_lgr_list.lock);
+ __smc_lgr_terminate(lgr);
+ spin_unlock_bh(&smc_lgr_list.lock);
+}
+
/* Called when IB port is terminated */
void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport)
{
struct smc_link_group *lgr, *l;
+ spin_lock_bh(&smc_lgr_list.lock);
list_for_each_entry_safe(lgr, l, &smc_lgr_list.list, list) {
if (lgr->lnk[SMC_SINGLE_LINK].smcibdev == smcibdev &&
lgr->lnk[SMC_SINGLE_LINK].ibport == ibport)
- smc_lgr_terminate(lgr);
+ __smc_lgr_terminate(lgr);
}
+ spin_unlock_bh(&smc_lgr_list.lock);
}
/* Determine vlan of internal TCP socket.