Skip to content

Commit e029fdc

Browse files
committed
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]>
1 parent 00777a6 commit e029fdc

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
@@ -80,8 +80,11 @@ const char *__attribute_const__ ibcm_reject_msg(int reason)
8080
}
8181
EXPORT_SYMBOL(ibcm_reject_msg);
8282

83+
struct cm_id_private;
8384
static void cm_add_one(struct ib_device *device);
8485
static void cm_remove_one(struct ib_device *device, void *client_data);
86+
static int cm_send_dreq_locked(struct cm_id_private *cm_id_priv,
87+
const void *private_data, u8 private_data_len);
8588

8689
static struct ib_client cm_client = {
8790
.name = "cm",
@@ -1084,10 +1087,12 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
10841087
NULL, 0, NULL, 0);
10851088
break;
10861089
case IB_CM_ESTABLISHED:
1087-
spin_unlock_irq(&cm_id_priv->lock);
1088-
if (cm_id_priv->qp_type == IB_QPT_XRC_TGT)
1090+
if (cm_id_priv->qp_type == IB_QPT_XRC_TGT) {
1091+
spin_unlock_irq(&cm_id_priv->lock);
10891092
break;
1090-
ib_send_cm_dreq(cm_id, NULL, 0);
1093+
}
1094+
cm_send_dreq_locked(cm_id_priv, NULL, 0);
1095+
spin_unlock_irq(&cm_id_priv->lock);
10911096
goto retest;
10921097
case IB_CM_DREQ_SENT:
10931098
ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
@@ -2604,35 +2609,32 @@ static void cm_format_dreq(struct cm_dreq_msg *dreq_msg,
26042609
private_data_len);
26052610
}
26062611

2607-
int ib_send_cm_dreq(struct ib_cm_id *cm_id,
2608-
const void *private_data,
2609-
u8 private_data_len)
2612+
static int cm_send_dreq_locked(struct cm_id_private *cm_id_priv,
2613+
const void *private_data, u8 private_data_len)
26102614
{
2611-
struct cm_id_private *cm_id_priv;
26122615
struct ib_mad_send_buf *msg;
2613-
unsigned long flags;
26142616
int ret;
26152617

2618+
lockdep_assert_held(&cm_id_priv->lock);
2619+
26162620
if (private_data && private_data_len > IB_CM_DREQ_PRIVATE_DATA_SIZE)
26172621
return -EINVAL;
26182622

2619-
cm_id_priv = container_of(cm_id, struct cm_id_private, id);
2620-
spin_lock_irqsave(&cm_id_priv->lock, flags);
2621-
if (cm_id->state != IB_CM_ESTABLISHED) {
2623+
if (cm_id_priv->id.state != IB_CM_ESTABLISHED) {
26222624
pr_debug("%s: local_id %d, cm_id->state: %d\n", __func__,
2623-
be32_to_cpu(cm_id->local_id), cm_id->state);
2624-
ret = -EINVAL;
2625-
goto out;
2625+
be32_to_cpu(cm_id_priv->id.local_id),
2626+
cm_id_priv->id.state);
2627+
return -EINVAL;
26262628
}
26272629

2628-
if (cm_id->lap_state == IB_CM_LAP_SENT ||
2629-
cm_id->lap_state == IB_CM_MRA_LAP_RCVD)
2630+
if (cm_id_priv->id.lap_state == IB_CM_LAP_SENT ||
2631+
cm_id_priv->id.lap_state == IB_CM_MRA_LAP_RCVD)
26302632
ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
26312633

26322634
ret = cm_alloc_msg(cm_id_priv, &msg);
26332635
if (ret) {
26342636
cm_enter_timewait(cm_id_priv);
2635-
goto out;
2637+
return ret;
26362638
}
26372639

26382640
cm_format_dreq((struct cm_dreq_msg *) msg->mad, cm_id_priv,
@@ -2643,14 +2645,26 @@ int ib_send_cm_dreq(struct ib_cm_id *cm_id,
26432645
ret = ib_post_send_mad(msg, NULL);
26442646
if (ret) {
26452647
cm_enter_timewait(cm_id_priv);
2646-
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
26472648
cm_free_msg(msg);
26482649
return ret;
26492650
}
26502651

2651-
cm_id->state = IB_CM_DREQ_SENT;
2652+
cm_id_priv->id.state = IB_CM_DREQ_SENT;
26522653
cm_id_priv->msg = msg;
2653-
out: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2654+
return 0;
2655+
}
2656+
2657+
int ib_send_cm_dreq(struct ib_cm_id *cm_id, const void *private_data,
2658+
u8 private_data_len)
2659+
{
2660+
struct cm_id_private *cm_id_priv =
2661+
container_of(cm_id, struct cm_id_private, id);
2662+
unsigned long flags;
2663+
int ret;
2664+
2665+
spin_lock_irqsave(&cm_id_priv->lock, flags);
2666+
ret = cm_send_dreq_locked(cm_id_priv, private_data, private_data_len);
2667+
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
26542668
return ret;
26552669
}
26562670
EXPORT_SYMBOL(ib_send_cm_dreq);

0 commit comments

Comments
 (0)