Skip to content

Commit a0a62ee

Browse files
Ursula BraunJakub Kicinski
Ursula Braun
authored and
Jakub Kicinski
committed
net/smc: separate locks for SMCD and SMCR link group lists
This patch introduces separate locks for the split SMCD and SMCR link group lists. Signed-off-by: Ursula Braun <[email protected]> Signed-off-by: Karsten Graul <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent a2351c5 commit a0a62ee

File tree

3 files changed

+44
-15
lines changed

3 files changed

+44
-15
lines changed

include/net/smc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ struct smcd_dev {
7676
u8 pnetid[SMC_MAX_PNETID_LEN];
7777
bool pnetid_by_user;
7878
struct list_head lgr_list;
79+
spinlock_t lgr_lock;
7980
};
8081

8182
struct smcd_dev *smcd_alloc_dev(struct device *parent, const char *name,

net/smc/smc_core.c

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@ static struct smc_lgr_list smc_lgr_list = { /* established link groups */
4242
static void smc_buf_free(struct smc_link_group *lgr, bool is_rmb,
4343
struct smc_buf_desc *buf_desc);
4444

45+
/* return head of link group list and its lock for a given link group */
46+
static inline struct list_head *smc_lgr_list_head(struct smc_link_group *lgr,
47+
spinlock_t **lgr_lock)
48+
{
49+
if (lgr->is_smcd) {
50+
*lgr_lock = &lgr->smcd->lgr_lock;
51+
return &lgr->smcd->lgr_list;
52+
}
53+
54+
*lgr_lock = &smc_lgr_list.lock;
55+
return &smc_lgr_list.list;
56+
}
57+
4558
static void smc_lgr_schedule_free_work(struct smc_link_group *lgr)
4659
{
4760
/* client link group creation always follows the server link group
@@ -157,19 +170,21 @@ static void smc_lgr_free_work(struct work_struct *work)
157170
struct smc_link_group *lgr = container_of(to_delayed_work(work),
158171
struct smc_link_group,
159172
free_work);
173+
spinlock_t *lgr_lock;
160174
bool conns;
161175

162-
spin_lock_bh(&smc_lgr_list.lock);
176+
smc_lgr_list_head(lgr, &lgr_lock);
177+
spin_lock_bh(lgr_lock);
163178
read_lock_bh(&lgr->conns_lock);
164179
conns = RB_EMPTY_ROOT(&lgr->conns_all);
165180
read_unlock_bh(&lgr->conns_lock);
166181
if (!conns) { /* number of lgr connections is no longer zero */
167-
spin_unlock_bh(&smc_lgr_list.lock);
182+
spin_unlock_bh(lgr_lock);
168183
return;
169184
}
170185
if (!list_empty(&lgr->list))
171186
list_del_init(&lgr->list); /* remove from smc_lgr_list */
172-
spin_unlock_bh(&smc_lgr_list.lock);
187+
spin_unlock_bh(lgr_lock);
173188

174189
if (!lgr->is_smcd && !lgr->terminating) {
175190
struct smc_link *lnk = &lgr->lnk[SMC_SINGLE_LINK];
@@ -200,6 +215,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
200215
struct smc_link_group *lgr;
201216
struct list_head *lgr_list;
202217
struct smc_link *lnk;
218+
spinlock_t *lgr_lock;
203219
u8 rndvec[3];
204220
int rc = 0;
205221
int i;
@@ -235,6 +251,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
235251
lgr->peer_gid = ini->ism_gid;
236252
lgr->smcd = ini->ism_dev;
237253
lgr_list = &ini->ism_dev->lgr_list;
254+
lgr_lock = &lgr->smcd->lgr_lock;
238255
} else {
239256
/* SMC-R specific settings */
240257
lgr->role = smc->listen_smc ? SMC_SERV : SMC_CLNT;
@@ -248,6 +265,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
248265
lnk->smcibdev = ini->ib_dev;
249266
lnk->ibport = ini->ib_port;
250267
lgr_list = &smc_lgr_list.list;
268+
lgr_lock = &smc_lgr_list.lock;
251269
lnk->path_mtu =
252270
ini->ib_dev->pattr[ini->ib_port - 1].active_mtu;
253271
if (!ini->ib_dev->initialized)
@@ -277,9 +295,9 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
277295
goto destroy_qp;
278296
}
279297
smc->conn.lgr = lgr;
280-
spin_lock_bh(&smc_lgr_list.lock);
298+
spin_lock_bh(lgr_lock);
281299
list_add(&lgr->list, lgr_list);
282-
spin_unlock_bh(&smc_lgr_list.lock);
300+
spin_unlock_bh(lgr_lock);
283301
return 0;
284302

285303
destroy_qp:
@@ -442,11 +460,15 @@ static void smc_lgr_free(struct smc_link_group *lgr)
442460

443461
void smc_lgr_forget(struct smc_link_group *lgr)
444462
{
445-
spin_lock_bh(&smc_lgr_list.lock);
463+
struct list_head *lgr_list;
464+
spinlock_t *lgr_lock;
465+
466+
lgr_list = smc_lgr_list_head(lgr, &lgr_lock);
467+
spin_lock_bh(lgr_lock);
446468
/* do not use this link group for new connections */
447-
if (!list_empty(&lgr->list))
448-
list_del_init(&lgr->list);
449-
spin_unlock_bh(&smc_lgr_list.lock);
469+
if (!list_empty(lgr_list))
470+
list_del_init(lgr_list);
471+
spin_unlock_bh(lgr_lock);
450472
}
451473

452474
/* terminate linkgroup abnormally */
@@ -487,9 +509,12 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr)
487509

488510
void smc_lgr_terminate(struct smc_link_group *lgr)
489511
{
490-
spin_lock_bh(&smc_lgr_list.lock);
512+
spinlock_t *lgr_lock;
513+
514+
smc_lgr_list_head(lgr, &lgr_lock);
515+
spin_lock_bh(lgr_lock);
491516
__smc_lgr_terminate(lgr);
492-
spin_unlock_bh(&smc_lgr_list.lock);
517+
spin_unlock_bh(lgr_lock);
493518
}
494519

495520
/* Called when IB port is terminated */
@@ -514,15 +539,15 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
514539
LIST_HEAD(lgr_free_list);
515540

516541
/* run common cleanup function and build free list */
517-
spin_lock_bh(&smc_lgr_list.lock);
542+
spin_lock_bh(&dev->lgr_lock);
518543
list_for_each_entry_safe(lgr, l, &dev->lgr_list, list) {
519544
if ((!peer_gid || lgr->peer_gid == peer_gid) &&
520545
(vlan == VLAN_VID_MASK || lgr->vlan_id == vlan)) {
521546
__smc_lgr_terminate(lgr);
522547
list_move(&lgr->list, &lgr_free_list);
523548
}
524549
}
525-
spin_unlock_bh(&smc_lgr_list.lock);
550+
spin_unlock_bh(&dev->lgr_lock);
526551

527552
/* cancel the regular free workers and actually free lgrs */
528553
list_for_each_entry_safe(lgr, l, &lgr_free_list, list) {
@@ -609,17 +634,19 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
609634
struct list_head *lgr_list;
610635
struct smc_link_group *lgr;
611636
enum smc_lgr_role role;
637+
spinlock_t *lgr_lock;
612638
int rc = 0;
613639

614640
lgr_list = ini->is_smcd ? &ini->ism_dev->lgr_list : &smc_lgr_list.list;
641+
lgr_lock = ini->is_smcd ? &ini->ism_dev->lgr_lock : &smc_lgr_list.lock;
615642
ini->cln_first_contact = SMC_FIRST_CONTACT;
616643
role = smc->listen_smc ? SMC_SERV : SMC_CLNT;
617644
if (role == SMC_CLNT && ini->srv_first_contact)
618645
/* create new link group as well */
619646
goto create;
620647

621648
/* determine if an existing link group can be reused */
622-
spin_lock_bh(&smc_lgr_list.lock);
649+
spin_lock_bh(lgr_lock);
623650
list_for_each_entry(lgr, lgr_list, list) {
624651
write_lock_bh(&lgr->conns_lock);
625652
if ((ini->is_smcd ?
@@ -640,7 +667,7 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
640667
}
641668
write_unlock_bh(&lgr->conns_lock);
642669
}
643-
spin_unlock_bh(&smc_lgr_list.lock);
670+
spin_unlock_bh(lgr_lock);
644671

645672
if (role == SMC_CLNT && !ini->srv_first_contact &&
646673
ini->cln_first_contact == SMC_FIRST_CONTACT) {

net/smc/smc_ism.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ struct smcd_dev *smcd_alloc_dev(struct device *parent, const char *name,
286286
smc_pnetid_by_dev_port(parent, 0, smcd->pnetid);
287287

288288
spin_lock_init(&smcd->lock);
289+
spin_lock_init(&smcd->lgr_lock);
289290
INIT_LIST_HEAD(&smcd->vlan);
290291
INIT_LIST_HEAD(&smcd->lgr_list);
291292
smcd->event_wq = alloc_ordered_workqueue("ism_evt_wq-%s)",

0 commit comments

Comments
 (0)