Beispiel #1
0
/**
 * Create a "free floating" memory descriptor - a MD that is not associated
 * with a ME. Such MDs are usually used in LNetPut() and LNetGet() operations.
 *
 * \param umd,unlink See the discussion for LNetMDAttach().
 * \param handle On successful returns, a handle to the newly created MD is
 * saved here. This handle can be used later in LNetMDUnlink(), LNetPut(),
 * and LNetGet() operations.
 *
 * \retval 0       On success.
 * \retval -EINVAL If \a umd is not valid.
 * \retval -ENOMEM If new MD cannot be allocated.
 * \retval -ENOENT \a umd.eq_handle does not point to a valid EQ. Note that
 * it's OK to supply a NULL \a umd.eq_handle by calling
 * LNetInvalidateHandle() on it.
 */
int
LNetMDBind(struct lnet_md umd, enum lnet_unlink unlink,
	   struct lnet_handle_md *handle)
{
	struct lnet_libmd *md;
	int cpt;
	int rc;

	LASSERT(the_lnet.ln_refcount > 0);

	if (lnet_md_validate(&umd))
		return -EINVAL;

	if ((umd.options & (LNET_MD_OP_GET | LNET_MD_OP_PUT))) {
		CERROR("Invalid option: GET|PUT illegal on active MDs\n");
		return -EINVAL;
	}

	md = lnet_md_alloc(&umd);
	if (!md)
		return -ENOMEM;

	rc = lnet_md_build(md, &umd, unlink);
	if (rc)
		goto out_free;

	cpt = lnet_res_lock_current();

	rc = lnet_md_link(md, umd.eq_handle, cpt);
	if (rc)
		goto out_unlock;

	lnet_md2handle(handle, md);

	lnet_res_unlock(cpt);
	return 0;

out_unlock:
	lnet_res_unlock(cpt);
out_free:
	lnet_md_free(md);

	return rc;
}
Beispiel #2
0
/**
 * Create a "free floating" memory descriptor - a MD that is not associated
 * with a ME. Such MDs are usually used in LNetPut() and LNetGet() operations.
 *
 * \param umd,unlink See the discussion for LNetMDAttach().
 * \param handle On successful returns, a handle to the newly created MD is
 * saved here. This handle can be used later in LNetMDUnlink(), LNetPut(),
 * and LNetGet() operations.
 *
 * \retval 0       On success.
 * \retval -EINVAL If \a umd is not valid.
 * \retval -ENOMEM If new MD cannot be allocated.
 * \retval -ENOENT \a umd.eq_handle does not point to a valid EQ. Note that
 * it's OK to supply a NULL \a umd.eq_handle by calling
 * LNetInvalidateHandle() on it.
 */
int
LNetMDBind(lnet_md_t umd, lnet_unlink_t unlink, lnet_handle_md_t *handle)
{
	lnet_libmd_t	*md;
	int		cpt;
	int		rc;

        LASSERT (the_lnet.ln_init);
        LASSERT (the_lnet.ln_refcount > 0);

        if (lnet_md_validate(&umd) != 0)
                return -EINVAL;

        if ((umd.options & (LNET_MD_OP_GET | LNET_MD_OP_PUT)) != 0) {
                CERROR("Invalid option: GET|PUT illegal on active MDs\n");
                return -EINVAL;
        }

        md = lnet_md_alloc(&umd);
        if (md == NULL)
                return -ENOMEM;

	rc = lnet_md_build(md, &umd, unlink);

	cpt = lnet_res_lock_current();
	if (rc != 0)
		goto failed;

	rc = lnet_md_link(md, umd.eq_handle, cpt);
	if (rc != 0)
		goto failed;

	lnet_md2handle(handle, md);

	lnet_res_unlock(cpt);
	return 0;

 failed:
	lnet_md_free_locked(md);

	lnet_res_unlock(cpt);
	return rc;
}
Beispiel #3
0
/**
 * Create a memory descriptor and attach it to a ME
 *
 * \param meh A handle for a ME to associate the new MD with.
 * \param umd Provides initial values for the user-visible parts of a MD.
 * Other than its use for initialization, there is no linkage between this
 * structure and the MD maintained by the LNet.
 * \param unlink A flag to indicate whether the MD is automatically unlinked
 * when it becomes inactive, either because the operation threshold drops to
 * zero or because the available memory becomes less than \a umd.max_size.
 * (Note that the check for unlinking a MD only occurs after the completion
 * of a successful operation on the MD.) The value LNET_UNLINK enables auto
 * unlinking; the value LNET_RETAIN disables it.
 * \param handle On successful returns, a handle to the newly created MD is
 * saved here. This handle can be used later in LNetMDUnlink().
 *
 * \retval 0       On success.
 * \retval -EINVAL If \a umd is not valid.
 * \retval -ENOMEM If new MD cannot be allocated.
 * \retval -ENOENT Either \a meh or \a umd.eq_handle does not point to a
 * valid object. Note that it's OK to supply a NULL \a umd.eq_handle by
 * calling LNetInvalidateHandle() on it.
 * \retval -EBUSY  If the ME pointed to by \a meh is already associated with
 * a MD.
 */
int
LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd,
	     lnet_unlink_t unlink, lnet_handle_md_t *handle)
{
	CFS_LIST_HEAD		(matches);
	CFS_LIST_HEAD		(drops);
	struct lnet_me		*me;
	struct lnet_libmd	*md;
	int			cpt;
	int			rc;

        LASSERT (the_lnet.ln_init);
        LASSERT (the_lnet.ln_refcount > 0);

        if (lnet_md_validate(&umd) != 0)
                return -EINVAL;

        if ((umd.options & (LNET_MD_OP_GET | LNET_MD_OP_PUT)) == 0) {
                CERROR("Invalid option: no MD_OP set\n");
                return -EINVAL;
        }

        md = lnet_md_alloc(&umd);
        if (md == NULL)
                return -ENOMEM;

	rc = lnet_md_build(md, &umd, unlink);
	cpt = lnet_cpt_of_cookie(meh.cookie);

	lnet_res_lock(cpt);
	if (rc != 0)
		goto failed;

	me = lnet_handle2me(&meh);
	if (me == NULL)
		rc = -ENOENT;
	else if (me->me_md != NULL)
		rc = -EBUSY;
	else
		rc = lnet_md_link(md, umd.eq_handle, cpt);

	if (rc != 0)
		goto failed;

	/* attach this MD to portal of ME and check if it matches any
	 * blocked msgs on this portal */
	lnet_ptl_attach_md(me, md, &matches, &drops);

	lnet_md2handle(handle, md);

	lnet_res_unlock(cpt);

	lnet_drop_delayed_msg_list(&drops, "Bad match");
	lnet_recv_delayed_msg_list(&matches);

	return 0;

 failed:
	lnet_md_free_locked(md);

	lnet_res_unlock(cpt);
	return rc;
}
Beispiel #4
0
/**
 * Create a memory descriptor and attach it to a ME
 *
 * \param meh A handle for a ME to associate the new MD with.
 * \param umd Provides initial values for the user-visible parts of a MD.
 * Other than its use for initialization, there is no linkage between this
 * structure and the MD maintained by the LNet.
 * \param unlink A flag to indicate whether the MD is automatically unlinked
 * when it becomes inactive, either because the operation threshold drops to
 * zero or because the available memory becomes less than \a umd.max_size.
 * (Note that the check for unlinking a MD only occurs after the completion
 * of a successful operation on the MD.) The value LNET_UNLINK enables auto
 * unlinking; the value LNET_RETAIN disables it.
 * \param handle On successful returns, a handle to the newly created MD is
 * saved here. This handle can be used later in LNetMDUnlink().
 *
 * \retval 0       On success.
 * \retval -EINVAL If \a umd is not valid.
 * \retval -ENOMEM If new MD cannot be allocated.
 * \retval -ENOENT Either \a meh or \a umd.eq_handle does not point to a
 * valid object. Note that it's OK to supply a NULL \a umd.eq_handle by
 * calling LNetInvalidateHandle() on it.
 * \retval -EBUSY  If the ME pointed to by \a meh is already associated with
 * a MD.
 */
int
LNetMDAttach(struct lnet_handle_me meh, struct lnet_md umd,
	     enum lnet_unlink unlink, struct lnet_handle_md *handle)
{
	LIST_HEAD(matches);
	LIST_HEAD(drops);
	struct lnet_me *me;
	struct lnet_libmd *md;
	int cpt;
	int rc;

	LASSERT(the_lnet.ln_refcount > 0);

	if (lnet_md_validate(&umd))
		return -EINVAL;

	if (!(umd.options & (LNET_MD_OP_GET | LNET_MD_OP_PUT))) {
		CERROR("Invalid option: no MD_OP set\n");
		return -EINVAL;
	}

	md = lnet_md_alloc(&umd);
	if (!md)
		return -ENOMEM;

	rc = lnet_md_build(md, &umd, unlink);
	if (rc)
		goto out_free;

	cpt = lnet_cpt_of_cookie(meh.cookie);

	lnet_res_lock(cpt);

	me = lnet_handle2me(&meh);
	if (!me)
		rc = -ENOENT;
	else if (me->me_md)
		rc = -EBUSY;
	else
		rc = lnet_md_link(md, umd.eq_handle, cpt);

	if (rc)
		goto out_unlock;

	/*
	 * attach this MD to portal of ME and check if it matches any
	 * blocked msgs on this portal
	 */
	lnet_ptl_attach_md(me, md, &matches, &drops);

	lnet_md2handle(handle, md);

	lnet_res_unlock(cpt);

	lnet_drop_delayed_msg_list(&drops, "Bad match");
	lnet_recv_delayed_msg_list(&matches);

	return 0;

out_unlock:
	lnet_res_unlock(cpt);
out_free:
	lnet_md_free(md);
	return rc;
}