+static int
+lnet_me_match_portal(lnet_portal_t *ptl, lnet_process_id_t id,
+ __u64 match_bits, __u64 ignore_bits)
+{
+ cfs_list_t *mhash = NULL;
+ int unique;
+
+ LASSERT (!(lnet_portal_is_unique(ptl) &&
+ lnet_portal_is_wildcard(ptl)));
+
+ /* prefer to check w/o any lock */
+ unique = lnet_match_is_unique(id, match_bits, ignore_bits);
+ if (likely(lnet_portal_is_unique(ptl) ||
+ lnet_portal_is_wildcard(ptl)))
+ goto match;
+
+ /* unset, new portal */
+ if (unique) {
+ mhash = lnet_portal_mhash_alloc();
+ if (mhash == NULL)
+ return -ENOMEM;
+ }
+
+ LNET_LOCK();
+ if (lnet_portal_is_unique(ptl) ||
+ lnet_portal_is_wildcard(ptl)) {
+ /* someone set it before me */
+ if (mhash != NULL)
+ lnet_portal_mhash_free(mhash);
+ LNET_UNLOCK();
+ goto match;
+ }
+
+ /* still not set */
+ LASSERT (ptl->ptl_mhash == NULL);
+ if (unique) {
+ ptl->ptl_mhash = mhash;
+ lnet_portal_setopt(ptl, LNET_PTL_MATCH_UNIQUE);
+ } else {
+ lnet_portal_setopt(ptl, LNET_PTL_MATCH_WILDCARD);
+ }
+ LNET_UNLOCK();
+ return 0;
+
+ match:
+ if (lnet_portal_is_unique(ptl) && !unique)
+ return -EPERM;
+
+ if (lnet_portal_is_wildcard(ptl) && unique)
+ return -EPERM;
+
+ return 0;
+}
+
+/**
+ * Create and attach a match entry to the match list of \a portal. The new
+ * ME is empty, i.e. not associated with a memory descriptor. LNetMDAttach()
+ * can be used to attach a MD to an empty ME.
+ *
+ * \param portal The portal table index where the ME should be attached.
+ * \param match_id Specifies the match criteria for the process ID of
+ * the requester. The constants LNET_PID_ANY and LNET_NID_ANY can be
+ * used to wildcard either of the identifiers in the lnet_process_id_t
+ * structure.
+ * \param match_bits,ignore_bits Specify the match criteria to apply
+ * to the match bits in the incoming request. The ignore bits are used
+ * to mask out insignificant bits in the incoming match bits. The resulting
+ * bits are then compared to the ME's match bits to determine if the
+ * incoming request meets the match criteria.
+ * \param unlink Indicates whether the ME should be unlinked when the memory
+ * descriptor associated with it is unlinked (Note that the check for
+ * unlinking a ME only occurs when the memory descriptor is unlinked.).
+ * Valid values are LNET_RETAIN and LNET_UNLINK.
+ * \param pos Indicates whether the new ME should be prepended or
+ * appended to the match list. Allowed constants: LNET_INS_BEFORE,
+ * LNET_INS_AFTER.
+ * \param handle On successful returns, a handle to the newly created ME
+ * object is saved here. This handle can be used later in LNetMEInsert(),
+ * LNetMEUnlink(), or LNetMDAttach() functions.
+ *
+ * \retval 0 On success.
+ * \retval -EINVAL If \a portal is invalid.
+ * \retval -ENOMEM If new ME object cannot be allocated.
+ */