Skip to content

Commit c4f6b6e

Browse files
jgunthorpejfvogel
authored andcommitted
RDMA/cm: Allow ib_send_cm_dreq() to be done under lock
The first thing ib_send_cm_dreq() does is obtain the lock, so use the usual unlocked wrapper, locked actor pattern here. This avoids a sketchy lock/unlock sequence (which could allow state to change) during cm_destroy_id(). Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]> Orabug: 31483278 (cherry picked from commit e029fdc) cherry-pick-repo=linux/kernel/git/torvalds/linux.git unmodified-from-upstream: e029fdc Signed-off-by: Ka-Cheong Poon <[email protected]> Tested-by: June Wang <[email protected]> Reviewed-by: Sharath Srinivasan <[email protected]>
1 parent e6bee7c commit c4f6b6e

File tree

1 file changed

+34
-20
lines changed
  • drivers/infiniband/core

1 file changed

+34
-20
lines changed

drivers/infiniband/core/cm.c

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,11 @@ const char *__attribute_const__ ibcm_reject_msg(int reason)
106106
}
107107
EXPORT_SYMBOL(ibcm_reject_msg);
108108

109+
struct cm_id_private;
109110
static void cm_add_one(struct ib_device *device);
110111
static void cm_remove_one(struct ib_device *device, void *client_data);
112+
static int cm_send_dreq_locked(struct cm_id_private *cm_id_priv,
113+
const void *private_data, u8 private_data_len);
111114

112115
static struct ib_client cm_client = {
113116
.name = "cm",
@@ -1081,10 +1084,12 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
10811084
NULL, 0, NULL, 0);
10821085
break;
10831086
case IB_CM_ESTABLISHED:
1084-
spin_unlock_irq(&cm_id_priv->lock);
1085-
if (cm_id_priv->qp_type == IB_QPT_XRC_TGT)
1087+
if (cm_id_priv->qp_type == IB_QPT_XRC_TGT) {
1088+
spin_unlock_irq(&cm_id_priv->lock);
10861089
break;
1087-
ib_send_cm_dreq(cm_id, NULL, 0);
1090+
}
1091+
cm_send_dreq_locked(cm_id_priv, NULL, 0);
1092+
spin_unlock_irq(&cm_id_priv->lock);
10881093
goto retest;
10891094
case IB_CM_DREQ_SENT:
10901095
ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
@@ -2489,35 +2494,32 @@ static void cm_format_dreq(struct cm_dreq_msg *dreq_msg,
24892494
memcpy(dreq_msg->private_data, private_data, private_data_len);
24902495
}
24912496

2492-
int ib_send_cm_dreq(struct ib_cm_id *cm_id,
2493-
const void *private_data,
2494-
u8 private_data_len)
2497+
static int cm_send_dreq_locked(struct cm_id_private *cm_id_priv,
2498+
const void *private_data, u8 private_data_len)
24952499
{
2496-
struct cm_id_private *cm_id_priv;
24972500
struct ib_mad_send_buf *msg;
2498-
unsigned long flags;
24992501
int ret;
25002502

2503+
lockdep_assert_held(&cm_id_priv->lock);
2504+
25012505
if (private_data && private_data_len > IB_CM_DREQ_PRIVATE_DATA_SIZE)
25022506
return -EINVAL;
25032507

2504-
cm_id_priv = container_of(cm_id, struct cm_id_private, id);
2505-
spin_lock_irqsave(&cm_id_priv->lock, flags);
2506-
if (cm_id->state != IB_CM_ESTABLISHED) {
2508+
if (cm_id_priv->id.state != IB_CM_ESTABLISHED) {
25072509
pr_debug("%s: local_id %d, cm_id->state: %d\n", __func__,
2508-
be32_to_cpu(cm_id->local_id), cm_id->state);
2509-
ret = -EINVAL;
2510-
goto out;
2510+
be32_to_cpu(cm_id_priv->id.local_id),
2511+
cm_id_priv->id.state);
2512+
return -EINVAL;
25112513
}
25122514

2513-
if (cm_id->lap_state == IB_CM_LAP_SENT ||
2514-
cm_id->lap_state == IB_CM_MRA_LAP_RCVD)
2515+
if (cm_id_priv->id.lap_state == IB_CM_LAP_SENT ||
2516+
cm_id_priv->id.lap_state == IB_CM_MRA_LAP_RCVD)
25152517
ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
25162518

25172519
ret = cm_alloc_msg(cm_id_priv, &msg);
25182520
if (ret) {
25192521
cm_enter_timewait(cm_id_priv);
2520-
goto out;
2522+
return ret;
25212523
}
25222524

25232525
cm_format_dreq((struct cm_dreq_msg *) msg->mad, cm_id_priv,
@@ -2528,14 +2530,26 @@ int ib_send_cm_dreq(struct ib_cm_id *cm_id,
25282530
ret = ib_post_send_mad(msg, NULL);
25292531
if (ret) {
25302532
cm_enter_timewait(cm_id_priv);
2531-
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
25322533
cm_free_msg(msg);
25332534
return ret;
25342535
}
25352536

2536-
cm_id->state = IB_CM_DREQ_SENT;
2537+
cm_id_priv->id.state = IB_CM_DREQ_SENT;
25372538
cm_id_priv->msg = msg;
2538-
out: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2539+
return 0;
2540+
}
2541+
2542+
int ib_send_cm_dreq(struct ib_cm_id *cm_id, const void *private_data,
2543+
u8 private_data_len)
2544+
{
2545+
struct cm_id_private *cm_id_priv =
2546+
container_of(cm_id, struct cm_id_private, id);
2547+
unsigned long flags;
2548+
int ret;
2549+
2550+
spin_lock_irqsave(&cm_id_priv->lock, flags);
2551+
ret = cm_send_dreq_locked(cm_id_priv, private_data, private_data_len);
2552+
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
25392553
return ret;
25402554
}
25412555
EXPORT_SYMBOL(ib_send_cm_dreq);

0 commit comments

Comments
 (0)