Whamcloud - gitweb
* Landed b_cray_portals_merge.
[fs/lustre-release.git] / lustre / portals / portals / api-wrap.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * api/api-wrap.c
5  * User-level wrappers that dispatch across the protection boundaries
6  *
7  *  Copyright (c) 2001-2003 Cluster File Systems, Inc.
8  *  Copyright (c) 2001-2002 Sandia National Laboratories
9  *
10  *   This file is part of Lustre, http://www.sf.net/projects/lustre/
11  *
12  *   Lustre is free software; you can redistribute it and/or
13  *   modify it under the terms of version 2 of the GNU General Public
14  *   License as published by the Free Software Foundation.
15  *
16  *   Lustre is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with Lustre; if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 # define DEBUG_SUBSYSTEM S_PORTALS
27 #include <portals/api-support.h>
28
29 static int do_forward(ptl_handle_any_t any_h, int cmd, void *argbuf,
30                       int argsize, void *retbuf, int retsize)
31 {
32         nal_t *nal;
33
34         if (!ptl_init) {
35                 CERROR("Not initialized\n");
36                 return PTL_NO_INIT;
37         }
38
39         nal = ptl_hndl2nal(&any_h);
40         if (!nal)
41                 return PTL_HANDLE_INVALID;
42
43         nal->forward(nal, cmd, argbuf, argsize, retbuf, retsize);
44
45         return PTL_OK;
46 }
47
48 int PtlGetId(ptl_handle_ni_t ni_handle, ptl_process_id_t *id)
49 {
50         PtlGetId_in args;
51         PtlGetId_out ret;
52         int rc;
53
54         args.handle_in = ni_handle;
55
56         rc = do_forward(ni_handle, PTL_GETID, &args, sizeof(args), &ret,
57                         sizeof(ret));
58         if (rc != PTL_OK)
59                 return rc;
60         
61         if (id)
62                 *id = ret.id_out;
63
64         return ret.rc;
65 }
66
67 int PtlFailNid (ptl_handle_ni_t interface, ptl_nid_t nid, unsigned int threshold) 
68 {
69         PtlFailNid_in  args;
70         PtlFailNid_out ret;
71         int            rc;
72         
73         args.interface = interface;
74         args.nid       = nid;
75         args.threshold = threshold;
76         
77         rc = do_forward (interface, PTL_FAILNID, 
78                          &args, sizeof(args), &ret, sizeof (ret));
79
80         return ((rc != PTL_OK) ? rc : ret.rc);
81 }
82
83 int PtlNIStatus(ptl_handle_ni_t interface_in, ptl_sr_index_t register_in,
84                 ptl_sr_value_t * status_out)
85 {
86         PtlNIStatus_in args;
87         PtlNIStatus_out ret;
88         int rc;
89
90         args.interface_in = interface_in;
91         args.register_in = register_in;
92
93         rc = do_forward(interface_in, PTL_NISTATUS, &args, sizeof(args), &ret,
94                         sizeof(ret));
95
96         if (rc != PTL_OK)
97                 return rc;
98
99         if (status_out)
100                 *status_out = ret.status_out;
101
102         return ret.rc;
103 }
104
105 int PtlNIDist(ptl_handle_ni_t interface_in, ptl_process_id_t process_in,
106               unsigned long *distance_out)
107 {
108         PtlNIDist_in args;
109         PtlNIDist_out ret;
110         int rc;
111
112         args.interface_in = interface_in;
113         args.process_in = process_in;
114
115         rc = do_forward(interface_in, PTL_NIDIST, &args, sizeof(args), &ret,
116                         sizeof(ret));
117
118         if (rc != PTL_OK)
119                 return rc;
120
121         if (distance_out)
122                 *distance_out = ret.distance_out;
123
124         return ret.rc;
125 }
126
127 int PtlMEAttach(ptl_handle_ni_t interface_in, ptl_pt_index_t index_in,
128                 ptl_process_id_t match_id_in, ptl_match_bits_t match_bits_in,
129                 ptl_match_bits_t ignore_bits_in, ptl_unlink_t unlink_in,
130                 ptl_ins_pos_t pos_in, ptl_handle_me_t * handle_out)
131 {
132         PtlMEAttach_in args;
133         PtlMEAttach_out ret;
134         int rc;
135
136         args.interface_in = interface_in;
137         args.index_in = index_in;
138         args.match_id_in = match_id_in;
139         args.match_bits_in = match_bits_in;
140         args.ignore_bits_in = ignore_bits_in;
141         args.unlink_in = unlink_in;
142         args.position_in = pos_in;
143
144         rc = do_forward(interface_in, PTL_MEATTACH, &args, sizeof(args), &ret,
145                         sizeof(ret));
146
147         if (rc != PTL_OK)
148                 return rc;
149
150         if (handle_out) {
151                 handle_out->nal_idx = interface_in.nal_idx;
152                 handle_out->cookie = ret.handle_out.cookie;
153         }
154
155         return ret.rc;
156 }
157
158 int PtlMEInsert(ptl_handle_me_t current_in, ptl_process_id_t match_id_in,
159                 ptl_match_bits_t match_bits_in, ptl_match_bits_t ignore_bits_in,
160                 ptl_unlink_t unlink_in, ptl_ins_pos_t position_in,
161                 ptl_handle_me_t * handle_out)
162 {
163         PtlMEInsert_in args;
164         PtlMEInsert_out ret;
165         int rc;
166
167         args.current_in = current_in;
168         args.match_id_in = match_id_in;
169         args.match_bits_in = match_bits_in;
170         args.ignore_bits_in = ignore_bits_in;
171         args.unlink_in = unlink_in;
172         args.position_in = position_in;
173
174         rc = do_forward(current_in, PTL_MEINSERT, &args, sizeof(args), &ret,
175                         sizeof(ret));
176
177         if (rc != PTL_OK)
178                 return (rc == PTL_HANDLE_INVALID) ? PTL_ME_INVALID : rc;
179
180         if (handle_out) {
181                 handle_out->nal_idx = current_in.nal_idx;
182                 handle_out->cookie = ret.handle_out.cookie;
183         }
184         return ret.rc;
185 }
186
187 int PtlMEUnlink(ptl_handle_me_t current_in)
188 {
189         PtlMEUnlink_in args;
190         PtlMEUnlink_out ret;
191         int rc;
192
193         args.current_in = current_in;
194         args.unlink_in = PTL_RETAIN;
195
196         rc = do_forward(current_in, PTL_MEUNLINK, &args, sizeof(args), &ret,
197                         sizeof(ret));
198
199         if (rc != PTL_OK)
200                 return (rc == PTL_HANDLE_INVALID) ? PTL_ME_INVALID : rc;
201
202         return ret.rc;
203 }
204
205 int PtlTblDump(ptl_handle_ni_t ni, int index_in)
206 {
207         PtlTblDump_in args;
208         PtlTblDump_out ret;
209         int rc;
210
211         args.index_in = index_in;
212
213         rc = do_forward(ni, PTL_TBLDUMP, &args, sizeof(args), &ret,
214                         sizeof(ret));
215
216         if (rc != PTL_OK)
217                 return rc;
218
219         return ret.rc;
220 }
221
222 int PtlMEDump(ptl_handle_me_t current_in)
223 {
224         PtlMEDump_in args;
225         PtlMEDump_out ret;
226         int rc;
227
228         args.current_in = current_in;
229
230         rc = do_forward(current_in, PTL_MEDUMP, &args, sizeof(args), &ret,
231                         sizeof(ret));
232
233         if (rc != PTL_OK)
234                 return (rc == PTL_HANDLE_INVALID) ? PTL_ME_INVALID : rc;
235
236         return ret.rc;
237 }
238
239 static ptl_handle_eq_t md2eq (ptl_md_t *md)
240 {
241         if (PtlHandleIsEqual (md->eventq, PTL_EQ_NONE))
242                 return (PTL_EQ_NONE);
243         
244         return (ptl_handle2usereq (&md->eventq)->cb_eq_handle);
245 }
246
247
248 int PtlMDAttach(ptl_handle_me_t me_in, ptl_md_t md_in,
249                 ptl_unlink_t unlink_in, ptl_handle_md_t * handle_out)
250 {
251         PtlMDAttach_in args;
252         PtlMDAttach_out ret;
253         int rc;
254
255         args.eq_in = md2eq(&md_in);
256         args.me_in = me_in;
257         args.md_in = md_in;
258         args.unlink_in = unlink_in;
259                 
260         rc = do_forward(me_in, PTL_MDATTACH, 
261                         &args, sizeof(args), &ret, sizeof(ret));
262
263         if (rc != PTL_OK)
264                 return (rc == PTL_HANDLE_INVALID) ? PTL_ME_INVALID : rc;
265
266         if (handle_out) {
267                 handle_out->nal_idx = me_in.nal_idx;
268                 handle_out->cookie = ret.handle_out.cookie;
269         }
270         return ret.rc;
271 }
272
273
274
275 int PtlMDBind(ptl_handle_ni_t ni_in, ptl_md_t md_in,
276               ptl_unlink_t unlink_in, ptl_handle_md_t * handle_out)
277 {
278         PtlMDBind_in args;
279         PtlMDBind_out ret;
280         int rc;
281
282         args.eq_in = md2eq(&md_in);
283         args.ni_in = ni_in;
284         args.md_in = md_in;
285         args.unlink_in = unlink_in;
286
287         rc = do_forward(ni_in, PTL_MDBIND, 
288                         &args, sizeof(args), &ret, sizeof(ret));
289
290         if (rc != PTL_OK)
291                 return rc;
292
293         if (handle_out) {
294                 handle_out->nal_idx = ni_in.nal_idx;
295                 handle_out->cookie = ret.handle_out.cookie;
296         }
297         return ret.rc;
298 }
299
300 int PtlMDUpdate(ptl_handle_md_t md_in, ptl_md_t *old_inout,
301                 ptl_md_t *new_inout, ptl_handle_eq_t testq_in)
302 {
303         PtlMDUpdate_internal_in args;
304         PtlMDUpdate_internal_out ret;
305         int rc;
306
307         args.md_in = md_in;
308
309         if (old_inout) {
310                 args.old_inout = *old_inout;
311                 args.old_inout_valid = 1;
312         } else
313                 args.old_inout_valid = 0;
314
315         if (new_inout) {
316                 args.new_inout = *new_inout;
317                 args.new_inout_valid = 1;
318         } else
319                 args.new_inout_valid = 0;
320
321         if (PtlHandleIsEqual (testq_in, PTL_EQ_NONE)) {
322                 args.testq_in = PTL_EQ_NONE;
323                 args.sequence_in = -1;
324         } else {
325                 ptl_eq_t *eq = ptl_handle2usereq (&testq_in);
326                 
327                 args.testq_in = eq->cb_eq_handle;
328                 args.sequence_in = eq->sequence;
329         }
330
331         rc = do_forward(md_in, PTL_MDUPDATE, &args, sizeof(args), &ret,
332                         sizeof(ret));
333         if (rc != PTL_OK)
334                 return (rc == PTL_HANDLE_INVALID) ? PTL_MD_INVALID : rc;
335
336         if (old_inout)
337                 *old_inout = ret.old_inout;
338
339         return ret.rc;
340 }
341
342 int PtlMDUnlink(ptl_handle_md_t md_in)
343 {
344         PtlMDUnlink_in args;
345         PtlMDUnlink_out ret;
346         int rc;
347
348         args.md_in = md_in;
349         rc = do_forward(md_in, PTL_MDUNLINK, &args, sizeof(args), &ret,
350                         sizeof(ret));
351         if (rc != PTL_OK)
352                 return (rc == PTL_HANDLE_INVALID) ? PTL_MD_INVALID : rc;
353
354         return ret.rc;
355 }
356
357 int PtlEQAlloc(ptl_handle_ni_t interface, ptl_size_t count,
358                ptl_eq_handler_t callback,
359                ptl_handle_eq_t * handle_out)
360 {
361         ptl_eq_t *eq = NULL;
362         ptl_event_t *ev = NULL;
363         PtlEQAlloc_in args;
364         PtlEQAlloc_out ret;
365         int rc, i;
366         nal_t *nal;
367
368         if (!ptl_init)
369                 return PTL_NO_INIT;
370         
371         nal = ptl_hndl2nal (&interface);
372         if (nal == NULL)
373                 return PTL_HANDLE_INVALID;
374
375         if (count != LOWEST_BIT_SET(count)) {   /* not a power of 2 already */
376                 do {                    /* knock off all but the top bit... */
377                         count &= ~LOWEST_BIT_SET (count);
378                 } while (count != LOWEST_BIT_SET(count));
379
380                 count <<= 1;                             /* ...and round up */
381         }
382
383         if (count == 0)        /* catch bad parameter / overflow on roundup */
384                 return (PTL_VAL_FAILED);
385
386         PORTAL_ALLOC(ev, count * sizeof(ptl_event_t));
387         if (!ev)
388                 return PTL_NO_SPACE;
389
390         for (i = 0; i < count; i++)
391                 ev[i].sequence = 0;
392
393         args.ni_in = interface;
394         args.count_in = count;
395         args.base_in = ev;
396         args.len_in = count * sizeof(*ev);
397         args.callback_in = callback;
398
399         rc = do_forward(interface, PTL_EQALLOC, &args, sizeof(args), &ret,
400                         sizeof(ret));
401         if (rc != PTL_OK)
402                 goto fail;
403         if (ret.rc)
404                 GOTO(fail, rc = ret.rc);
405
406         PORTAL_ALLOC(eq, sizeof(*eq));
407         if (!eq) {
408                 rc = PTL_NO_SPACE;
409                 goto fail;
410         }
411
412         eq->sequence = 1;
413         eq->size = count;
414         eq->base = ev;
415
416         /* EQ handles are a little wierd.  PtlEQGet() just looks at the
417          * queued events in shared memory.  It doesn't want to do_forward()
418          * at all, so the cookie in the EQ handle we pass out of here is
419          * simply a pointer to the event queue we just set up.  We stash
420          * the handle returned by do_forward(), so we can pass it back via
421          * do_forward() when we need to. */
422
423         eq->cb_eq_handle.nal_idx = interface.nal_idx;
424         eq->cb_eq_handle.cookie = ret.handle_out.cookie;
425
426         handle_out->nal_idx = interface.nal_idx;
427         handle_out->cookie = (__u64)((unsigned long)eq);
428         return PTL_OK;
429
430 fail:
431         PORTAL_FREE(ev, count * sizeof(ptl_event_t));
432         return rc;
433 }
434
435 int PtlEQFree(ptl_handle_eq_t eventq)
436 {
437         PtlEQFree_in args;
438         PtlEQFree_out ret;
439         ptl_eq_t *eq;
440         int rc;
441
442         eq = ptl_handle2usereq (&eventq);
443         args.eventq_in = eq->cb_eq_handle;
444
445         rc = do_forward(eq->cb_eq_handle, PTL_EQFREE, &args,
446                         sizeof(args), &ret, sizeof(ret));
447
448         /* XXX we're betting rc == PTL_OK here */
449         PORTAL_FREE(eq->base, eq->size * sizeof(ptl_event_t));
450         PORTAL_FREE(eq, sizeof(*eq));
451
452         return rc;
453 }
454
455 int PtlACEntry(ptl_handle_ni_t ni_in, ptl_ac_index_t index_in,
456                ptl_process_id_t match_id_in, ptl_pt_index_t portal_in)
457 {
458         PtlACEntry_in args;
459         PtlACEntry_out ret;
460         int rc;
461
462         /*
463          * Copy arguments into the argument block to
464          * hand to the forwarding object
465          */
466         args.ni_in = ni_in;
467         args.index_in = index_in;
468         args.match_id_in = match_id_in;
469         args.portal_in = portal_in;
470
471         rc = do_forward(ni_in, PTL_ACENTRY, &args, sizeof(args), &ret,
472                         sizeof(ret));
473
474         return (rc != PTL_OK) ? rc : ret.rc;
475 }
476
477 int PtlPut(ptl_handle_md_t md_in, ptl_ack_req_t ack_req_in,
478            ptl_process_id_t target_in, ptl_pt_index_t portal_in,
479            ptl_ac_index_t cookie_in, ptl_match_bits_t match_bits_in,
480            ptl_size_t offset_in, ptl_hdr_data_t hdr_data_in)
481 {
482         PtlPut_in args;
483         PtlPut_out ret;
484         int rc;
485
486         /*
487          * Copy arguments into the argument block to
488          * hand to the forwarding object
489          */
490         args.md_in = md_in;
491         args.ack_req_in = ack_req_in;
492         args.target_in = target_in;
493         args.portal_in = portal_in;
494         args.cookie_in = cookie_in;
495         args.match_bits_in = match_bits_in;
496         args.offset_in = offset_in;
497         args.hdr_data_in = hdr_data_in;
498
499         rc = do_forward(md_in, PTL_PUT, &args, sizeof(args), &ret, sizeof(ret));
500
501         return (rc != PTL_OK) ? rc : ret.rc;
502 }
503
504 int PtlGet(ptl_handle_md_t md_in, ptl_process_id_t target_in,
505            ptl_pt_index_t portal_in, ptl_ac_index_t cookie_in,
506            ptl_match_bits_t match_bits_in, ptl_size_t offset_in)
507 {
508         PtlGet_in args;
509         PtlGet_out ret;
510         int rc;
511
512         /*
513          * Copy arguments into the argument block to
514          * hand to the forwarding object
515          */
516         args.md_in = md_in;
517         args.target_in = target_in;
518         args.portal_in = portal_in;
519         args.cookie_in = cookie_in;
520         args.match_bits_in = match_bits_in;
521         args.offset_in = offset_in;
522
523         rc = do_forward(md_in, PTL_GET, &args, sizeof(args), &ret, sizeof(ret));
524
525         return (rc != PTL_OK) ? rc : ret.rc;
526 }