in prov/gni/src/gnix_mr.c [200:335]
int _gnix_mr_reg(struct fid *fid, const void *buf, size_t len,
uint64_t access, uint64_t offset,
uint64_t requested_key, uint64_t flags,
struct fid_mr **mr_o, void *context,
struct gnix_auth_key *auth_key,
int reserved)
{
struct gnix_fid_mem_desc *mr = NULL;
struct gnix_fid_domain *domain;
int rc;
uint64_t reg_addr, reg_len;
struct _gnix_fi_reg_context fi_reg_context = {
.access = access,
.offset = offset,
.requested_key = requested_key,
.flags = flags,
.context = context,
.auth_key = auth_key,
.reserved = reserved,
};
struct gnix_mr_cache_info *info;
GNIX_TRACE(FI_LOG_MR, "\n");
GNIX_INFO(FI_LOG_MR, "reg: buf=%p len=%llu\n", buf, len);
/* Flags are reserved for future use and must be 0. */
if (OFI_UNLIKELY(flags))
return -FI_EBADFLAGS;
/* The offset parameter is reserved for future use and must be 0.
* Additionally, check for invalid pointers, bad access flags and the
* correct fclass on associated fid
*/
if (offset || !buf || !mr_o || !access ||
(access & ~(FI_READ | FI_WRITE | FI_RECV | FI_SEND |
FI_REMOTE_READ |
FI_REMOTE_WRITE)) ||
(fid->fclass != FI_CLASS_DOMAIN))
return -FI_EINVAL;
domain = container_of(fid, struct gnix_fid_domain, domain_fid.fid);
if (auth_key->using_vmdh && !reserved &&
requested_key >= auth_key->attr.user_key_limit)
return -FI_EKEYREJECTED;
if (!reserved && auth_key->using_vmdh) {
/* adjust requested key by rank offset */
fi_reg_context.requested_key += auth_key->key_offset;
GNIX_DEBUG(FI_LOG_DOMAIN,
"user requested key %d, but adjusting by "
"rank offset as key %d\n",
requested_key, fi_reg_context.requested_key);
}
if (auth_key->using_vmdh && !reserved &&
requested_key < auth_key->attr.user_key_limit) {
rc = _gnix_test_and_set_bit(auth_key->user,
fi_reg_context.requested_key);
if (rc) {
GNIX_WARN(FI_LOG_DOMAIN, "key already in use, key=%d\n",
fi_reg_context.requested_key);
return -FI_ENOKEY;
}
}
/* if this is a provider registration using VMDH and 0 was provided
* as the key, pick any available */
if (auth_key->using_vmdh && reserved && !requested_key) {
requested_key = _gnix_get_next_reserved_key(auth_key);
if (requested_key <= 0)
return -FI_ENOKEY;
fi_reg_context.requested_key = requested_key;
}
info = &domain->mr_cache_info[auth_key->ptag];
reg_addr = ((uint64_t) buf) & ~((1 << GNIX_MR_PAGE_SHIFT) - 1);
reg_len = __calculate_length((uint64_t) buf, len,
1 << GNIX_MR_PAGE_SHIFT);
/* call cache register op to retrieve the right entry */
fastlock_acquire(&info->mr_cache_lock);
if (OFI_UNLIKELY(!domain->mr_ops))
_gnix_open_cache(domain, GNIX_DEFAULT_CACHE_TYPE);
if (OFI_UNLIKELY(!domain->mr_ops->is_init(domain, auth_key))) {
rc = domain->mr_ops->init(domain, auth_key);
if (rc != FI_SUCCESS) {
fastlock_release(&info->mr_cache_lock);
goto err;
}
}
rc = domain->mr_ops->reg_mr(domain,
(uint64_t) reg_addr, reg_len, &fi_reg_context,
(void **) &mr);
fastlock_release(&info->mr_cache_lock);
/* check retcode */
if (OFI_UNLIKELY(rc != FI_SUCCESS))
goto err;
/* md.mr_fid */
mr->mr_fid.mem_desc = mr;
mr->mr_fid.fid.fclass = FI_CLASS_MR;
mr->mr_fid.fid.context = context;
mr->mr_fid.fid.ops = &fi_gnix_mr_ops;
/* setup internal key structure */
mr->mr_fid.key = _gnix_convert_mhdl_to_key(&mr->mem_hndl);
if (!reserved && auth_key->using_vmdh) {
/* When using scalable, the key is a virtual index to the
vmdh table */
mr->mr_fid.key = requested_key;
}
mr->auth_key = auth_key;
if (reserved && auth_key->using_vmdh) {
rc = __gnix_mr_refresh(mr, reg_addr, reg_len);
if (rc != FI_SUCCESS)
GNIX_FATAL(FI_LOG_MR,
"failed to enabled internal provider registration, ret=%d",
rc);
}
_gnix_ref_get(mr->domain);
/* set up mr_o out pointer */
*mr_o = &mr->mr_fid;
return FI_SUCCESS;
err:
return rc;
}