aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorSteve Wise <swise@opengridcomputing.com>2012-03-07 17:48:11 -0500
committerRoland Dreier <roland@purestorage.com>2012-03-07 18:14:53 -0500
commit3eae7c9f97415ac1f5ab5db4eeb03cde689eb427 (patch)
treefa29c0cc9e465395808607cc9506445ba7473729 /drivers/infiniband
parent8154c07fe14e387c5a7c7f2eb70534813634e45e (diff)
RDMA/iwcm: Reject connect requests if cmid is not in LISTEN state
When destroying a listening cmid, the iwcm first marks the state of the cmid as DESTROYING, then releases the lock and calls into the iWARP provider to destroy the endpoint. Since the cmid is not locked, its possible for the iWARP provider to pass a connection request event to the iwcm, which will be silently dropped by the iwcm. This causes the iWARP provider to never free up the resources from this connection because the assumption is the iwcm will accept or reject this connection. The solution is to reject these connection requests. Signed-off-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/core/iwcm.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index 1a696f76b616..0bb99bb38809 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -624,17 +624,6 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
624 */ 624 */
625 BUG_ON(iw_event->status); 625 BUG_ON(iw_event->status);
626 626
627 /*
628 * We could be destroying the listening id. If so, ignore this
629 * upcall.
630 */
631 spin_lock_irqsave(&listen_id_priv->lock, flags);
632 if (listen_id_priv->state != IW_CM_STATE_LISTEN) {
633 spin_unlock_irqrestore(&listen_id_priv->lock, flags);
634 goto out;
635 }
636 spin_unlock_irqrestore(&listen_id_priv->lock, flags);
637
638 cm_id = iw_create_cm_id(listen_id_priv->id.device, 627 cm_id = iw_create_cm_id(listen_id_priv->id.device,
639 listen_id_priv->id.cm_handler, 628 listen_id_priv->id.cm_handler,
640 listen_id_priv->id.context); 629 listen_id_priv->id.context);
@@ -649,6 +638,19 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
649 cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); 638 cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
650 cm_id_priv->state = IW_CM_STATE_CONN_RECV; 639 cm_id_priv->state = IW_CM_STATE_CONN_RECV;
651 640
641 /*
642 * We could be destroying the listening id. If so, ignore this
643 * upcall.
644 */
645 spin_lock_irqsave(&listen_id_priv->lock, flags);
646 if (listen_id_priv->state != IW_CM_STATE_LISTEN) {
647 spin_unlock_irqrestore(&listen_id_priv->lock, flags);
648 iw_cm_reject(cm_id, NULL, 0);
649 iw_destroy_cm_id(cm_id);
650 goto out;
651 }
652 spin_unlock_irqrestore(&listen_id_priv->lock, flags);
653
652 ret = alloc_work_entries(cm_id_priv, 3); 654 ret = alloc_work_entries(cm_id_priv, 3);
653 if (ret) { 655 if (ret) {
654 iw_cm_reject(cm_id, NULL, 0); 656 iw_cm_reject(cm_id, NULL, 0);