librdmacm: fix race in ucma_init()
[mirror/winof/.git] / ulp / librdmacm / src / cma.cpp
index 6f4e5e1..7d31c30 100644 (file)
@@ -38,7 +38,6 @@
 #include <iba/ibat.h>\r
 #include "cma.h"\r
 #include "..\..\..\etc\user\comp_channel.cpp"\r
-#include "..\..\..\etc\user\dlist.c"\r
 \r
 static struct ibvw_windata windata;\r
 \r
@@ -92,63 +91,49 @@ struct cma_event {
 static struct cma_device *cma_dev_array;\r
 static int cma_dev_cnt;\r
 \r
-static void ucma_cleanup(void)\r
-{\r
-       if (cma_dev_cnt > 0) {\r
-               while (cma_dev_cnt > 0) {\r
-                       ibv_close_device(cma_dev_array[--cma_dev_cnt].verbs);\r
-               }\r
-               delete cma_dev_array;\r
-               cma_dev_cnt = 0;\r
-       }\r
-       if (windata.prov != NULL) {\r
-               ibvw_release_windata(&windata, IBVW_WINDATA_VERSION);\r
-               windata.prov = NULL;\r
-       }\r
-}\r
-\r
 static int ucma_init(void)\r
 {\r
        struct ibv_device **dev_list = NULL;\r
        struct cma_device *cma_dev;\r
        struct ibv_device_attr attr;\r
-       int i, ret;\r
+       int i, ret, dev_cnt;\r
 \r
        EnterCriticalSection(&lock);\r
-       if (cma_dev_cnt > 0) {\r
+       if (cma_dev_cnt) {\r
                goto out;\r
        }\r
 \r
        ret = ibvw_get_windata(&windata, IBVW_WINDATA_VERSION);\r
        if (ret) {\r
-               goto err;\r
+               goto err1;\r
        }\r
 \r
-       dev_list = ibv_get_device_list(&cma_dev_cnt);\r
+       dev_list = ibv_get_device_list(&dev_cnt);\r
        if (dev_list == NULL) {\r
                ret = -1;\r
-               goto err;\r
+               goto err2;\r
        }\r
 \r
-       cma_dev_array = new struct cma_device[cma_dev_cnt];\r
+       cma_dev_array = new struct cma_device[dev_cnt];\r
        if (cma_dev_array == NULL) {\r
                ret = -1;\r
-               goto err;\r
+               goto err3;\r
        }\r
 \r
-       for (i = 0; dev_list[i]; ++i) {\r
+       for (i = 0; dev_list[i];) {\r
                cma_dev = &cma_dev_array[i];\r
 \r
                cma_dev->guid = ibv_get_device_guid(dev_list[i]);\r
                cma_dev->verbs = ibv_open_device(dev_list[i]);\r
                if (cma_dev->verbs == NULL) {\r
                        ret = -1;\r
-                       goto err;\r
+                       goto err4;\r
                }\r
 \r
+               ++i;\r
                ret = ibv_query_device(cma_dev->verbs, &attr);\r
                if (ret) {\r
-                       goto err;\r
+                       goto err4;\r
                }\r
 \r
                cma_dev->port_cnt = attr.phys_port_cnt;\r
@@ -156,16 +141,22 @@ static int ucma_init(void)
                cma_dev->max_responder_resources = (uint8_t) attr.max_qp_rd_atom;\r
        }\r
        ibv_free_device_list(dev_list);\r
+       cma_dev_cnt = dev_cnt;\r
 out:\r
        LeaveCriticalSection(&lock);\r
        return 0;\r
 \r
-err:\r
-       ucma_cleanup();\r
-       LeaveCriticalSection(&lock);\r
-       if (dev_list) {\r
-               ibv_free_device_list(dev_list);\r
+err4:\r
+       while (i) {\r
+               ibv_close_device(cma_dev_array[--i].verbs);\r
        }\r
+       delete cma_dev_array;\r
+err3:\r
+       ibv_free_device_list(dev_list);\r
+err2:\r
+       ibvw_release_windata(&windata, IBVW_WINDATA_VERSION);\r
+err1:\r
+       LeaveCriticalSection(&lock);\r
        return ret;\r
 }\r
 \r
@@ -498,7 +489,16 @@ int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)
        IBAT_PATH_BLOB path;\r
        HRESULT hr;\r
 \r
-       hr = IBAT::Resolve(&id->route.addr.src_addr, &id->route.addr.dst_addr, &path);\r
+       do {\r
+               hr = IBAT::Resolve(&id->route.addr.src_addr, &id->route.addr.dst_addr, &path);\r
+               if (hr != E_PENDING) {\r
+                       break;\r
+               }\r
+               timeout_ms -= 10;\r
+               if (timeout_ms > 0)\r
+                       Sleep(10);\r
+       } while (timeout_ms > 0);\r
+\r
        if (FAILED(hr)) {\r
                return hr;\r
        }\r
@@ -987,6 +987,7 @@ int rdma_get_cm_event(struct rdma_event_channel *channel,
 \r
                ret = CompChannelPoll(&channel->channel, &entry);\r
                if (ret) {\r
+                       delete evt;\r
                        return ret;\r
                }\r
 \r