Skip to content

Commit de910bd

Browse files
Or GerlitzRoland Dreier
Or Gerlitz
authored and
Roland Dreier
committed
RDMA/cma: Simplify locking needed for serialization of callbacks
The RDMA CM has some logic in place to make sure that callbacks on a given CM ID are delivered to the consumer in a serialized manner. Specifically it has code to protect against a device removal racing with a running callback function. This patch simplifies this logic by using a mutex per ID instead of a wait queue and atomic variable. This means that cma_disable_remove() now is more properly named to cma_disable_callback(), and cma_enable_remove() can now be removed because it just would become a trivial wrapper around mutex_unlock(). Signed-off-by: Or Gerlitz <ogerlitz@voltaire.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
1 parent 64c5e61 commit de910bd

File tree

1 file changed

+50
-56
lines changed
  • drivers/infiniband/core

1 file changed

+50
-56
lines changed

drivers/infiniband/core/cma.c

+50-56
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,7 @@ struct rdma_id_private {
130130

131131
struct completion comp;
132132
atomic_t refcount;
133-
wait_queue_head_t wait_remove;
134-
atomic_t dev_remove;
133+
struct mutex handler_mutex;
135134

136135
int backlog;
137136
int timeout_ms;
@@ -355,26 +354,15 @@ static void cma_deref_id(struct rdma_id_private *id_priv)
355354
complete(&id_priv->comp);
356355
}
357356

358-
static int cma_disable_remove(struct rdma_id_private *id_priv,
357+
static int cma_disable_callback(struct rdma_id_private *id_priv,
359358
enum cma_state state)
360359
{
361-
unsigned long flags;
362-
int ret;
363-
364-
spin_lock_irqsave(&id_priv->lock, flags);
365-
if (id_priv->state == state) {
366-
atomic_inc(&id_priv->dev_remove);
367-
ret = 0;
368-
} else
369-
ret = -EINVAL;
370-
spin_unlock_irqrestore(&id_priv->lock, flags);
371-
return ret;
372-
}
373-
374-
static void cma_enable_remove(struct rdma_id_private *id_priv)
375-
{
376-
if (atomic_dec_and_test(&id_priv->dev_remove))
377-
wake_up(&id_priv->wait_remove);
360+
mutex_lock(&id_priv->handler_mutex);
361+
if (id_priv->state != state) {
362+
mutex_unlock(&id_priv->handler_mutex);
363+
return -EINVAL;
364+
}
365+
return 0;
378366
}
379367

380368
static int cma_has_cm_dev(struct rdma_id_private *id_priv)
@@ -399,8 +387,7 @@ struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
399387
mutex_init(&id_priv->qp_mutex);
400388
init_completion(&id_priv->comp);
401389
atomic_set(&id_priv->refcount, 1);
402-
init_waitqueue_head(&id_priv->wait_remove);
403-
atomic_set(&id_priv->dev_remove, 0);
390+
mutex_init(&id_priv->handler_mutex);
404391
INIT_LIST_HEAD(&id_priv->listen_list);
405392
INIT_LIST_HEAD(&id_priv->mc_list);
406393
get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num);
@@ -927,7 +914,7 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
927914
struct rdma_cm_event event;
928915
int ret = 0;
929916

930-
if (cma_disable_remove(id_priv, CMA_CONNECT))
917+
if (cma_disable_callback(id_priv, CMA_CONNECT))
931918
return 0;
932919

933920
memset(&event, 0, sizeof event);
@@ -984,12 +971,12 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
984971
/* Destroy the CM ID by returning a non-zero value. */
985972
id_priv->cm_id.ib = NULL;
986973
cma_exch(id_priv, CMA_DESTROYING);
987-
cma_enable_remove(id_priv);
974+
mutex_unlock(&id_priv->handler_mutex);
988975
rdma_destroy_id(&id_priv->id);
989976
return ret;
990977
}
991978
out:
992-
cma_enable_remove(id_priv);
979+
mutex_unlock(&id_priv->handler_mutex);
993980
return ret;
994981
}
995982

@@ -1101,7 +1088,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
11011088
int offset, ret;
11021089

11031090
listen_id = cm_id->context;
1104-
if (cma_disable_remove(listen_id, CMA_LISTEN))
1091+
if (cma_disable_callback(listen_id, CMA_LISTEN))
11051092
return -ECONNABORTED;
11061093

11071094
memset(&event, 0, sizeof event);
@@ -1122,7 +1109,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
11221109
goto out;
11231110
}
11241111

1125-
atomic_inc(&conn_id->dev_remove);
1112+
mutex_lock_nested(&conn_id->handler_mutex, SINGLE_DEPTH_NESTING);
11261113
mutex_lock(&lock);
11271114
ret = cma_acquire_dev(conn_id);
11281115
mutex_unlock(&lock);
@@ -1144,7 +1131,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
11441131
!cma_is_ud_ps(conn_id->id.ps))
11451132
ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0);
11461133
mutex_unlock(&lock);
1147-
cma_enable_remove(conn_id);
1134+
mutex_unlock(&conn_id->handler_mutex);
11481135
goto out;
11491136
}
11501137

@@ -1153,11 +1140,11 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
11531140

11541141
release_conn_id:
11551142
cma_exch(conn_id, CMA_DESTROYING);
1156-
cma_enable_remove(conn_id);
1143+
mutex_unlock(&conn_id->handler_mutex);
11571144
rdma_destroy_id(&conn_id->id);
11581145

11591146
out:
1160-
cma_enable_remove(listen_id);
1147+
mutex_unlock(&listen_id->handler_mutex);
11611148
return ret;
11621149
}
11631150

@@ -1223,7 +1210,7 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
12231210
struct sockaddr_in *sin;
12241211
int ret = 0;
12251212

1226-
if (cma_disable_remove(id_priv, CMA_CONNECT))
1213+
if (cma_disable_callback(id_priv, CMA_CONNECT))
12271214
return 0;
12281215

12291216
memset(&event, 0, sizeof event);
@@ -1267,12 +1254,12 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
12671254
/* Destroy the CM ID by returning a non-zero value. */
12681255
id_priv->cm_id.iw = NULL;
12691256
cma_exch(id_priv, CMA_DESTROYING);
1270-
cma_enable_remove(id_priv);
1257+
mutex_unlock(&id_priv->handler_mutex);
12711258
rdma_destroy_id(&id_priv->id);
12721259
return ret;
12731260
}
12741261

1275-
cma_enable_remove(id_priv);
1262+
mutex_unlock(&id_priv->handler_mutex);
12761263
return ret;
12771264
}
12781265

@@ -1288,7 +1275,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
12881275
struct ib_device_attr attr;
12891276

12901277
listen_id = cm_id->context;
1291-
if (cma_disable_remove(listen_id, CMA_LISTEN))
1278+
if (cma_disable_callback(listen_id, CMA_LISTEN))
12921279
return -ECONNABORTED;
12931280

12941281
/* Create a new RDMA id for the new IW CM ID */
@@ -1300,19 +1287,19 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
13001287
goto out;
13011288
}
13021289
conn_id = container_of(new_cm_id, struct rdma_id_private, id);
1303-
atomic_inc(&conn_id->dev_remove);
1290+
mutex_lock_nested(&conn_id->handler_mutex, SINGLE_DEPTH_NESTING);
13041291
conn_id->state = CMA_CONNECT;
13051292

13061293
dev = ip_dev_find(&init_net, iw_event->local_addr.sin_addr.s_addr);
13071294
if (!dev) {
13081295
ret = -EADDRNOTAVAIL;
1309-
cma_enable_remove(conn_id);
1296+
mutex_unlock(&conn_id->handler_mutex);
13101297
rdma_destroy_id(new_cm_id);
13111298
goto out;
13121299
}
13131300
ret = rdma_copy_addr(&conn_id->id.route.addr.dev_addr, dev, NULL);
13141301
if (ret) {
1315-
cma_enable_remove(conn_id);
1302+
mutex_unlock(&conn_id->handler_mutex);
13161303
rdma_destroy_id(new_cm_id);
13171304
goto out;
13181305
}
@@ -1321,7 +1308,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
13211308
ret = cma_acquire_dev(conn_id);
13221309
mutex_unlock(&lock);
13231310
if (ret) {
1324-
cma_enable_remove(conn_id);
1311+
mutex_unlock(&conn_id->handler_mutex);
13251312
rdma_destroy_id(new_cm_id);
13261313
goto out;
13271314
}
@@ -1337,7 +1324,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
13371324

13381325
ret = ib_query_device(conn_id->id.device, &attr);
13391326
if (ret) {
1340-
cma_enable_remove(conn_id);
1327+
mutex_unlock(&conn_id->handler_mutex);
13411328
rdma_destroy_id(new_cm_id);
13421329
goto out;
13431330
}
@@ -1353,14 +1340,17 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
13531340
/* User wants to destroy the CM ID */
13541341
conn_id->cm_id.iw = NULL;
13551342
cma_exch(conn_id, CMA_DESTROYING);
1356-
cma_enable_remove(conn_id);
1343+
mutex_unlock(&conn_id->handler_mutex);
13571344
rdma_destroy_id(&conn_id->id);
1345+
goto out;
13581346
}
13591347

1348+
mutex_unlock(&conn_id->handler_mutex);
1349+
13601350
out:
13611351
if (dev)
13621352
dev_put(dev);
1363-
cma_enable_remove(listen_id);
1353+
mutex_unlock(&listen_id->handler_mutex);
13641354
return ret;
13651355
}
13661356

@@ -1592,7 +1582,7 @@ static void cma_work_handler(struct work_struct *_work)
15921582
struct rdma_id_private *id_priv = work->id;
15931583
int destroy = 0;
15941584

1595-
atomic_inc(&id_priv->dev_remove);
1585+
mutex_lock(&id_priv->handler_mutex);
15961586
if (!cma_comp_exch(id_priv, work->old_state, work->new_state))
15971587
goto out;
15981588

@@ -1601,7 +1591,7 @@ static void cma_work_handler(struct work_struct *_work)
16011591
destroy = 1;
16021592
}
16031593
out:
1604-
cma_enable_remove(id_priv);
1594+
mutex_unlock(&id_priv->handler_mutex);
16051595
cma_deref_id(id_priv);
16061596
if (destroy)
16071597
rdma_destroy_id(&id_priv->id);
@@ -1764,7 +1754,7 @@ static void addr_handler(int status, struct sockaddr *src_addr,
17641754
struct rdma_cm_event event;
17651755

17661756
memset(&event, 0, sizeof event);
1767-
atomic_inc(&id_priv->dev_remove);
1757+
mutex_lock(&id_priv->handler_mutex);
17681758

17691759
/*
17701760
* Grab mutex to block rdma_destroy_id() from removing the device while
@@ -1793,13 +1783,13 @@ static void addr_handler(int status, struct sockaddr *src_addr,
17931783

17941784
if (id_priv->id.event_handler(&id_priv->id, &event)) {
17951785
cma_exch(id_priv, CMA_DESTROYING);
1796-
cma_enable_remove(id_priv);
1786+
mutex_unlock(&id_priv->handler_mutex);
17971787
cma_deref_id(id_priv);
17981788
rdma_destroy_id(&id_priv->id);
17991789
return;
18001790
}
18011791
out:
1802-
cma_enable_remove(id_priv);
1792+
mutex_unlock(&id_priv->handler_mutex);
18031793
cma_deref_id(id_priv);
18041794
}
18051795

@@ -2126,7 +2116,7 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
21262116
struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd;
21272117
int ret = 0;
21282118

2129-
if (cma_disable_remove(id_priv, CMA_CONNECT))
2119+
if (cma_disable_callback(id_priv, CMA_CONNECT))
21302120
return 0;
21312121

21322122
memset(&event, 0, sizeof event);
@@ -2167,12 +2157,12 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
21672157
/* Destroy the CM ID by returning a non-zero value. */
21682158
id_priv->cm_id.ib = NULL;
21692159
cma_exch(id_priv, CMA_DESTROYING);
2170-
cma_enable_remove(id_priv);
2160+
mutex_unlock(&id_priv->handler_mutex);
21712161
rdma_destroy_id(&id_priv->id);
21722162
return ret;
21732163
}
21742164
out:
2175-
cma_enable_remove(id_priv);
2165+
mutex_unlock(&id_priv->handler_mutex);
21762166
return ret;
21772167
}
21782168

@@ -2570,8 +2560,8 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
25702560
int ret;
25712561

25722562
id_priv = mc->id_priv;
2573-
if (cma_disable_remove(id_priv, CMA_ADDR_BOUND) &&
2574-
cma_disable_remove(id_priv, CMA_ADDR_RESOLVED))
2563+
if (cma_disable_callback(id_priv, CMA_ADDR_BOUND) &&
2564+
cma_disable_callback(id_priv, CMA_ADDR_RESOLVED))
25752565
return 0;
25762566

25772567
mutex_lock(&id_priv->qp_mutex);
@@ -2596,12 +2586,12 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
25962586
ret = id_priv->id.event_handler(&id_priv->id, &event);
25972587
if (ret) {
25982588
cma_exch(id_priv, CMA_DESTROYING);
2599-
cma_enable_remove(id_priv);
2589+
mutex_unlock(&id_priv->handler_mutex);
26002590
rdma_destroy_id(&id_priv->id);
26012591
return 0;
26022592
}
26032593

2604-
cma_enable_remove(id_priv);
2594+
mutex_unlock(&id_priv->handler_mutex);
26052595
return 0;
26062596
}
26072597

@@ -2760,22 +2750,26 @@ static int cma_remove_id_dev(struct rdma_id_private *id_priv)
27602750
{
27612751
struct rdma_cm_event event;
27622752
enum cma_state state;
2753+
int ret = 0;
27632754

27642755
/* Record that we want to remove the device */
27652756
state = cma_exch(id_priv, CMA_DEVICE_REMOVAL);
27662757
if (state == CMA_DESTROYING)
27672758
return 0;
27682759

27692760
cma_cancel_operation(id_priv, state);
2770-
wait_event(id_priv->wait_remove, !atomic_read(&id_priv->dev_remove));
2761+
mutex_lock(&id_priv->handler_mutex);
27712762

27722763
/* Check for destruction from another callback. */
27732764
if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL))
2774-
return 0;
2765+
goto out;
27752766

27762767
memset(&event, 0, sizeof event);
27772768
event.event = RDMA_CM_EVENT_DEVICE_REMOVAL;
2778-
return id_priv->id.event_handler(&id_priv->id, &event);
2769+
ret = id_priv->id.event_handler(&id_priv->id, &event);
2770+
out:
2771+
mutex_unlock(&id_priv->handler_mutex);
2772+
return ret;
27792773
}
27802774

27812775
static void cma_process_remove(struct cma_device *cma_dev)

0 commit comments

Comments
 (0)