This closes a window where address resolution can attach an rdma_cm_id
to a device during destruction of the rdma_cm_id.  This can result in
the rdma_cm_id remaining in the device list after its memory has been
freed.

Signed-off-by: Sean Hefty <[EMAIL PROTECTED]>
---
I generated this patch off the tip of the for-2.6.19 git branch, so
it applies on top of the iWarp changes.

Also, OF is looking at hosting git repositories.  Once available,
I will publish the patches there.

diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index c54c55a..2964dab 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -279,7 +279,7 @@ static int cma_acquire_dev(struct rdma_i
        default:
                return -ENODEV;
        }
-       mutex_lock(&lock);
+
        list_for_each_entry(cma_dev, &dev_list, list) {
                ret = ib_find_cached_gid(cma_dev->device, &gid,
                                         &id_priv->id.port_num, NULL);
@@ -288,7 +288,6 @@ static int cma_acquire_dev(struct rdma_i
                        break;
                }
        }
-       mutex_unlock(&lock);
        return ret;
 }
 
@@ -712,7 +711,9 @@ void rdma_destroy_id(struct rdma_cm_id *
        state = cma_exch(id_priv, CMA_DESTROYING);
        cma_cancel_operation(id_priv, state);
 
+       mutex_lock(&lock);
        if (id_priv->cma_dev) {
+               mutex_unlock(&lock);
                switch (rdma_node_get_transport(id->device->node_type)) {
                case RDMA_TRANSPORT_IB:
                        if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
@@ -727,8 +728,8 @@ void rdma_destroy_id(struct rdma_cm_id *
                }
                mutex_lock(&lock);
                cma_detach_from_dev(id_priv);
-               mutex_unlock(&lock);
        }
+       mutex_unlock(&lock);
 
        cma_release_port(id_priv);
        cma_deref_id(id_priv);
@@ -925,7 +926,9 @@ static int cma_req_handler(struct ib_cm_
        }
 
        atomic_inc(&conn_id->dev_remove);
+       mutex_lock(&lock);
        ret = cma_acquire_dev(conn_id);
+       mutex_unlock(&lock);
        if (ret) {
                ret = -ENODEV;
                cma_release_remove(conn_id);
@@ -1097,7 +1100,9 @@ static int iw_conn_req_handler(struct iw
                goto out;
        }
 
+       mutex_lock(&lock);
        ret = cma_acquire_dev(conn_id);
+       mutex_unlock(&lock);
        if (ret) {
                cma_release_remove(conn_id);
                rdma_destroy_id(new_cm_id);
@@ -1507,16 +1512,26 @@ static void addr_handler(int status, str
        enum rdma_cm_event_type event;
 
        atomic_inc(&id_priv->dev_remove);
-       if (!id_priv->cma_dev && !status)
+
+       /*
+        * Grab mutex to block rdma_destroy_id() from removing the device while
+        * we're trying to acquire it.
+        */
+       mutex_lock(&lock);
+       if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED)) {
+               mutex_unlock(&lock);
+               goto out;
+       }
+
+       if (!status && !id_priv->cma_dev)
                status = cma_acquire_dev(id_priv);
+       mutex_unlock(&lock);
 
        if (status) {
-               if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND))
+               if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ADDR_BOUND))
                        goto out;
                event = RDMA_CM_EVENT_ADDR_ERROR;
        } else {
-               if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED))
-                       goto out;
                memcpy(&id_priv->id.route.addr.src_addr, src_addr,
                       ip_addr_size(src_addr));
                event = RDMA_CM_EVENT_ADDR_RESOLVED;
@@ -1740,8 +1755,11 @@ int rdma_bind_addr(struct rdma_cm_id *id
 
        if (!cma_any_addr(addr)) {
                ret = rdma_translate_ip(addr, &id->route.addr.dev_addr);
-               if (!ret)
+               if (!ret) {
+                       mutex_lock(&lock);
                        ret = cma_acquire_dev(id_priv);
+                       mutex_unlock(&lock);
+               }
                if (ret)
                        goto err;
        }


_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to