Whamcloud - gitweb
smash the HEAD with the contents of b_cmd. HEAD_PRE_CMD_SMASH and
[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                 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
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_HANDLE_INVALID) ? PTL_ME_INVALID : 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_HANDLE_INVALID) ? PTL_ME_INVALID : 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_HANDLE_INVALID) ? PTL_ME_INVALID : 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                 CERROR("PtlMDAttach/Bind/Update: Not initialized\n");
266                 return PTL_NO_INIT;
267         }
268
269         nal = ptl_hndl2nal(&current_in);
270         if (!nal)
271                 return PTL_HANDLE_INVALID;
272
273         if (nal->validate != NULL)                /* nal->validate not a NOOP */
274         {
275                 if ((md_in.options & PTL_MD_IOVEC) == 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 (PtlHandleIsEqual (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_HANDLE_INVALID) ? PTL_ME_INVALID : 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_unlink_t unlink_in, 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         args.unlink_in = unlink_in;
351
352         rc = do_forward(ni_in, PTL_MDBIND, 
353                         &args, sizeof(args), &ret, sizeof(ret));
354
355         if (rc != PTL_OK)
356                 return rc;
357
358         if (handle_out) {
359                 handle_out->nal_idx = ni_in.nal_idx;
360                 handle_out->cookie = ret.handle_out.cookie;
361         }
362         return ret.rc;
363 }
364
365 int PtlMDUpdate(ptl_handle_md_t md_in, ptl_md_t *old_inout,
366                 ptl_md_t *new_inout, ptl_handle_eq_t testq_in)
367 {
368         PtlMDUpdate_internal_in args;
369         PtlMDUpdate_internal_out ret;
370         int rc;
371
372         args.md_in = md_in;
373
374         if (old_inout) {
375                 args.old_inout = *old_inout;
376                 args.old_inout_valid = 1;
377         } else
378                 args.old_inout_valid = 0;
379
380         if (new_inout) {
381                 rc = validate_md (md_in, *new_inout);
382                 if (rc != PTL_OK)
383                         return (rc == PTL_HANDLE_INVALID) ? PTL_MD_INVALID : rc;
384                 args.new_inout = *new_inout;
385                 args.new_inout_valid = 1;
386         } else
387                 args.new_inout_valid = 0;
388
389         if (PtlHandleIsEqual (testq_in, PTL_EQ_NONE)) {
390                 args.testq_in = PTL_EQ_NONE;
391                 args.sequence_in = -1;
392         } else {
393                 ptl_eq_t *eq = ptl_handle2usereq (&testq_in);
394                 
395                 args.testq_in = eq->cb_eq_handle;
396                 args.sequence_in = eq->sequence;
397         }
398
399         rc = do_forward(md_in, PTL_MDUPDATE, &args, sizeof(args), &ret,
400                         sizeof(ret));
401         if (rc != PTL_OK)
402                 return (rc == PTL_HANDLE_INVALID) ? PTL_MD_INVALID : rc;
403
404         if (old_inout)
405                 *old_inout = ret.old_inout;
406
407         return ret.rc;
408 }
409
410 int PtlMDUnlink(ptl_handle_md_t md_in)
411 {
412         PtlMDUnlink_in args;
413         PtlMDUnlink_out ret;
414         int rc;
415
416         args.md_in = md_in;
417         rc = do_forward(md_in, PTL_MDUNLINK, &args, sizeof(args), &ret,
418                         sizeof(ret));
419         if (rc != PTL_OK)
420                 return (rc == PTL_HANDLE_INVALID) ? PTL_MD_INVALID : rc;
421
422         return ret.rc;
423 }
424
425 int PtlEQAlloc(ptl_handle_ni_t interface, ptl_size_t count,
426                int (*callback) (ptl_event_t * event),
427                ptl_handle_eq_t * handle_out)
428 {
429         ptl_eq_t *eq = NULL;
430         ptl_event_t *ev = NULL;
431         PtlEQAlloc_in args;
432         PtlEQAlloc_out ret;
433         int rc, i;
434         nal_t *nal;
435
436         if (!ptl_init)
437                 return PTL_NO_INIT;
438         
439         nal = ptl_hndl2nal (&interface);
440         if (nal == NULL)
441                 return PTL_HANDLE_INVALID;
442
443         if (count != LOWEST_BIT_SET(count)) {   /* not a power of 2 already */
444                 do {                    /* knock off all but the top bit... */
445                         count &= ~LOWEST_BIT_SET (count);
446                 } while (count != LOWEST_BIT_SET(count));
447
448                 count <<= 1;                             /* ...and round up */
449         }
450
451         if (count == 0)        /* catch bad parameter / overflow on roundup */
452                 return (PTL_VAL_FAILED);
453
454         PORTAL_ALLOC(ev, count * sizeof(ptl_event_t));
455         if (!ev)
456                 return PTL_NO_SPACE;
457
458         for (i = 0; i < count; i++)
459                 ev[i].sequence = 0;
460
461         if (nal->validate != NULL) {
462                 rc = nal->validate(nal, ev, count * sizeof(ptl_event_t));
463                 if (rc != PTL_OK)
464                         goto fail;
465         }
466
467         args.ni_in = interface;
468         args.count_in = count;
469         args.base_in = ev;
470         args.len_in = count * sizeof(*ev);
471         args.callback_in = callback;
472
473         rc = do_forward(interface, PTL_EQALLOC, &args, sizeof(args), &ret,
474                         sizeof(ret));
475         if (rc != PTL_OK)
476                 goto fail;
477         if (ret.rc)
478                 GOTO(fail, rc = ret.rc);
479
480         PORTAL_ALLOC(eq, sizeof(*eq));
481         if (!eq) {
482                 rc = PTL_NO_SPACE;
483                 goto fail;
484         }
485
486         eq->sequence = 1;
487         eq->size = count;
488         eq->base = ev;
489
490         /* EQ handles are a little wierd.  PtlEQGet() just looks at the
491          * queued events in shared memory.  It doesn't want to do_forward()
492          * at all, so the cookie in the EQ handle we pass out of here is
493          * simply a pointer to the event queue we just set up.  We stash
494          * the handle returned by do_forward(), so we can pass it back via
495          * do_forward() when we need to. */
496
497         eq->cb_eq_handle.nal_idx = interface.nal_idx;
498         eq->cb_eq_handle.cookie = ret.handle_out.cookie;
499
500         handle_out->nal_idx = interface.nal_idx;
501         handle_out->cookie = (__u64)((unsigned long)eq);
502         return PTL_OK;
503
504 fail:
505         PORTAL_FREE(ev, count * sizeof(ptl_event_t));
506         return rc;
507 }
508
509 int PtlEQFree(ptl_handle_eq_t eventq)
510 {
511         PtlEQFree_in args;
512         PtlEQFree_out ret;
513         ptl_eq_t *eq;
514         int rc;
515
516         eq = ptl_handle2usereq (&eventq);
517         args.eventq_in = eq->cb_eq_handle;
518
519         rc = do_forward(eq->cb_eq_handle, PTL_EQFREE, &args,
520                         sizeof(args), &ret, sizeof(ret));
521
522         /* XXX we're betting rc == PTL_OK here */
523         PORTAL_FREE(eq->base, eq->size * sizeof(ptl_event_t));
524         PORTAL_FREE(eq, sizeof(*eq));
525
526         return rc;
527 }
528
529 int PtlACEntry(ptl_handle_ni_t ni_in, ptl_ac_index_t index_in,
530                ptl_process_id_t match_id_in, ptl_pt_index_t portal_in)
531 {
532         PtlACEntry_in args;
533         PtlACEntry_out ret;
534         int rc;
535
536         /*
537          * Copy arguments into the argument block to
538          * hand to the forwarding object
539          */
540         args.ni_in = ni_in;
541         args.index_in = index_in;
542         args.match_id_in = match_id_in;
543         args.portal_in = portal_in;
544
545         rc = do_forward(ni_in, PTL_ACENTRY, &args, sizeof(args), &ret,
546                         sizeof(ret));
547
548         return (rc != PTL_OK) ? rc : ret.rc;
549 }
550
551 int PtlPut(ptl_handle_md_t md_in, ptl_ack_req_t ack_req_in,
552            ptl_process_id_t target_in, ptl_pt_index_t portal_in,
553            ptl_ac_index_t cookie_in, ptl_match_bits_t match_bits_in,
554            ptl_size_t offset_in, ptl_hdr_data_t hdr_data_in)
555 {
556         PtlPut_in args;
557         PtlPut_out ret;
558         int rc;
559
560         /*
561          * Copy arguments into the argument block to
562          * hand to the forwarding object
563          */
564         args.md_in = md_in;
565         args.ack_req_in = ack_req_in;
566         args.target_in = target_in;
567         args.portal_in = portal_in;
568         args.cookie_in = cookie_in;
569         args.match_bits_in = match_bits_in;
570         args.offset_in = offset_in;
571         args.hdr_data_in = hdr_data_in;
572
573         rc = do_forward(md_in, PTL_PUT, &args, sizeof(args), &ret, sizeof(ret));
574
575         return (rc != PTL_OK) ? rc : ret.rc;
576 }
577
578 int PtlGet(ptl_handle_md_t md_in, ptl_process_id_t target_in,
579            ptl_pt_index_t portal_in, ptl_ac_index_t cookie_in,
580            ptl_match_bits_t match_bits_in, ptl_size_t offset_in)
581 {
582         PtlGet_in args;
583         PtlGet_out ret;
584         int rc;
585
586         /*
587          * Copy arguments into the argument block to
588          * hand to the forwarding object
589          */
590         args.md_in = md_in;
591         args.target_in = target_in;
592         args.portal_in = portal_in;
593         args.cookie_in = cookie_in;
594         args.match_bits_in = match_bits_in;
595         args.offset_in = offset_in;
596
597         rc = do_forward(md_in, PTL_GET, &args, sizeof(args), &ret, sizeof(ret));
598
599         return (rc != PTL_OK) ? rc : ret.rc;
600 }