Whamcloud - gitweb
e54707f946aad83a22a67af6f05a17407ae6f6a0
[fs/lustre-release.git] / lnet / lnet / 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                 fprintf(stderr, "PtlGetId: Not initialized\n");
36                 return PTL_NOINIT;
37         }
38
39         nal = ptl_hndl2nal(&any_h);
40         if (!nal)
41                 return PTL_INV_HANDLE;
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
128
129 unsigned int PtlNIDebug(ptl_handle_ni_t ni, unsigned int mask_in)
130 {
131         PtlNIDebug_in args;
132         PtlNIDebug_out ret;
133         int rc;
134
135         args.mask_in = mask_in;
136
137         rc = do_forward(ni, PTL_NIDEBUG, &args, sizeof(args), &ret,
138                         sizeof(ret));
139
140         if (rc != PTL_OK)
141                 return rc;
142
143         return ret.rc;
144 }
145
146 int PtlMEAttach(ptl_handle_ni_t interface_in, ptl_pt_index_t index_in,
147                 ptl_process_id_t match_id_in, ptl_match_bits_t match_bits_in,
148                 ptl_match_bits_t ignore_bits_in, ptl_unlink_t unlink_in,
149                 ptl_ins_pos_t pos_in, ptl_handle_me_t * handle_out)
150 {
151         PtlMEAttach_in args;
152         PtlMEAttach_out ret;
153         int rc;
154
155         args.interface_in = interface_in;
156         args.index_in = index_in;
157         args.match_id_in = match_id_in;
158         args.match_bits_in = match_bits_in;
159         args.ignore_bits_in = ignore_bits_in;
160         args.unlink_in = unlink_in;
161         args.position_in = pos_in;
162
163         rc = do_forward(interface_in, PTL_MEATTACH, &args, sizeof(args), &ret,
164                         sizeof(ret));
165
166         if (rc != PTL_OK)
167                 return rc;
168
169         if (handle_out) {
170                 handle_out->nal_idx = interface_in.nal_idx;
171                 handle_out->cookie = ret.handle_out.cookie;
172         }
173
174         return ret.rc;
175 }
176
177 int PtlMEInsert(ptl_handle_me_t current_in, ptl_process_id_t match_id_in,
178                 ptl_match_bits_t match_bits_in, ptl_match_bits_t ignore_bits_in,
179                 ptl_unlink_t unlink_in, ptl_ins_pos_t position_in,
180                 ptl_handle_me_t * handle_out)
181 {
182         PtlMEInsert_in args;
183         PtlMEInsert_out ret;
184         int rc;
185
186         args.current_in = current_in;
187         args.match_id_in = match_id_in;
188         args.match_bits_in = match_bits_in;
189         args.ignore_bits_in = ignore_bits_in;
190         args.unlink_in = unlink_in;
191         args.position_in = position_in;
192
193         rc = do_forward(current_in, PTL_MEINSERT, &args, sizeof(args), &ret,
194                         sizeof(ret));
195
196         if (rc != PTL_OK)
197                 return (rc == PTL_INV_HANDLE) ? PTL_INV_ME : rc;
198
199         if (handle_out) {
200                 handle_out->nal_idx = current_in.nal_idx;
201                 handle_out->cookie = ret.handle_out.cookie;
202         }
203         return ret.rc;
204 }
205
206 int PtlMEUnlink(ptl_handle_me_t current_in)
207 {
208         PtlMEUnlink_in args;
209         PtlMEUnlink_out ret;
210         int rc;
211
212         args.current_in = current_in;
213         args.unlink_in = PTL_RETAIN;
214
215         rc = do_forward(current_in, PTL_MEUNLINK, &args, sizeof(args), &ret,
216                         sizeof(ret));
217
218         if (rc != PTL_OK)
219                 return (rc == PTL_INV_HANDLE) ? PTL_INV_ME : rc;
220
221         return ret.rc;
222 }
223
224 int PtlTblDump(ptl_handle_ni_t ni, int index_in)
225 {
226         PtlTblDump_in args;
227         PtlTblDump_out ret;
228         int rc;
229
230         args.index_in = index_in;
231
232         rc = do_forward(ni, PTL_TBLDUMP, &args, sizeof(args), &ret,
233                         sizeof(ret));
234
235         if (rc != PTL_OK)
236                 return rc;
237
238         return ret.rc;
239 }
240
241 int PtlMEDump(ptl_handle_me_t current_in)
242 {
243         PtlMEDump_in args;
244         PtlMEDump_out ret;
245         int rc;
246
247         args.current_in = current_in;
248
249         rc = do_forward(current_in, PTL_MEDUMP, &args, sizeof(args), &ret,
250                         sizeof(ret));
251
252         if (rc != PTL_OK)
253                 return (rc == PTL_INV_HANDLE) ? PTL_INV_ME : rc;
254
255         return ret.rc;
256 }
257
258 static int validate_md(ptl_handle_any_t current_in, ptl_md_t md_in)
259 {
260         nal_t *nal;
261         int rc;
262         int i;
263
264         if (!ptl_init) {
265                 fprintf(stderr, "PtlMDAttach/Bind/Update: Not initialized\n");
266                 return PTL_NOINIT;
267         }
268
269         nal = ptl_hndl2nal(&current_in);
270         if (!nal)
271                 return PTL_INV_HANDLE;
272
273         if (nal->validate != NULL)                /* nal->validate not a NOOP */
274         {
275                 if ((md_in.options & PTL_MD_IOV) == 0)        /* contiguous */
276                 {
277                         rc = nal->validate (nal, md_in.start, md_in.length);
278                         if (rc)
279                                 return (PTL_SEGV);
280                 }
281                 else
282                 {
283                         struct iovec *iov = (struct iovec *)md_in.start;
284
285                         for (i = 0; i < md_in.niov; i++, iov++)
286                         {
287                                 rc = nal->validate (nal, iov->iov_base, iov->iov_len);
288                                 if (rc)
289                                         return (PTL_SEGV);
290                         }
291                 }
292         }
293
294         return 0;
295 }
296
297 static ptl_handle_eq_t md2eq (ptl_md_t *md)
298 {
299         if (PtlHandleEqual (md->eventq, PTL_EQ_NONE))
300                 return (PTL_EQ_NONE);
301         
302         return (ptl_handle2usereq (&md->eventq)->cb_eq_handle);
303 }
304
305
306 int PtlMDAttach(ptl_handle_me_t me_in, ptl_md_t md_in,
307                 ptl_unlink_t unlink_in, ptl_handle_md_t * handle_out)
308 {
309         PtlMDAttach_in args;
310         PtlMDAttach_out ret;
311         int rc;
312
313         rc = validate_md(me_in, md_in);
314         if (rc == PTL_OK) {
315                 args.eq_in = md2eq(&md_in);
316                 args.me_in = me_in;
317                 args.md_in = md_in;
318                 args.unlink_in = unlink_in;
319                 
320                 rc = do_forward(me_in, PTL_MDATTACH, 
321                                 &args, sizeof(args), &ret, sizeof(ret));
322         }
323
324         if (rc != PTL_OK)
325                 return (rc == PTL_INV_HANDLE) ? PTL_INV_ME : rc;
326
327         if (handle_out) {
328                 handle_out->nal_idx = me_in.nal_idx;
329                 handle_out->cookie = ret.handle_out.cookie;
330         }
331         return ret.rc;
332 }
333
334
335
336 int PtlMDBind(ptl_handle_ni_t ni_in, ptl_md_t md_in,
337                        ptl_handle_md_t * handle_out)
338 {
339         PtlMDBind_in args;
340         PtlMDBind_out ret;
341         int rc;
342
343         rc = validate_md(ni_in, md_in);
344         if (rc != PTL_OK)
345                 return rc;
346
347         args.eq_in = md2eq(&md_in);
348         args.ni_in = ni_in;
349         args.md_in = md_in;
350
351         rc = do_forward(ni_in, PTL_MDBIND, 
352                         &args, sizeof(args), &ret, sizeof(ret));
353
354         if (rc != PTL_OK)
355                 return rc;
356
357         if (handle_out) {
358                 handle_out->nal_idx = ni_in.nal_idx;
359                 handle_out->cookie = ret.handle_out.cookie;
360         }
361         return ret.rc;
362 }
363
364 int PtlMDUpdate(ptl_handle_md_t md_in, ptl_md_t *old_inout,
365                 ptl_md_t *new_inout, ptl_handle_eq_t testq_in)
366 {
367         PtlMDUpdate_internal_in args;
368         PtlMDUpdate_internal_out ret;
369         int rc;
370
371         args.md_in = md_in;
372
373         if (old_inout) {
374                 args.old_inout = *old_inout;
375                 args.old_inout_valid = 1;
376         } else
377                 args.old_inout_valid = 0;
378
379         if (new_inout) {
380                 rc = validate_md (md_in, *new_inout);
381                 if (rc != PTL_OK)
382                         return (rc == PTL_INV_HANDLE) ? PTL_INV_MD : rc;
383                 args.new_inout = *new_inout;
384                 args.new_inout_valid = 1;
385         } else
386                 args.new_inout_valid = 0;
387
388         if (PtlHandleEqual (testq_in, PTL_EQ_NONE)) {
389                 args.testq_in = PTL_EQ_NONE;
390                 args.sequence_in = -1;
391         } else {
392                 ptl_eq_t *eq = ptl_handle2usereq (&testq_in);
393                 
394                 args.testq_in = eq->cb_eq_handle;
395                 args.sequence_in = eq->sequence;
396         }
397
398         rc = do_forward(md_in, PTL_MDUPDATE, &args, sizeof(args), &ret,
399                         sizeof(ret));
400         if (rc != PTL_OK)
401                 return (rc == PTL_INV_HANDLE) ? PTL_INV_MD : rc;
402
403         if (old_inout)
404                 *old_inout = ret.old_inout;
405
406         return ret.rc;
407 }
408
409 int PtlMDUnlink(ptl_handle_md_t md_in)
410 {
411         PtlMDUnlink_in args;
412         PtlMDUnlink_out ret;
413         int rc;
414
415         args.md_in = md_in;
416         rc = do_forward(md_in, PTL_MDUNLINK, &args, sizeof(args), &ret,
417                         sizeof(ret));
418         if (rc != PTL_OK)
419                 return (rc == PTL_INV_HANDLE) ? PTL_INV_MD : rc;
420
421         return ret.rc;
422 }
423
424 int PtlEQAlloc(ptl_handle_ni_t interface, ptl_size_t count,
425                int (*callback) (ptl_event_t * event),
426                ptl_handle_eq_t * handle_out)
427 {
428         ptl_eq_t *eq = NULL;
429         ptl_event_t *ev = NULL;
430         PtlEQAlloc_in args;
431         PtlEQAlloc_out ret;
432         int rc, i;
433         nal_t *nal;
434
435         if (!ptl_init)
436                 return PTL_NOINIT;
437         
438         nal = ptl_hndl2nal (&interface);
439         if (nal == NULL)
440                 return PTL_INV_HANDLE;
441
442         if (count != LOWEST_BIT_SET(count)) {   /* not a power of 2 already */
443                 do {                    /* knock off all but the top bit... */
444                         count &= ~LOWEST_BIT_SET (count);
445                 } while (count != LOWEST_BIT_SET(count));
446
447                 count <<= 1;                             /* ...and round up */
448         }
449
450         if (count == 0)        /* catch bad parameter / overflow on roundup */
451                 return (PTL_VAL_FAILED);
452
453         PORTAL_ALLOC(ev, count * sizeof(ptl_event_t));
454         if (!ev)
455                 return PTL_NOSPACE;
456
457         for (i = 0; i < count; i++)
458                 ev[i].sequence = 0;
459
460         if (nal->validate != NULL) {
461                 rc = nal->validate(nal, ev, count * sizeof(ptl_event_t));
462                 if (rc != PTL_OK)
463                         goto fail;
464         }
465
466         args.ni_in = interface;
467         args.count_in = count;
468         args.base_in = ev;
469         args.len_in = count * sizeof(*ev);
470         args.callback_in = callback;
471
472         rc = do_forward(interface, PTL_EQALLOC, &args, sizeof(args), &ret,
473                         sizeof(ret));
474         if (rc != PTL_OK)
475                 goto fail;
476         if (ret.rc)
477                 GOTO(fail, rc = ret.rc);
478
479         PORTAL_ALLOC(eq, sizeof(*eq));
480         if (!eq) {
481                 rc = PTL_NOSPACE;
482                 goto fail;
483         }
484
485         eq->sequence = 1;
486         eq->size = count;
487         eq->base = ev;
488
489         /* EQ handles are a little wierd.  PtlEQGet() just looks at the
490          * queued events in shared memory.  It doesn't want to do_forward()
491          * at all, so the cookie in the EQ handle we pass out of here is
492          * simply a pointer to the event queue we just set up.  We stash
493          * the handle returned by do_forward(), so we can pass it back via
494          * do_forward() when we need to. */
495
496         eq->cb_eq_handle.nal_idx = interface.nal_idx;
497         eq->cb_eq_handle.cookie = ret.handle_out.cookie;
498
499         handle_out->nal_idx = interface.nal_idx;
500         handle_out->cookie = (__u64)((unsigned long)eq);
501         return PTL_OK;
502
503 fail:
504         PORTAL_FREE(ev, count * sizeof(ptl_event_t));
505         return rc;
506 }
507
508 int PtlEQFree(ptl_handle_eq_t eventq)
509 {
510         PtlEQFree_in args;
511         PtlEQFree_out ret;
512         ptl_eq_t *eq;
513         int rc;
514
515         eq = ptl_handle2usereq (&eventq);
516         args.eventq_in = eq->cb_eq_handle;
517
518         rc = do_forward(eq->cb_eq_handle, PTL_EQFREE, &args,
519                         sizeof(args), &ret, sizeof(ret));
520
521         /* XXX we're betting rc == PTL_OK here */
522         PORTAL_FREE(eq->base, eq->size * sizeof(ptl_event_t));
523         PORTAL_FREE(eq, sizeof(*eq));
524
525         return rc;
526 }
527
528 int PtlACEntry(ptl_handle_ni_t ni_in, ptl_ac_index_t index_in,
529                ptl_process_id_t match_id_in, ptl_pt_index_t portal_in)
530 {
531         PtlACEntry_in args;
532         PtlACEntry_out ret;
533         int rc;
534
535         /*
536          * Copy arguments into the argument block to
537          * hand to the forwarding object
538          */
539         args.ni_in = ni_in;
540         args.index_in = index_in;
541         args.match_id_in = match_id_in;
542         args.portal_in = portal_in;
543
544         rc = do_forward(ni_in, PTL_ACENTRY, &args, sizeof(args), &ret,
545                         sizeof(ret));
546
547         return (rc != PTL_OK) ? rc : ret.rc;
548 }
549
550 int PtlPut(ptl_handle_md_t md_in, ptl_ack_req_t ack_req_in,
551            ptl_process_id_t target_in, ptl_pt_index_t portal_in,
552            ptl_ac_index_t cookie_in, ptl_match_bits_t match_bits_in,
553            ptl_size_t offset_in, ptl_hdr_data_t hdr_data_in)
554 {
555         PtlPut_in args;
556         PtlPut_out ret;
557         int rc;
558
559         /*
560          * Copy arguments into the argument block to
561          * hand to the forwarding object
562          */
563         args.md_in = md_in;
564         args.ack_req_in = ack_req_in;
565         args.target_in = target_in;
566         args.portal_in = portal_in;
567         args.cookie_in = cookie_in;
568         args.match_bits_in = match_bits_in;
569         args.offset_in = offset_in;
570         args.hdr_data_in = hdr_data_in;
571
572         rc = do_forward(md_in, PTL_PUT, &args, sizeof(args), &ret, sizeof(ret));
573
574         return (rc != PTL_OK) ? rc : ret.rc;
575 }
576
577 int PtlGet(ptl_handle_md_t md_in, ptl_process_id_t target_in,
578            ptl_pt_index_t portal_in, ptl_ac_index_t cookie_in,
579            ptl_match_bits_t match_bits_in, ptl_size_t offset_in)
580 {
581         PtlGet_in args;
582         PtlGet_out ret;
583         int rc;
584
585         /*
586          * Copy arguments into the argument block to
587          * hand to the forwarding object
588          */
589         args.md_in = md_in;
590         args.target_in = target_in;
591         args.portal_in = portal_in;
592         args.cookie_in = cookie_in;
593         args.match_bits_in = match_bits_in;
594         args.offset_in = offset_in;
595
596         rc = do_forward(md_in, PTL_GET, &args, sizeof(args), &ret, sizeof(ret));
597
598         return (rc != PTL_OK) ? rc : ret.rc;
599 }