Skip to content

Commit a62f325

Browse files
committed
IB/cm: use rwlock for MAD agent lock
JIRA: https://issues.redhat.com/browse/RHEL-110100 commit 4dab26b Author: Jacob Moroni <jmoroni@google.com> Date: Thu Feb 20 17:56:12 2025 +0000 IB/cm: use rwlock for MAD agent lock In workloads where there are many processes establishing connections using RDMA CM in parallel (large scale MPI), there can be heavy contention for mad_agent_lock in cm_alloc_msg. This contention can occur while inside of a spin_lock_irq region, leading to interrupts being disabled for extended durations on many cores. Furthermore, it leads to the serialization of rdma_create_ah calls, which has negative performance impacts for NICs which are capable of processing multiple address handle creations in parallel. The end result is the machine becoming unresponsive, hung task warnings, netdev TX timeouts, etc. Since the lock appears to be only for protection from cm_remove_one, it can be changed to a rwlock to resolve these issues. Reproducer: Server: for i in $(seq 1 512); do ucmatose -c 32 -p $((i + 5000)) & done Client: for i in $(seq 1 512); do ucmatose -c 32 -p $((i + 5000)) -s 10.2.0.52 & done Fixes: 76039ac ("IB/cm: Protect cm_dev, cm_ports and mad_agent with kref and lock") Link: https://patch.msgid.link/r/20250220175612.2763122-1-jmoroni@google.com Signed-off-by: Jacob Moroni <jmoroni@google.com> Acked-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Kamal Heib <kheib@redhat.com>
1 parent 92b0c9c commit a62f325

File tree

1 file changed

+8
-8
lines changed
  • drivers/infiniband/core

1 file changed

+8
-8
lines changed

drivers/infiniband/core/cm.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ struct cm_port {
167167
struct cm_device {
168168
struct kref kref;
169169
struct list_head list;
170-
spinlock_t mad_agent_lock;
170+
rwlock_t mad_agent_lock;
171171
struct ib_device *ib_device;
172172
u8 ack_delay;
173173
int going_down;
@@ -285,7 +285,7 @@ static struct ib_mad_send_buf *cm_alloc_msg(struct cm_id_private *cm_id_priv)
285285
if (!cm_id_priv->av.port)
286286
return ERR_PTR(-EINVAL);
287287

288-
spin_lock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
288+
read_lock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
289289
mad_agent = cm_id_priv->av.port->mad_agent;
290290
if (!mad_agent) {
291291
m = ERR_PTR(-EINVAL);
@@ -311,7 +311,7 @@ static struct ib_mad_send_buf *cm_alloc_msg(struct cm_id_private *cm_id_priv)
311311
m->ah = ah;
312312

313313
out:
314-
spin_unlock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
314+
read_unlock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
315315
return m;
316316
}
317317

@@ -1297,10 +1297,10 @@ static __be64 cm_form_tid(struct cm_id_private *cm_id_priv)
12971297
if (!cm_id_priv->av.port)
12981298
return cpu_to_be64(low_tid);
12991299

1300-
spin_lock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
1300+
read_lock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
13011301
if (cm_id_priv->av.port->mad_agent)
13021302
hi_tid = ((u64)cm_id_priv->av.port->mad_agent->hi_tid) << 32;
1303-
spin_unlock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
1303+
read_unlock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
13041304
return cpu_to_be64(hi_tid | low_tid);
13051305
}
13061306

@@ -4378,7 +4378,7 @@ static int cm_add_one(struct ib_device *ib_device)
43784378
return -ENOMEM;
43794379

43804380
kref_init(&cm_dev->kref);
4381-
spin_lock_init(&cm_dev->mad_agent_lock);
4381+
rwlock_init(&cm_dev->mad_agent_lock);
43824382
cm_dev->ib_device = ib_device;
43834383
cm_dev->ack_delay = ib_device->attrs.local_ca_ack_delay;
43844384
cm_dev->going_down = 0;
@@ -4494,9 +4494,9 @@ static void cm_remove_one(struct ib_device *ib_device, void *client_data)
44944494
* The above ensures no call paths from the work are running,
44954495
* the remaining paths all take the mad_agent_lock.
44964496
*/
4497-
spin_lock(&cm_dev->mad_agent_lock);
4497+
write_lock(&cm_dev->mad_agent_lock);
44984498
port->mad_agent = NULL;
4499-
spin_unlock(&cm_dev->mad_agent_lock);
4499+
write_unlock(&cm_dev->mad_agent_lock);
45004500
ib_unregister_mad_agent(mad_agent);
45014501
ib_port_unregister_client_groups(ib_device, i,
45024502
cm_counter_groups);

0 commit comments

Comments
 (0)