Whamcloud - gitweb
b=3031
[fs/lustre-release.git] / lnet / lnet / api-ni.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2001-2003 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.sf.net/projects/lustre/
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #define DEBUG_SUBSYSTEM S_PORTALS
23 #include <portals/api-support.h>
24
25 int ptl_init;
26
27 /* Put some magic in the NI handle so uninitialised/zeroed handles are easy
28  * to spot */
29 #define NI_HANDLE_MAGIC  0xebc0de00
30 #define NI_HANDLE_MASK   0x000000ff
31
32 static struct nal_t *ptl_nal_table[NAL_MAX_NR + 1];
33
34 #ifdef __KERNEL__
35 struct semaphore ptl_mutex;
36
37 static void ptl_mutex_enter (void) 
38 {
39         mutex_down (&ptl_mutex);
40 }
41
42 static void ptl_mutex_exit (void)
43 {
44         mutex_up (&ptl_mutex);
45 }
46 #else
47 static void ptl_mutex_enter (void)
48 {
49 }
50
51 static void ptl_mutex_exit (void) 
52 {
53 }
54 #endif
55
56 nal_t *ptl_hndl2nal(ptl_handle_any_t *handle)
57 {
58         unsigned int idx = handle->nal_idx;
59
60         /* XXX we really rely on the caller NOT racing with interface
61          * setup/teardown.  That ensures her NI handle can't get
62          * invalidated out from under her (or worse, swapped for a
63          * completely different interface!) */
64
65         LASSERT (ptl_init);
66
67         if (((idx ^ NI_HANDLE_MAGIC) & ~NI_HANDLE_MASK) != 0)
68                 return NULL;
69
70         idx &= NI_HANDLE_MASK;
71         
72         if (idx > NAL_MAX_NR ||
73             ptl_nal_table[idx] == NULL ||
74             ptl_nal_table[idx]->nal_refct == 0)
75                 return NULL;
76
77         return ptl_nal_table[idx];
78 }
79
80 int ptl_register_nal (ptl_interface_t interface, nal_t *nal)
81 {
82         int    rc;
83         
84         ptl_mutex_enter();
85         
86         if (interface < 0 || interface > NAL_MAX_NR)
87                 rc = PTL_IFACE_INVALID;
88         else if (ptl_nal_table[interface] != NULL)
89                 rc = PTL_IFACE_DUP;
90         else {
91                 rc = PTL_OK;
92                 ptl_nal_table[interface] = nal;
93                 LASSERT(nal->nal_refct == 0);
94         }
95
96         ptl_mutex_exit();
97         return (rc);
98 }
99
100 void ptl_unregister_nal (ptl_interface_t interface)
101 {
102         LASSERT(interface >= 0 && interface <= NAL_MAX_NR);
103         LASSERT(ptl_nal_table[interface] != NULL);
104         LASSERT(ptl_nal_table[interface]->nal_refct == 0);
105         
106         ptl_mutex_enter();
107         
108         ptl_nal_table[interface] = NULL;
109
110         ptl_mutex_exit();
111 }
112
113 int PtlInit(int *max_interfaces)
114 {
115         LASSERT(!strcmp(ptl_err_str[PTL_MAX_ERRNO], "PTL_MAX_ERRNO"));
116
117         /* If this assertion fails, we need more bits in NI_HANDLE_MASK and
118          * to shift NI_HANDLE_MAGIC left appropriately */
119         LASSERT (NAL_MAX_NR < (NI_HANDLE_MASK + 1));
120         
121         if (max_interfaces != NULL)
122                 *max_interfaces = NAL_MAX_NR + 1;
123
124         ptl_mutex_enter();
125
126         if (!ptl_init) {
127                 /* NULL pointers, clear flags */
128                 memset(ptl_nal_table, 0, sizeof(ptl_nal_table));
129 #ifndef __KERNEL__
130                 /* Kernel NALs register themselves when their module loads,
131                  * and unregister themselves when their module is unloaded.
132                  * Userspace NALs, are plugged in explicitly here... */
133                 {
134                         extern nal_t procapi_nal;
135
136                         /* XXX pretend it's socknal to keep liblustre happy... */
137                         ptl_nal_table[SOCKNAL] = &procapi_nal;
138                         LASSERT (procapi_nal.nal_refct == 0);
139                 }
140 #endif
141                 ptl_init = 1;
142         }
143
144         ptl_mutex_exit();
145         
146         return PTL_OK;
147 }
148
149 void PtlFini(void)
150 {
151         nal_t  *nal;
152         int     i;
153
154         ptl_mutex_enter();
155
156         if (ptl_init) {
157                 for (i = 0; i <= NAL_MAX_NR; i++) {
158
159                         nal = ptl_nal_table[i];
160                         if (nal == NULL)
161                                 continue;
162                         
163                         if (nal->nal_refct != 0) {
164                                 CWARN("NAL %x has outstanding refcount %d\n",
165                                       i, nal->nal_refct);
166                                 nal->nal_ni_fini(nal);
167                         }
168                         
169                         ptl_nal_table[i] = NULL;
170                 }
171
172                 ptl_init = 0;
173         }
174         
175         ptl_mutex_exit();
176 }
177
178 int PtlNIInit(ptl_interface_t interface, ptl_pid_t requested_pid,
179               ptl_ni_limits_t *desired_limits, ptl_ni_limits_t *actual_limits,
180               ptl_handle_ni_t *handle)
181 {
182         nal_t *nal;
183         int    i;
184         int    rc;
185
186         if (!ptl_init)
187                 return PTL_NO_INIT;
188
189         ptl_mutex_enter ();
190
191         if (interface == PTL_IFACE_DEFAULT) {
192                 for (i = 0; i <= NAL_MAX_NR; i++)
193                         if (ptl_nal_table[i] != NULL) {
194                                 interface = i;
195                                 break;
196                         }
197                 /* NB if no interfaces are registered, 'interface' will
198                  * fail the valid test below */
199         }
200         
201         if (interface < 0 || 
202             interface > NAL_MAX_NR ||
203             ptl_nal_table[interface] == NULL) {
204                 GOTO(out, rc = PTL_IFACE_INVALID);
205         }
206
207         nal = ptl_nal_table[interface];
208         nal->nal_handle.nal_idx = (NI_HANDLE_MAGIC & ~NI_HANDLE_MASK) | interface;
209         nal->nal_handle.cookie = 0;
210         
211         CDEBUG(D_OTHER, "Starting up NAL (%x) refs %d\n", interface, nal->nal_refct);
212         rc = nal->nal_ni_init(nal, requested_pid, desired_limits, actual_limits);
213
214         if (rc != PTL_OK) {
215                 CERROR("Error %d starting up NAL %x, refs %d\n", rc,
216                        interface, nal->nal_refct);
217                 GOTO(out, rc);
218         }
219         
220         if (nal->nal_refct != 0) {
221                 /* Caller gets to know if this was the first ref or not */
222                 rc = PTL_IFACE_DUP;
223         }
224         
225         nal->nal_refct++;
226         *handle = nal->nal_handle;
227
228  out:
229         ptl_mutex_exit ();
230
231         return rc;
232 }
233
234 int PtlNIFini(ptl_handle_ni_t ni)
235 {
236         nal_t *nal;
237         int    idx;
238
239         if (!ptl_init)
240                 return PTL_NO_INIT;
241
242         ptl_mutex_enter ();
243
244         nal = ptl_hndl2nal (&ni);
245         if (nal == NULL) {
246                 ptl_mutex_exit ();
247                 return PTL_HANDLE_INVALID;
248         }
249
250         idx = ni.nal_idx & NI_HANDLE_MASK;
251
252         LASSERT(nal->nal_refct > 0);
253
254         nal->nal_refct--;
255
256         /* nal_refct == 0 tells nal->shutdown to really shut down */
257         nal->nal_ni_fini(nal);
258
259         ptl_mutex_exit ();
260         return PTL_OK;
261 }