static int usdf_fabric_getname(uint32_t version, struct usd_device_attrs *dap, char **name) { int ret = FI_SUCCESS; char *bufp = NULL; struct in_addr in; char *addrnetw; if (FI_VERSION_GE(version, FI_VERSION(1, 4))) { in.s_addr = dap->uda_ipaddr_be & dap->uda_netmask_be; addrnetw = inet_ntoa(in); ret = asprintf(&bufp, "%s/%d", addrnetw, dap->uda_prefixlen); if (ret < 0) { USDF_DBG( "asprintf failed while creating fabric name\n"); ret = -ENOMEM; } } else { bufp = strdup(dap->uda_devname); if (!bufp) { USDF_DBG("strdup failed while creating fabric name\n"); ret = -errno; } } *name = bufp; return ret; }
static ssize_t fi_ibv_eq_readerr(struct fid_eq *eq, struct fi_eq_err_entry *entry, uint64_t flags) { struct fi_ibv_eq *_eq; uint32_t api_version; void *err_data = NULL; size_t err_data_size = 0; _eq = container_of(eq, struct fi_ibv_eq, eq_fid.fid); if (!_eq->err.err) return 0; api_version = _eq->fab->util_fabric.fabric_fid.api_version; if ((FI_VERSION_GE(api_version, FI_VERSION(1, 5))) && entry->err_data && entry->err_data_size) { err_data_size = MIN(entry->err_data_size, _eq->err.err_data_size); err_data = _eq->err.err_data; } *entry = _eq->err; if (err_data) { memcpy(entry->err_data, err_data, err_data_size); entry->err_data_size = err_data_size; } _eq->err.err = 0; _eq->err.prov_errno = 0; return sizeof(*entry); }
void ofi_eq_handle_err_entry(uint32_t api_version, struct fi_eq_err_entry *err_entry, struct fi_eq_err_entry *user_err_entry) { if ((FI_VERSION_GE(api_version, FI_VERSION(1, 5))) && user_err_entry->err_data && user_err_entry->err_data_size) { void *err_data = user_err_entry->err_data; size_t err_data_size = MIN(err_entry->err_data_size, user_err_entry->err_data_size); memcpy(err_data, err_entry->err_data, err_data_size); *user_err_entry = *err_entry; user_err_entry->err_data = err_data; user_err_entry->err_data_size = err_data_size; free(err_entry->err_data); err_entry->err_data = NULL; err_entry->err_data_size = 0; } else { *user_err_entry = *err_entry; } err_entry->err = 0; err_entry->prov_errno = 0; }
int rxm_info_to_core(uint32_t version, struct fi_info *hints, struct fi_info *core_info) { core_info->caps = FI_MSG; /* Support modes that ofi_rxm could handle */ if (FI_VERSION_GE(version, FI_VERSION(1, 5))) core_info->domain_attr->mr_mode |= FI_MR_LOCAL; else core_info->mode |= (FI_LOCAL_MR | FI_RX_CQ_DATA); if (hints) { /* No fi_info modes apart from FI_LOCAL_MR, FI_RX_CQ_DATA * can be passed along to the core provider */ // core_info->mode |= hints->mode; if (hints->domain_attr) { if (FI_VERSION_GE(version, FI_VERSION(1, 5))) { /* Allow only those mr modes that can be * passed along to the core provider */ core_info->domain_attr->mr_mode |= hints->domain_attr->mr_mode & OFI_MR_BASIC_MAP; } else { core_info->domain_attr->mr_mode = hints->domain_attr->mr_mode; } core_info->domain_attr->caps |= hints->domain_attr->caps; } } else { /* Since hints is NULL fake support for FI_MR_BASIC to allow * discovery of core providers like verbs which require it */ if (FI_VERSION_GE(version, FI_VERSION(1, 5))) core_info->domain_attr->mr_mode |= OFI_MR_BASIC_MAP; else /* Specify FI_MR_UNSPEC so that providers that support * FI_MR_SCALABLE aren't dropped */ core_info->domain_attr->mr_mode = FI_MR_UNSPEC; } core_info->ep_attr->rx_ctx_cnt = FI_SHARED_CONTEXT; core_info->ep_attr->type = FI_EP_MSG; return 0; }
static ssize_t fi_ibv_cq_readerr(struct fid_cq *cq_fid, struct fi_cq_err_entry *entry, uint64_t flags) { struct fi_ibv_cq *cq; struct fi_ibv_wce *wce; struct slist_entry *slist_entry; uint32_t api_version; cq = container_of(cq_fid, struct fi_ibv_cq, util_cq.cq_fid); cq->util_cq.cq_fastlock_acquire(&cq->util_cq.cq_lock); if (slist_empty(&cq->wcq)) goto err; wce = container_of(cq->wcq.head, struct fi_ibv_wce, entry); if (!wce->wc.status) goto err; api_version = cq->util_cq.domain->fabric->fabric_fid.api_version; slist_entry = slist_remove_head(&cq->wcq); cq->util_cq.cq_fastlock_release(&cq->util_cq.cq_lock); wce = container_of(slist_entry, struct fi_ibv_wce, entry); entry->op_context = (void *)(uintptr_t)wce->wc.wr_id; entry->err = EIO; entry->prov_errno = wce->wc.status; fi_ibv_handle_wc(&wce->wc, &entry->flags, &entry->len, &entry->data); if ((FI_VERSION_GE(api_version, FI_VERSION(1, 5))) && entry->err_data && entry->err_data_size) { entry->err_data_size = MIN(entry->err_data_size, sizeof(wce->wc.vendor_err)); memcpy(entry->err_data, &wce->wc.vendor_err, entry->err_data_size); } else { memcpy(&entry->err_data, &wce->wc.vendor_err, sizeof(wce->wc.vendor_err)); } util_buf_release(cq->wce_pool, wce); return 1; err: cq->util_cq.cq_fastlock_release(&cq->util_cq.cq_lock); return -FI_EAGAIN; }
int usdf_domain_getname(uint32_t version, struct usd_device_attrs *dap, char **name) { int ret = FI_SUCCESS; char *buf = NULL; if (FI_VERSION_GE(version, FI_VERSION(1, 4))) { buf = strdup(dap->uda_devname); if (!buf) { ret = -errno; USDF_DBG("strdup failed while creating domain name\n"); } } *name = buf; return ret; }
static ssize_t sock_cq_readerr(struct fid_cq *cq, struct fi_cq_err_entry *buf, uint64_t flags) { struct sock_cq *sock_cq; ssize_t ret; struct fi_cq_err_entry entry; uint32_t api_version; size_t err_data_size = 0; void *err_data = NULL; sock_cq = container_of(cq, struct sock_cq, cq_fid); if (sock_cq->domain->progress_mode == FI_PROGRESS_MANUAL) sock_cq_progress(sock_cq); fastlock_acquire(&sock_cq->lock); if (ofi_rbused(&sock_cq->cqerr_rb) >= sizeof(struct fi_cq_err_entry)) { api_version = sock_cq->domain->fab->fab_fid.api_version; ofi_rbread(&sock_cq->cqerr_rb, &entry, sizeof(entry)); if ((FI_VERSION_GE(api_version, FI_VERSION(1, 5))) && buf->err_data && buf->err_data_size) { err_data = buf->err_data; err_data_size = buf->err_data_size; *buf = entry; buf->err_data = err_data; /* Fill provided user's buffer */ buf->err_data_size = MIN(entry.err_data_size, err_data_size); memcpy(buf->err_data, entry.err_data, buf->err_data_size); } else { *buf = entry; } ret = 1; } else { ret = -FI_EAGAIN; } fastlock_release(&sock_cq->lock); return ret; }
int DEFAULT_SYMVER_PRE(fi_fabric)(struct fi_fabric_attr *attr, struct fid_fabric **fabric, void *context) { struct ofi_prov *prov; const char *top_name; int ret; if (!attr || !attr->prov_name || !attr->name) return -FI_EINVAL; if (!ofi_init) fi_ini(); top_name = strrchr(attr->prov_name, OFI_NAME_DELIM); if (top_name) top_name++; else top_name = attr->prov_name; if (!top_name) return -FI_EINVAL; prov = ofi_getprov(top_name, strlen(top_name)); if (!prov || !prov->provider || !prov->provider->fabric) return -FI_ENODEV; ret = prov->provider->fabric(attr, fabric, context); if (!ret) { if (FI_VERSION_GE(prov->provider->fi_version, FI_VERSION(1, 5))) (*fabric)->api_version = attr->api_version; FI_INFO(&core_prov, FI_LOG_CORE, "Opened fabric: %s\n", attr->name); ofi_hook_install(*fabric, fabric, prov->provider); } return ret; }
static int fi_register_provider(struct fi_provider *provider, void *dlhandle) { struct fi_prov_context *ctx; struct fi_prov *prov; int ret; if (!provider) { ret = -FI_EINVAL; goto cleanup; } FI_INFO(&core_prov, FI_LOG_CORE, "registering provider: %s (%d.%d)\n", provider->name, FI_MAJOR(provider->version), FI_MINOR(provider->version)); /* The current core implementation is not backward compatible * with providers that support a release earlier than v1.3. * See commit 0f4b6651. */ if (provider->fi_version < FI_VERSION(1, 3)) { FI_INFO(&core_prov, FI_LOG_CORE, "provider has unsupported FI version " "(provider %d.%d != libfabric %d.%d); ignoring\n", FI_MAJOR(provider->fi_version), FI_MINOR(provider->fi_version), FI_MAJOR_VERSION, FI_MINOR_VERSION); ret = -FI_ENOSYS; goto cleanup; } if (fi_apply_filter(&prov_filter, provider->name)) { FI_INFO(&core_prov, FI_LOG_CORE, "\"%s\" filtered by provider include/exclude list, skipping\n", provider->name); ret = -FI_ENODEV; goto cleanup; } if (fi_apply_filter(&prov_log_filter, provider->name)) { ctx = (struct fi_prov_context *) &provider->context; ctx->disable_logging = 1; } prov = fi_getprov(provider->name); if (prov) { /* If this provider is older than an already-loaded * provider of the same name, then discard this one. */ if (FI_VERSION_GE(prov->provider->version, provider->version)) { FI_INFO(&core_prov, FI_LOG_CORE, "a newer %s provider was already loaded; " "ignoring this one\n", provider->name); ret = -FI_EALREADY; goto cleanup; } /* This provider is newer than an already-loaded * provider of the same name, so discard the * already-loaded one. */ FI_INFO(&core_prov, FI_LOG_CORE, "an older %s provider was already loaded; " "keeping this one and ignoring the older one\n", provider->name); cleanup_provider(prov->provider, prov->dlhandle); prov->dlhandle = dlhandle; prov->provider = provider; return 0; } prov = calloc(sizeof *prov, 1); if (!prov) { ret = -FI_ENOMEM; goto cleanup; } prov->dlhandle = dlhandle; prov->provider = provider; if (prov_tail) prov_tail->next = prov; else prov_head = prov; prov_tail = prov; return 0; cleanup: cleanup_provider(provider, dlhandle); return ret; }
static int usdf_fill_info_dgram( uint32_t version, struct fi_info *hints, struct sockaddr_in *src, struct sockaddr_in *dest, struct usd_device_attrs *dap, struct fi_info **fi_first, struct fi_info **fi_last) { struct fi_info *fi; struct fi_fabric_attr *fattrp; uint32_t addr_format; int ret; fi = fi_allocinfo(); if (fi == NULL) { ret = -FI_ENOMEM; goto fail; } fi->caps = USDF_DGRAM_CAPS; if (hints != NULL) { fi->mode = hints->mode & USDF_DGRAM_SUPP_MODE; addr_format = hints->addr_format; /* check that we are capable of what's requested */ if ((hints->caps & ~USDF_DGRAM_CAPS) != 0) { ret = -FI_ENODATA; goto fail; } /* app must support these modes */ if ((hints->mode & USDF_DGRAM_REQ_MODE) != USDF_DGRAM_REQ_MODE) { ret = -FI_ENODATA; goto fail; } fi->handle = hints->handle; } else { fi->mode = USDF_DGRAM_SUPP_MODE; addr_format = FI_FORMAT_UNSPEC; } fi->ep_attr->type = FI_EP_DGRAM; ret = usdf_fill_addr_info(fi, addr_format, src, dest, dap); if (ret != 0) { goto fail; } /* fabric attrs */ fattrp = fi->fabric_attr; fattrp->name = strdup(dap->uda_devname); if (fattrp->name == NULL) { ret = -FI_ENOMEM; goto fail; } if (fi->mode & FI_MSG_PREFIX) { if (FI_VERSION_GE(version, FI_VERSION(1, 1))) fi->ep_attr->msg_prefix_size = USDF_HDR_BUF_ENTRY; else fi->mode &= ~FI_MSG_PREFIX; } ret = usdf_dgram_fill_ep_attr(hints, fi, dap); if (ret) goto fail; ret = usdf_dgram_fill_dom_attr(hints, fi); if (ret) goto fail; ret = usdf_dgram_fill_tx_attr(hints, fi, dap); if (ret) goto fail; ret = usdf_dgram_fill_rx_attr(hints, fi, dap); if (ret) goto fail; /* add to tail of list */ if (*fi_first == NULL) { *fi_first = fi; } else { (*fi_last)->next = fi; } *fi_last = fi; return 0; fail: if (fi != NULL) { fi_freeinfo(fi); } return ret; }
static int _gnix_ep_getinfo(enum fi_ep_type ep_type, uint32_t version, const char *node, const char *service, uint64_t flags, struct fi_info *hints, struct fi_info **info) { uint64_t mode = GNIX_FAB_MODES; struct fi_info *gnix_info = NULL; int ret = -FI_ENODATA; GNIX_TRACE(FI_LOG_FABRIC, "\n"); if ((hints && hints->ep_attr) && (hints->ep_attr->type != FI_EP_UNSPEC && hints->ep_attr->type != ep_type)) { return -FI_ENODATA; } gnix_info = _gnix_allocinfo(); if (!gnix_info) return -FI_ENOMEM; gnix_info->ep_attr->type = ep_type; if (hints) { /* TODO: Add version check when we decide on how to do it */ if (hints->addr_format == FI_ADDR_STR) { gnix_info->addr_format = FI_ADDR_STR; } if (hints->ep_attr) { /* Only support FI_PROTO_GNI protocol. */ switch (hints->ep_attr->protocol) { case FI_PROTO_UNSPEC: case FI_PROTO_GNI: break; default: goto err; } if ((hints->ep_attr->tx_ctx_cnt > GNIX_SEP_MAX_CNT) && (hints->ep_attr->tx_ctx_cnt != FI_SHARED_CONTEXT)) { goto err; } if (hints->ep_attr->rx_ctx_cnt > GNIX_SEP_MAX_CNT) goto err; if (hints->ep_attr->tx_ctx_cnt) gnix_info->ep_attr->tx_ctx_cnt = hints->ep_attr->tx_ctx_cnt; if (hints->ep_attr->rx_ctx_cnt) gnix_info->ep_attr->rx_ctx_cnt = hints->ep_attr->rx_ctx_cnt; if (hints->ep_attr->max_msg_size > GNIX_MAX_MSG_SIZE) goto err; } GNIX_DEBUG(FI_LOG_FABRIC, "Passed EP attributes check\n"); /* * check the mode field */ if (hints->mode) { if ((hints->mode & GNIX_FAB_MODES) != GNIX_FAB_MODES) { goto err; } mode = hints->mode & ~GNIX_FAB_MODES_CLEAR; } GNIX_DEBUG(FI_LOG_FABRIC, "Passed mode check\n"); if (hints->caps) { /* The provider must support all requested * capabilities. */ if ((hints->caps & GNIX_EP_CAPS_FULL) != hints->caps) goto err; /* The provider may silently enable secondary * capabilities that do not introduce any overhead. */ gnix_info->caps = hints->caps | GNIX_EP_SEC_CAPS; } GNIX_DEBUG(FI_LOG_FABRIC, "Passed caps check gnix_info->caps = 0x%016lx\n", gnix_info->caps); if (hints->tx_attr) { if ((hints->tx_attr->op_flags & GNIX_EP_OP_FLAGS) != hints->tx_attr->op_flags) { goto err; } if (hints->tx_attr->inject_size > GNIX_INJECT_SIZE) { goto err; } gnix_info->tx_attr->op_flags = hints->tx_attr->op_flags & GNIX_EP_OP_FLAGS; } GNIX_DEBUG(FI_LOG_FABRIC, "Passed TX attributes check\n"); if (hints->rx_attr) { if ((hints->rx_attr->op_flags & GNIX_EP_OP_FLAGS) != hints->rx_attr->op_flags) { goto err; } gnix_info->rx_attr->op_flags = hints->rx_attr->op_flags & GNIX_EP_OP_FLAGS; } if (hints->fabric_attr && hints->fabric_attr->name && strncmp(hints->fabric_attr->name, gnix_fab_name, strlen(gnix_fab_name))) { goto err; } GNIX_DEBUG(FI_LOG_FABRIC, "Passed fabric name check\n"); if (hints->domain_attr) { if (hints->domain_attr->name && strncmp(hints->domain_attr->name, gnix_dom_name, strlen(gnix_dom_name))) { goto err; } if (hints->domain_attr->control_progress != FI_PROGRESS_UNSPEC) gnix_info->domain_attr->control_progress = hints->domain_attr->control_progress; if (hints->domain_attr->data_progress != FI_PROGRESS_UNSPEC) gnix_info->domain_attr->data_progress = hints->domain_attr->data_progress; switch (hints->domain_attr->mr_mode) { case FI_MR_UNSPEC: case FI_MR_BASIC: if (FI_VERSION_GE(version, FI_VERSION(1, 5))) { hints->domain_attr->mr_mode = OFI_MR_BASIC_MAP; } break; case FI_MR_SCALABLE: GNIX_WARN(FI_LOG_FABRIC, "GNI provider doesn't currently support MR_SCALABLE\n"); goto err; } switch (hints->domain_attr->threading) { case FI_THREAD_COMPLETION: gnix_info->domain_attr->threading = hints->domain_attr->threading; break; default: break; } if (hints->domain_attr->caps) { if (hints->domain_attr->caps & ~GNIX_DOM_CAPS) { GNIX_WARN(FI_LOG_FABRIC, "Invalid domain caps\n"); goto err; } gnix_info->domain_attr->caps = hints->domain_attr->caps; } ret = ofi_check_domain_attr(&gnix_prov, version, gnix_info->domain_attr, hints->domain_attr); if (ret) { GNIX_WARN(FI_LOG_FABRIC, "GNI failed domain attributes check\n"); goto err; } GNIX_DEBUG(FI_LOG_FABRIC, "Passed the domain attributes check\n"); } } ret = __gnix_getinfo_resolve_node(node, service, flags, hints, gnix_info); if (ret != FI_SUCCESS) goto err; gnix_info->mode = mode; gnix_info->fabric_attr->name = strdup(gnix_fab_name); gnix_info->tx_attr->caps = gnix_info->caps; gnix_info->tx_attr->mode = gnix_info->mode; gnix_info->rx_attr->caps = gnix_info->caps; gnix_info->rx_attr->mode = gnix_info->mode; *info = gnix_info; GNIX_DEBUG(FI_LOG_FABRIC, "Returning EP type: %s\n", fi_tostr(&ep_type, FI_TYPE_EP_TYPE)); return FI_SUCCESS; err: fi_freeinfo(gnix_info); return ret; }
static int psmx_getinfo(uint32_t version, const char *node, const char *service, uint64_t flags, const struct fi_info *hints, struct fi_info **info) { struct fi_info *psmx_info; uint32_t cnt = 0; psm_epid_t *dest_addr = NULL; struct psmx_src_name *src_addr = NULL; int ep_type = FI_EP_RDM; int av_type = FI_AV_UNSPEC; uint64_t mode = FI_CONTEXT; enum fi_mr_mode mr_mode = FI_MR_SCALABLE; enum fi_threading threading = FI_THREAD_COMPLETION; enum fi_progress control_progress = FI_PROGRESS_MANUAL; enum fi_progress data_progress = FI_PROGRESS_MANUAL; int caps = 0; uint64_t max_tag_value = 0; int err = -FI_ENODATA; int svc0, svc = PSMX_ANY_SERVICE; FI_INFO(&psmx_prov, FI_LOG_CORE,"\n"); *info = NULL; /* Perform some quick check first to avoid unnecessary operations */ if (hints) { if (hints->fabric_attr && hints->fabric_attr->name && strcasecmp(hints->fabric_attr->name, PSMX_FABRIC_NAME)) { FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->fabric_name=%s, supported=%s\n", hints->fabric_attr->name, PSMX_FABRIC_NAME); goto err_out; } if (hints->domain_attr && hints->domain_attr->name && strcasecmp(hints->domain_attr->name, PSMX_DOMAIN_NAME)) { FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->domain_name=%s, supported=%s\n", hints->domain_attr->name, PSMX_DOMAIN_NAME); goto err_out; } if (hints->ep_attr) { switch (hints->ep_attr->type) { case FI_EP_UNSPEC: case FI_EP_DGRAM: case FI_EP_RDM: break; default: FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->ep_attr->type=%d, supported=%d,%d,%d.\n", hints->ep_attr->type, FI_EP_UNSPEC, FI_EP_DGRAM, FI_EP_RDM); goto err_out; } } if ((hints->caps & PSMX_CAPS) != hints->caps && (hints->caps & PSMX_CAPS2) != hints->caps) { uint64_t psmx_caps = PSMX_CAPS; uint64_t psmx_caps2 = PSMX_CAPS2; PSMX_INFO_DIFF("hints->caps", hints->caps, psmx_caps, FI_TYPE_CAPS); PSMX_INFO_DIFF("alternatively, hints->caps", hints->caps, psmx_caps2, FI_TYPE_CAPS); goto err_out; } } if (FI_VERSION_GE(version, FI_VERSION(1,5))) mr_mode = 0; if (psmx_init_lib()) return -FI_ENODATA; if (psmx_compat_lib) { /* * native PSM running over TrueScale doesn't have the issue handled * here. it's only present when PSM is supported via the psm2-compat * library, where the PSM functions are just wrappers around the PSM2 * counterparts. * * psm2_ep_num_devunits() may wait for 15 seconds before return * when /dev/hfi1_0 is not present. Check the existence of any hfi1 * device interface first to avoid this delay. Note that the devices * don't necessarily appear consecutively so we need to check all * possible device names before returning "no device found" error. * This also means if "/dev/hfi1_0" doesn't exist but other devices * exist, we are still going to see the delay; but that's a rare case. */ glob_t glob_buf; if ((glob("/dev/hfi1_[0-9]", 0, NULL, &glob_buf) != 0) && (glob("/dev/hfi1_[0-9][0-9]", GLOB_APPEND, NULL, &glob_buf) != 0)) { FI_INFO(&psmx_prov, FI_LOG_CORE, "no hfi1 device is found.\n"); return -FI_ENODATA; } globfree(&glob_buf); } if (psm_ep_num_devunits(&cnt) || !cnt) { FI_INFO(&psmx_prov, FI_LOG_CORE, "no PSM device is found.\n"); return -FI_ENODATA; } src_addr = calloc(1, sizeof(*src_addr)); if (!src_addr) { FI_INFO(&psmx_prov, FI_LOG_CORE, "failed to allocate src addr.\n"); return -FI_ENODATA; } src_addr->signature = 0xFFFF; src_addr->unit = PSMX_DEFAULT_UNIT; src_addr->port = PSMX_DEFAULT_PORT; src_addr->service = PSMX_ANY_SERVICE; if (flags & FI_SOURCE) { if (node) sscanf(node, "%*[^:]:%" SCNi8 ":%" SCNu8, &src_addr->unit, &src_addr->port); if (service) sscanf(service, "%" SCNu32, &src_addr->service); FI_INFO(&psmx_prov, FI_LOG_CORE, "node '%s' service '%s' converted to <unit=%d, port=%d, service=%d>\n", node, service, src_addr->unit, src_addr->port, src_addr->service); } else if (node) { psm_uuid_t uuid; psmx_get_uuid(uuid); struct util_ns ns = { .port = psmx_uuid_to_port(uuid), .name_len = sizeof(*dest_addr), .service_len = sizeof(svc), .service_cmp = psmx_ns_service_cmp, .is_service_wildcard = psmx_ns_is_service_wildcard, }; ofi_ns_init(&ns); if (service) svc = atoi(service); svc0 = svc; dest_addr = (psm_epid_t *)ofi_ns_resolve_name(&ns, node, &svc); if (dest_addr) { FI_INFO(&psmx_prov, FI_LOG_CORE, "'%s:%u' resolved to <epid=%"PRIu64">:%u\n", node, svc0, *dest_addr, svc); } else { FI_INFO(&psmx_prov, FI_LOG_CORE, "failed to resolve '%s:%u'.\n", node, svc); err = -FI_ENODATA; goto err_out; } } if (hints) { switch (hints->addr_format) { case FI_FORMAT_UNSPEC: case FI_ADDR_PSMX: break; default: FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->addr_format=%d, supported=%d,%d.\n", hints->addr_format, FI_FORMAT_UNSPEC, FI_ADDR_PSMX); goto err_out; } if (hints->ep_attr) { switch (hints->ep_attr->protocol) { case FI_PROTO_UNSPEC: case FI_PROTO_PSMX: break; default: FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->protocol=%d, supported=%d %d\n", hints->ep_attr->protocol, FI_PROTO_UNSPEC, FI_PROTO_PSMX); goto err_out; } if (hints->ep_attr->tx_ctx_cnt > 1 && hints->ep_attr->tx_ctx_cnt != FI_SHARED_CONTEXT) { FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->ep_attr->tx_ctx_cnt=%"PRIu64", supported=0,1\n", hints->ep_attr->tx_ctx_cnt); goto err_out; } if (hints->ep_attr->rx_ctx_cnt > 1) { FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->ep_attr->rx_ctx_cnt=%"PRIu64", supported=0,1\n", hints->ep_attr->rx_ctx_cnt); goto err_out; } } if (hints->tx_attr) { if ((hints->tx_attr->op_flags & PSMX_OP_FLAGS) != hints->tx_attr->op_flags) { uint64_t psmx_op_flags = PSMX_OP_FLAGS; PSMX_INFO_DIFF("hints->tx_attr->of_flags", hints->tx_attr->op_flags, psmx_op_flags, FI_TYPE_OP_FLAGS); goto err_out; } if (hints->tx_attr->inject_size > PSMX_INJECT_SIZE) { FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->tx_attr->inject_size=%"PRIu64"," "supported=%d.\n", hints->tx_attr->inject_size, PSMX_INJECT_SIZE); goto err_out; } } if (hints->rx_attr && (hints->rx_attr->op_flags & PSMX_OP_FLAGS) != hints->rx_attr->op_flags) { uint64_t psmx_op_flags = PSMX_OP_FLAGS; PSMX_INFO_DIFF("hints->rx_attr->of_flags", hints->rx_attr->op_flags, psmx_op_flags, FI_TYPE_OP_FLAGS); goto err_out; } if ((hints->caps & FI_TAGGED) || ((hints->caps & FI_MSG) && !psmx_env.am_msg)) { if ((hints->mode & FI_CONTEXT) != FI_CONTEXT) { uint64_t psmx_mode = FI_CONTEXT; PSMX_INFO_DIFF("hints->mode", hints->mode, psmx_mode, FI_TYPE_MODE); goto err_out; } } else { mode = 0; } if (hints->domain_attr) { switch (hints->domain_attr->av_type) { case FI_AV_UNSPEC: case FI_AV_MAP: case FI_AV_TABLE: av_type = hints->domain_attr->av_type; break; default: FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->domain_attr->av_type=%d, supported=%d %d %d\n", hints->domain_attr->av_type, FI_AV_UNSPEC, FI_AV_MAP, FI_AV_TABLE); goto err_out; } if (hints->domain_attr->mr_mode == FI_MR_BASIC) { mr_mode = FI_MR_BASIC; } else if (hints->domain_attr->mr_mode == FI_MR_SCALABLE) { mr_mode = FI_MR_SCALABLE; } else if (hints->domain_attr->mr_mode & (FI_MR_BASIC | FI_MR_SCALABLE)) { FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->domain_attr->mr_mode has FI_MR_BASIC or FI_MR_SCALABLE " "combined with other bits\n"); goto err_out; } switch (hints->domain_attr->threading) { case FI_THREAD_UNSPEC: break; case FI_THREAD_FID: case FI_THREAD_ENDPOINT: case FI_THREAD_COMPLETION: case FI_THREAD_DOMAIN: threading = hints->domain_attr->threading; break; default: FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->domain_attr->threading=%d, supported=%d %d %d %d %d\n", hints->domain_attr->threading, FI_THREAD_UNSPEC, FI_THREAD_FID, FI_THREAD_ENDPOINT, FI_THREAD_COMPLETION, FI_THREAD_DOMAIN); goto err_out; } switch (hints->domain_attr->control_progress) { case FI_PROGRESS_UNSPEC: break; case FI_PROGRESS_MANUAL: case FI_PROGRESS_AUTO: control_progress = hints->domain_attr->control_progress; break; default: FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->domain_attr->control_progress=%d, supported=%d %d %d\n", hints->domain_attr->control_progress, FI_PROGRESS_UNSPEC, FI_PROGRESS_MANUAL, FI_PROGRESS_AUTO); goto err_out; } switch (hints->domain_attr->data_progress) { case FI_PROGRESS_UNSPEC: break; case FI_PROGRESS_MANUAL: case FI_PROGRESS_AUTO: data_progress = hints->domain_attr->data_progress; break; default: FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->domain_attr->data_progress=%d, supported=%d %d %d\n", hints->domain_attr->data_progress, FI_PROGRESS_UNSPEC, FI_PROGRESS_MANUAL, FI_PROGRESS_AUTO); goto err_out; } if (hints->domain_attr->caps & FI_SHARED_AV) { FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->domain_attr->caps=%lx, shared AV is unsupported\n", hints->domain_attr->caps); goto err_out; } } if (hints->ep_attr) { if (hints->ep_attr->max_msg_size > PSMX_MAX_MSG_SIZE) { FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->ep_attr->max_msg_size=%"PRIu64"," "supported=%llu.\n", hints->ep_attr->max_msg_size, PSMX_MAX_MSG_SIZE); goto err_out; } max_tag_value = ofi_max_tag(hints->ep_attr->mem_tag_format); } if (hints->tx_attr) { if ((hints->tx_attr->msg_order & PSMX_MSG_ORDER) != hints->tx_attr->msg_order) { uint64_t psmx_msg_order = PSMX_MSG_ORDER; PSMX_INFO_DIFF("hints->tx_attr->msg_order", hints->tx_attr->msg_order, psmx_msg_order, FI_TYPE_MSG_ORDER); goto err_out; } if ((hints->tx_attr->comp_order & PSMX_COMP_ORDER) != hints->tx_attr->comp_order) { uint64_t psmx_comp_order = PSMX_COMP_ORDER; PSMX_INFO_DIFF("hints->tx_attr->comp_order", hints->tx_attr->comp_order, psmx_comp_order, FI_TYPE_MSG_ORDER); goto err_out; } if (hints->tx_attr->inject_size > PSMX_INJECT_SIZE) { FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->tx_attr->inject_size=%ld," "supported=%d.\n", hints->tx_attr->inject_size, PSMX_INJECT_SIZE); goto err_out; } if (hints->tx_attr->iov_limit > 1) { FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->tx_attr->iov_limit=%ld," "supported=1.\n", hints->tx_attr->iov_limit); goto err_out; } if (hints->tx_attr->rma_iov_limit > 1) { FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->tx_attr->rma_iov_limit=%ld," "supported=1.\n", hints->tx_attr->rma_iov_limit); goto err_out; } } if (hints->rx_attr) { if ((hints->rx_attr->msg_order & PSMX_MSG_ORDER) != hints->rx_attr->msg_order) { uint64_t psmx_msg_order = PSMX_MSG_ORDER; PSMX_INFO_DIFF("hints->rx_attr->msg_order", hints->rx_attr->msg_order, psmx_msg_order, FI_TYPE_MSG_ORDER); goto err_out; } if ((hints->rx_attr->comp_order & PSMX_COMP_ORDER) != hints->rx_attr->comp_order) { uint64_t psmx_comp_order = PSMX_COMP_ORDER; PSMX_INFO_DIFF("hints->rx_attr->comp_order", hints->rx_attr->comp_order, psmx_comp_order, FI_TYPE_MSG_ORDER); goto err_out; } if (hints->rx_attr->iov_limit > 1) { FI_INFO(&psmx_prov, FI_LOG_CORE, "hints->rx_attr->iov_limit=%ld," "supported=1.\n", hints->rx_attr->iov_limit); goto err_out; } } caps = hints->caps; /* TODO: check other fields of hints */ } if (psmx_reserve_tag_bits(&caps, &max_tag_value) < 0) goto err_out; psmx_info = fi_allocinfo(); if (!psmx_info) { err = -FI_ENOMEM; goto err_out; } psmx_info->ep_attr->type = ep_type; psmx_info->ep_attr->protocol = FI_PROTO_PSMX; psmx_info->ep_attr->protocol_version = PSM_VERNO; psmx_info->ep_attr->max_msg_size = PSMX_MAX_MSG_SIZE; psmx_info->ep_attr->max_order_raw_size = PSMX_RMA_ORDER_SIZE; psmx_info->ep_attr->max_order_war_size = PSMX_RMA_ORDER_SIZE; psmx_info->ep_attr->max_order_waw_size = PSMX_RMA_ORDER_SIZE; psmx_info->ep_attr->mem_tag_format = ofi_tag_format(max_tag_value); psmx_info->ep_attr->tx_ctx_cnt = 1; psmx_info->ep_attr->rx_ctx_cnt = 1; psmx_info->domain_attr->threading = threading; psmx_info->domain_attr->control_progress = control_progress; psmx_info->domain_attr->data_progress = data_progress; psmx_info->domain_attr->name = strdup(PSMX_DOMAIN_NAME); psmx_info->domain_attr->resource_mgmt = FI_RM_ENABLED; psmx_info->domain_attr->av_type = av_type; psmx_info->domain_attr->mr_mode = mr_mode; psmx_info->domain_attr->mr_key_size = sizeof(uint64_t); psmx_info->domain_attr->cq_data_size = 4; psmx_info->domain_attr->cq_cnt = 65535; psmx_info->domain_attr->ep_cnt = 65535; psmx_info->domain_attr->tx_ctx_cnt = 1; psmx_info->domain_attr->rx_ctx_cnt = 1; psmx_info->domain_attr->max_ep_tx_ctx = 1; psmx_info->domain_attr->max_ep_rx_ctx = 1; psmx_info->domain_attr->max_ep_stx_ctx = 65535; psmx_info->domain_attr->max_ep_srx_ctx = 0; psmx_info->domain_attr->cntr_cnt = 65535; psmx_info->domain_attr->mr_iov_limit = 65535; psmx_info->domain_attr->caps = PSMX_DOM_CAPS; psmx_info->domain_attr->mode = 0; psmx_info->domain_attr->mr_cnt = 65535; psmx_info->next = NULL; psmx_info->caps = (hints && hints->caps) ? hints->caps : caps; psmx_info->mode = mode; psmx_info->addr_format = FI_ADDR_PSMX; psmx_info->src_addr = src_addr; psmx_info->src_addrlen = sizeof(*src_addr); psmx_info->dest_addr = dest_addr; psmx_info->dest_addrlen = sizeof(*dest_addr); psmx_info->fabric_attr->name = strdup(PSMX_FABRIC_NAME); psmx_info->fabric_attr->prov_name = NULL; psmx_info->fabric_attr->prov_version = PSMX_VERSION; psmx_info->tx_attr->caps = psmx_info->caps; psmx_info->tx_attr->mode = psmx_info->mode; psmx_info->tx_attr->op_flags = (hints && hints->tx_attr && hints->tx_attr->op_flags) ? hints->tx_attr->op_flags : 0; psmx_info->tx_attr->msg_order = PSMX_MSG_ORDER; psmx_info->tx_attr->comp_order = PSMX_COMP_ORDER; psmx_info->tx_attr->inject_size = PSMX_INJECT_SIZE; psmx_info->tx_attr->size = UINT64_MAX; psmx_info->tx_attr->iov_limit = 1; psmx_info->tx_attr->rma_iov_limit = 1; psmx_info->rx_attr->caps = psmx_info->caps; psmx_info->rx_attr->mode = psmx_info->mode; psmx_info->rx_attr->op_flags = (hints && hints->rx_attr && hints->rx_attr->op_flags) ? hints->rx_attr->op_flags : 0; psmx_info->rx_attr->msg_order = PSMX_MSG_ORDER; psmx_info->rx_attr->comp_order = PSMX_COMP_ORDER; psmx_info->rx_attr->total_buffered_recv = ~(0ULL); /* that's how PSM handles it internally! */ psmx_info->rx_attr->size = UINT64_MAX; psmx_info->rx_attr->iov_limit = 1; *info = psmx_info; return 0; err_out: free(dest_addr); free(src_addr); return err; } static void psmx_fini(void) { FI_INFO(&psmx_prov, FI_LOG_CORE, "\n"); if (! --psmx_init_count && psmx_lib_initialized) { /* This function is called from a library destructor, which is called * automatically when exit() is called. The call to psm_finalize() * might cause deadlock if the applicaiton is terminated with Ctrl-C * -- the application could be inside a PSM call, holding a lock that * psm_finalize() tries to acquire. This can be avoided by only * calling psm_finalize() when PSM is guaranteed to be unused. */ if (psmx_active_fabric) { FI_INFO(&psmx_prov, FI_LOG_CORE, "psmx_active_fabric != NULL, skip psm_finalize\n"); } else { psm_finalize(); psmx_lib_initialized = 0; } } }
static int ofi_register_provider(struct fi_provider *provider, void *dlhandle) { struct fi_prov_context *ctx; struct ofi_prov *prov = NULL; int ret; if (!provider || !provider->name) { FI_WARN(&core_prov, FI_LOG_CORE, "no provider structure or name\n"); ret = -FI_EINVAL; goto cleanup; } FI_INFO(&core_prov, FI_LOG_CORE, "registering provider: %s (%d.%d)\n", provider->name, FI_MAJOR(provider->version), FI_MINOR(provider->version)); if (!provider->getinfo || !provider->fabric) { FI_WARN(&core_prov, FI_LOG_CORE, "provider missing mandatory entry points\n"); ret = -FI_EINVAL; goto cleanup; } /* The current core implementation is not backward compatible * with providers that support a release earlier than v1.3. * See commit 0f4b6651. */ if (provider->fi_version < FI_VERSION(1, 3)) { FI_INFO(&core_prov, FI_LOG_CORE, "provider has unsupported FI version " "(provider %d.%d != libfabric %d.%d); ignoring\n", FI_MAJOR(provider->fi_version), FI_MINOR(provider->fi_version), FI_MAJOR_VERSION, FI_MINOR_VERSION); ret = -FI_ENOSYS; goto cleanup; } ctx = (struct fi_prov_context *) &provider->context; ctx->is_util_prov = ofi_has_util_prefix(provider->name); if (ofi_getinfo_filter(provider)) { FI_INFO(&core_prov, FI_LOG_CORE, "\"%s\" filtered by provider include/exclude " "list, skipping\n", provider->name); ret = -FI_ENODEV; goto cleanup; } if (ofi_apply_filter(&prov_log_filter, provider->name)) ctx->disable_logging = 1; prov = ofi_getprov(provider->name, strlen(provider->name)); if (prov) { /* If this provider has not been init yet, then we add the * provider and dlhandle to the struct and exit. */ if (prov->provider == NULL) goto update_prov_registry; /* If this provider is older than an already-loaded * provider of the same name, then discard this one. */ if (FI_VERSION_GE(prov->provider->version, provider->version)) { FI_INFO(&core_prov, FI_LOG_CORE, "a newer %s provider was already loaded; " "ignoring this one\n", provider->name); ret = -FI_EALREADY; goto cleanup; } /* This provider is newer than an already-loaded * provider of the same name, so discard the * already-loaded one. */ FI_INFO(&core_prov, FI_LOG_CORE, "an older %s provider was already loaded; " "keeping this one and ignoring the older one\n", provider->name); cleanup_provider(prov->provider, prov->dlhandle); } else { prov = ofi_create_prov_entry(provider->name); if (!prov) { ret = -FI_EOTHER; goto cleanup; } } update_prov_registry: prov->dlhandle = dlhandle; prov->provider = provider; return 0; cleanup: cleanup_provider(provider, dlhandle); return ret; }