diff options
author | Hans Wippel <hwippel@linux.ibm.com> | 2018-05-23 16:38:10 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-05-23 16:02:35 -0400 |
commit | b9f227c37071d1115cec791b328b684e2c4ba414 (patch) | |
tree | 4e9aa72c19e959194f004950d1c70c5969550fb7 /net | |
parent | 2351abe6f8736167a187cec867933bc66c3284c0 (diff) | |
download | linux-stable-b9f227c37071d1115cec791b328b684e2c4ba414.tar.gz linux-stable-b9f227c37071d1115cec791b328b684e2c4ba414.tar.bz2 linux-stable-b9f227c37071d1115cec791b328b684e2c4ba414.zip |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/smc/smc_core.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c index 1e5c0e90a706..21c244f53b0a 100644 --- a/net/smc/smc_core.c +++ b/net/smc/smc_core.c @@ -346,7 +346,7 @@ void smc_lgr_forget(struct smc_link_group *lgr) } /* 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; @@ -355,7 +355,8 @@ void smc_lgr_terminate(struct smc_link_group *lgr) 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); @@ -377,16 +378,25 @@ void smc_lgr_terminate(struct smc_link_group *lgr) 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. |