/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * api/api-wrap.c * User-level wrappers that dispatch across the protection boundaries * * Copyright (c) 2001-2003 Cluster File Systems, Inc. * Copyright (c) 2001-2002 Sandia National Laboratories * * This file is part of Lustre, http://www.sf.net/projects/lustre/ * * Lustre is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. * * Lustre is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Lustre; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ # define DEBUG_SUBSYSTEM S_PORTALS #include static int do_forward(ptl_handle_any_t any_h, int cmd, void *argbuf, int argsize, void *retbuf, int retsize) { nal_t *nal; if (!ptl_init) { CERROR("Not initialized\n"); return PTL_NO_INIT; } nal = ptl_hndl2nal(&any_h); if (!nal) return PTL_HANDLE_INVALID; nal->forward(nal, cmd, argbuf, argsize, retbuf, retsize); return PTL_OK; } int PtlGetId(ptl_handle_ni_t ni_handle, ptl_process_id_t *id) { PtlGetId_in args; PtlGetId_out ret; int rc; args.handle_in = ni_handle; rc = do_forward(ni_handle, PTL_GETID, &args, sizeof(args), &ret, sizeof(ret)); if (rc != PTL_OK) return rc; if (id) *id = ret.id_out; return ret.rc; } int PtlFailNid (ptl_handle_ni_t interface, ptl_nid_t nid, unsigned int threshold) { PtlFailNid_in args; PtlFailNid_out ret; int rc; args.interface = interface; args.nid = nid; args.threshold = threshold; rc = do_forward (interface, PTL_FAILNID, &args, sizeof(args), &ret, sizeof (ret)); return ((rc != PTL_OK) ? rc : ret.rc); } int PtlNIStatus(ptl_handle_ni_t interface_in, ptl_sr_index_t register_in, ptl_sr_value_t * status_out) { PtlNIStatus_in args; PtlNIStatus_out ret; int rc; args.interface_in = interface_in; args.register_in = register_in; rc = do_forward(interface_in, PTL_NISTATUS, &args, sizeof(args), &ret, sizeof(ret)); if (rc != PTL_OK) return rc; if (status_out) *status_out = ret.status_out; return ret.rc; } int PtlNIDist(ptl_handle_ni_t interface_in, ptl_process_id_t process_in, unsigned long *distance_out) { PtlNIDist_in args; PtlNIDist_out ret; int rc; args.interface_in = interface_in; args.process_in = process_in; rc = do_forward(interface_in, PTL_NIDIST, &args, sizeof(args), &ret, sizeof(ret)); if (rc != PTL_OK) return rc; if (distance_out) *distance_out = ret.distance_out; return ret.rc; } int PtlMEAttach(ptl_handle_ni_t interface_in, ptl_pt_index_t index_in, ptl_process_id_t match_id_in, ptl_match_bits_t match_bits_in, ptl_match_bits_t ignore_bits_in, ptl_unlink_t unlink_in, ptl_ins_pos_t pos_in, ptl_handle_me_t * handle_out) { PtlMEAttach_in args; PtlMEAttach_out ret; int rc; args.interface_in = interface_in; args.index_in = index_in; args.match_id_in = match_id_in; args.match_bits_in = match_bits_in; args.ignore_bits_in = ignore_bits_in; args.unlink_in = unlink_in; args.position_in = pos_in; rc = do_forward(interface_in, PTL_MEATTACH, &args, sizeof(args), &ret, sizeof(ret)); if (rc != PTL_OK) return rc; if (handle_out) { handle_out->nal_idx = interface_in.nal_idx; handle_out->cookie = ret.handle_out.cookie; } return ret.rc; } int PtlMEInsert(ptl_handle_me_t current_in, ptl_process_id_t match_id_in, ptl_match_bits_t match_bits_in, ptl_match_bits_t ignore_bits_in, ptl_unlink_t unlink_in, ptl_ins_pos_t position_in, ptl_handle_me_t * handle_out) { PtlMEInsert_in args; PtlMEInsert_out ret; int rc; args.current_in = current_in; args.match_id_in = match_id_in; args.match_bits_in = match_bits_in; args.ignore_bits_in = ignore_bits_in; args.unlink_in = unlink_in; args.position_in = position_in; rc = do_forward(current_in, PTL_MEINSERT, &args, sizeof(args), &ret, sizeof(ret)); if (rc != PTL_OK) return (rc == PTL_HANDLE_INVALID) ? PTL_ME_INVALID : rc; if (handle_out) { handle_out->nal_idx = current_in.nal_idx; handle_out->cookie = ret.handle_out.cookie; } return ret.rc; } int PtlMEUnlink(ptl_handle_me_t current_in) { PtlMEUnlink_in args; PtlMEUnlink_out ret; int rc; args.current_in = current_in; args.unlink_in = PTL_RETAIN; rc = do_forward(current_in, PTL_MEUNLINK, &args, sizeof(args), &ret, sizeof(ret)); if (rc != PTL_OK) return (rc == PTL_HANDLE_INVALID) ? PTL_ME_INVALID : rc; return ret.rc; } int PtlTblDump(ptl_handle_ni_t ni, int index_in) { PtlTblDump_in args; PtlTblDump_out ret; int rc; args.index_in = index_in; rc = do_forward(ni, PTL_TBLDUMP, &args, sizeof(args), &ret, sizeof(ret)); if (rc != PTL_OK) return rc; return ret.rc; } int PtlMEDump(ptl_handle_me_t current_in) { PtlMEDump_in args; PtlMEDump_out ret; int rc; args.current_in = current_in; rc = do_forward(current_in, PTL_MEDUMP, &args, sizeof(args), &ret, sizeof(ret)); if (rc != PTL_OK) return (rc == PTL_HANDLE_INVALID) ? PTL_ME_INVALID : rc; return ret.rc; } static ptl_handle_eq_t md2eq (ptl_md_t *md) { if (PtlHandleIsEqual (md->eventq, PTL_EQ_NONE)) return (PTL_EQ_NONE); return (ptl_handle2usereq (&md->eventq)->cb_eq_handle); } int PtlMDAttach(ptl_handle_me_t me_in, ptl_md_t md_in, ptl_unlink_t unlink_in, ptl_handle_md_t * handle_out) { PtlMDAttach_in args; PtlMDAttach_out ret; int rc; args.eq_in = md2eq(&md_in); args.me_in = me_in; args.md_in = md_in; args.unlink_in = unlink_in; rc = do_forward(me_in, PTL_MDATTACH, &args, sizeof(args), &ret, sizeof(ret)); if (rc != PTL_OK) return (rc == PTL_HANDLE_INVALID) ? PTL_ME_INVALID : rc; if (handle_out) { handle_out->nal_idx = me_in.nal_idx; handle_out->cookie = ret.handle_out.cookie; } return ret.rc; } int PtlMDBind(ptl_handle_ni_t ni_in, ptl_md_t md_in, ptl_unlink_t unlink_in, ptl_handle_md_t * handle_out) { PtlMDBind_in args; PtlMDBind_out ret; int rc; args.eq_in = md2eq(&md_in); args.ni_in = ni_in; args.md_in = md_in; args.unlink_in = unlink_in; rc = do_forward(ni_in, PTL_MDBIND, &args, sizeof(args), &ret, sizeof(ret)); if (rc != PTL_OK) return rc; if (handle_out) { handle_out->nal_idx = ni_in.nal_idx; handle_out->cookie = ret.handle_out.cookie; } return ret.rc; } int PtlMDUpdate(ptl_handle_md_t md_in, ptl_md_t *old_inout, ptl_md_t *new_inout, ptl_handle_eq_t testq_in) { PtlMDUpdate_internal_in args; PtlMDUpdate_internal_out ret; int rc; args.md_in = md_in; if (old_inout) { args.old_inout = *old_inout; args.old_inout_valid = 1; } else args.old_inout_valid = 0; if (new_inout) { args.new_inout = *new_inout; args.new_inout_valid = 1; } else args.new_inout_valid = 0; if (PtlHandleIsEqual (testq_in, PTL_EQ_NONE)) { args.testq_in = PTL_EQ_NONE; args.sequence_in = -1; } else { ptl_eq_t *eq = ptl_handle2usereq (&testq_in); args.testq_in = eq->cb_eq_handle; args.sequence_in = eq->sequence; } rc = do_forward(md_in, PTL_MDUPDATE, &args, sizeof(args), &ret, sizeof(ret)); if (rc != PTL_OK) return (rc == PTL_HANDLE_INVALID) ? PTL_MD_INVALID : rc; if (old_inout) *old_inout = ret.old_inout; return ret.rc; } int PtlMDUnlink(ptl_handle_md_t md_in) { PtlMDUnlink_in args; PtlMDUnlink_out ret; int rc; args.md_in = md_in; rc = do_forward(md_in, PTL_MDUNLINK, &args, sizeof(args), &ret, sizeof(ret)); if (rc != PTL_OK) return (rc == PTL_HANDLE_INVALID) ? PTL_MD_INVALID : rc; return ret.rc; } int PtlEQAlloc(ptl_handle_ni_t interface, ptl_size_t count, ptl_eq_handler_t callback, ptl_handle_eq_t * handle_out) { ptl_eq_t *eq = NULL; ptl_event_t *ev = NULL; PtlEQAlloc_in args; PtlEQAlloc_out ret; int rc, i; nal_t *nal; if (!ptl_init) return PTL_NO_INIT; nal = ptl_hndl2nal (&interface); if (nal == NULL) return PTL_HANDLE_INVALID; if (count != LOWEST_BIT_SET(count)) { /* not a power of 2 already */ do { /* knock off all but the top bit... */ count &= ~LOWEST_BIT_SET (count); } while (count != LOWEST_BIT_SET(count)); count <<= 1; /* ...and round up */ } if (count == 0) /* catch bad parameter / overflow on roundup */ return (PTL_VAL_FAILED); PORTAL_ALLOC(ev, count * sizeof(ptl_event_t)); if (!ev) return PTL_NO_SPACE; for (i = 0; i < count; i++) ev[i].sequence = 0; args.ni_in = interface; args.count_in = count; args.base_in = ev; args.len_in = count * sizeof(*ev); args.callback_in = callback; rc = do_forward(interface, PTL_EQALLOC, &args, sizeof(args), &ret, sizeof(ret)); if (rc != PTL_OK) goto fail; if (ret.rc) GOTO(fail, rc = ret.rc); PORTAL_ALLOC(eq, sizeof(*eq)); if (!eq) { rc = PTL_NO_SPACE; goto fail; } eq->sequence = 1; eq->size = count; eq->base = ev; /* EQ handles are a little wierd. PtlEQGet() just looks at the * queued events in shared memory. It doesn't want to do_forward() * at all, so the cookie in the EQ handle we pass out of here is * simply a pointer to the event queue we just set up. We stash * the handle returned by do_forward(), so we can pass it back via * do_forward() when we need to. */ eq->cb_eq_handle.nal_idx = interface.nal_idx; eq->cb_eq_handle.cookie = ret.handle_out.cookie; handle_out->nal_idx = interface.nal_idx; handle_out->cookie = (__u64)((unsigned long)eq); return PTL_OK; fail: PORTAL_FREE(ev, count * sizeof(ptl_event_t)); return rc; } int PtlEQFree(ptl_handle_eq_t eventq) { PtlEQFree_in args; PtlEQFree_out ret; ptl_eq_t *eq; int rc; eq = ptl_handle2usereq (&eventq); args.eventq_in = eq->cb_eq_handle; rc = do_forward(eq->cb_eq_handle, PTL_EQFREE, &args, sizeof(args), &ret, sizeof(ret)); /* XXX we're betting rc == PTL_OK here */ PORTAL_FREE(eq->base, eq->size * sizeof(ptl_event_t)); PORTAL_FREE(eq, sizeof(*eq)); return rc; } int PtlACEntry(ptl_handle_ni_t ni_in, ptl_ac_index_t index_in, ptl_process_id_t match_id_in, ptl_pt_index_t portal_in) { PtlACEntry_in args; PtlACEntry_out ret; int rc; /* * Copy arguments into the argument block to * hand to the forwarding object */ args.ni_in = ni_in; args.index_in = index_in; args.match_id_in = match_id_in; args.portal_in = portal_in; rc = do_forward(ni_in, PTL_ACENTRY, &args, sizeof(args), &ret, sizeof(ret)); return (rc != PTL_OK) ? rc : ret.rc; } int PtlPut(ptl_handle_md_t md_in, ptl_ack_req_t ack_req_in, ptl_process_id_t target_in, ptl_pt_index_t portal_in, ptl_ac_index_t cookie_in, ptl_match_bits_t match_bits_in, ptl_size_t offset_in, ptl_hdr_data_t hdr_data_in) { PtlPut_in args; PtlPut_out ret; int rc; /* * Copy arguments into the argument block to * hand to the forwarding object */ args.md_in = md_in; args.ack_req_in = ack_req_in; args.target_in = target_in; args.portal_in = portal_in; args.cookie_in = cookie_in; args.match_bits_in = match_bits_in; args.offset_in = offset_in; args.hdr_data_in = hdr_data_in; rc = do_forward(md_in, PTL_PUT, &args, sizeof(args), &ret, sizeof(ret)); return (rc != PTL_OK) ? rc : ret.rc; } int PtlGet(ptl_handle_md_t md_in, ptl_process_id_t target_in, ptl_pt_index_t portal_in, ptl_ac_index_t cookie_in, ptl_match_bits_t match_bits_in, ptl_size_t offset_in) { PtlGet_in args; PtlGet_out ret; int rc; /* * Copy arguments into the argument block to * hand to the forwarding object */ args.md_in = md_in; args.target_in = target_in; args.portal_in = portal_in; args.cookie_in = cookie_in; args.match_bits_in = match_bits_in; args.offset_in = offset_in; rc = do_forward(md_in, PTL_GET, &args, sizeof(args), &ret, sizeof(ret)); return (rc != PTL_OK) ? rc : ret.rc; }