提交 a7db89eb 编写于 作者: S Steve Wise 提交者: Roland Dreier

RDMA/cxgb4: Lock around accept/reject downcalls

There is a race between ULP threads doing an accept/reject, and the
ingress processing thread handling close/abort for the same connection.
The accept/reject path needs to hold the lock to serialize these paths.
Signed-off-by: NSteve Wise <swise@opengridcomputing.com>

[ Fold in locking fix found by Dan Carpenter <dan.carpenter@oracle.com>.
  - Roland ]
Signed-off-by: NRoland Dreier <roland@purestorage.com>
上级 9c88aa00
...@@ -760,7 +760,7 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb, ...@@ -760,7 +760,7 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
ep->mpa_skb = skb; ep->mpa_skb = skb;
c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
start_ep_timer(ep); start_ep_timer(ep);
state_set(&ep->com, MPA_REQ_SENT); __state_set(&ep->com, MPA_REQ_SENT);
ep->mpa_attr.initiator = 1; ep->mpa_attr.initiator = 1;
ep->snd_seq += mpalen; ep->snd_seq += mpalen;
return; return;
...@@ -926,7 +926,7 @@ static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen) ...@@ -926,7 +926,7 @@ static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen)
skb_get(skb); skb_get(skb);
t4_set_arp_err_handler(skb, NULL, arp_failure_discard); t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
ep->mpa_skb = skb; ep->mpa_skb = skb;
state_set(&ep->com, MPA_REP_SENT); __state_set(&ep->com, MPA_REP_SENT);
ep->snd_seq += mpalen; ep->snd_seq += mpalen;
return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
} }
...@@ -944,6 +944,7 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -944,6 +944,7 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb)
PDBG("%s ep %p tid %u snd_isn %u rcv_isn %u\n", __func__, ep, tid, PDBG("%s ep %p tid %u snd_isn %u rcv_isn %u\n", __func__, ep, tid,
be32_to_cpu(req->snd_isn), be32_to_cpu(req->rcv_isn)); be32_to_cpu(req->snd_isn), be32_to_cpu(req->rcv_isn));
mutex_lock(&ep->com.mutex);
dst_confirm(ep->dst); dst_confirm(ep->dst);
/* setup the hwtid for this connection */ /* setup the hwtid for this connection */
...@@ -967,7 +968,7 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -967,7 +968,7 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb)
send_mpa_req(ep, skb, 1); send_mpa_req(ep, skb, 1);
else else
send_mpa_req(ep, skb, mpa_rev); send_mpa_req(ep, skb, mpa_rev);
mutex_unlock(&ep->com.mutex);
return 0; return 0;
} }
...@@ -2511,22 +2512,28 @@ static int fw4_ack(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -2511,22 +2512,28 @@ static int fw4_ack(struct c4iw_dev *dev, struct sk_buff *skb)
int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
{ {
int err; int err = 0;
int disconnect = 0;
struct c4iw_ep *ep = to_ep(cm_id); struct c4iw_ep *ep = to_ep(cm_id);
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
if (state_read(&ep->com) == DEAD) { mutex_lock(&ep->com.mutex);
if (ep->com.state == DEAD) {
mutex_unlock(&ep->com.mutex);
c4iw_put_ep(&ep->com); c4iw_put_ep(&ep->com);
return -ECONNRESET; return -ECONNRESET;
} }
set_bit(ULP_REJECT, &ep->com.history); set_bit(ULP_REJECT, &ep->com.history);
BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD); BUG_ON(ep->com.state != MPA_REQ_RCVD);
if (mpa_rev == 0) if (mpa_rev == 0)
abort_connection(ep, NULL, GFP_KERNEL); abort_connection(ep, NULL, GFP_KERNEL);
else { else {
err = send_mpa_reject(ep, pdata, pdata_len); err = send_mpa_reject(ep, pdata, pdata_len);
err = c4iw_ep_disconnect(ep, 0, GFP_KERNEL); disconnect = 1;
} }
mutex_unlock(&ep->com.mutex);
if (disconnect)
err = c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
c4iw_put_ep(&ep->com); c4iw_put_ep(&ep->com);
return 0; return 0;
} }
...@@ -2541,12 +2548,14 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) ...@@ -2541,12 +2548,14 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
struct c4iw_qp *qp = get_qhp(h, conn_param->qpn); struct c4iw_qp *qp = get_qhp(h, conn_param->qpn);
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
if (state_read(&ep->com) == DEAD) {
mutex_lock(&ep->com.mutex);
if (ep->com.state == DEAD) {
err = -ECONNRESET; err = -ECONNRESET;
goto err; goto err;
} }
BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD); BUG_ON(ep->com.state != MPA_REQ_RCVD);
BUG_ON(!qp); BUG_ON(!qp);
set_bit(ULP_ACCEPT, &ep->com.history); set_bit(ULP_ACCEPT, &ep->com.history);
...@@ -2615,14 +2624,16 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) ...@@ -2615,14 +2624,16 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (err) if (err)
goto err1; goto err1;
state_set(&ep->com, FPDU_MODE); __state_set(&ep->com, FPDU_MODE);
established_upcall(ep); established_upcall(ep);
mutex_unlock(&ep->com.mutex);
c4iw_put_ep(&ep->com); c4iw_put_ep(&ep->com);
return 0; return 0;
err1: err1:
ep->com.cm_id = NULL; ep->com.cm_id = NULL;
cm_id->rem_ref(cm_id); cm_id->rem_ref(cm_id);
err: err:
mutex_unlock(&ep->com.mutex);
c4iw_put_ep(&ep->com); c4iw_put_ep(&ep->com);
return err; return err;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册