Skip to content

Commit e502124

Browse files
jgunthorpejfvogel
authored andcommitted
RDMA/cm: Allow ib_send_cm_rej() to be done under lock
The first thing ib_send_cm_rej() 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(). While here simplify some of the logic in the implementation. 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 81ddb41) cherry-pick-repo=linux/kernel/git/torvalds/linux.git unmodified-from-upstream: 81ddb41 Signed-off-by: Ka-Cheong Poon <[email protected]> Tested-by: June Wang <[email protected]> Reviewed-by: Sharath Srinivasan <[email protected]>
1 parent 02a7fe2 commit e502124

File tree

1 file changed

+52
-40
lines changed
  • drivers/infiniband/core

1 file changed

+52
-40
lines changed

drivers/infiniband/core/cm.c

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ static int cm_send_dreq_locked(struct cm_id_private *cm_id_priv,
113113
const void *private_data, u8 private_data_len);
114114
static int cm_send_drep_locked(struct cm_id_private *cm_id_priv,
115115
void *private_data, u8 private_data_len);
116+
static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
117+
enum ib_cm_rej_reason reason, void *ari,
118+
u8 ari_length, const void *private_data,
119+
u8 private_data_len);
116120

117121
static struct ib_client cm_client = {
118122
.name = "cm",
@@ -1057,21 +1061,22 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
10571061
case IB_CM_REQ_SENT:
10581062
case IB_CM_MRA_REQ_RCVD:
10591063
ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
1064+
cm_send_rej_locked(cm_id_priv, IB_CM_REJ_TIMEOUT,
1065+
&cm_id_priv->id.device->node_guid,
1066+
sizeof(cm_id_priv->id.device->node_guid),
1067+
NULL, 0);
10601068
spin_unlock_irq(&cm_id_priv->lock);
1061-
ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT,
1062-
&cm_id_priv->id.device->node_guid,
1063-
sizeof cm_id_priv->id.device->node_guid,
1064-
NULL, 0);
10651069
break;
10661070
case IB_CM_REQ_RCVD:
10671071
if (err == -ENOMEM) {
10681072
/* Do not reject to allow future retries. */
10691073
cm_reset_to_idle(cm_id_priv);
10701074
spin_unlock_irq(&cm_id_priv->lock);
10711075
} else {
1076+
cm_send_rej_locked(cm_id_priv,
1077+
IB_CM_REJ_CONSUMER_DEFINED, NULL, 0,
1078+
NULL, 0);
10721079
spin_unlock_irq(&cm_id_priv->lock);
1073-
ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
1074-
NULL, 0, NULL, 0);
10751080
}
10761081
break;
10771082
case IB_CM_REP_SENT:
@@ -1081,9 +1086,9 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
10811086
case IB_CM_MRA_REQ_SENT:
10821087
case IB_CM_REP_RCVD:
10831088
case IB_CM_MRA_REP_SENT:
1089+
cm_send_rej_locked(cm_id_priv, IB_CM_REJ_CONSUMER_DEFINED, NULL,
1090+
0, NULL, 0);
10841091
spin_unlock_irq(&cm_id_priv->lock);
1085-
ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
1086-
NULL, 0, NULL, 0);
10871092
break;
10881093
case IB_CM_ESTABLISHED:
10891094
if (cm_id_priv->qp_type == IB_QPT_XRC_TGT) {
@@ -2773,65 +2778,72 @@ static int cm_drep_handler(struct cm_work *work)
27732778
return -EINVAL;
27742779
}
27752780

2776-
int ib_send_cm_rej(struct ib_cm_id *cm_id,
2777-
enum ib_cm_rej_reason reason,
2778-
void *ari,
2779-
u8 ari_length,
2780-
const void *private_data,
2781-
u8 private_data_len)
2781+
static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
2782+
enum ib_cm_rej_reason reason, void *ari,
2783+
u8 ari_length, const void *private_data,
2784+
u8 private_data_len)
27822785
{
2783-
struct cm_id_private *cm_id_priv;
27842786
struct ib_mad_send_buf *msg;
2785-
unsigned long flags;
27862787
int ret;
27872788

2789+
lockdep_assert_held(&cm_id_priv->lock);
2790+
27882791
if ((private_data && private_data_len > IB_CM_REJ_PRIVATE_DATA_SIZE) ||
27892792
(ari && ari_length > IB_CM_REJ_ARI_LENGTH))
27902793
return -EINVAL;
27912794

2792-
cm_id_priv = container_of(cm_id, struct cm_id_private, id);
2793-
2794-
spin_lock_irqsave(&cm_id_priv->lock, flags);
2795-
switch (cm_id->state) {
2795+
switch (cm_id_priv->id.state) {
27962796
case IB_CM_REQ_SENT:
27972797
case IB_CM_MRA_REQ_RCVD:
27982798
case IB_CM_REQ_RCVD:
27992799
case IB_CM_MRA_REQ_SENT:
28002800
case IB_CM_REP_RCVD:
28012801
case IB_CM_MRA_REP_SENT:
2802-
ret = cm_alloc_msg(cm_id_priv, &msg);
2803-
if (!ret)
2804-
cm_format_rej((struct cm_rej_msg *) msg->mad,
2805-
cm_id_priv, reason, ari, ari_length,
2806-
private_data, private_data_len);
2807-
28082802
cm_reset_to_idle(cm_id_priv);
2803+
ret = cm_alloc_msg(cm_id_priv, &msg);
2804+
if (ret)
2805+
return ret;
2806+
cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv, reason,
2807+
ari, ari_length, private_data, private_data_len);
28092808
break;
28102809
case IB_CM_REP_SENT:
28112810
case IB_CM_MRA_REP_RCVD:
2812-
ret = cm_alloc_msg(cm_id_priv, &msg);
2813-
if (!ret)
2814-
cm_format_rej((struct cm_rej_msg *) msg->mad,
2815-
cm_id_priv, reason, ari, ari_length,
2816-
private_data, private_data_len);
2817-
28182811
cm_enter_timewait(cm_id_priv);
2812+
ret = cm_alloc_msg(cm_id_priv, &msg);
2813+
if (ret)
2814+
return ret;
2815+
cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv, reason,
2816+
ari, ari_length, private_data, private_data_len);
28192817
break;
28202818
default:
28212819
pr_debug("%s: local_id %d, cm_id->state: %d\n", __func__,
2822-
be32_to_cpu(cm_id_priv->id.local_id), cm_id->state);
2823-
ret = -EINVAL;
2824-
goto out;
2820+
be32_to_cpu(cm_id_priv->id.local_id),
2821+
cm_id_priv->id.state);
2822+
return -EINVAL;
28252823
}
28262824

2827-
if (ret)
2828-
goto out;
2829-
28302825
ret = ib_post_send_mad(msg, NULL);
2831-
if (ret)
2826+
if (ret) {
28322827
cm_free_msg(msg);
2828+
return ret;
2829+
}
28332830

2834-
out: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2831+
return 0;
2832+
}
2833+
2834+
int ib_send_cm_rej(struct ib_cm_id *cm_id, enum ib_cm_rej_reason reason,
2835+
void *ari, u8 ari_length, const void *private_data,
2836+
u8 private_data_len)
2837+
{
2838+
struct cm_id_private *cm_id_priv =
2839+
container_of(cm_id, struct cm_id_private, id);
2840+
unsigned long flags;
2841+
int ret;
2842+
2843+
spin_lock_irqsave(&cm_id_priv->lock, flags);
2844+
ret = cm_send_rej_locked(cm_id_priv, reason, ari, ari_length,
2845+
private_data, private_data_len);
2846+
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
28352847
return ret;
28362848
}
28372849
EXPORT_SYMBOL(ib_send_cm_rej);

0 commit comments

Comments
 (0)