Whamcloud - gitweb
b21619 hash ME on RDMA portal i=isaac i=maxim
[fs/lustre-release.git] / lnet / lnet / lib-me.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lnet/lnet/lib-me.c
37  *
38  * Match Entry management routines
39  */
40
41 #define DEBUG_SUBSYSTEM S_LNET
42
43 #include <lnet/lib-lnet.h>
44
45 static int
46 lnet_me_match_portal(lnet_portal_t *ptl, lnet_process_id_t id,
47                      __u64 match_bits, __u64 ignore_bits)
48 {
49         cfs_list_t       *mhash = NULL;
50         int               unique;
51
52         LASSERT (!(lnet_portal_is_unique(ptl) &&
53                    lnet_portal_is_wildcard(ptl)));
54
55         /* prefer to check w/o any lock */
56         unique = lnet_match_is_unique(id, match_bits, ignore_bits);
57         if (likely(lnet_portal_is_unique(ptl) ||
58                    lnet_portal_is_wildcard(ptl)))
59                 goto match;
60
61         /* unset, new portal */
62         if (unique) {
63                 mhash = lnet_portal_mhash_alloc();
64                 if (mhash == NULL)
65                         return -ENOMEM;
66         }
67
68         LNET_LOCK();
69         if (lnet_portal_is_unique(ptl) ||
70             lnet_portal_is_wildcard(ptl)) {
71                 /* someone set it before me */
72                 if (mhash != NULL)
73                         lnet_portal_mhash_free(mhash);
74                 LNET_UNLOCK();
75                 goto match;
76         }
77
78         /* still not set */
79         LASSERT (ptl->ptl_mhash == NULL);
80         if (unique) {
81                 ptl->ptl_mhash = mhash;
82                 lnet_portal_setopt(ptl, LNET_PTL_MATCH_UNIQUE);
83         } else {
84                 lnet_portal_setopt(ptl, LNET_PTL_MATCH_WILDCARD);
85         }
86         LNET_UNLOCK();
87         return 0;
88
89  match:
90         if (lnet_portal_is_unique(ptl) && !unique)
91                 return -EPERM;
92
93         if (lnet_portal_is_wildcard(ptl) && unique)
94                 return -EPERM;
95
96         return 0;
97 }
98
99 int
100 LNetMEAttach(unsigned int portal,
101              lnet_process_id_t match_id,
102              __u64 match_bits, __u64 ignore_bits,
103              lnet_unlink_t unlink, lnet_ins_pos_t pos,
104              lnet_handle_me_t *handle)
105 {
106         lnet_me_t        *me;
107         lnet_portal_t    *ptl;
108         cfs_list_t       *head;
109         int               rc;
110
111         LASSERT (the_lnet.ln_init);
112         LASSERT (the_lnet.ln_refcount > 0);
113
114         if ((int)portal >= the_lnet.ln_nportals)
115                 return -EINVAL;
116
117         ptl = &the_lnet.ln_portals[portal];
118         rc = lnet_me_match_portal(ptl, match_id, match_bits, ignore_bits);
119         if (rc != 0)
120                 return rc;
121
122         me = lnet_me_alloc();
123         if (me == NULL)
124                 return -ENOMEM;
125
126         LNET_LOCK();
127
128         me->me_portal = portal;
129         me->me_match_id = match_id;
130         me->me_match_bits = match_bits;
131         me->me_ignore_bits = ignore_bits;
132         me->me_unlink = unlink;
133         me->me_md = NULL;
134
135         lnet_initialise_handle (&me->me_lh, LNET_COOKIE_TYPE_ME);
136         head = lnet_portal_me_head(portal, match_id, match_bits);
137         LASSERT (head != NULL);
138
139         if (pos == LNET_INS_AFTER)
140                 cfs_list_add_tail(&me->me_list, head);
141         else
142                 cfs_list_add(&me->me_list, head);
143
144         lnet_me2handle(handle, me);
145
146         LNET_UNLOCK();
147
148         return 0;
149 }
150
151 int
152 LNetMEInsert(lnet_handle_me_t current_meh,
153              lnet_process_id_t match_id,
154              __u64 match_bits, __u64 ignore_bits,
155              lnet_unlink_t unlink, lnet_ins_pos_t pos,
156              lnet_handle_me_t *handle)
157 {
158         lnet_me_t     *current_me;
159         lnet_me_t     *new_me;
160         lnet_portal_t *ptl;
161
162         LASSERT (the_lnet.ln_init);
163         LASSERT (the_lnet.ln_refcount > 0);
164
165         new_me = lnet_me_alloc();
166         if (new_me == NULL)
167                 return -ENOMEM;
168
169         LNET_LOCK();
170
171         current_me = lnet_handle2me(&current_meh);
172         if (current_me == NULL) {
173                 lnet_me_free (new_me);
174
175                 LNET_UNLOCK();
176                 return -ENOENT;
177         }
178
179         LASSERT (current_me->me_portal < the_lnet.ln_nportals);
180
181         ptl = &the_lnet.ln_portals[current_me->me_portal];
182         if (lnet_portal_is_unique(ptl)) {
183                 /* nosense to insertion on unique portal */
184                 lnet_me_free (new_me);
185                 LNET_UNLOCK();
186                 return -EPERM;
187         }
188
189         new_me->me_portal = current_me->me_portal;
190         new_me->me_match_id = match_id;
191         new_me->me_match_bits = match_bits;
192         new_me->me_ignore_bits = ignore_bits;
193         new_me->me_unlink = unlink;
194         new_me->me_md = NULL;
195
196         lnet_initialise_handle (&new_me->me_lh, LNET_COOKIE_TYPE_ME);
197
198         if (pos == LNET_INS_AFTER)
199                 cfs_list_add(&new_me->me_list, &current_me->me_list);
200         else
201                 cfs_list_add_tail(&new_me->me_list, &current_me->me_list);
202
203         lnet_me2handle(handle, new_me);
204
205         LNET_UNLOCK();
206
207         return 0;
208 }
209
210 int
211 LNetMEUnlink(lnet_handle_me_t meh)
212 {
213         lnet_me_t    *me;
214         lnet_libmd_t *md;
215         lnet_event_t  ev;
216
217         LASSERT (the_lnet.ln_init);
218         LASSERT (the_lnet.ln_refcount > 0);
219
220         LNET_LOCK();
221
222         me = lnet_handle2me(&meh);
223         if (me == NULL) {
224                 LNET_UNLOCK();
225                 return -ENOENT;
226         }
227
228         md = me->me_md;
229         if (md != NULL &&
230             md->md_eq != NULL &&
231             md->md_refcount == 0) {
232                 lnet_build_unlink_event(md, &ev);
233                 lnet_enq_event_locked(md->md_eq, &ev);
234         }
235
236         lnet_me_unlink(me);
237
238         LNET_UNLOCK();
239         return 0;
240 }
241
242 /* call with LNET_LOCK please */
243 void
244 lnet_me_unlink(lnet_me_t *me)
245 {
246         cfs_list_del (&me->me_list);
247
248         if (me->me_md != NULL) {
249                 me->me_md->md_me = NULL;
250                 lnet_md_unlink(me->me_md);
251         }
252
253         lnet_invalidate_handle (&me->me_lh);
254         lnet_me_free(me);
255 }
256
257 #if 0
258 static void
259 lib_me_dump(lnet_me_t *me)
260 {
261         CWARN("Match Entry %p ("LPX64")\n", me,
262               me->me_lh.lh_cookie);
263
264         CWARN("\tMatch/Ignore\t= %016lx / %016lx\n",
265               me->me_match_bits, me->me_ignore_bits);
266
267         CWARN("\tMD\t= %p\n", me->md);
268         CWARN("\tprev\t= %p\n",
269               cfs_list_entry(me->me_list.prev, lnet_me_t, me_list));
270         CWARN("\tnext\t= %p\n",
271               cfs_list_entry(me->me_list.next, lnet_me_t, me_list));
272 }
273 #endif