10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57387SRobert.Gordon@Sun.COM * Common Development and Distribution License (the "License"). 67387SRobert.Gordon@Sun.COM * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 2211551SSiddheshwar.Mahesh@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 260Sstevel@tonic-gate /* All Rights Reserved */ 270Sstevel@tonic-gate /* 280Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 290Sstevel@tonic-gate * 4.3 BSD under license from the Regents of the University of 300Sstevel@tonic-gate * California. 310Sstevel@tonic-gate */ 320Sstevel@tonic-gate 330Sstevel@tonic-gate #include <sys/param.h> 340Sstevel@tonic-gate #include <sys/types.h> 350Sstevel@tonic-gate #include <sys/user.h> 360Sstevel@tonic-gate #include <sys/systm.h> 370Sstevel@tonic-gate #include <sys/sysmacros.h> 380Sstevel@tonic-gate #include <sys/errno.h> 390Sstevel@tonic-gate #include <sys/kmem.h> 400Sstevel@tonic-gate #include <sys/debug.h> 410Sstevel@tonic-gate #include <sys/systm.h> 420Sstevel@tonic-gate #include <sys/kstat.h> 430Sstevel@tonic-gate #include <sys/t_lock.h> 440Sstevel@tonic-gate #include <sys/ddi.h> 450Sstevel@tonic-gate #include <sys/cmn_err.h> 460Sstevel@tonic-gate #include <sys/time.h> 470Sstevel@tonic-gate #include <sys/isa_defs.h> 480Sstevel@tonic-gate #include <sys/zone.h> 497387SRobert.Gordon@Sun.COM #include <sys/sdt.h> 500Sstevel@tonic-gate 510Sstevel@tonic-gate #include <rpc/types.h> 520Sstevel@tonic-gate #include <rpc/xdr.h> 530Sstevel@tonic-gate #include <rpc/auth.h> 540Sstevel@tonic-gate #include <rpc/clnt.h> 550Sstevel@tonic-gate #include <rpc/rpc_msg.h> 560Sstevel@tonic-gate #include <rpc/rpc_rdma.h> 577387SRobert.Gordon@Sun.COM #include <nfs/nfs.h> 587387SRobert.Gordon@Sun.COM #include <nfs/nfs4_kprot.h> 590Sstevel@tonic-gate 607387SRobert.Gordon@Sun.COM static uint32_t rdma_bufs_rqst = RDMA_BUFS_RQST; 617387SRobert.Gordon@Sun.COM 627387SRobert.Gordon@Sun.COM static int clnt_compose_rpcmsg(CLIENT *, rpcproc_t, rdma_buf_t *, 637387SRobert.Gordon@Sun.COM XDR *, xdrproc_t, caddr_t); 647387SRobert.Gordon@Sun.COM static int clnt_compose_rdma_header(CONN *, CLIENT *, rdma_buf_t *, 657387SRobert.Gordon@Sun.COM XDR **, uint_t *); 667387SRobert.Gordon@Sun.COM static int clnt_setup_rlist(CONN *, XDR *, XDR *); 679348SSiddheshwar.Mahesh@Sun.COM static int clnt_setup_wlist(CONN *, XDR *, XDR *, rdma_buf_t *); 687387SRobert.Gordon@Sun.COM static int clnt_setup_long_reply(CONN *, struct clist **, uint_t); 697387SRobert.Gordon@Sun.COM static void clnt_check_credit(CONN *); 707387SRobert.Gordon@Sun.COM static void clnt_return_credit(CONN *); 717387SRobert.Gordon@Sun.COM static void clnt_decode_long_reply(CONN *, struct clist *, 727387SRobert.Gordon@Sun.COM struct clist *, XDR *, XDR **, struct clist *, 737387SRobert.Gordon@Sun.COM struct clist *, uint_t, uint_t); 747387SRobert.Gordon@Sun.COM 757387SRobert.Gordon@Sun.COM static void clnt_update_credit(CONN *, uint32_t); 760Sstevel@tonic-gate 770Sstevel@tonic-gate static enum clnt_stat clnt_rdma_kcallit(CLIENT *, rpcproc_t, xdrproc_t, 780Sstevel@tonic-gate caddr_t, xdrproc_t, caddr_t, struct timeval); 790Sstevel@tonic-gate static void clnt_rdma_kabort(CLIENT *); 800Sstevel@tonic-gate static void clnt_rdma_kerror(CLIENT *, struct rpc_err *); 810Sstevel@tonic-gate static bool_t clnt_rdma_kfreeres(CLIENT *, xdrproc_t, caddr_t); 820Sstevel@tonic-gate static void clnt_rdma_kdestroy(CLIENT *); 830Sstevel@tonic-gate static bool_t clnt_rdma_kcontrol(CLIENT *, int, char *); 840Sstevel@tonic-gate static int clnt_rdma_ksettimers(CLIENT *, struct rpc_timers *, 850Sstevel@tonic-gate struct rpc_timers *, int, void(*)(int, int, caddr_t), caddr_t, uint32_t); 860Sstevel@tonic-gate 870Sstevel@tonic-gate /* 880Sstevel@tonic-gate * Operations vector for RDMA based RPC 890Sstevel@tonic-gate */ 900Sstevel@tonic-gate static struct clnt_ops rdma_clnt_ops = { 910Sstevel@tonic-gate clnt_rdma_kcallit, /* do rpc call */ 920Sstevel@tonic-gate clnt_rdma_kabort, /* abort call */ 930Sstevel@tonic-gate clnt_rdma_kerror, /* return error status */ 940Sstevel@tonic-gate clnt_rdma_kfreeres, /* free results */ 950Sstevel@tonic-gate clnt_rdma_kdestroy, /* destroy rpc handle */ 960Sstevel@tonic-gate clnt_rdma_kcontrol, /* the ioctl() of rpc */ 970Sstevel@tonic-gate clnt_rdma_ksettimers, /* set retry timers */ 980Sstevel@tonic-gate }; 990Sstevel@tonic-gate 1000Sstevel@tonic-gate /* 1010Sstevel@tonic-gate * The size of the preserialized RPC header information. 1020Sstevel@tonic-gate */ 1030Sstevel@tonic-gate #define CKU_HDRSIZE 20 1047387SRobert.Gordon@Sun.COM #define CLNT_RDMA_SUCCESS 0 1057387SRobert.Gordon@Sun.COM #define CLNT_RDMA_FAIL (-1) 1067387SRobert.Gordon@Sun.COM 1077387SRobert.Gordon@Sun.COM #define AUTH_REFRESH_COUNT 2 1087387SRobert.Gordon@Sun.COM 1097387SRobert.Gordon@Sun.COM #define IS_RPCSEC_GSS(authh) \ 1107387SRobert.Gordon@Sun.COM (authh->cl_auth->ah_cred.oa_flavor == RPCSEC_GSS) 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate /* 1130Sstevel@tonic-gate * Per RPC RDMA endpoint details 1140Sstevel@tonic-gate */ 1150Sstevel@tonic-gate typedef struct cku_private { 1160Sstevel@tonic-gate CLIENT cku_client; /* client handle */ 1170Sstevel@tonic-gate rdma_mod_t *cku_rd_mod; /* underlying RDMA mod */ 1180Sstevel@tonic-gate void *cku_rd_handle; /* underlying RDMA device */ 1199733SFaramarz.Jalalian@Sun.COM struct netbuf cku_srcaddr; /* source address for retries */ 1200Sstevel@tonic-gate struct netbuf cku_addr; /* remote netbuf address */ 1210Sstevel@tonic-gate int cku_addrfmly; /* for finding addr_type */ 1220Sstevel@tonic-gate struct rpc_err cku_err; /* error status */ 1230Sstevel@tonic-gate struct cred *cku_cred; /* credentials */ 1240Sstevel@tonic-gate XDR cku_outxdr; /* xdr stream for output */ 1250Sstevel@tonic-gate uint32_t cku_outsz; 1260Sstevel@tonic-gate XDR cku_inxdr; /* xdr stream for input */ 1270Sstevel@tonic-gate char cku_rpchdr[CKU_HDRSIZE+4]; /* rpc header */ 1280Sstevel@tonic-gate uint32_t cku_xid; /* current XID */ 1290Sstevel@tonic-gate } cku_private_t; 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate #define CLNT_RDMA_DELAY 10 /* secs to delay after a connection failure */ 1320Sstevel@tonic-gate static int clnt_rdma_min_delay = CLNT_RDMA_DELAY; 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate struct { 1350Sstevel@tonic-gate kstat_named_t rccalls; 1360Sstevel@tonic-gate kstat_named_t rcbadcalls; 1370Sstevel@tonic-gate kstat_named_t rcbadxids; 1380Sstevel@tonic-gate kstat_named_t rctimeouts; 1390Sstevel@tonic-gate kstat_named_t rcnewcreds; 1400Sstevel@tonic-gate kstat_named_t rcbadverfs; 1410Sstevel@tonic-gate kstat_named_t rctimers; 1420Sstevel@tonic-gate kstat_named_t rccantconn; 1430Sstevel@tonic-gate kstat_named_t rcnomem; 1440Sstevel@tonic-gate kstat_named_t rcintrs; 1450Sstevel@tonic-gate kstat_named_t rclongrpcs; 1460Sstevel@tonic-gate } rdmarcstat = { 1470Sstevel@tonic-gate { "calls", KSTAT_DATA_UINT64 }, 1480Sstevel@tonic-gate { "badcalls", KSTAT_DATA_UINT64 }, 1490Sstevel@tonic-gate { "badxids", KSTAT_DATA_UINT64 }, 1500Sstevel@tonic-gate { "timeouts", KSTAT_DATA_UINT64 }, 1510Sstevel@tonic-gate { "newcreds", KSTAT_DATA_UINT64 }, 1520Sstevel@tonic-gate { "badverfs", KSTAT_DATA_UINT64 }, 1530Sstevel@tonic-gate { "timers", KSTAT_DATA_UINT64 }, 1540Sstevel@tonic-gate { "cantconn", KSTAT_DATA_UINT64 }, 1550Sstevel@tonic-gate { "nomem", KSTAT_DATA_UINT64 }, 1560Sstevel@tonic-gate { "interrupts", KSTAT_DATA_UINT64 }, 1570Sstevel@tonic-gate { "longrpc", KSTAT_DATA_UINT64 } 1580Sstevel@tonic-gate }; 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate kstat_named_t *rdmarcstat_ptr = (kstat_named_t *)&rdmarcstat; 1610Sstevel@tonic-gate uint_t rdmarcstat_ndata = sizeof (rdmarcstat) / sizeof (kstat_named_t); 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate #ifdef DEBUG 1640Sstevel@tonic-gate int rdma_clnt_debug = 0; 1650Sstevel@tonic-gate #endif 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate #ifdef accurate_stats 1680Sstevel@tonic-gate extern kmutex_t rdmarcstat_lock; /* mutex for rcstat updates */ 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate #define RCSTAT_INCR(x) \ 1710Sstevel@tonic-gate mutex_enter(&rdmarcstat_lock); \ 1720Sstevel@tonic-gate rdmarcstat.x.value.ui64++; \ 1730Sstevel@tonic-gate mutex_exit(&rdmarcstat_lock); 1740Sstevel@tonic-gate #else 1750Sstevel@tonic-gate #define RCSTAT_INCR(x) \ 1760Sstevel@tonic-gate rdmarcstat.x.value.ui64++; 1770Sstevel@tonic-gate #endif 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate #define ptoh(p) (&((p)->cku_client)) 1800Sstevel@tonic-gate #define htop(h) ((cku_private_t *)((h)->cl_private)) 1810Sstevel@tonic-gate 1827387SRobert.Gordon@Sun.COM uint_t 1837387SRobert.Gordon@Sun.COM calc_length(uint_t len) 1847387SRobert.Gordon@Sun.COM { 1857387SRobert.Gordon@Sun.COM len = RNDUP(len); 1867387SRobert.Gordon@Sun.COM 1877387SRobert.Gordon@Sun.COM if (len <= 64 * 1024) { 1887387SRobert.Gordon@Sun.COM if (len > 32 * 1024) { 1897387SRobert.Gordon@Sun.COM len = 64 * 1024; 1907387SRobert.Gordon@Sun.COM } else { 1917387SRobert.Gordon@Sun.COM if (len > 16 * 1024) { 1927387SRobert.Gordon@Sun.COM len = 32 * 1024; 1937387SRobert.Gordon@Sun.COM } else { 1947387SRobert.Gordon@Sun.COM if (len > 8 * 1024) { 1957387SRobert.Gordon@Sun.COM len = 16 * 1024; 1967387SRobert.Gordon@Sun.COM } else { 1977387SRobert.Gordon@Sun.COM len = 8 * 1024; 1987387SRobert.Gordon@Sun.COM } 1997387SRobert.Gordon@Sun.COM } 2007387SRobert.Gordon@Sun.COM } 2017387SRobert.Gordon@Sun.COM } 2027387SRobert.Gordon@Sun.COM return (len); 2037387SRobert.Gordon@Sun.COM } 2040Sstevel@tonic-gate int 2050Sstevel@tonic-gate clnt_rdma_kcreate(char *proto, void *handle, struct netbuf *raddr, int family, 2060Sstevel@tonic-gate rpcprog_t pgm, rpcvers_t vers, struct cred *cred, CLIENT **cl) 2070Sstevel@tonic-gate { 2080Sstevel@tonic-gate CLIENT *h; 2090Sstevel@tonic-gate struct cku_private *p; 2100Sstevel@tonic-gate struct rpc_msg call_msg; 2110Sstevel@tonic-gate rdma_registry_t *rp; 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate ASSERT(INGLOBALZONE(curproc)); 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate if (cl == NULL) 2160Sstevel@tonic-gate return (EINVAL); 2170Sstevel@tonic-gate *cl = NULL; 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate p = kmem_zalloc(sizeof (*p), KM_SLEEP); 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate /* 2220Sstevel@tonic-gate * Find underlying RDMATF plugin 2230Sstevel@tonic-gate */ 2240Sstevel@tonic-gate rw_enter(&rdma_lock, RW_READER); 2250Sstevel@tonic-gate rp = rdma_mod_head; 2260Sstevel@tonic-gate while (rp != NULL) { 2270Sstevel@tonic-gate if (strcmp(rp->r_mod->rdma_api, proto)) 2280Sstevel@tonic-gate rp = rp->r_next; 2290Sstevel@tonic-gate else { 2300Sstevel@tonic-gate p->cku_rd_mod = rp->r_mod; 2310Sstevel@tonic-gate p->cku_rd_handle = handle; 2320Sstevel@tonic-gate break; 2330Sstevel@tonic-gate } 2340Sstevel@tonic-gate } 2350Sstevel@tonic-gate rw_exit(&rdma_lock); 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate if (p->cku_rd_mod == NULL) { 2380Sstevel@tonic-gate /* 2390Sstevel@tonic-gate * Should not happen. 2400Sstevel@tonic-gate * No matching RDMATF plugin. 2410Sstevel@tonic-gate */ 2420Sstevel@tonic-gate kmem_free(p, sizeof (struct cku_private)); 2430Sstevel@tonic-gate return (EINVAL); 2440Sstevel@tonic-gate } 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate h = ptoh(p); 2470Sstevel@tonic-gate h->cl_ops = &rdma_clnt_ops; 2480Sstevel@tonic-gate h->cl_private = (caddr_t)p; 2490Sstevel@tonic-gate h->cl_auth = authkern_create(); 2500Sstevel@tonic-gate 2510Sstevel@tonic-gate /* call message, just used to pre-serialize below */ 2520Sstevel@tonic-gate call_msg.rm_xid = 0; 2530Sstevel@tonic-gate call_msg.rm_direction = CALL; 2540Sstevel@tonic-gate call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; 2550Sstevel@tonic-gate call_msg.rm_call.cb_prog = pgm; 2560Sstevel@tonic-gate call_msg.rm_call.cb_vers = vers; 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate xdrmem_create(&p->cku_outxdr, p->cku_rpchdr, CKU_HDRSIZE, XDR_ENCODE); 2590Sstevel@tonic-gate /* pre-serialize call message header */ 2600Sstevel@tonic-gate if (!xdr_callhdr(&p->cku_outxdr, &call_msg)) { 2610Sstevel@tonic-gate XDR_DESTROY(&p->cku_outxdr); 2620Sstevel@tonic-gate auth_destroy(h->cl_auth); 2630Sstevel@tonic-gate kmem_free(p, sizeof (struct cku_private)); 2640Sstevel@tonic-gate return (EINVAL); 2650Sstevel@tonic-gate } 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate /* 2680Sstevel@tonic-gate * Set up the rpc information 2690Sstevel@tonic-gate */ 2700Sstevel@tonic-gate p->cku_cred = cred; 2719733SFaramarz.Jalalian@Sun.COM p->cku_srcaddr.buf = kmem_zalloc(raddr->maxlen, KM_SLEEP); 2729733SFaramarz.Jalalian@Sun.COM p->cku_srcaddr.maxlen = raddr->maxlen; 2739733SFaramarz.Jalalian@Sun.COM p->cku_srcaddr.len = 0; 2740Sstevel@tonic-gate p->cku_addr.buf = kmem_zalloc(raddr->maxlen, KM_SLEEP); 2750Sstevel@tonic-gate p->cku_addr.maxlen = raddr->maxlen; 2760Sstevel@tonic-gate p->cku_addr.len = raddr->len; 2770Sstevel@tonic-gate bcopy(raddr->buf, p->cku_addr.buf, raddr->len); 2780Sstevel@tonic-gate p->cku_addrfmly = family; 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate *cl = h; 2810Sstevel@tonic-gate return (0); 2820Sstevel@tonic-gate } 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate static void 2850Sstevel@tonic-gate clnt_rdma_kdestroy(CLIENT *h) 2860Sstevel@tonic-gate { 2870Sstevel@tonic-gate struct cku_private *p = htop(h); 2880Sstevel@tonic-gate 2899733SFaramarz.Jalalian@Sun.COM kmem_free(p->cku_srcaddr.buf, p->cku_srcaddr.maxlen); 2900Sstevel@tonic-gate kmem_free(p->cku_addr.buf, p->cku_addr.maxlen); 2910Sstevel@tonic-gate kmem_free(p, sizeof (*p)); 2920Sstevel@tonic-gate } 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate void 2950Sstevel@tonic-gate clnt_rdma_kinit(CLIENT *h, char *proto, void *handle, struct netbuf *raddr, 2960Sstevel@tonic-gate struct cred *cred) 2970Sstevel@tonic-gate { 2980Sstevel@tonic-gate struct cku_private *p = htop(h); 2990Sstevel@tonic-gate rdma_registry_t *rp; 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate ASSERT(INGLOBALZONE(curproc)); 3020Sstevel@tonic-gate /* 3030Sstevel@tonic-gate * Find underlying RDMATF plugin 3040Sstevel@tonic-gate */ 3050Sstevel@tonic-gate p->cku_rd_mod = NULL; 3060Sstevel@tonic-gate rw_enter(&rdma_lock, RW_READER); 3070Sstevel@tonic-gate rp = rdma_mod_head; 3080Sstevel@tonic-gate while (rp != NULL) { 3090Sstevel@tonic-gate if (strcmp(rp->r_mod->rdma_api, proto)) 3100Sstevel@tonic-gate rp = rp->r_next; 3110Sstevel@tonic-gate else { 3120Sstevel@tonic-gate p->cku_rd_mod = rp->r_mod; 3130Sstevel@tonic-gate p->cku_rd_handle = handle; 3140Sstevel@tonic-gate break; 3150Sstevel@tonic-gate } 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate } 3180Sstevel@tonic-gate rw_exit(&rdma_lock); 3190Sstevel@tonic-gate 3200Sstevel@tonic-gate /* 3210Sstevel@tonic-gate * Set up the rpc information 3220Sstevel@tonic-gate */ 3230Sstevel@tonic-gate p->cku_cred = cred; 3240Sstevel@tonic-gate p->cku_xid = 0; 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate if (p->cku_addr.maxlen < raddr->len) { 3270Sstevel@tonic-gate if (p->cku_addr.maxlen != 0 && p->cku_addr.buf != NULL) 3280Sstevel@tonic-gate kmem_free(p->cku_addr.buf, p->cku_addr.maxlen); 3290Sstevel@tonic-gate p->cku_addr.buf = kmem_zalloc(raddr->maxlen, KM_SLEEP); 3300Sstevel@tonic-gate p->cku_addr.maxlen = raddr->maxlen; 3310Sstevel@tonic-gate } 3320Sstevel@tonic-gate 3339733SFaramarz.Jalalian@Sun.COM p->cku_srcaddr.len = 0; 3349733SFaramarz.Jalalian@Sun.COM 3350Sstevel@tonic-gate p->cku_addr.len = raddr->len; 3360Sstevel@tonic-gate bcopy(raddr->buf, p->cku_addr.buf, raddr->len); 3370Sstevel@tonic-gate h->cl_ops = &rdma_clnt_ops; 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate 3407387SRobert.Gordon@Sun.COM static int 3417387SRobert.Gordon@Sun.COM clnt_compose_rpcmsg(CLIENT *h, rpcproc_t procnum, 3427387SRobert.Gordon@Sun.COM rdma_buf_t *rpcmsg, XDR *xdrs, 3437387SRobert.Gordon@Sun.COM xdrproc_t xdr_args, caddr_t argsp) 3447387SRobert.Gordon@Sun.COM { 3457387SRobert.Gordon@Sun.COM cku_private_t *p = htop(h); 3467387SRobert.Gordon@Sun.COM 3477387SRobert.Gordon@Sun.COM if (h->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) { 3487387SRobert.Gordon@Sun.COM /* 3497387SRobert.Gordon@Sun.COM * Copy in the preserialized RPC header 3507387SRobert.Gordon@Sun.COM * information. 3517387SRobert.Gordon@Sun.COM */ 3527387SRobert.Gordon@Sun.COM bcopy(p->cku_rpchdr, rpcmsg->addr, CKU_HDRSIZE); 3537387SRobert.Gordon@Sun.COM 3547387SRobert.Gordon@Sun.COM /* 3557387SRobert.Gordon@Sun.COM * transaction id is the 1st thing in the output 3567387SRobert.Gordon@Sun.COM * buffer. 3577387SRobert.Gordon@Sun.COM */ 3587387SRobert.Gordon@Sun.COM /* LINTED pointer alignment */ 3597387SRobert.Gordon@Sun.COM (*(uint32_t *)(rpcmsg->addr)) = p->cku_xid; 3607387SRobert.Gordon@Sun.COM 3617387SRobert.Gordon@Sun.COM /* Skip the preserialized stuff. */ 3627387SRobert.Gordon@Sun.COM XDR_SETPOS(xdrs, CKU_HDRSIZE); 3637387SRobert.Gordon@Sun.COM 3647387SRobert.Gordon@Sun.COM /* Serialize dynamic stuff into the output buffer. */ 3657387SRobert.Gordon@Sun.COM if ((!XDR_PUTINT32(xdrs, (int32_t *)&procnum)) || 3667387SRobert.Gordon@Sun.COM (!AUTH_MARSHALL(h->cl_auth, xdrs, p->cku_cred)) || 3677387SRobert.Gordon@Sun.COM (!(*xdr_args)(xdrs, argsp))) { 3687387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__rpcmsg__dynargs); 3697387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL); 3707387SRobert.Gordon@Sun.COM } 3717387SRobert.Gordon@Sun.COM p->cku_outsz = XDR_GETPOS(xdrs); 3727387SRobert.Gordon@Sun.COM } else { 3737387SRobert.Gordon@Sun.COM uint32_t *uproc = (uint32_t *)&p->cku_rpchdr[CKU_HDRSIZE]; 3747387SRobert.Gordon@Sun.COM IXDR_PUT_U_INT32(uproc, procnum); 3757387SRobert.Gordon@Sun.COM (*(uint32_t *)(&p->cku_rpchdr[0])) = p->cku_xid; 3767387SRobert.Gordon@Sun.COM XDR_SETPOS(xdrs, 0); 3777387SRobert.Gordon@Sun.COM 3787387SRobert.Gordon@Sun.COM /* Serialize the procedure number and the arguments. */ 3797387SRobert.Gordon@Sun.COM if (!AUTH_WRAP(h->cl_auth, (caddr_t)p->cku_rpchdr, 3807387SRobert.Gordon@Sun.COM CKU_HDRSIZE+4, xdrs, xdr_args, argsp)) { 3817387SRobert.Gordon@Sun.COM if (rpcmsg->addr != xdrs->x_base) { 3827387SRobert.Gordon@Sun.COM rpcmsg->addr = xdrs->x_base; 3837387SRobert.Gordon@Sun.COM rpcmsg->len = xdr_getbufsize(xdrs); 3847387SRobert.Gordon@Sun.COM } 3857387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__rpcmsg__procnum); 3867387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL); 3877387SRobert.Gordon@Sun.COM } 3887387SRobert.Gordon@Sun.COM /* 3897387SRobert.Gordon@Sun.COM * If we had to allocate a new buffer while encoding 3907387SRobert.Gordon@Sun.COM * then update the addr and len. 3917387SRobert.Gordon@Sun.COM */ 3927387SRobert.Gordon@Sun.COM if (rpcmsg->addr != xdrs->x_base) { 3937387SRobert.Gordon@Sun.COM rpcmsg->addr = xdrs->x_base; 3947387SRobert.Gordon@Sun.COM rpcmsg->len = xdr_getbufsize(xdrs); 3957387SRobert.Gordon@Sun.COM } 3967387SRobert.Gordon@Sun.COM 3977387SRobert.Gordon@Sun.COM p->cku_outsz = XDR_GETPOS(xdrs); 3987387SRobert.Gordon@Sun.COM DTRACE_PROBE1(krpc__i__compose__size__sec, int, p->cku_outsz) 3997387SRobert.Gordon@Sun.COM } 4007387SRobert.Gordon@Sun.COM 4017387SRobert.Gordon@Sun.COM return (CLNT_RDMA_SUCCESS); 4027387SRobert.Gordon@Sun.COM } 4037387SRobert.Gordon@Sun.COM 4047387SRobert.Gordon@Sun.COM static int 4057387SRobert.Gordon@Sun.COM clnt_compose_rdma_header(CONN *conn, CLIENT *h, rdma_buf_t *clmsg, 4067387SRobert.Gordon@Sun.COM XDR **xdrs, uint_t *op) 4077387SRobert.Gordon@Sun.COM { 4087387SRobert.Gordon@Sun.COM cku_private_t *p = htop(h); 4097387SRobert.Gordon@Sun.COM uint_t vers; 4107387SRobert.Gordon@Sun.COM uint32_t rdma_credit = rdma_bufs_rqst; 4117387SRobert.Gordon@Sun.COM 4127387SRobert.Gordon@Sun.COM vers = RPCRDMA_VERS; 4137387SRobert.Gordon@Sun.COM clmsg->type = SEND_BUFFER; 4147387SRobert.Gordon@Sun.COM 4157387SRobert.Gordon@Sun.COM if (rdma_buf_alloc(conn, clmsg)) { 4167387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL); 4177387SRobert.Gordon@Sun.COM } 4187387SRobert.Gordon@Sun.COM 4197387SRobert.Gordon@Sun.COM *xdrs = &p->cku_outxdr; 4207387SRobert.Gordon@Sun.COM xdrmem_create(*xdrs, clmsg->addr, clmsg->len, XDR_ENCODE); 4217387SRobert.Gordon@Sun.COM 4227387SRobert.Gordon@Sun.COM (*(uint32_t *)clmsg->addr) = p->cku_xid; 4237387SRobert.Gordon@Sun.COM XDR_SETPOS(*xdrs, sizeof (uint32_t)); 4247387SRobert.Gordon@Sun.COM (void) xdr_u_int(*xdrs, &vers); 4257387SRobert.Gordon@Sun.COM (void) xdr_u_int(*xdrs, &rdma_credit); 4267387SRobert.Gordon@Sun.COM (void) xdr_u_int(*xdrs, op); 4277387SRobert.Gordon@Sun.COM 4287387SRobert.Gordon@Sun.COM return (CLNT_RDMA_SUCCESS); 4297387SRobert.Gordon@Sun.COM } 4307387SRobert.Gordon@Sun.COM 4317387SRobert.Gordon@Sun.COM /* 4327387SRobert.Gordon@Sun.COM * If xp_cl is NULL value, then the RPC payload will NOT carry 4337387SRobert.Gordon@Sun.COM * an RDMA READ chunk list, in this case we insert FALSE into 4347387SRobert.Gordon@Sun.COM * the XDR stream. Otherwise we use the clist and RDMA register 4357387SRobert.Gordon@Sun.COM * the memory and encode the clist into the outbound XDR stream. 4367387SRobert.Gordon@Sun.COM */ 4377387SRobert.Gordon@Sun.COM static int 4387387SRobert.Gordon@Sun.COM clnt_setup_rlist(CONN *conn, XDR *xdrs, XDR *call_xdrp) 4397387SRobert.Gordon@Sun.COM { 4407387SRobert.Gordon@Sun.COM int status; 4417387SRobert.Gordon@Sun.COM struct clist *rclp; 4427387SRobert.Gordon@Sun.COM int32_t xdr_flag = XDR_RDMA_RLIST_REG; 4437387SRobert.Gordon@Sun.COM 4447387SRobert.Gordon@Sun.COM XDR_CONTROL(call_xdrp, XDR_RDMA_GET_RLIST, &rclp); 4457387SRobert.Gordon@Sun.COM 4467387SRobert.Gordon@Sun.COM if (rclp != NULL) { 4477387SRobert.Gordon@Sun.COM status = clist_register(conn, rclp, CLIST_REG_SOURCE); 4487387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 4497387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL); 4507387SRobert.Gordon@Sun.COM } 4517387SRobert.Gordon@Sun.COM XDR_CONTROL(call_xdrp, XDR_RDMA_SET_FLAGS, &xdr_flag); 4527387SRobert.Gordon@Sun.COM } 4537387SRobert.Gordon@Sun.COM (void) xdr_do_clist(xdrs, &rclp); 4547387SRobert.Gordon@Sun.COM 4557387SRobert.Gordon@Sun.COM return (CLNT_RDMA_SUCCESS); 4567387SRobert.Gordon@Sun.COM } 4577387SRobert.Gordon@Sun.COM 4587387SRobert.Gordon@Sun.COM /* 4597387SRobert.Gordon@Sun.COM * If xp_wcl is NULL value, then the RPC payload will NOT carry 4607387SRobert.Gordon@Sun.COM * an RDMA WRITE chunk list, in this case we insert FALSE into 4617387SRobert.Gordon@Sun.COM * the XDR stream. Otherwise we use the clist and RDMA register 4627387SRobert.Gordon@Sun.COM * the memory and encode the clist into the outbound XDR stream. 4637387SRobert.Gordon@Sun.COM */ 4647387SRobert.Gordon@Sun.COM static int 4659348SSiddheshwar.Mahesh@Sun.COM clnt_setup_wlist(CONN *conn, XDR *xdrs, XDR *call_xdrp, rdma_buf_t *rndbuf) 4667387SRobert.Gordon@Sun.COM { 4677387SRobert.Gordon@Sun.COM int status; 4689348SSiddheshwar.Mahesh@Sun.COM struct clist *wlist, *rndcl; 4699348SSiddheshwar.Mahesh@Sun.COM int wlen, rndlen; 4707387SRobert.Gordon@Sun.COM int32_t xdr_flag = XDR_RDMA_WLIST_REG; 4717387SRobert.Gordon@Sun.COM 4727387SRobert.Gordon@Sun.COM XDR_CONTROL(call_xdrp, XDR_RDMA_GET_WLIST, &wlist); 4737387SRobert.Gordon@Sun.COM 4747387SRobert.Gordon@Sun.COM if (wlist != NULL) { 4759348SSiddheshwar.Mahesh@Sun.COM /* 4769348SSiddheshwar.Mahesh@Sun.COM * If we are sending a non 4-byte alligned length 4779348SSiddheshwar.Mahesh@Sun.COM * the server will roundup the length to 4-byte 4789348SSiddheshwar.Mahesh@Sun.COM * boundary. In such a case, a trailing chunk is 4799348SSiddheshwar.Mahesh@Sun.COM * added to take any spill over roundup bytes. 4809348SSiddheshwar.Mahesh@Sun.COM */ 4819348SSiddheshwar.Mahesh@Sun.COM wlen = clist_len(wlist); 4829348SSiddheshwar.Mahesh@Sun.COM rndlen = (roundup(wlen, BYTES_PER_XDR_UNIT) - wlen); 4839348SSiddheshwar.Mahesh@Sun.COM if (rndlen) { 4849348SSiddheshwar.Mahesh@Sun.COM rndcl = clist_alloc(); 4859348SSiddheshwar.Mahesh@Sun.COM /* 4869348SSiddheshwar.Mahesh@Sun.COM * calc_length() will allocate a PAGESIZE 4879348SSiddheshwar.Mahesh@Sun.COM * buffer below. 4889348SSiddheshwar.Mahesh@Sun.COM */ 4899348SSiddheshwar.Mahesh@Sun.COM rndcl->c_len = calc_length(rndlen); 4909348SSiddheshwar.Mahesh@Sun.COM rndcl->rb_longbuf.type = RDMA_LONG_BUFFER; 4919348SSiddheshwar.Mahesh@Sun.COM rndcl->rb_longbuf.len = rndcl->c_len; 4929348SSiddheshwar.Mahesh@Sun.COM if (rdma_buf_alloc(conn, &rndcl->rb_longbuf)) { 4939348SSiddheshwar.Mahesh@Sun.COM clist_free(rndcl); 4949348SSiddheshwar.Mahesh@Sun.COM return (CLNT_RDMA_FAIL); 4959348SSiddheshwar.Mahesh@Sun.COM } 4969348SSiddheshwar.Mahesh@Sun.COM 4979348SSiddheshwar.Mahesh@Sun.COM /* Roundup buffer freed back in caller */ 4989348SSiddheshwar.Mahesh@Sun.COM *rndbuf = rndcl->rb_longbuf; 4999348SSiddheshwar.Mahesh@Sun.COM 5009348SSiddheshwar.Mahesh@Sun.COM rndcl->u.c_daddr3 = rndcl->rb_longbuf.addr; 5019348SSiddheshwar.Mahesh@Sun.COM rndcl->c_next = NULL; 5029348SSiddheshwar.Mahesh@Sun.COM rndcl->c_dmemhandle = rndcl->rb_longbuf.handle; 5039348SSiddheshwar.Mahesh@Sun.COM wlist->c_next = rndcl; 5049348SSiddheshwar.Mahesh@Sun.COM } 5059348SSiddheshwar.Mahesh@Sun.COM 5067387SRobert.Gordon@Sun.COM status = clist_register(conn, wlist, CLIST_REG_DST); 5077387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 5089348SSiddheshwar.Mahesh@Sun.COM rdma_buf_free(conn, rndbuf); 5099348SSiddheshwar.Mahesh@Sun.COM bzero(rndbuf, sizeof (rdma_buf_t)); 5107387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL); 5117387SRobert.Gordon@Sun.COM } 5127387SRobert.Gordon@Sun.COM XDR_CONTROL(call_xdrp, XDR_RDMA_SET_FLAGS, &xdr_flag); 5137387SRobert.Gordon@Sun.COM } 5147387SRobert.Gordon@Sun.COM 5159348SSiddheshwar.Mahesh@Sun.COM if (!xdr_encode_wlist(xdrs, wlist)) { 5169348SSiddheshwar.Mahesh@Sun.COM if (rndlen) { 5179348SSiddheshwar.Mahesh@Sun.COM rdma_buf_free(conn, rndbuf); 5189348SSiddheshwar.Mahesh@Sun.COM bzero(rndbuf, sizeof (rdma_buf_t)); 5199348SSiddheshwar.Mahesh@Sun.COM } 5207387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL); 5219348SSiddheshwar.Mahesh@Sun.COM } 5227387SRobert.Gordon@Sun.COM 5237387SRobert.Gordon@Sun.COM return (CLNT_RDMA_SUCCESS); 5247387SRobert.Gordon@Sun.COM } 5257387SRobert.Gordon@Sun.COM 5267387SRobert.Gordon@Sun.COM static int 5277387SRobert.Gordon@Sun.COM clnt_setup_long_reply(CONN *conn, struct clist **clpp, uint_t length) 5287387SRobert.Gordon@Sun.COM { 5297387SRobert.Gordon@Sun.COM if (length == 0) { 5307387SRobert.Gordon@Sun.COM *clpp = NULL; 5317387SRobert.Gordon@Sun.COM return (CLNT_RDMA_SUCCESS); 5327387SRobert.Gordon@Sun.COM } 5337387SRobert.Gordon@Sun.COM 5347387SRobert.Gordon@Sun.COM *clpp = clist_alloc(); 5357387SRobert.Gordon@Sun.COM 5367387SRobert.Gordon@Sun.COM (*clpp)->rb_longbuf.len = calc_length(length); 5377387SRobert.Gordon@Sun.COM (*clpp)->rb_longbuf.type = RDMA_LONG_BUFFER; 5387387SRobert.Gordon@Sun.COM 5397387SRobert.Gordon@Sun.COM if (rdma_buf_alloc(conn, &((*clpp)->rb_longbuf))) { 5407387SRobert.Gordon@Sun.COM clist_free(*clpp); 5417387SRobert.Gordon@Sun.COM *clpp = NULL; 5427387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL); 5437387SRobert.Gordon@Sun.COM } 5447387SRobert.Gordon@Sun.COM 5457387SRobert.Gordon@Sun.COM (*clpp)->u.c_daddr3 = (*clpp)->rb_longbuf.addr; 5467387SRobert.Gordon@Sun.COM (*clpp)->c_len = (*clpp)->rb_longbuf.len; 5477387SRobert.Gordon@Sun.COM (*clpp)->c_next = NULL; 5487387SRobert.Gordon@Sun.COM (*clpp)->c_dmemhandle = (*clpp)->rb_longbuf.handle; 5497387SRobert.Gordon@Sun.COM 5507387SRobert.Gordon@Sun.COM if (clist_register(conn, *clpp, CLIST_REG_DST)) { 5517387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__longrep_regbuf); 5527387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &((*clpp)->rb_longbuf)); 5537387SRobert.Gordon@Sun.COM clist_free(*clpp); 55411551SSiddheshwar.Mahesh@Sun.COM *clpp = NULL; 5557387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL); 5567387SRobert.Gordon@Sun.COM } 5577387SRobert.Gordon@Sun.COM 5587387SRobert.Gordon@Sun.COM return (CLNT_RDMA_SUCCESS); 5597387SRobert.Gordon@Sun.COM } 5607387SRobert.Gordon@Sun.COM 5610Sstevel@tonic-gate /* ARGSUSED */ 5620Sstevel@tonic-gate static enum clnt_stat 5630Sstevel@tonic-gate clnt_rdma_kcallit(CLIENT *h, rpcproc_t procnum, xdrproc_t xdr_args, 5647387SRobert.Gordon@Sun.COM caddr_t argsp, xdrproc_t xdr_results, caddr_t resultsp, 5657387SRobert.Gordon@Sun.COM struct timeval wait) 5660Sstevel@tonic-gate { 5670Sstevel@tonic-gate cku_private_t *p = htop(h); 5687387SRobert.Gordon@Sun.COM 5697387SRobert.Gordon@Sun.COM int try_call_again; 5707387SRobert.Gordon@Sun.COM int refresh_attempt = AUTH_REFRESH_COUNT; 5710Sstevel@tonic-gate int status; 5727387SRobert.Gordon@Sun.COM int msglen; 5737387SRobert.Gordon@Sun.COM 5747387SRobert.Gordon@Sun.COM XDR *call_xdrp, callxdr; /* for xdrrdma encoding the RPC call */ 5757387SRobert.Gordon@Sun.COM XDR *reply_xdrp, replyxdr; /* for xdrrdma decoding the RPC reply */ 5767387SRobert.Gordon@Sun.COM XDR *rdmahdr_o_xdrs, *rdmahdr_i_xdrs; 5777387SRobert.Gordon@Sun.COM 5780Sstevel@tonic-gate struct rpc_msg reply_msg; 5798695SRajkumar.Sivaprakasam@Sun.COM rdma_registry_t *m; 5807387SRobert.Gordon@Sun.COM 5817387SRobert.Gordon@Sun.COM struct clist *cl_sendlist; 5827387SRobert.Gordon@Sun.COM struct clist *cl_recvlist; 5837387SRobert.Gordon@Sun.COM struct clist *cl; 5847387SRobert.Gordon@Sun.COM struct clist *cl_rpcmsg; 5857387SRobert.Gordon@Sun.COM struct clist *cl_rdma_reply; 5867387SRobert.Gordon@Sun.COM struct clist *cl_rpcreply_wlist; 5877387SRobert.Gordon@Sun.COM struct clist *cl_long_reply; 5889348SSiddheshwar.Mahesh@Sun.COM rdma_buf_t rndup; 5897387SRobert.Gordon@Sun.COM 5907387SRobert.Gordon@Sun.COM uint_t vers; 5917387SRobert.Gordon@Sun.COM uint_t op; 5920Sstevel@tonic-gate uint_t off; 5937387SRobert.Gordon@Sun.COM uint32_t seg_array_len; 5947387SRobert.Gordon@Sun.COM uint_t long_reply_len; 5957387SRobert.Gordon@Sun.COM uint_t rpcsec_gss; 5967387SRobert.Gordon@Sun.COM uint_t gss_i_or_p; 5977387SRobert.Gordon@Sun.COM 5980Sstevel@tonic-gate CONN *conn = NULL; 5997387SRobert.Gordon@Sun.COM rdma_buf_t clmsg; 6007387SRobert.Gordon@Sun.COM rdma_buf_t rpcmsg; 6017387SRobert.Gordon@Sun.COM rdma_chunkinfo_lengths_t rcil; 6027387SRobert.Gordon@Sun.COM 6030Sstevel@tonic-gate clock_t ticks; 6047387SRobert.Gordon@Sun.COM bool_t wlist_exists_reply; 6057387SRobert.Gordon@Sun.COM 6067387SRobert.Gordon@Sun.COM uint32_t rdma_credit = rdma_bufs_rqst; 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate RCSTAT_INCR(rccalls); 6097387SRobert.Gordon@Sun.COM 6107387SRobert.Gordon@Sun.COM call_again: 6117387SRobert.Gordon@Sun.COM 6127387SRobert.Gordon@Sun.COM bzero(&clmsg, sizeof (clmsg)); 6137387SRobert.Gordon@Sun.COM bzero(&rpcmsg, sizeof (rpcmsg)); 6149348SSiddheshwar.Mahesh@Sun.COM bzero(&rndup, sizeof (rndup)); 6157387SRobert.Gordon@Sun.COM try_call_again = 0; 6167387SRobert.Gordon@Sun.COM cl_sendlist = NULL; 6177387SRobert.Gordon@Sun.COM cl_recvlist = NULL; 6187387SRobert.Gordon@Sun.COM cl = NULL; 6197387SRobert.Gordon@Sun.COM cl_rpcmsg = NULL; 6207387SRobert.Gordon@Sun.COM cl_rdma_reply = NULL; 6217387SRobert.Gordon@Sun.COM call_xdrp = NULL; 6227387SRobert.Gordon@Sun.COM reply_xdrp = NULL; 6237387SRobert.Gordon@Sun.COM wlist_exists_reply = FALSE; 6247387SRobert.Gordon@Sun.COM cl_rpcreply_wlist = NULL; 6257387SRobert.Gordon@Sun.COM cl_long_reply = NULL; 6267387SRobert.Gordon@Sun.COM rcil.rcil_len = 0; 6277387SRobert.Gordon@Sun.COM rcil.rcil_len_alt = 0; 6287387SRobert.Gordon@Sun.COM long_reply_len = 0; 6297387SRobert.Gordon@Sun.COM 6308695SRajkumar.Sivaprakasam@Sun.COM rw_enter(&rdma_lock, RW_READER); 6318695SRajkumar.Sivaprakasam@Sun.COM m = (rdma_registry_t *)p->cku_rd_handle; 6328695SRajkumar.Sivaprakasam@Sun.COM if (m->r_mod_state == RDMA_MOD_INACTIVE) { 6338695SRajkumar.Sivaprakasam@Sun.COM /* 6348695SRajkumar.Sivaprakasam@Sun.COM * If we didn't find a matching RDMA module in the registry 6358695SRajkumar.Sivaprakasam@Sun.COM * then there is no transport. 6368695SRajkumar.Sivaprakasam@Sun.COM */ 6378695SRajkumar.Sivaprakasam@Sun.COM rw_exit(&rdma_lock); 6388695SRajkumar.Sivaprakasam@Sun.COM p->cku_err.re_status = RPC_CANTSEND; 6398695SRajkumar.Sivaprakasam@Sun.COM p->cku_err.re_errno = EIO; 6408695SRajkumar.Sivaprakasam@Sun.COM ticks = clnt_rdma_min_delay * drv_usectohz(1000000); 6418695SRajkumar.Sivaprakasam@Sun.COM if (h->cl_nosignal == TRUE) { 6428695SRajkumar.Sivaprakasam@Sun.COM delay(ticks); 6438695SRajkumar.Sivaprakasam@Sun.COM } else { 6448695SRajkumar.Sivaprakasam@Sun.COM if (delay_sig(ticks) == EINTR) { 6458695SRajkumar.Sivaprakasam@Sun.COM p->cku_err.re_status = RPC_INTR; 6468695SRajkumar.Sivaprakasam@Sun.COM p->cku_err.re_errno = EINTR; 6478695SRajkumar.Sivaprakasam@Sun.COM } 6488695SRajkumar.Sivaprakasam@Sun.COM } 6498695SRajkumar.Sivaprakasam@Sun.COM return (RPC_CANTSEND); 6508695SRajkumar.Sivaprakasam@Sun.COM } 6510Sstevel@tonic-gate /* 6520Sstevel@tonic-gate * Get unique xid 6530Sstevel@tonic-gate */ 6540Sstevel@tonic-gate if (p->cku_xid == 0) 6550Sstevel@tonic-gate p->cku_xid = alloc_xid(); 6560Sstevel@tonic-gate 6579733SFaramarz.Jalalian@Sun.COM status = RDMA_GET_CONN(p->cku_rd_mod->rdma_ops, &p->cku_srcaddr, 6589733SFaramarz.Jalalian@Sun.COM &p->cku_addr, p->cku_addrfmly, p->cku_rd_handle, &conn); 6598695SRajkumar.Sivaprakasam@Sun.COM rw_exit(&rdma_lock); 6600Sstevel@tonic-gate 6617387SRobert.Gordon@Sun.COM /* 6627387SRobert.Gordon@Sun.COM * If there is a problem with the connection reflect the issue 6637387SRobert.Gordon@Sun.COM * back to the higher level to address, we MAY delay for a short 6647387SRobert.Gordon@Sun.COM * period so that we are kind to the transport. 6657387SRobert.Gordon@Sun.COM */ 6660Sstevel@tonic-gate if (conn == NULL) { 6670Sstevel@tonic-gate /* 6680Sstevel@tonic-gate * Connect failed to server. Could be because of one 6690Sstevel@tonic-gate * of several things. In some cases we don't want 6700Sstevel@tonic-gate * the caller to retry immediately - delay before 6710Sstevel@tonic-gate * returning to caller. 6720Sstevel@tonic-gate */ 6730Sstevel@tonic-gate switch (status) { 6740Sstevel@tonic-gate case RDMA_TIMEDOUT: 6750Sstevel@tonic-gate /* 6760Sstevel@tonic-gate * Already timed out. No need to delay 6770Sstevel@tonic-gate * some more. 6780Sstevel@tonic-gate */ 6790Sstevel@tonic-gate p->cku_err.re_status = RPC_TIMEDOUT; 6800Sstevel@tonic-gate p->cku_err.re_errno = ETIMEDOUT; 6810Sstevel@tonic-gate break; 6820Sstevel@tonic-gate case RDMA_INTR: 6830Sstevel@tonic-gate /* 6840Sstevel@tonic-gate * Failed because of an signal. Very likely 6850Sstevel@tonic-gate * the caller will not retry. 6860Sstevel@tonic-gate */ 6870Sstevel@tonic-gate p->cku_err.re_status = RPC_INTR; 6880Sstevel@tonic-gate p->cku_err.re_errno = EINTR; 6890Sstevel@tonic-gate break; 6900Sstevel@tonic-gate default: 6910Sstevel@tonic-gate /* 6920Sstevel@tonic-gate * All other failures - server down or service 6930Sstevel@tonic-gate * down or temporary resource failure. Delay before 6940Sstevel@tonic-gate * returning to caller. 6950Sstevel@tonic-gate */ 6960Sstevel@tonic-gate ticks = clnt_rdma_min_delay * drv_usectohz(1000000); 6970Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTCONNECT; 6980Sstevel@tonic-gate p->cku_err.re_errno = EIO; 6990Sstevel@tonic-gate 7000Sstevel@tonic-gate if (h->cl_nosignal == TRUE) { 7010Sstevel@tonic-gate delay(ticks); 7020Sstevel@tonic-gate } else { 7030Sstevel@tonic-gate if (delay_sig(ticks) == EINTR) { 7040Sstevel@tonic-gate p->cku_err.re_status = RPC_INTR; 7050Sstevel@tonic-gate p->cku_err.re_errno = EINTR; 7060Sstevel@tonic-gate } 7070Sstevel@tonic-gate } 7080Sstevel@tonic-gate break; 7090Sstevel@tonic-gate } 7100Sstevel@tonic-gate 7110Sstevel@tonic-gate return (p->cku_err.re_status); 7120Sstevel@tonic-gate } 7137387SRobert.Gordon@Sun.COM 7149733SFaramarz.Jalalian@Sun.COM if (p->cku_srcaddr.maxlen < conn->c_laddr.len) { 7159733SFaramarz.Jalalian@Sun.COM if ((p->cku_srcaddr.maxlen != 0) && 7169733SFaramarz.Jalalian@Sun.COM (p->cku_srcaddr.buf != NULL)) 7179733SFaramarz.Jalalian@Sun.COM kmem_free(p->cku_srcaddr.buf, p->cku_srcaddr.maxlen); 7189733SFaramarz.Jalalian@Sun.COM p->cku_srcaddr.buf = kmem_zalloc(conn->c_laddr.maxlen, 7199733SFaramarz.Jalalian@Sun.COM KM_SLEEP); 7209733SFaramarz.Jalalian@Sun.COM p->cku_srcaddr.maxlen = conn->c_laddr.maxlen; 7219733SFaramarz.Jalalian@Sun.COM } 7229733SFaramarz.Jalalian@Sun.COM 7239733SFaramarz.Jalalian@Sun.COM p->cku_srcaddr.len = conn->c_laddr.len; 7249733SFaramarz.Jalalian@Sun.COM bcopy(conn->c_laddr.buf, p->cku_srcaddr.buf, conn->c_laddr.len); 7259733SFaramarz.Jalalian@Sun.COM 7267387SRobert.Gordon@Sun.COM clnt_check_credit(conn); 7270Sstevel@tonic-gate 7287387SRobert.Gordon@Sun.COM status = CLNT_RDMA_FAIL; 7297387SRobert.Gordon@Sun.COM 7307387SRobert.Gordon@Sun.COM rpcsec_gss = gss_i_or_p = FALSE; 7310Sstevel@tonic-gate 7327387SRobert.Gordon@Sun.COM if (IS_RPCSEC_GSS(h)) { 7337387SRobert.Gordon@Sun.COM rpcsec_gss = TRUE; 7347387SRobert.Gordon@Sun.COM if (rpc_gss_get_service_type(h->cl_auth) == 7357387SRobert.Gordon@Sun.COM rpc_gss_svc_integrity || 7367387SRobert.Gordon@Sun.COM rpc_gss_get_service_type(h->cl_auth) == 7377387SRobert.Gordon@Sun.COM rpc_gss_svc_privacy) 7387387SRobert.Gordon@Sun.COM gss_i_or_p = TRUE; 7390Sstevel@tonic-gate } 7400Sstevel@tonic-gate 7417387SRobert.Gordon@Sun.COM /* 7427387SRobert.Gordon@Sun.COM * Try a regular RDMA message if RPCSEC_GSS is not being used 7437387SRobert.Gordon@Sun.COM * or if RPCSEC_GSS is being used for authentication only. 7447387SRobert.Gordon@Sun.COM */ 7457387SRobert.Gordon@Sun.COM if (rpcsec_gss == FALSE || 7467387SRobert.Gordon@Sun.COM (rpcsec_gss == TRUE && gss_i_or_p == FALSE)) { 7470Sstevel@tonic-gate /* 7487387SRobert.Gordon@Sun.COM * Grab a send buffer for the request. Try to 7497387SRobert.Gordon@Sun.COM * encode it to see if it fits. If not, then it 7507387SRobert.Gordon@Sun.COM * needs to be sent in a chunk. 7510Sstevel@tonic-gate */ 7527387SRobert.Gordon@Sun.COM rpcmsg.type = SEND_BUFFER; 7537387SRobert.Gordon@Sun.COM if (rdma_buf_alloc(conn, &rpcmsg)) { 7547387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__callit_nobufs); 7550Sstevel@tonic-gate goto done; 7560Sstevel@tonic-gate } 7577387SRobert.Gordon@Sun.COM 7587387SRobert.Gordon@Sun.COM /* First try to encode into regular send buffer */ 7597387SRobert.Gordon@Sun.COM op = RDMA_MSG; 7600Sstevel@tonic-gate 7617387SRobert.Gordon@Sun.COM call_xdrp = &callxdr; 7627387SRobert.Gordon@Sun.COM 7637387SRobert.Gordon@Sun.COM xdrrdma_create(call_xdrp, rpcmsg.addr, rpcmsg.len, 7647387SRobert.Gordon@Sun.COM rdma_minchunk, NULL, XDR_ENCODE, conn); 7650Sstevel@tonic-gate 7667387SRobert.Gordon@Sun.COM status = clnt_compose_rpcmsg(h, procnum, &rpcmsg, call_xdrp, 7677387SRobert.Gordon@Sun.COM xdr_args, argsp); 7687387SRobert.Gordon@Sun.COM 7697387SRobert.Gordon@Sun.COM if (status != CLNT_RDMA_SUCCESS) { 7707387SRobert.Gordon@Sun.COM /* Clean up from previous encode attempt */ 7717387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &rpcmsg); 7727387SRobert.Gordon@Sun.COM XDR_DESTROY(call_xdrp); 7730Sstevel@tonic-gate } else { 7747387SRobert.Gordon@Sun.COM XDR_CONTROL(call_xdrp, XDR_RDMA_GET_CHUNK_LEN, &rcil); 7750Sstevel@tonic-gate } 7760Sstevel@tonic-gate } 7770Sstevel@tonic-gate 7787387SRobert.Gordon@Sun.COM /* If the encode didn't work, then try a NOMSG */ 7797387SRobert.Gordon@Sun.COM if (status != CLNT_RDMA_SUCCESS) { 7807387SRobert.Gordon@Sun.COM 7817387SRobert.Gordon@Sun.COM msglen = CKU_HDRSIZE + BYTES_PER_XDR_UNIT + MAX_AUTH_BYTES + 7827387SRobert.Gordon@Sun.COM xdr_sizeof(xdr_args, argsp); 7837387SRobert.Gordon@Sun.COM 7847387SRobert.Gordon@Sun.COM msglen = calc_length(msglen); 7857387SRobert.Gordon@Sun.COM 7867387SRobert.Gordon@Sun.COM /* pick up the lengths for the reply buffer needed */ 7877387SRobert.Gordon@Sun.COM (void) xdrrdma_sizeof(xdr_args, argsp, 0, 7887387SRobert.Gordon@Sun.COM &rcil.rcil_len, &rcil.rcil_len_alt); 7897387SRobert.Gordon@Sun.COM 7907387SRobert.Gordon@Sun.COM /* 7917387SRobert.Gordon@Sun.COM * Construct a clist to describe the CHUNK_BUFFER 7927387SRobert.Gordon@Sun.COM * for the rpcmsg. 7937387SRobert.Gordon@Sun.COM */ 7947387SRobert.Gordon@Sun.COM cl_rpcmsg = clist_alloc(); 7957387SRobert.Gordon@Sun.COM cl_rpcmsg->c_len = msglen; 7967387SRobert.Gordon@Sun.COM cl_rpcmsg->rb_longbuf.type = RDMA_LONG_BUFFER; 7977387SRobert.Gordon@Sun.COM cl_rpcmsg->rb_longbuf.len = msglen; 7987387SRobert.Gordon@Sun.COM if (rdma_buf_alloc(conn, &cl_rpcmsg->rb_longbuf)) { 7997387SRobert.Gordon@Sun.COM clist_free(cl_rpcmsg); 8007387SRobert.Gordon@Sun.COM goto done; 8017387SRobert.Gordon@Sun.COM } 8027387SRobert.Gordon@Sun.COM cl_rpcmsg->w.c_saddr3 = cl_rpcmsg->rb_longbuf.addr; 8037387SRobert.Gordon@Sun.COM 8047387SRobert.Gordon@Sun.COM op = RDMA_NOMSG; 8057387SRobert.Gordon@Sun.COM call_xdrp = &callxdr; 8067387SRobert.Gordon@Sun.COM 8077387SRobert.Gordon@Sun.COM xdrrdma_create(call_xdrp, cl_rpcmsg->rb_longbuf.addr, 8087387SRobert.Gordon@Sun.COM cl_rpcmsg->rb_longbuf.len, 0, 8097387SRobert.Gordon@Sun.COM cl_rpcmsg, XDR_ENCODE, conn); 8107387SRobert.Gordon@Sun.COM 811*11591SFaramarz.Jalalian@Sun.COM status = clnt_compose_rpcmsg(h, procnum, &cl_rpcmsg->rb_longbuf, 812*11591SFaramarz.Jalalian@Sun.COM call_xdrp, xdr_args, argsp); 8137387SRobert.Gordon@Sun.COM 814*11591SFaramarz.Jalalian@Sun.COM DTRACE_PROBE2(krpc__i__clntrdma__callit__longbuf, int, status, 815*11591SFaramarz.Jalalian@Sun.COM int, msglen); 8167387SRobert.Gordon@Sun.COM if (status != CLNT_RDMA_SUCCESS) { 8177387SRobert.Gordon@Sun.COM p->cku_err.re_status = RPC_CANTENCODEARGS; 8187387SRobert.Gordon@Sun.COM p->cku_err.re_errno = EIO; 8197387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__callit__composemsg); 8207387SRobert.Gordon@Sun.COM goto done; 8217387SRobert.Gordon@Sun.COM } 8227387SRobert.Gordon@Sun.COM } 8237387SRobert.Gordon@Sun.COM 8247387SRobert.Gordon@Sun.COM /* 8257387SRobert.Gordon@Sun.COM * During the XDR_ENCODE we may have "allocated" an RDMA READ or 8267387SRobert.Gordon@Sun.COM * RDMA WRITE clist. 8277387SRobert.Gordon@Sun.COM * 8287387SRobert.Gordon@Sun.COM * First pull the RDMA READ chunk list from the XDR private 8297387SRobert.Gordon@Sun.COM * area to keep it handy. 8307387SRobert.Gordon@Sun.COM */ 8317387SRobert.Gordon@Sun.COM XDR_CONTROL(call_xdrp, XDR_RDMA_GET_RLIST, &cl); 8327387SRobert.Gordon@Sun.COM 8337387SRobert.Gordon@Sun.COM if (gss_i_or_p) { 8347387SRobert.Gordon@Sun.COM long_reply_len = rcil.rcil_len + rcil.rcil_len_alt; 8357387SRobert.Gordon@Sun.COM long_reply_len += MAX_AUTH_BYTES; 8367387SRobert.Gordon@Sun.COM } else { 8377387SRobert.Gordon@Sun.COM long_reply_len = rcil.rcil_len; 8387387SRobert.Gordon@Sun.COM } 8390Sstevel@tonic-gate 8400Sstevel@tonic-gate /* 8410Sstevel@tonic-gate * Update the chunk size information for the Long RPC msg. 8420Sstevel@tonic-gate */ 8430Sstevel@tonic-gate if (cl && op == RDMA_NOMSG) 8440Sstevel@tonic-gate cl->c_len = p->cku_outsz; 8450Sstevel@tonic-gate 8460Sstevel@tonic-gate /* 8477387SRobert.Gordon@Sun.COM * Prepare the RDMA header. On success xdrs will hold the result 8487387SRobert.Gordon@Sun.COM * of xdrmem_create() for a SEND_BUFFER. 8490Sstevel@tonic-gate */ 8507387SRobert.Gordon@Sun.COM status = clnt_compose_rdma_header(conn, h, &clmsg, 8517387SRobert.Gordon@Sun.COM &rdmahdr_o_xdrs, &op); 8527387SRobert.Gordon@Sun.COM 8537387SRobert.Gordon@Sun.COM if (status != CLNT_RDMA_SUCCESS) { 8540Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTSEND; 8550Sstevel@tonic-gate p->cku_err.re_errno = EIO; 8560Sstevel@tonic-gate RCSTAT_INCR(rcnomem); 8577387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__callit__nobufs2); 8580Sstevel@tonic-gate goto done; 8590Sstevel@tonic-gate } 8607387SRobert.Gordon@Sun.COM 8610Sstevel@tonic-gate /* 8627387SRobert.Gordon@Sun.COM * Now insert the RDMA READ list iff present 8630Sstevel@tonic-gate */ 8647387SRobert.Gordon@Sun.COM status = clnt_setup_rlist(conn, rdmahdr_o_xdrs, call_xdrp); 8657387SRobert.Gordon@Sun.COM if (status != CLNT_RDMA_SUCCESS) { 8667387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__callit__clistreg); 8677387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &clmsg); 8687387SRobert.Gordon@Sun.COM p->cku_err.re_status = RPC_CANTSEND; 8697387SRobert.Gordon@Sun.COM p->cku_err.re_errno = EIO; 8707387SRobert.Gordon@Sun.COM goto done; 8717387SRobert.Gordon@Sun.COM } 8727387SRobert.Gordon@Sun.COM 8737387SRobert.Gordon@Sun.COM /* 8747387SRobert.Gordon@Sun.COM * Setup RDMA WRITE chunk list for nfs read operation 8757387SRobert.Gordon@Sun.COM * other operations will have a NULL which will result 8767387SRobert.Gordon@Sun.COM * as a NULL list in the XDR stream. 8777387SRobert.Gordon@Sun.COM */ 8789348SSiddheshwar.Mahesh@Sun.COM status = clnt_setup_wlist(conn, rdmahdr_o_xdrs, call_xdrp, &rndup); 8797387SRobert.Gordon@Sun.COM if (status != CLNT_RDMA_SUCCESS) { 8807387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &clmsg); 8817387SRobert.Gordon@Sun.COM p->cku_err.re_status = RPC_CANTSEND; 8827387SRobert.Gordon@Sun.COM p->cku_err.re_errno = EIO; 8837387SRobert.Gordon@Sun.COM goto done; 8847387SRobert.Gordon@Sun.COM } 8850Sstevel@tonic-gate 8860Sstevel@tonic-gate /* 8877387SRobert.Gordon@Sun.COM * If NULL call and RPCSEC_GSS, provide a chunk such that 8887387SRobert.Gordon@Sun.COM * large responses can flow back to the client. 8897387SRobert.Gordon@Sun.COM * If RPCSEC_GSS with integrity or privacy is in use, get chunk. 8900Sstevel@tonic-gate */ 8917387SRobert.Gordon@Sun.COM if ((procnum == 0 && rpcsec_gss == TRUE) || 8927387SRobert.Gordon@Sun.COM (rpcsec_gss == TRUE && gss_i_or_p == TRUE)) 8937387SRobert.Gordon@Sun.COM long_reply_len += 1024; 8940Sstevel@tonic-gate 8957387SRobert.Gordon@Sun.COM status = clnt_setup_long_reply(conn, &cl_long_reply, long_reply_len); 8960Sstevel@tonic-gate 897*11591SFaramarz.Jalalian@Sun.COM DTRACE_PROBE2(krpc__i__clntrdma__callit__longreply, int, status, 898*11591SFaramarz.Jalalian@Sun.COM int, long_reply_len); 899*11591SFaramarz.Jalalian@Sun.COM 9007387SRobert.Gordon@Sun.COM if (status != CLNT_RDMA_SUCCESS) { 9017387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &clmsg); 9027387SRobert.Gordon@Sun.COM p->cku_err.re_status = RPC_CANTSEND; 9037387SRobert.Gordon@Sun.COM p->cku_err.re_errno = EIO; 9047387SRobert.Gordon@Sun.COM goto done; 9050Sstevel@tonic-gate } 9060Sstevel@tonic-gate 9070Sstevel@tonic-gate /* 9087387SRobert.Gordon@Sun.COM * XDR encode the RDMA_REPLY write chunk 9097387SRobert.Gordon@Sun.COM */ 9107387SRobert.Gordon@Sun.COM seg_array_len = (cl_long_reply ? 1 : 0); 9117387SRobert.Gordon@Sun.COM (void) xdr_encode_reply_wchunk(rdmahdr_o_xdrs, cl_long_reply, 9127387SRobert.Gordon@Sun.COM seg_array_len); 9137387SRobert.Gordon@Sun.COM 9147387SRobert.Gordon@Sun.COM /* 9157387SRobert.Gordon@Sun.COM * Construct a clist in "sendlist" that represents what we 9167387SRobert.Gordon@Sun.COM * will push over the wire. 9177387SRobert.Gordon@Sun.COM * 9180Sstevel@tonic-gate * Start with the RDMA header and clist (if any) 9190Sstevel@tonic-gate */ 9207387SRobert.Gordon@Sun.COM clist_add(&cl_sendlist, 0, XDR_GETPOS(rdmahdr_o_xdrs), &clmsg.handle, 9217387SRobert.Gordon@Sun.COM clmsg.addr, NULL, NULL); 9220Sstevel@tonic-gate 9230Sstevel@tonic-gate /* 9247387SRobert.Gordon@Sun.COM * Put the RPC call message in sendlist if small RPC 9250Sstevel@tonic-gate */ 9260Sstevel@tonic-gate if (op == RDMA_MSG) { 9277387SRobert.Gordon@Sun.COM clist_add(&cl_sendlist, 0, p->cku_outsz, &rpcmsg.handle, 9287387SRobert.Gordon@Sun.COM rpcmsg.addr, NULL, NULL); 9290Sstevel@tonic-gate } else { 9300Sstevel@tonic-gate /* Long RPC already in chunk list */ 9310Sstevel@tonic-gate RCSTAT_INCR(rclongrpcs); 9320Sstevel@tonic-gate } 9330Sstevel@tonic-gate 9340Sstevel@tonic-gate /* 9350Sstevel@tonic-gate * Set up a reply buffer ready for the reply 9360Sstevel@tonic-gate */ 9370Sstevel@tonic-gate status = rdma_clnt_postrecv(conn, p->cku_xid); 9380Sstevel@tonic-gate if (status != RDMA_SUCCESS) { 9390Sstevel@tonic-gate rdma_buf_free(conn, &clmsg); 9400Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTSEND; 9410Sstevel@tonic-gate p->cku_err.re_errno = EIO; 9420Sstevel@tonic-gate goto done; 9430Sstevel@tonic-gate } 9447387SRobert.Gordon@Sun.COM 9450Sstevel@tonic-gate /* 9460Sstevel@tonic-gate * sync the memory for dma 9470Sstevel@tonic-gate */ 9480Sstevel@tonic-gate if (cl != NULL) { 9497387SRobert.Gordon@Sun.COM status = clist_syncmem(conn, cl, CLIST_REG_SOURCE); 9500Sstevel@tonic-gate if (status != RDMA_SUCCESS) { 9517387SRobert.Gordon@Sun.COM (void) rdma_clnt_postrecv_remove(conn, p->cku_xid); 9520Sstevel@tonic-gate rdma_buf_free(conn, &clmsg); 9530Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTSEND; 9540Sstevel@tonic-gate p->cku_err.re_errno = EIO; 9550Sstevel@tonic-gate goto done; 9560Sstevel@tonic-gate } 9570Sstevel@tonic-gate } 9580Sstevel@tonic-gate 9590Sstevel@tonic-gate /* 9607387SRobert.Gordon@Sun.COM * Send the RDMA Header and RPC call message to the server 9610Sstevel@tonic-gate */ 9627387SRobert.Gordon@Sun.COM status = RDMA_SEND(conn, cl_sendlist, p->cku_xid); 9630Sstevel@tonic-gate if (status != RDMA_SUCCESS) { 9647387SRobert.Gordon@Sun.COM (void) rdma_clnt_postrecv_remove(conn, p->cku_xid); 9650Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTSEND; 9660Sstevel@tonic-gate p->cku_err.re_errno = EIO; 9670Sstevel@tonic-gate goto done; 9680Sstevel@tonic-gate } 9697387SRobert.Gordon@Sun.COM 9707387SRobert.Gordon@Sun.COM /* 9717387SRobert.Gordon@Sun.COM * RDMA plugin now owns the send msg buffers. 9727387SRobert.Gordon@Sun.COM * Clear them out and don't free them. 9737387SRobert.Gordon@Sun.COM */ 9747387SRobert.Gordon@Sun.COM clmsg.addr = NULL; 9757387SRobert.Gordon@Sun.COM if (rpcmsg.type == SEND_BUFFER) 9767387SRobert.Gordon@Sun.COM rpcmsg.addr = NULL; 9770Sstevel@tonic-gate 9780Sstevel@tonic-gate /* 9790Sstevel@tonic-gate * Recv rpc reply 9800Sstevel@tonic-gate */ 9817387SRobert.Gordon@Sun.COM status = RDMA_RECV(conn, &cl_recvlist, p->cku_xid); 9820Sstevel@tonic-gate 9830Sstevel@tonic-gate /* 9840Sstevel@tonic-gate * Now check recv status 9850Sstevel@tonic-gate */ 9860Sstevel@tonic-gate if (status != 0) { 9870Sstevel@tonic-gate if (status == RDMA_INTR) { 9880Sstevel@tonic-gate p->cku_err.re_status = RPC_INTR; 9890Sstevel@tonic-gate p->cku_err.re_errno = EINTR; 9900Sstevel@tonic-gate RCSTAT_INCR(rcintrs); 9910Sstevel@tonic-gate } else if (status == RPC_TIMEDOUT) { 9920Sstevel@tonic-gate p->cku_err.re_status = RPC_TIMEDOUT; 9930Sstevel@tonic-gate p->cku_err.re_errno = ETIMEDOUT; 9940Sstevel@tonic-gate RCSTAT_INCR(rctimeouts); 9950Sstevel@tonic-gate } else { 9960Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTRECV; 9970Sstevel@tonic-gate p->cku_err.re_errno = EIO; 9980Sstevel@tonic-gate } 9990Sstevel@tonic-gate goto done; 10000Sstevel@tonic-gate } 10017387SRobert.Gordon@Sun.COM 10020Sstevel@tonic-gate /* 10030Sstevel@tonic-gate * Process the reply message. 10040Sstevel@tonic-gate * 10050Sstevel@tonic-gate * First the chunk list (if any) 10060Sstevel@tonic-gate */ 10077387SRobert.Gordon@Sun.COM rdmahdr_i_xdrs = &(p->cku_inxdr); 10087387SRobert.Gordon@Sun.COM xdrmem_create(rdmahdr_i_xdrs, 10097387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)cl_recvlist->w.c_saddr3, 10107387SRobert.Gordon@Sun.COM cl_recvlist->c_len, XDR_DECODE); 10117387SRobert.Gordon@Sun.COM 10120Sstevel@tonic-gate /* 10130Sstevel@tonic-gate * Treat xid as opaque (xid is the first entity 10140Sstevel@tonic-gate * in the rpc rdma message). 10157387SRobert.Gordon@Sun.COM * Skip xid and set the xdr position accordingly. 10160Sstevel@tonic-gate */ 10177387SRobert.Gordon@Sun.COM XDR_SETPOS(rdmahdr_i_xdrs, sizeof (uint32_t)); 10187387SRobert.Gordon@Sun.COM (void) xdr_u_int(rdmahdr_i_xdrs, &vers); 10197387SRobert.Gordon@Sun.COM (void) xdr_u_int(rdmahdr_i_xdrs, &rdma_credit); 10207387SRobert.Gordon@Sun.COM (void) xdr_u_int(rdmahdr_i_xdrs, &op); 10217387SRobert.Gordon@Sun.COM (void) xdr_do_clist(rdmahdr_i_xdrs, &cl); 10227387SRobert.Gordon@Sun.COM 10237387SRobert.Gordon@Sun.COM clnt_update_credit(conn, rdma_credit); 10247387SRobert.Gordon@Sun.COM 10257387SRobert.Gordon@Sun.COM wlist_exists_reply = FALSE; 10267387SRobert.Gordon@Sun.COM if (! xdr_decode_wlist(rdmahdr_i_xdrs, &cl_rpcreply_wlist, 10277387SRobert.Gordon@Sun.COM &wlist_exists_reply)) { 10287387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__callit__wlist_decode); 10297387SRobert.Gordon@Sun.COM p->cku_err.re_status = RPC_CANTDECODERES; 10307387SRobert.Gordon@Sun.COM p->cku_err.re_errno = EIO; 10317387SRobert.Gordon@Sun.COM goto done; 10327387SRobert.Gordon@Sun.COM } 10330Sstevel@tonic-gate 10340Sstevel@tonic-gate /* 10357387SRobert.Gordon@Sun.COM * The server shouldn't have sent a RDMA_SEND that 10367387SRobert.Gordon@Sun.COM * the client needs to RDMA_WRITE a reply back to 10377387SRobert.Gordon@Sun.COM * the server. So silently ignoring what the 10387387SRobert.Gordon@Sun.COM * server returns in the rdma_reply section of the 10397387SRobert.Gordon@Sun.COM * header. 10400Sstevel@tonic-gate */ 10417387SRobert.Gordon@Sun.COM (void) xdr_decode_reply_wchunk(rdmahdr_i_xdrs, &cl_rdma_reply); 10427387SRobert.Gordon@Sun.COM off = xdr_getpos(rdmahdr_i_xdrs); 10430Sstevel@tonic-gate 10447387SRobert.Gordon@Sun.COM clnt_decode_long_reply(conn, cl_long_reply, 10457387SRobert.Gordon@Sun.COM cl_rdma_reply, &replyxdr, &reply_xdrp, 10467387SRobert.Gordon@Sun.COM cl, cl_recvlist, op, off); 10470Sstevel@tonic-gate 10487387SRobert.Gordon@Sun.COM if (reply_xdrp == NULL) 10497387SRobert.Gordon@Sun.COM goto done; 10500Sstevel@tonic-gate 10517387SRobert.Gordon@Sun.COM if (wlist_exists_reply) { 10527387SRobert.Gordon@Sun.COM XDR_CONTROL(reply_xdrp, XDR_RDMA_SET_WLIST, cl_rpcreply_wlist); 10530Sstevel@tonic-gate } 10540Sstevel@tonic-gate 10550Sstevel@tonic-gate reply_msg.rm_direction = REPLY; 10560Sstevel@tonic-gate reply_msg.rm_reply.rp_stat = MSG_ACCEPTED; 10570Sstevel@tonic-gate reply_msg.acpted_rply.ar_stat = SUCCESS; 10580Sstevel@tonic-gate reply_msg.acpted_rply.ar_verf = _null_auth; 10597387SRobert.Gordon@Sun.COM 10600Sstevel@tonic-gate /* 10610Sstevel@tonic-gate * xdr_results will be done in AUTH_UNWRAP. 10620Sstevel@tonic-gate */ 10630Sstevel@tonic-gate reply_msg.acpted_rply.ar_results.where = NULL; 10640Sstevel@tonic-gate reply_msg.acpted_rply.ar_results.proc = xdr_void; 10650Sstevel@tonic-gate 10660Sstevel@tonic-gate /* 10670Sstevel@tonic-gate * Decode and validate the response. 10680Sstevel@tonic-gate */ 10697387SRobert.Gordon@Sun.COM if (xdr_replymsg(reply_xdrp, &reply_msg)) { 10700Sstevel@tonic-gate enum clnt_stat re_status; 10710Sstevel@tonic-gate 10720Sstevel@tonic-gate _seterr_reply(&reply_msg, &(p->cku_err)); 10730Sstevel@tonic-gate 10740Sstevel@tonic-gate re_status = p->cku_err.re_status; 10750Sstevel@tonic-gate if (re_status == RPC_SUCCESS) { 10760Sstevel@tonic-gate /* 10770Sstevel@tonic-gate * Reply is good, check auth. 10780Sstevel@tonic-gate */ 10790Sstevel@tonic-gate if (!AUTH_VALIDATE(h->cl_auth, 10800Sstevel@tonic-gate &reply_msg.acpted_rply.ar_verf)) { 10810Sstevel@tonic-gate p->cku_err.re_status = RPC_AUTHERROR; 10820Sstevel@tonic-gate p->cku_err.re_why = AUTH_INVALIDRESP; 10830Sstevel@tonic-gate RCSTAT_INCR(rcbadverfs); 10847387SRobert.Gordon@Sun.COM DTRACE_PROBE( 10857387SRobert.Gordon@Sun.COM krpc__e__clntrdma__callit__authvalidate); 10867387SRobert.Gordon@Sun.COM } else if (!AUTH_UNWRAP(h->cl_auth, reply_xdrp, 10870Sstevel@tonic-gate xdr_results, resultsp)) { 10880Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTDECODERES; 10890Sstevel@tonic-gate p->cku_err.re_errno = EIO; 10907387SRobert.Gordon@Sun.COM DTRACE_PROBE( 10917387SRobert.Gordon@Sun.COM krpc__e__clntrdma__callit__authunwrap); 10920Sstevel@tonic-gate } 10930Sstevel@tonic-gate } else { 10940Sstevel@tonic-gate /* set errno in case we can't recover */ 10950Sstevel@tonic-gate if (re_status != RPC_VERSMISMATCH && 10960Sstevel@tonic-gate re_status != RPC_AUTHERROR && 10970Sstevel@tonic-gate re_status != RPC_PROGVERSMISMATCH) 10980Sstevel@tonic-gate p->cku_err.re_errno = EIO; 10990Sstevel@tonic-gate 11000Sstevel@tonic-gate if (re_status == RPC_AUTHERROR) { 11017387SRobert.Gordon@Sun.COM if ((refresh_attempt > 0) && 11027387SRobert.Gordon@Sun.COM AUTH_REFRESH(h->cl_auth, &reply_msg, 11037387SRobert.Gordon@Sun.COM p->cku_cred)) { 11047387SRobert.Gordon@Sun.COM refresh_attempt--; 11057387SRobert.Gordon@Sun.COM try_call_again = 1; 11067387SRobert.Gordon@Sun.COM goto done; 11077387SRobert.Gordon@Sun.COM } 11087387SRobert.Gordon@Sun.COM 11097387SRobert.Gordon@Sun.COM try_call_again = 0; 11107387SRobert.Gordon@Sun.COM 11117387SRobert.Gordon@Sun.COM /* 11127387SRobert.Gordon@Sun.COM * We have used the client handle to 11137387SRobert.Gordon@Sun.COM * do an AUTH_REFRESH and the RPC status may 11147387SRobert.Gordon@Sun.COM * be set to RPC_SUCCESS; Let's make sure to 11157387SRobert.Gordon@Sun.COM * set it to RPC_AUTHERROR. 11167387SRobert.Gordon@Sun.COM */ 11177387SRobert.Gordon@Sun.COM p->cku_err.re_status = RPC_AUTHERROR; 11187387SRobert.Gordon@Sun.COM 11190Sstevel@tonic-gate /* 11200Sstevel@tonic-gate * Map recoverable and unrecoverable 11210Sstevel@tonic-gate * authentication errors to appropriate 11220Sstevel@tonic-gate * errno 11230Sstevel@tonic-gate */ 11240Sstevel@tonic-gate switch (p->cku_err.re_why) { 11250Sstevel@tonic-gate case AUTH_BADCRED: 11260Sstevel@tonic-gate case AUTH_BADVERF: 11270Sstevel@tonic-gate case AUTH_INVALIDRESP: 11280Sstevel@tonic-gate case AUTH_TOOWEAK: 11290Sstevel@tonic-gate case AUTH_FAILED: 11300Sstevel@tonic-gate case RPCSEC_GSS_NOCRED: 11310Sstevel@tonic-gate case RPCSEC_GSS_FAILED: 11320Sstevel@tonic-gate p->cku_err.re_errno = EACCES; 11330Sstevel@tonic-gate break; 11340Sstevel@tonic-gate case AUTH_REJECTEDCRED: 11350Sstevel@tonic-gate case AUTH_REJECTEDVERF: 11360Sstevel@tonic-gate default: 11370Sstevel@tonic-gate p->cku_err.re_errno = EIO; 11380Sstevel@tonic-gate break; 11390Sstevel@tonic-gate } 11400Sstevel@tonic-gate } 11417387SRobert.Gordon@Sun.COM DTRACE_PROBE1(krpc__e__clntrdma__callit__rpcfailed, 11427387SRobert.Gordon@Sun.COM int, p->cku_err.re_why); 11430Sstevel@tonic-gate } 11440Sstevel@tonic-gate } else { 11450Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTDECODERES; 11460Sstevel@tonic-gate p->cku_err.re_errno = EIO; 11477387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__callit__replymsg); 11480Sstevel@tonic-gate } 11490Sstevel@tonic-gate 11507387SRobert.Gordon@Sun.COM done: 11517387SRobert.Gordon@Sun.COM clnt_return_credit(conn); 11527387SRobert.Gordon@Sun.COM 11537387SRobert.Gordon@Sun.COM if (cl_sendlist != NULL) 11547387SRobert.Gordon@Sun.COM clist_free(cl_sendlist); 11557387SRobert.Gordon@Sun.COM 11560Sstevel@tonic-gate /* 11570Sstevel@tonic-gate * If rpc reply is in a chunk, free it now. 11580Sstevel@tonic-gate */ 11597387SRobert.Gordon@Sun.COM if (cl_long_reply) { 11609348SSiddheshwar.Mahesh@Sun.COM (void) clist_deregister(conn, cl_long_reply); 11617387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &cl_long_reply->rb_longbuf); 11627387SRobert.Gordon@Sun.COM clist_free(cl_long_reply); 11637387SRobert.Gordon@Sun.COM } 11640Sstevel@tonic-gate 11657387SRobert.Gordon@Sun.COM if (call_xdrp) 11667387SRobert.Gordon@Sun.COM XDR_DESTROY(call_xdrp); 11670Sstevel@tonic-gate 11689348SSiddheshwar.Mahesh@Sun.COM if (rndup.rb_private) { 11699348SSiddheshwar.Mahesh@Sun.COM rdma_buf_free(conn, &rndup); 11709348SSiddheshwar.Mahesh@Sun.COM } 11719348SSiddheshwar.Mahesh@Sun.COM 11727387SRobert.Gordon@Sun.COM if (reply_xdrp) { 11737387SRobert.Gordon@Sun.COM (void) xdr_rpc_free_verifier(reply_xdrp, &reply_msg); 11747387SRobert.Gordon@Sun.COM XDR_DESTROY(reply_xdrp); 11750Sstevel@tonic-gate } 11760Sstevel@tonic-gate 11777387SRobert.Gordon@Sun.COM if (cl_rdma_reply) { 11787387SRobert.Gordon@Sun.COM clist_free(cl_rdma_reply); 11790Sstevel@tonic-gate } 11800Sstevel@tonic-gate 11817387SRobert.Gordon@Sun.COM if (cl_recvlist) { 11827387SRobert.Gordon@Sun.COM rdma_buf_t recvmsg = {0}; 11837387SRobert.Gordon@Sun.COM recvmsg.addr = (caddr_t)(uintptr_t)cl_recvlist->w.c_saddr3; 11840Sstevel@tonic-gate recvmsg.type = RECV_BUFFER; 11850Sstevel@tonic-gate RDMA_BUF_FREE(conn, &recvmsg); 11867387SRobert.Gordon@Sun.COM clist_free(cl_recvlist); 11870Sstevel@tonic-gate } 11887387SRobert.Gordon@Sun.COM 11890Sstevel@tonic-gate RDMA_REL_CONN(conn); 11907387SRobert.Gordon@Sun.COM 11917387SRobert.Gordon@Sun.COM if (try_call_again) 11927387SRobert.Gordon@Sun.COM goto call_again; 11937387SRobert.Gordon@Sun.COM 11940Sstevel@tonic-gate if (p->cku_err.re_status != RPC_SUCCESS) { 11950Sstevel@tonic-gate RCSTAT_INCR(rcbadcalls); 11960Sstevel@tonic-gate } 11970Sstevel@tonic-gate return (p->cku_err.re_status); 11980Sstevel@tonic-gate } 11990Sstevel@tonic-gate 12007387SRobert.Gordon@Sun.COM 12017387SRobert.Gordon@Sun.COM static void 12027387SRobert.Gordon@Sun.COM clnt_decode_long_reply(CONN *conn, 12037387SRobert.Gordon@Sun.COM struct clist *cl_long_reply, 12047387SRobert.Gordon@Sun.COM struct clist *cl_rdma_reply, XDR *xdrs, 12057387SRobert.Gordon@Sun.COM XDR **rxdrp, struct clist *cl, 12067387SRobert.Gordon@Sun.COM struct clist *cl_recvlist, 12077387SRobert.Gordon@Sun.COM uint_t op, uint_t off) 12087387SRobert.Gordon@Sun.COM { 12097387SRobert.Gordon@Sun.COM if (op != RDMA_NOMSG) { 12107387SRobert.Gordon@Sun.COM DTRACE_PROBE1(krpc__i__longrepl__rdmamsg__len, 12117387SRobert.Gordon@Sun.COM int, cl_recvlist->c_len - off); 12127387SRobert.Gordon@Sun.COM xdrrdma_create(xdrs, 12137387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)(cl_recvlist->w.c_saddr3 + off), 12147387SRobert.Gordon@Sun.COM cl_recvlist->c_len - off, 0, cl, XDR_DECODE, conn); 12157387SRobert.Gordon@Sun.COM *rxdrp = xdrs; 12167387SRobert.Gordon@Sun.COM return; 12177387SRobert.Gordon@Sun.COM } 12187387SRobert.Gordon@Sun.COM 12197387SRobert.Gordon@Sun.COM /* op must be RDMA_NOMSG */ 12207387SRobert.Gordon@Sun.COM if (cl) { 12217387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__declongreply__serverreadlist); 12227387SRobert.Gordon@Sun.COM return; 12237387SRobert.Gordon@Sun.COM } 12247387SRobert.Gordon@Sun.COM 12257387SRobert.Gordon@Sun.COM if (cl_long_reply->u.c_daddr) { 12267387SRobert.Gordon@Sun.COM DTRACE_PROBE1(krpc__i__longrepl__rdmanomsg__len, 12277387SRobert.Gordon@Sun.COM int, cl_rdma_reply->c_len); 12287387SRobert.Gordon@Sun.COM 12297387SRobert.Gordon@Sun.COM xdrrdma_create(xdrs, (caddr_t)cl_long_reply->u.c_daddr3, 12307387SRobert.Gordon@Sun.COM cl_rdma_reply->c_len, 0, NULL, XDR_DECODE, conn); 12317387SRobert.Gordon@Sun.COM 12327387SRobert.Gordon@Sun.COM *rxdrp = xdrs; 12337387SRobert.Gordon@Sun.COM } 12347387SRobert.Gordon@Sun.COM } 12357387SRobert.Gordon@Sun.COM 12367387SRobert.Gordon@Sun.COM static void 12377387SRobert.Gordon@Sun.COM clnt_return_credit(CONN *conn) 12387387SRobert.Gordon@Sun.COM { 12397387SRobert.Gordon@Sun.COM rdma_clnt_cred_ctrl_t *cc_info = &conn->rdma_conn_cred_ctrl_u.c_clnt_cc; 12407387SRobert.Gordon@Sun.COM 12417387SRobert.Gordon@Sun.COM mutex_enter(&conn->c_lock); 12427387SRobert.Gordon@Sun.COM cc_info->clnt_cc_in_flight_ops--; 12437387SRobert.Gordon@Sun.COM cv_signal(&cc_info->clnt_cc_cv); 12447387SRobert.Gordon@Sun.COM mutex_exit(&conn->c_lock); 12457387SRobert.Gordon@Sun.COM } 12467387SRobert.Gordon@Sun.COM 12477387SRobert.Gordon@Sun.COM static void 12487387SRobert.Gordon@Sun.COM clnt_update_credit(CONN *conn, uint32_t rdma_credit) 12497387SRobert.Gordon@Sun.COM { 12507387SRobert.Gordon@Sun.COM rdma_clnt_cred_ctrl_t *cc_info = &conn->rdma_conn_cred_ctrl_u.c_clnt_cc; 12517387SRobert.Gordon@Sun.COM 12527387SRobert.Gordon@Sun.COM /* 12537387SRobert.Gordon@Sun.COM * If the granted has not altered, avoid taking the 12547387SRobert.Gordon@Sun.COM * mutex, to essentially do nothing.. 12557387SRobert.Gordon@Sun.COM */ 12567387SRobert.Gordon@Sun.COM if (cc_info->clnt_cc_granted_ops == rdma_credit) 12577387SRobert.Gordon@Sun.COM return; 12587387SRobert.Gordon@Sun.COM /* 12597387SRobert.Gordon@Sun.COM * Get the granted number of buffers for credit control. 12607387SRobert.Gordon@Sun.COM */ 12617387SRobert.Gordon@Sun.COM mutex_enter(&conn->c_lock); 12627387SRobert.Gordon@Sun.COM cc_info->clnt_cc_granted_ops = rdma_credit; 12637387SRobert.Gordon@Sun.COM mutex_exit(&conn->c_lock); 12647387SRobert.Gordon@Sun.COM } 12657387SRobert.Gordon@Sun.COM 12667387SRobert.Gordon@Sun.COM static void 12677387SRobert.Gordon@Sun.COM clnt_check_credit(CONN *conn) 12687387SRobert.Gordon@Sun.COM { 12697387SRobert.Gordon@Sun.COM rdma_clnt_cred_ctrl_t *cc_info = &conn->rdma_conn_cred_ctrl_u.c_clnt_cc; 12707387SRobert.Gordon@Sun.COM 12717387SRobert.Gordon@Sun.COM /* 12727387SRobert.Gordon@Sun.COM * Make sure we are not going over our allowed buffer use 12737387SRobert.Gordon@Sun.COM * (and make sure we have gotten a granted value before). 12747387SRobert.Gordon@Sun.COM */ 12757387SRobert.Gordon@Sun.COM mutex_enter(&conn->c_lock); 12767387SRobert.Gordon@Sun.COM while (cc_info->clnt_cc_in_flight_ops >= cc_info->clnt_cc_granted_ops && 12777387SRobert.Gordon@Sun.COM cc_info->clnt_cc_granted_ops != 0) { 12787387SRobert.Gordon@Sun.COM /* 12797387SRobert.Gordon@Sun.COM * Client has maxed out its granted buffers due to 12807387SRobert.Gordon@Sun.COM * credit control. Current handling is to block and wait. 12817387SRobert.Gordon@Sun.COM */ 12827387SRobert.Gordon@Sun.COM cv_wait(&cc_info->clnt_cc_cv, &conn->c_lock); 12837387SRobert.Gordon@Sun.COM } 12847387SRobert.Gordon@Sun.COM cc_info->clnt_cc_in_flight_ops++; 12857387SRobert.Gordon@Sun.COM mutex_exit(&conn->c_lock); 12867387SRobert.Gordon@Sun.COM } 12877387SRobert.Gordon@Sun.COM 12880Sstevel@tonic-gate /* ARGSUSED */ 12890Sstevel@tonic-gate static void 12900Sstevel@tonic-gate clnt_rdma_kabort(CLIENT *h) 12910Sstevel@tonic-gate { 12920Sstevel@tonic-gate } 12930Sstevel@tonic-gate 12940Sstevel@tonic-gate static void 12950Sstevel@tonic-gate clnt_rdma_kerror(CLIENT *h, struct rpc_err *err) 12960Sstevel@tonic-gate { 12970Sstevel@tonic-gate struct cku_private *p = htop(h); 12980Sstevel@tonic-gate *err = p->cku_err; 12990Sstevel@tonic-gate } 13000Sstevel@tonic-gate 13010Sstevel@tonic-gate static bool_t 13020Sstevel@tonic-gate clnt_rdma_kfreeres(CLIENT *h, xdrproc_t xdr_res, caddr_t res_ptr) 13030Sstevel@tonic-gate { 13040Sstevel@tonic-gate struct cku_private *p = htop(h); 13050Sstevel@tonic-gate XDR *xdrs; 13060Sstevel@tonic-gate 13070Sstevel@tonic-gate xdrs = &(p->cku_outxdr); 13080Sstevel@tonic-gate xdrs->x_op = XDR_FREE; 13090Sstevel@tonic-gate return ((*xdr_res)(xdrs, res_ptr)); 13100Sstevel@tonic-gate } 13110Sstevel@tonic-gate 13120Sstevel@tonic-gate /* ARGSUSED */ 13130Sstevel@tonic-gate static bool_t 13140Sstevel@tonic-gate clnt_rdma_kcontrol(CLIENT *h, int cmd, char *arg) 13150Sstevel@tonic-gate { 13160Sstevel@tonic-gate return (TRUE); 13170Sstevel@tonic-gate } 13180Sstevel@tonic-gate 13190Sstevel@tonic-gate /* ARGSUSED */ 13200Sstevel@tonic-gate static int 13210Sstevel@tonic-gate clnt_rdma_ksettimers(CLIENT *h, struct rpc_timers *t, struct rpc_timers *all, 13220Sstevel@tonic-gate int minimum, void(*feedback)(int, int, caddr_t), caddr_t arg, 13230Sstevel@tonic-gate uint32_t xid) 13240Sstevel@tonic-gate { 13250Sstevel@tonic-gate RCSTAT_INCR(rctimers); 13260Sstevel@tonic-gate return (0); 13270Sstevel@tonic-gate } 13280Sstevel@tonic-gate 13290Sstevel@tonic-gate int 13300Sstevel@tonic-gate rdma_reachable(int addr_type, struct netbuf *addr, struct knetconfig **knconf) 13310Sstevel@tonic-gate { 13320Sstevel@tonic-gate rdma_registry_t *rp; 13330Sstevel@tonic-gate void *handle = NULL; 13340Sstevel@tonic-gate struct knetconfig *knc; 13350Sstevel@tonic-gate char *pf, *p; 13360Sstevel@tonic-gate rdma_stat status; 13370Sstevel@tonic-gate int error = 0; 13380Sstevel@tonic-gate 13390Sstevel@tonic-gate if (!INGLOBALZONE(curproc)) 13400Sstevel@tonic-gate return (-1); 13417387SRobert.Gordon@Sun.COM 13420Sstevel@tonic-gate /* 13430Sstevel@tonic-gate * modload the RDMA plugins if not already done. 13440Sstevel@tonic-gate */ 13450Sstevel@tonic-gate if (!rdma_modloaded) { 13460Sstevel@tonic-gate mutex_enter(&rdma_modload_lock); 13470Sstevel@tonic-gate if (!rdma_modloaded) { 13480Sstevel@tonic-gate error = rdma_modload(); 13490Sstevel@tonic-gate } 13500Sstevel@tonic-gate mutex_exit(&rdma_modload_lock); 13510Sstevel@tonic-gate if (error) 13520Sstevel@tonic-gate return (-1); 13530Sstevel@tonic-gate } 13540Sstevel@tonic-gate 13550Sstevel@tonic-gate if (!rdma_dev_available) 13560Sstevel@tonic-gate return (-1); 13570Sstevel@tonic-gate 13580Sstevel@tonic-gate rw_enter(&rdma_lock, RW_READER); 13590Sstevel@tonic-gate rp = rdma_mod_head; 13600Sstevel@tonic-gate while (rp != NULL) { 13618695SRajkumar.Sivaprakasam@Sun.COM if (rp->r_mod_state == RDMA_MOD_INACTIVE) { 13628695SRajkumar.Sivaprakasam@Sun.COM rp = rp->r_next; 13638695SRajkumar.Sivaprakasam@Sun.COM continue; 13648695SRajkumar.Sivaprakasam@Sun.COM } 13650Sstevel@tonic-gate status = RDMA_REACHABLE(rp->r_mod->rdma_ops, addr_type, addr, 13660Sstevel@tonic-gate &handle); 13670Sstevel@tonic-gate if (status == RDMA_SUCCESS) { 13680Sstevel@tonic-gate knc = kmem_zalloc(sizeof (struct knetconfig), 13697387SRobert.Gordon@Sun.COM KM_SLEEP); 13700Sstevel@tonic-gate knc->knc_semantics = NC_TPI_RDMA; 13710Sstevel@tonic-gate pf = kmem_alloc(KNC_STRSIZE, KM_SLEEP); 13720Sstevel@tonic-gate p = kmem_alloc(KNC_STRSIZE, KM_SLEEP); 13730Sstevel@tonic-gate if (addr_type == AF_INET) 13740Sstevel@tonic-gate (void) strncpy(pf, NC_INET, KNC_STRSIZE); 13750Sstevel@tonic-gate else if (addr_type == AF_INET6) 13760Sstevel@tonic-gate (void) strncpy(pf, NC_INET6, KNC_STRSIZE); 13770Sstevel@tonic-gate pf[KNC_STRSIZE - 1] = '\0'; 13780Sstevel@tonic-gate 13790Sstevel@tonic-gate (void) strncpy(p, rp->r_mod->rdma_api, KNC_STRSIZE); 13800Sstevel@tonic-gate p[KNC_STRSIZE - 1] = '\0'; 13810Sstevel@tonic-gate 13820Sstevel@tonic-gate knc->knc_protofmly = pf; 13830Sstevel@tonic-gate knc->knc_proto = p; 13848695SRajkumar.Sivaprakasam@Sun.COM knc->knc_rdev = (dev_t)rp; 13850Sstevel@tonic-gate *knconf = knc; 13860Sstevel@tonic-gate rw_exit(&rdma_lock); 13870Sstevel@tonic-gate return (0); 13880Sstevel@tonic-gate } 13890Sstevel@tonic-gate rp = rp->r_next; 13900Sstevel@tonic-gate } 13910Sstevel@tonic-gate rw_exit(&rdma_lock); 13920Sstevel@tonic-gate return (-1); 13930Sstevel@tonic-gate } 1394