#include <byteswap.h>
#include <stddef.h>
#include <netdb.h>
+#include <syslog.h>
#include "cma.h"
+#include "indexer.h"
#include <infiniband/driver.h>
#include <infiniband/marshall.h>
#include <rdma/rdma_cma.h>
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static int abi_ver = RDMA_USER_CM_MAX_ABI_VERSION;
int af_ib_support;
+static struct index_map ucma_idm;
+static fastlock_t idm_lock;
static void ucma_cleanup(void)
{
ibv_close_device(cma_dev_array[cma_dev_cnt].verbs);
}
+ fastlock_destroy(&idm_lock);
free(cma_dev_array);
cma_dev_cnt = 0;
}
return 0;
}
+ fastlock_init(&idm_lock);
ret = check_abi_version();
if (ret)
goto err1;
err2:
ibv_free_device_list(dev_list);
err1:
+ fastlock_destroy(&idm_lock);
pthread_mutex_unlock(&mut);
return ret;
}
pthread_mutex_unlock(&mut);
}
+static void ucma_insert_id(struct cma_id_private *id_priv)
+{
+ fastlock_acquire(&idm_lock);
+ idm_set(&ucma_idm, id_priv->handle, id_priv);
+ fastlock_release(&idm_lock);
+}
+
+static void ucma_remove_id(struct cma_id_private *id_priv)
+{
+ if (id_priv->handle <= IDX_MAX_INDEX)
+ idm_clear(&ucma_idm, id_priv->handle);
+}
+
+static struct cma_id_private *ucma_lookup_id(int handle)
+{
+ return idm_lookup(&ucma_idm, handle);
+}
+
static void ucma_free_id(struct cma_id_private *id_priv)
{
+ ucma_remove_id(id_priv);
if (id_priv->cma_dev)
ucma_put_device(id_priv->cma_dev);
pthread_cond_destroy(&id_priv->cond);
id_priv->id.context = context;
id_priv->id.ps = ps;
id_priv->id.qp_type = qp_type;
+ id_priv->handle = 0xFFFFFFFF;
if (!channel) {
id_priv->id.channel = rdma_create_event_channel();
VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
id_priv->handle = resp.id;
+ ucma_insert_id(id_priv);
*id = &id_priv->id;
return 0;
evt->event.listen_id = &evt->id_priv->id;
evt->event.id = &id_priv->id;
id_priv->handle = handle;
+ ucma_insert_id(id_priv);
id_priv->initiator_depth = evt->event.param.conn.initiator_depth;
id_priv->responder_resources = evt->event.param.conn.responder_resources;
VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
evt->event.event = resp.event;
- evt->id_priv = (void *) (uintptr_t) resp.uid;
+ /*
+ * We should have a non-zero uid, except for connection requests.
+ * But a bug in older kernels can report a uid 0. Work-around this
+ * issue by looking up the cma_id based on the kernel's id when the
+ * uid is 0 and we're processing a connection established event.
+ * In all other cases, if the uid is 0, we discard the event, like
+ * the kernel should have done.
+ */
+ if (resp.uid) {
+ evt->id_priv = (void *) (uintptr_t) resp.uid;
+ } else {
+ evt->id_priv = ucma_lookup_id(resp.id);
+ if (!evt->id_priv) {
+ syslog(LOG_WARNING, PFX "Warning: discarding unmatched "
+ "event - rdma_destroy_id may hang.\n");
+ goto retry;
+ }
+ if (resp.event != RDMA_CM_EVENT_ESTABLISHED) {
+ ucma_complete_event(evt->id_priv);
+ goto retry;
+ }
+ }
evt->event.id = &evt->id_priv->id;
evt->event.status = resp.status;