Skip to content

Commit 81ddb41

Browse files
committed
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]>
1 parent 87cabf3 commit 81ddb41

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
@@ -87,6 +87,10 @@ static int cm_send_dreq_locked(struct cm_id_private *cm_id_priv,
8787
const void *private_data, u8 private_data_len);
8888
static int cm_send_drep_locked(struct cm_id_private *cm_id_priv,
8989
void *private_data, u8 private_data_len);
90+
static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
91+
enum ib_cm_rej_reason reason, void *ari,
92+
u8 ari_length, const void *private_data,
93+
u8 private_data_len);
9094

9195
static struct ib_client cm_client = {
9296
.name = "cm",
@@ -1060,21 +1064,22 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
10601064
case IB_CM_REQ_SENT:
10611065
case IB_CM_MRA_REQ_RCVD:
10621066
ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
1067+
cm_send_rej_locked(cm_id_priv, IB_CM_REJ_TIMEOUT,
1068+
&cm_id_priv->id.device->node_guid,
1069+
sizeof(cm_id_priv->id.device->node_guid),
1070+
NULL, 0);
10631071
spin_unlock_irq(&cm_id_priv->lock);
1064-
ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT,
1065-
&cm_id_priv->id.device->node_guid,
1066-
sizeof cm_id_priv->id.device->node_guid,
1067-
NULL, 0);
10681072
break;
10691073
case IB_CM_REQ_RCVD:
10701074
if (err == -ENOMEM) {
10711075
/* Do not reject to allow future retries. */
10721076
cm_reset_to_idle(cm_id_priv);
10731077
spin_unlock_irq(&cm_id_priv->lock);
10741078
} else {
1079+
cm_send_rej_locked(cm_id_priv,
1080+
IB_CM_REJ_CONSUMER_DEFINED, NULL, 0,
1081+
NULL, 0);
10751082
spin_unlock_irq(&cm_id_priv->lock);
1076-
ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
1077-
NULL, 0, NULL, 0);
10781083
}
10791084
break;
10801085
case IB_CM_REP_SENT:
@@ -1084,9 +1089,9 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
10841089
case IB_CM_MRA_REQ_SENT:
10851090
case IB_CM_REP_RCVD:
10861091
case IB_CM_MRA_REP_SENT:
1092+
cm_send_rej_locked(cm_id_priv, IB_CM_REJ_CONSUMER_DEFINED, NULL,
1093+
0, NULL, 0);
10871094
spin_unlock_irq(&cm_id_priv->lock);
1088-
ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
1089-
NULL, 0, NULL, 0);
10901095
break;
10911096
case IB_CM_ESTABLISHED:
10921097
if (cm_id_priv->qp_type == IB_QPT_XRC_TGT) {
@@ -2899,65 +2904,72 @@ static int cm_drep_handler(struct cm_work *work)
28992904
return -EINVAL;
29002905
}
29012906

2902-
int ib_send_cm_rej(struct ib_cm_id *cm_id,
2903-
enum ib_cm_rej_reason reason,
2904-
void *ari,
2905-
u8 ari_length,
2906-
const void *private_data,
2907-
u8 private_data_len)
2907+
static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
2908+
enum ib_cm_rej_reason reason, void *ari,
2909+
u8 ari_length, const void *private_data,
2910+
u8 private_data_len)
29082911
{
2909-
struct cm_id_private *cm_id_priv;
29102912
struct ib_mad_send_buf *msg;
2911-
unsigned long flags;
29122913
int ret;
29132914

2915+
lockdep_assert_held(&cm_id_priv->lock);
2916+
29142917
if ((private_data && private_data_len > IB_CM_REJ_PRIVATE_DATA_SIZE) ||
29152918
(ari && ari_length > IB_CM_REJ_ARI_LENGTH))
29162919
return -EINVAL;
29172920

2918-
cm_id_priv = container_of(cm_id, struct cm_id_private, id);
2919-
2920-
spin_lock_irqsave(&cm_id_priv->lock, flags);
2921-
switch (cm_id->state) {
2921+
switch (cm_id_priv->id.state) {
29222922
case IB_CM_REQ_SENT:
29232923
case IB_CM_MRA_REQ_RCVD:
29242924
case IB_CM_REQ_RCVD:
29252925
case IB_CM_MRA_REQ_SENT:
29262926
case IB_CM_REP_RCVD:
29272927
case IB_CM_MRA_REP_SENT:
2928-
ret = cm_alloc_msg(cm_id_priv, &msg);
2929-
if (!ret)
2930-
cm_format_rej((struct cm_rej_msg *) msg->mad,
2931-
cm_id_priv, reason, ari, ari_length,
2932-
private_data, private_data_len);
2933-
29342928
cm_reset_to_idle(cm_id_priv);
2929+
ret = cm_alloc_msg(cm_id_priv, &msg);
2930+
if (ret)
2931+
return ret;
2932+
cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv, reason,
2933+
ari, ari_length, private_data, private_data_len);
29352934
break;
29362935
case IB_CM_REP_SENT:
29372936
case IB_CM_MRA_REP_RCVD:
2938-
ret = cm_alloc_msg(cm_id_priv, &msg);
2939-
if (!ret)
2940-
cm_format_rej((struct cm_rej_msg *) msg->mad,
2941-
cm_id_priv, reason, ari, ari_length,
2942-
private_data, private_data_len);
2943-
29442937
cm_enter_timewait(cm_id_priv);
2938+
ret = cm_alloc_msg(cm_id_priv, &msg);
2939+
if (ret)
2940+
return ret;
2941+
cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv, reason,
2942+
ari, ari_length, private_data, private_data_len);
29452943
break;
29462944
default:
29472945
pr_debug("%s: local_id %d, cm_id->state: %d\n", __func__,
2948-
be32_to_cpu(cm_id_priv->id.local_id), cm_id->state);
2949-
ret = -EINVAL;
2950-
goto out;
2946+
be32_to_cpu(cm_id_priv->id.local_id),
2947+
cm_id_priv->id.state);
2948+
return -EINVAL;
29512949
}
29522950

2953-
if (ret)
2954-
goto out;
2955-
29562951
ret = ib_post_send_mad(msg, NULL);
2957-
if (ret)
2952+
if (ret) {
29582953
cm_free_msg(msg);
2954+
return ret;
2955+
}
29592956

2960-
out: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2957+
return 0;
2958+
}
2959+
2960+
int ib_send_cm_rej(struct ib_cm_id *cm_id, enum ib_cm_rej_reason reason,
2961+
void *ari, u8 ari_length, const void *private_data,
2962+
u8 private_data_len)
2963+
{
2964+
struct cm_id_private *cm_id_priv =
2965+
container_of(cm_id, struct cm_id_private, id);
2966+
unsigned long flags;
2967+
int ret;
2968+
2969+
spin_lock_irqsave(&cm_id_priv->lock, flags);
2970+
ret = cm_send_rej_locked(cm_id_priv, reason, ari, ari_length,
2971+
private_data, private_data_len);
2972+
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
29612973
return ret;
29622974
}
29632975
EXPORT_SYMBOL(ib_send_cm_rej);

0 commit comments

Comments
 (0)