linux/drivers/staging/lustre/lnet/lnet/lib-me.c
<<
>>
Prefs
   1/*
   2 * GPL HEADER START
   3 *
   4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 only,
   8 * as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful, but
  11 * WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 * General Public License version 2 for more details (a copy is included
  14 * in the LICENSE file that accompanied this code).
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * version 2 along with this program; If not, see
  18 * http://www.gnu.org/licenses/gpl-2.0.html
  19 *
  20 * GPL HEADER END
  21 */
  22/*
  23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24 * Use is subject to license terms.
  25 *
  26 * Copyright (c) 2012, Intel Corporation.
  27 */
  28/*
  29 * This file is part of Lustre, http://www.lustre.org/
  30 * Lustre is a trademark of Sun Microsystems, Inc.
  31 *
  32 * lnet/lnet/lib-me.c
  33 *
  34 * Match Entry management routines
  35 */
  36
  37#define DEBUG_SUBSYSTEM S_LNET
  38
  39#include "../../include/linux/lnet/lib-lnet.h"
  40
  41/**
  42 * Create and attach a match entry to the match list of \a portal. The new
  43 * ME is empty, i.e. not associated with a memory descriptor. LNetMDAttach()
  44 * can be used to attach a MD to an empty ME.
  45 *
  46 * \param portal The portal table index where the ME should be attached.
  47 * \param match_id Specifies the match criteria for the process ID of
  48 * the requester. The constants LNET_PID_ANY and LNET_NID_ANY can be
  49 * used to wildcard either of the identifiers in the lnet_process_id_t
  50 * structure.
  51 * \param match_bits,ignore_bits Specify the match criteria to apply
  52 * to the match bits in the incoming request. The ignore bits are used
  53 * to mask out insignificant bits in the incoming match bits. The resulting
  54 * bits are then compared to the ME's match bits to determine if the
  55 * incoming request meets the match criteria.
  56 * \param unlink Indicates whether the ME should be unlinked when the memory
  57 * descriptor associated with it is unlinked (Note that the check for
  58 * unlinking a ME only occurs when the memory descriptor is unlinked.).
  59 * Valid values are LNET_RETAIN and LNET_UNLINK.
  60 * \param pos Indicates whether the new ME should be prepended or
  61 * appended to the match list. Allowed constants: LNET_INS_BEFORE,
  62 * LNET_INS_AFTER.
  63 * \param handle On successful returns, a handle to the newly created ME
  64 * object is saved here. This handle can be used later in LNetMEInsert(),
  65 * LNetMEUnlink(), or LNetMDAttach() functions.
  66 *
  67 * \retval 0       On success.
  68 * \retval -EINVAL If \a portal is invalid.
  69 * \retval -ENOMEM If new ME object cannot be allocated.
  70 */
  71int
  72LNetMEAttach(unsigned int portal,
  73             lnet_process_id_t match_id,
  74             __u64 match_bits, __u64 ignore_bits,
  75             lnet_unlink_t unlink, lnet_ins_pos_t pos,
  76             lnet_handle_me_t *handle)
  77{
  78        struct lnet_match_table *mtable;
  79        struct lnet_me *me;
  80        struct list_head *head;
  81
  82        LASSERT(the_lnet.ln_refcount > 0);
  83
  84        if ((int)portal >= the_lnet.ln_nportals)
  85                return -EINVAL;
  86
  87        mtable = lnet_mt_of_attach(portal, match_id,
  88                                   match_bits, ignore_bits, pos);
  89        if (!mtable) /* can't match portal type */
  90                return -EPERM;
  91
  92        me = lnet_me_alloc();
  93        if (!me)
  94                return -ENOMEM;
  95
  96        lnet_res_lock(mtable->mt_cpt);
  97
  98        me->me_portal = portal;
  99        me->me_match_id = match_id;
 100        me->me_match_bits = match_bits;
 101        me->me_ignore_bits = ignore_bits;
 102        me->me_unlink = unlink;
 103        me->me_md = NULL;
 104
 105        lnet_res_lh_initialize(the_lnet.ln_me_containers[mtable->mt_cpt],
 106                               &me->me_lh);
 107        if (ignore_bits)
 108                head = &mtable->mt_mhash[LNET_MT_HASH_IGNORE];
 109        else
 110                head = lnet_mt_match_head(mtable, match_id, match_bits);
 111
 112        me->me_pos = head - &mtable->mt_mhash[0];
 113        if (pos == LNET_INS_AFTER || pos == LNET_INS_LOCAL)
 114                list_add_tail(&me->me_list, head);
 115        else
 116                list_add(&me->me_list, head);
 117
 118        lnet_me2handle(handle, me);
 119
 120        lnet_res_unlock(mtable->mt_cpt);
 121        return 0;
 122}
 123EXPORT_SYMBOL(LNetMEAttach);
 124
 125/**
 126 * Create and a match entry and insert it before or after the ME pointed to by
 127 * \a current_meh. The new ME is empty, i.e. not associated with a memory
 128 * descriptor. LNetMDAttach() can be used to attach a MD to an empty ME.
 129 *
 130 * This function is identical to LNetMEAttach() except for the position
 131 * where the new ME is inserted.
 132 *
 133 * \param current_meh A handle for a ME. The new ME will be inserted
 134 * immediately before or immediately after this ME.
 135 * \param match_id,match_bits,ignore_bits,unlink,pos,handle See the discussion
 136 * for LNetMEAttach().
 137 *
 138 * \retval 0       On success.
 139 * \retval -ENOMEM If new ME object cannot be allocated.
 140 * \retval -ENOENT If \a current_meh does not point to a valid match entry.
 141 */
 142int
 143LNetMEInsert(lnet_handle_me_t current_meh,
 144             lnet_process_id_t match_id,
 145             __u64 match_bits, __u64 ignore_bits,
 146             lnet_unlink_t unlink, lnet_ins_pos_t pos,
 147             lnet_handle_me_t *handle)
 148{
 149        struct lnet_me *current_me;
 150        struct lnet_me *new_me;
 151        struct lnet_portal *ptl;
 152        int cpt;
 153
 154        LASSERT(the_lnet.ln_refcount > 0);
 155
 156        if (pos == LNET_INS_LOCAL)
 157                return -EPERM;
 158
 159        new_me = lnet_me_alloc();
 160        if (!new_me)
 161                return -ENOMEM;
 162
 163        cpt = lnet_cpt_of_cookie(current_meh.cookie);
 164
 165        lnet_res_lock(cpt);
 166
 167        current_me = lnet_handle2me(&current_meh);
 168        if (!current_me) {
 169                lnet_me_free(new_me);
 170
 171                lnet_res_unlock(cpt);
 172                return -ENOENT;
 173        }
 174
 175        LASSERT(current_me->me_portal < the_lnet.ln_nportals);
 176
 177        ptl = the_lnet.ln_portals[current_me->me_portal];
 178        if (lnet_ptl_is_unique(ptl)) {
 179                /* nosense to insertion on unique portal */
 180                lnet_me_free(new_me);
 181                lnet_res_unlock(cpt);
 182                return -EPERM;
 183        }
 184
 185        new_me->me_pos = current_me->me_pos;
 186        new_me->me_portal = current_me->me_portal;
 187        new_me->me_match_id = match_id;
 188        new_me->me_match_bits = match_bits;
 189        new_me->me_ignore_bits = ignore_bits;
 190        new_me->me_unlink = unlink;
 191        new_me->me_md = NULL;
 192
 193        lnet_res_lh_initialize(the_lnet.ln_me_containers[cpt], &new_me->me_lh);
 194
 195        if (pos == LNET_INS_AFTER)
 196                list_add(&new_me->me_list, &current_me->me_list);
 197        else
 198                list_add_tail(&new_me->me_list, &current_me->me_list);
 199
 200        lnet_me2handle(handle, new_me);
 201
 202        lnet_res_unlock(cpt);
 203
 204        return 0;
 205}
 206EXPORT_SYMBOL(LNetMEInsert);
 207
 208/**
 209 * Unlink a match entry from its match list.
 210 *
 211 * This operation also releases any resources associated with the ME. If a
 212 * memory descriptor is attached to the ME, then it will be unlinked as well
 213 * and an unlink event will be generated. It is an error to use the ME handle
 214 * after calling LNetMEUnlink().
 215 *
 216 * \param meh A handle for the ME to be unlinked.
 217 *
 218 * \retval 0       On success.
 219 * \retval -ENOENT If \a meh does not point to a valid ME.
 220 * \see LNetMDUnlink() for the discussion on delivering unlink event.
 221 */
 222int
 223LNetMEUnlink(lnet_handle_me_t meh)
 224{
 225        lnet_me_t *me;
 226        lnet_libmd_t *md;
 227        lnet_event_t ev;
 228        int cpt;
 229
 230        LASSERT(the_lnet.ln_refcount > 0);
 231
 232        cpt = lnet_cpt_of_cookie(meh.cookie);
 233        lnet_res_lock(cpt);
 234
 235        me = lnet_handle2me(&meh);
 236        if (!me) {
 237                lnet_res_unlock(cpt);
 238                return -ENOENT;
 239        }
 240
 241        md = me->me_md;
 242        if (md) {
 243                md->md_flags |= LNET_MD_FLAG_ABORTED;
 244                if (md->md_eq && !md->md_refcount) {
 245                        lnet_build_unlink_event(md, &ev);
 246                        lnet_eq_enqueue_event(md->md_eq, &ev);
 247                }
 248        }
 249
 250        lnet_me_unlink(me);
 251
 252        lnet_res_unlock(cpt);
 253        return 0;
 254}
 255EXPORT_SYMBOL(LNetMEUnlink);
 256
 257/* call with lnet_res_lock please */
 258void
 259lnet_me_unlink(lnet_me_t *me)
 260{
 261        list_del(&me->me_list);
 262
 263        if (me->me_md) {
 264                lnet_libmd_t *md = me->me_md;
 265
 266                /* detach MD from portal of this ME */
 267                lnet_ptl_detach_md(me, md);
 268                lnet_md_unlink(md);
 269        }
 270
 271        lnet_res_lh_invalidate(&me->me_lh);
 272        lnet_me_free(me);
 273}
 274
 275#if 0
 276static void
 277lib_me_dump(lnet_me_t *me)
 278{
 279        CWARN("Match Entry %p (%#llx)\n", me,
 280              me->me_lh.lh_cookie);
 281
 282        CWARN("\tMatch/Ignore\t= %016lx / %016lx\n",
 283              me->me_match_bits, me->me_ignore_bits);
 284
 285        CWARN("\tMD\t= %p\n", me->md);
 286        CWARN("\tprev\t= %p\n",
 287              list_entry(me->me_list.prev, lnet_me_t, me_list));
 288        CWARN("\tnext\t= %p\n",
 289              list_entry(me->me_list.next, lnet_me_t, me_list));
 290}
 291#endif
 292