int _gnix_mbox_allocator_create(struct gnix_nic *nic,
				gni_cq_handle_t cq_handle,
				enum gnix_page_size page_size,
				size_t mbox_size,
				size_t mpmmap,
				struct gnix_mbox_alloc_handle **alloc_handle)
{
	struct gnix_mbox_alloc_handle *handle;
	char error_buf[256];
	char *error;
	int ret;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	if (!nic || !mbox_size || !mpmmap || !alloc_handle) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			  "Invalid parameter to allocator_create.\n");
		return -FI_EINVAL;
	}

	*alloc_handle = NULL;

	handle = calloc(1, sizeof(*handle));
	if (!handle) {
		error = strerror_r(errno, error_buf, sizeof(error_buf));
		GNIX_WARN(FI_LOG_EP_CTRL,
			  "Error allocating alloc handle: %s\n",
			  error);
		return -FI_ENOMEM;
	}

	handle->page_size = page_size * 1024 * 1024;
	handle->mbox_size = mbox_size;
	handle->mpmmap = mpmmap;
	handle->nic_handle = nic;
	handle->cq_handle = cq_handle;
	fastlock_init(&handle->lock);

	ret = __open_huge_page(handle);
	if (ret) {
		GNIX_WARN(FI_LOG_EP_CTRL, "Error opening huge page.\n");
		goto err_huge_page;
	}

	ret = __create_slab(handle);
	if (ret) {
		GNIX_WARN(FI_LOG_EP_CTRL, "Slab creation failed.\n");
		goto err_slab_creation;
	}

	*alloc_handle = handle;

	return ret;

err_slab_creation:
	free(handle->filename);
err_huge_page:
	free(handle);
	return ret;
}
int _gnix_mbox_alloc(struct gnix_mbox_alloc_handle *alloc_handle,
		     struct gnix_mbox **ptr)
{
	struct gnix_slab *slab;
	int position;
	int ret;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	if (!alloc_handle || !ptr) {
		GNIX_WARN(FI_LOG_EP_CTRL, "Invalid alloc_handle or ptr.\n");
		ret = -FI_EINVAL;
		goto err;
	}

	fastlock_acquire(&alloc_handle->lock);
	position = __find_free(alloc_handle, &slab);
	if (position < 0) {
		GNIX_DEBUG(FI_LOG_EP_CTRL, "Creating new slab.\n");
		ret = __create_slab(alloc_handle);
		if (ret) {
			GNIX_WARN(FI_LOG_EP_CTRL, "Slab creation failed.\n");
			goto err;
		}

		slab = container_of(alloc_handle->slab_list.tail,
				    struct gnix_slab, list_entry);
		position = ret;
	}
int _gnix_mbox_allocator_create(struct gnix_nic *nic,
				gni_cq_handle_t cq_handle,
				enum gnix_page_size page_size,
				size_t mbox_size,
				size_t mpmmap,
				struct gnix_mbox_alloc_handle **alloc_handle)
{
	struct gnix_mbox_alloc_handle *handle;
	char error_buf[256];
	char *error;
	int ret;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	if (!nic || !mbox_size || !mpmmap || !alloc_handle) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			  "Invalid parameter to allocator_create.\n");
		return -FI_EINVAL;
	}

	*alloc_handle = NULL;

	handle = calloc(1, sizeof(*handle));
	if (!handle) {
		error = strerror_r(errno, error_buf, sizeof(error_buf));
		GNIX_WARN(FI_LOG_EP_CTRL,
			  "Error allocating alloc handle: %s\n",
			  error);
		return -FI_ENOMEM;
	}

	handle->page_size = page_size * 1024 * 1024;
	handle->mbox_size = mbox_size;
	handle->mpmmap = mpmmap;
	handle->nic_handle = nic;
	handle->cq_handle = cq_handle;
	fastlock_init(&handle->lock);

	ret = __open_huge_page(handle);
	if (ret == FI_SUCCESS) {
		ret = __create_slab(handle);
		if (ret != FI_SUCCESS) {
			GNIX_WARN(FI_LOG_EP_CTRL, "Slab creation failed.\n");
		}
	} else {
		GNIX_WARN(FI_LOG_EP_CTRL, "Error opening huge page.\n");
	}

	/*
	 * try plan B - try to use anonymous mapping (base page size).
	 * If a file was successfully opened, close fd and free filename
	 * field in the handle.
	 */

	if ((ret != FI_SUCCESS) &&
		(gnix_mbox_alloc_allow_fallback == true)) {
		if (handle->filename != NULL) {
			free(handle->filename);
			handle->filename = NULL;
		}
		if (handle->fd != -1) {
			ret = close(handle->fd);
			handle->fd = -1;
			if (ret) {
				GNIX_WARN(FI_LOG_EP_CTRL,
				 "Error closing huge page - %d\n",
				  ret);
			}
		}

		ret = __create_slab(handle);
		if (ret != FI_SUCCESS) {
			GNIX_WARN(FI_LOG_EP_CTRL,
				"Slab(anon) creation failed.\n");
		}
	}

	if (ret == FI_SUCCESS) {
		*alloc_handle = handle;
	} else {
		free(handle);
	}

	return ret;
}