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 5*7387SRobert.Gordon@Sun.COM * Common Development and Distribution License (the "License"). 6*7387SRobert.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 /* 22*7387SRobert.Gordon@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 26*7387SRobert.Gordon@Sun.COM /* 27*7387SRobert.Gordon@Sun.COM * Copyright (c) 2007, The Ohio State University. All rights reserved. 28*7387SRobert.Gordon@Sun.COM * 29*7387SRobert.Gordon@Sun.COM * Portions of this source code is developed by the team members of 30*7387SRobert.Gordon@Sun.COM * The Ohio State University's Network-Based Computing Laboratory (NBCL), 31*7387SRobert.Gordon@Sun.COM * headed by Professor Dhabaleswar K. (DK) Panda. 32*7387SRobert.Gordon@Sun.COM * 33*7387SRobert.Gordon@Sun.COM * Acknowledgements to contributions from developors: 34*7387SRobert.Gordon@Sun.COM * Ranjit Noronha: noronha@cse.ohio-state.edu 35*7387SRobert.Gordon@Sun.COM * Lei Chai : chail@cse.ohio-state.edu 36*7387SRobert.Gordon@Sun.COM * Weikuan Yu : yuw@cse.ohio-state.edu 37*7387SRobert.Gordon@Sun.COM * 38*7387SRobert.Gordon@Sun.COM */ 390Sstevel@tonic-gate 400Sstevel@tonic-gate /* 410Sstevel@tonic-gate * xdr_rdma.c, XDR implementation using RDMA to move large chunks 420Sstevel@tonic-gate */ 430Sstevel@tonic-gate 440Sstevel@tonic-gate #include <sys/param.h> 450Sstevel@tonic-gate #include <sys/types.h> 460Sstevel@tonic-gate #include <sys/systm.h> 470Sstevel@tonic-gate #include <sys/kmem.h> 48*7387SRobert.Gordon@Sun.COM #include <sys/sdt.h> 49*7387SRobert.Gordon@Sun.COM #include <sys/debug.h> 500Sstevel@tonic-gate 510Sstevel@tonic-gate #include <rpc/types.h> 520Sstevel@tonic-gate #include <rpc/xdr.h> 530Sstevel@tonic-gate #include <sys/cmn_err.h> 540Sstevel@tonic-gate #include <rpc/rpc_sztypes.h> 550Sstevel@tonic-gate #include <rpc/rpc_rdma.h> 56*7387SRobert.Gordon@Sun.COM #include <sys/sysmacros.h> 570Sstevel@tonic-gate 58*7387SRobert.Gordon@Sun.COM static bool_t xdrrdma_getint32(XDR *, int32_t *); 59*7387SRobert.Gordon@Sun.COM static bool_t xdrrdma_putint32(XDR *, int32_t *); 60*7387SRobert.Gordon@Sun.COM static bool_t xdrrdma_getbytes(XDR *, caddr_t, int); 61*7387SRobert.Gordon@Sun.COM static bool_t xdrrdma_putbytes(XDR *, caddr_t, int); 62*7387SRobert.Gordon@Sun.COM uint_t xdrrdma_getpos(XDR *); 63*7387SRobert.Gordon@Sun.COM bool_t xdrrdma_setpos(XDR *, uint_t); 64*7387SRobert.Gordon@Sun.COM static rpc_inline_t *xdrrdma_inline(XDR *, int); 65*7387SRobert.Gordon@Sun.COM void xdrrdma_destroy(XDR *); 66*7387SRobert.Gordon@Sun.COM static bool_t xdrrdma_control(XDR *, int, void *); 67*7387SRobert.Gordon@Sun.COM 68*7387SRobert.Gordon@Sun.COM struct xdr_ops xdrrdmablk_ops = { 69*7387SRobert.Gordon@Sun.COM xdrrdma_getbytes, 70*7387SRobert.Gordon@Sun.COM xdrrdma_putbytes, 71*7387SRobert.Gordon@Sun.COM xdrrdma_getpos, 72*7387SRobert.Gordon@Sun.COM xdrrdma_setpos, 73*7387SRobert.Gordon@Sun.COM xdrrdma_inline, 74*7387SRobert.Gordon@Sun.COM xdrrdma_destroy, 75*7387SRobert.Gordon@Sun.COM xdrrdma_control, 76*7387SRobert.Gordon@Sun.COM xdrrdma_getint32, 77*7387SRobert.Gordon@Sun.COM xdrrdma_putint32 78*7387SRobert.Gordon@Sun.COM }; 79*7387SRobert.Gordon@Sun.COM 80*7387SRobert.Gordon@Sun.COM struct xdr_ops xdrrdma_ops = { 81*7387SRobert.Gordon@Sun.COM xdrrdma_getbytes, 82*7387SRobert.Gordon@Sun.COM xdrrdma_putbytes, 83*7387SRobert.Gordon@Sun.COM xdrrdma_getpos, 84*7387SRobert.Gordon@Sun.COM xdrrdma_setpos, 85*7387SRobert.Gordon@Sun.COM xdrrdma_inline, 86*7387SRobert.Gordon@Sun.COM xdrrdma_destroy, 87*7387SRobert.Gordon@Sun.COM xdrrdma_control, 88*7387SRobert.Gordon@Sun.COM xdrrdma_getint32, 89*7387SRobert.Gordon@Sun.COM xdrrdma_putint32 90*7387SRobert.Gordon@Sun.COM }; 910Sstevel@tonic-gate 920Sstevel@tonic-gate /* 93*7387SRobert.Gordon@Sun.COM * A chunk list entry identifies a chunk of opaque data to be moved 94*7387SRobert.Gordon@Sun.COM * separately from the rest of the RPC message. xp_min_chunk = 0, is a 95*7387SRobert.Gordon@Sun.COM * special case for ENCODING, which means do not chunk the incoming stream of 96*7387SRobert.Gordon@Sun.COM * data. 970Sstevel@tonic-gate */ 980Sstevel@tonic-gate 99*7387SRobert.Gordon@Sun.COM typedef struct { 1000Sstevel@tonic-gate caddr_t xp_offp; 1010Sstevel@tonic-gate int xp_min_chunk; 1020Sstevel@tonic-gate uint_t xp_flags; /* Controls setting for rdma xdr */ 103*7387SRobert.Gordon@Sun.COM int xp_buf_size; /* size of xdr buffer */ 104*7387SRobert.Gordon@Sun.COM struct clist *xp_rcl; /* head of chunk list */ 105*7387SRobert.Gordon@Sun.COM struct clist **xp_rcl_next; /* location to place/find next chunk */ 106*7387SRobert.Gordon@Sun.COM struct clist *xp_wcl; /* head of write chunk list */ 1070Sstevel@tonic-gate CONN *xp_conn; /* connection for chunk data xfer */ 108*7387SRobert.Gordon@Sun.COM uint_t xp_reply_chunk_len; 109*7387SRobert.Gordon@Sun.COM /* used to track length for security modes: integrity/privacy */ 110*7387SRobert.Gordon@Sun.COM uint_t xp_reply_chunk_len_alt; 111*7387SRobert.Gordon@Sun.COM } xrdma_private_t; 112*7387SRobert.Gordon@Sun.COM 113*7387SRobert.Gordon@Sun.COM extern kmem_cache_t *clist_cache; 114*7387SRobert.Gordon@Sun.COM 115*7387SRobert.Gordon@Sun.COM bool_t 116*7387SRobert.Gordon@Sun.COM xdrrdma_getrdmablk(XDR *xdrs, struct clist **rlist, uint_t *sizep, 117*7387SRobert.Gordon@Sun.COM CONN **conn, const uint_t maxsize) 118*7387SRobert.Gordon@Sun.COM { 119*7387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 120*7387SRobert.Gordon@Sun.COM struct clist *cle = *(xdrp->xp_rcl_next); 121*7387SRobert.Gordon@Sun.COM struct clist *cls = *(xdrp->xp_rcl_next); 122*7387SRobert.Gordon@Sun.COM struct clist *rdclist = NULL, *prev = NULL; 123*7387SRobert.Gordon@Sun.COM bool_t retval = TRUE; 124*7387SRobert.Gordon@Sun.COM uint32_t cur_offset = 0; 125*7387SRobert.Gordon@Sun.COM uint32_t total_segments = 0; 126*7387SRobert.Gordon@Sun.COM uint32_t actual_segments = 0; 127*7387SRobert.Gordon@Sun.COM uint32_t alen; 128*7387SRobert.Gordon@Sun.COM uint_t total_len; 129*7387SRobert.Gordon@Sun.COM 130*7387SRobert.Gordon@Sun.COM ASSERT(xdrs->x_op != XDR_FREE); 131*7387SRobert.Gordon@Sun.COM 132*7387SRobert.Gordon@Sun.COM /* 133*7387SRobert.Gordon@Sun.COM * first deal with the length since xdr bytes are counted 134*7387SRobert.Gordon@Sun.COM */ 135*7387SRobert.Gordon@Sun.COM if (!xdr_u_int(xdrs, sizep)) { 136*7387SRobert.Gordon@Sun.COM DTRACE_PROBE(xdr__e__getrdmablk_sizep_fail); 137*7387SRobert.Gordon@Sun.COM return (FALSE); 138*7387SRobert.Gordon@Sun.COM } 139*7387SRobert.Gordon@Sun.COM total_len = *sizep; 140*7387SRobert.Gordon@Sun.COM if (total_len > maxsize) { 141*7387SRobert.Gordon@Sun.COM DTRACE_PROBE2(xdr__e__getrdmablk_bad_size, 142*7387SRobert.Gordon@Sun.COM int, total_len, int, maxsize); 143*7387SRobert.Gordon@Sun.COM return (FALSE); 144*7387SRobert.Gordon@Sun.COM } 145*7387SRobert.Gordon@Sun.COM (*conn) = xdrp->xp_conn; 146*7387SRobert.Gordon@Sun.COM 147*7387SRobert.Gordon@Sun.COM /* 148*7387SRobert.Gordon@Sun.COM * if no data we are done 149*7387SRobert.Gordon@Sun.COM */ 150*7387SRobert.Gordon@Sun.COM if (total_len == 0) 151*7387SRobert.Gordon@Sun.COM return (TRUE); 152*7387SRobert.Gordon@Sun.COM 153*7387SRobert.Gordon@Sun.COM while (cle) { 154*7387SRobert.Gordon@Sun.COM total_segments++; 155*7387SRobert.Gordon@Sun.COM cle = cle->c_next; 156*7387SRobert.Gordon@Sun.COM } 157*7387SRobert.Gordon@Sun.COM 158*7387SRobert.Gordon@Sun.COM cle = *(xdrp->xp_rcl_next); 159*7387SRobert.Gordon@Sun.COM 160*7387SRobert.Gordon@Sun.COM /* 161*7387SRobert.Gordon@Sun.COM * If there was a chunk at the current offset, then setup a read 162*7387SRobert.Gordon@Sun.COM * chunk list which records the destination address and length 163*7387SRobert.Gordon@Sun.COM * and will RDMA READ the data in later. 164*7387SRobert.Gordon@Sun.COM */ 165*7387SRobert.Gordon@Sun.COM if (cle == NULL) 166*7387SRobert.Gordon@Sun.COM return (FALSE); 1670Sstevel@tonic-gate 168*7387SRobert.Gordon@Sun.COM if (cle->c_xdroff != (xdrp->xp_offp - xdrs->x_base)) 169*7387SRobert.Gordon@Sun.COM return (FALSE); 170*7387SRobert.Gordon@Sun.COM 171*7387SRobert.Gordon@Sun.COM /* 172*7387SRobert.Gordon@Sun.COM * Setup the chunk list with appropriate 173*7387SRobert.Gordon@Sun.COM * address (offset) and length 174*7387SRobert.Gordon@Sun.COM */ 175*7387SRobert.Gordon@Sun.COM for (actual_segments = 0; 176*7387SRobert.Gordon@Sun.COM actual_segments < total_segments; actual_segments++) { 177*7387SRobert.Gordon@Sun.COM if (total_len <= 0) 178*7387SRobert.Gordon@Sun.COM break; 179*7387SRobert.Gordon@Sun.COM cle->u.c_daddr = (uint64) cur_offset; 180*7387SRobert.Gordon@Sun.COM alen = 0; 181*7387SRobert.Gordon@Sun.COM if (cle->c_len > total_len) { 182*7387SRobert.Gordon@Sun.COM alen = cle->c_len; 183*7387SRobert.Gordon@Sun.COM cle->c_len = total_len; 184*7387SRobert.Gordon@Sun.COM } 185*7387SRobert.Gordon@Sun.COM if (!alen) 186*7387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &cle->c_next; 187*7387SRobert.Gordon@Sun.COM 188*7387SRobert.Gordon@Sun.COM cur_offset += cle->c_len; 189*7387SRobert.Gordon@Sun.COM total_len -= cle->c_len; 190*7387SRobert.Gordon@Sun.COM 191*7387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) == 0 && 192*7387SRobert.Gordon@Sun.COM total_len > 0) { 193*7387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__xdrrdma_getblk_chunktooshort); 194*7387SRobert.Gordon@Sun.COM retval = FALSE; 195*7387SRobert.Gordon@Sun.COM } 196*7387SRobert.Gordon@Sun.COM 197*7387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) > 0 && 198*7387SRobert.Gordon@Sun.COM total_len == 0) { 199*7387SRobert.Gordon@Sun.COM DTRACE_PROBE2(krpc__e__xdrrdma_getblk_toobig, 200*7387SRobert.Gordon@Sun.COM int, total_segments, int, actual_segments); 201*7387SRobert.Gordon@Sun.COM } 202*7387SRobert.Gordon@Sun.COM 203*7387SRobert.Gordon@Sun.COM rdclist = clist_alloc(); 204*7387SRobert.Gordon@Sun.COM (*rdclist) = (*cle); 205*7387SRobert.Gordon@Sun.COM if ((*rlist) == NULL) 206*7387SRobert.Gordon@Sun.COM (*rlist) = rdclist; 207*7387SRobert.Gordon@Sun.COM if (prev == NULL) 208*7387SRobert.Gordon@Sun.COM prev = rdclist; 209*7387SRobert.Gordon@Sun.COM else { 210*7387SRobert.Gordon@Sun.COM prev->c_next = rdclist; 211*7387SRobert.Gordon@Sun.COM prev = rdclist; 212*7387SRobert.Gordon@Sun.COM } 213*7387SRobert.Gordon@Sun.COM 214*7387SRobert.Gordon@Sun.COM cle = cle->c_next; 215*7387SRobert.Gordon@Sun.COM } 216*7387SRobert.Gordon@Sun.COM 217*7387SRobert.Gordon@Sun.COM out: 218*7387SRobert.Gordon@Sun.COM if (prev != NULL) 219*7387SRobert.Gordon@Sun.COM prev->c_next = NULL; 220*7387SRobert.Gordon@Sun.COM 221*7387SRobert.Gordon@Sun.COM cle = cls; 222*7387SRobert.Gordon@Sun.COM if (alen) { 223*7387SRobert.Gordon@Sun.COM cle->w.c_saddr = 224*7387SRobert.Gordon@Sun.COM (uint64)(uintptr_t)cle->w.c_saddr + cle->c_len; 225*7387SRobert.Gordon@Sun.COM cle->c_len = alen - cle->c_len; 226*7387SRobert.Gordon@Sun.COM } 227*7387SRobert.Gordon@Sun.COM 228*7387SRobert.Gordon@Sun.COM return (retval); 229*7387SRobert.Gordon@Sun.COM } 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate /* 232*7387SRobert.Gordon@Sun.COM * The procedure xdrrdma_create initializes a stream descriptor for a memory 233*7387SRobert.Gordon@Sun.COM * buffer. 2340Sstevel@tonic-gate */ 2350Sstevel@tonic-gate void 2360Sstevel@tonic-gate xdrrdma_create(XDR *xdrs, caddr_t addr, uint_t size, 237*7387SRobert.Gordon@Sun.COM int min_chunk, struct clist *cl, enum xdr_op op, CONN *conn) 2380Sstevel@tonic-gate { 239*7387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp; 240*7387SRobert.Gordon@Sun.COM struct clist *cle; 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate xdrs->x_op = op; 243*7387SRobert.Gordon@Sun.COM xdrs->x_ops = &xdrrdma_ops; 2440Sstevel@tonic-gate xdrs->x_base = addr; 2450Sstevel@tonic-gate xdrs->x_handy = size; 2460Sstevel@tonic-gate xdrs->x_public = NULL; 2470Sstevel@tonic-gate 248*7387SRobert.Gordon@Sun.COM xdrp = (xrdma_private_t *)kmem_zalloc(sizeof (xrdma_private_t), 249*7387SRobert.Gordon@Sun.COM KM_SLEEP); 2500Sstevel@tonic-gate xdrs->x_private = (caddr_t)xdrp; 2510Sstevel@tonic-gate xdrp->xp_offp = addr; 2520Sstevel@tonic-gate xdrp->xp_min_chunk = min_chunk; 2530Sstevel@tonic-gate xdrp->xp_flags = 0; 2540Sstevel@tonic-gate xdrp->xp_buf_size = size; 255*7387SRobert.Gordon@Sun.COM xdrp->xp_rcl = cl; 256*7387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len = 0; 257*7387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len_alt = 0; 258*7387SRobert.Gordon@Sun.COM 2590Sstevel@tonic-gate if (op == XDR_ENCODE && cl != NULL) { 260*7387SRobert.Gordon@Sun.COM /* Find last element in chunk list and set xp_rcl_next */ 261*7387SRobert.Gordon@Sun.COM for (cle = cl; cle->c_next != NULL; cle = cle->c_next) 262*7387SRobert.Gordon@Sun.COM continue; 263*7387SRobert.Gordon@Sun.COM 264*7387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &(cle->c_next); 265*7387SRobert.Gordon@Sun.COM } else { 266*7387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &(xdrp->xp_rcl); 267*7387SRobert.Gordon@Sun.COM } 268*7387SRobert.Gordon@Sun.COM 269*7387SRobert.Gordon@Sun.COM xdrp->xp_wcl = NULL; 270*7387SRobert.Gordon@Sun.COM 2710Sstevel@tonic-gate xdrp->xp_conn = conn; 272*7387SRobert.Gordon@Sun.COM if (xdrp->xp_min_chunk != 0) 273*7387SRobert.Gordon@Sun.COM xdrp->xp_flags |= XDR_RDMA_CHUNK; 2740Sstevel@tonic-gate } 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate /* ARGSUSED */ 2770Sstevel@tonic-gate void 278*7387SRobert.Gordon@Sun.COM xdrrdma_destroy(XDR * xdrs) 2790Sstevel@tonic-gate { 280*7387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 281*7387SRobert.Gordon@Sun.COM 282*7387SRobert.Gordon@Sun.COM if (xdrp == NULL) 283*7387SRobert.Gordon@Sun.COM return; 284*7387SRobert.Gordon@Sun.COM 285*7387SRobert.Gordon@Sun.COM if (xdrp->xp_wcl) { 286*7387SRobert.Gordon@Sun.COM if (xdrp->xp_flags & XDR_RDMA_WLIST_REG) { 287*7387SRobert.Gordon@Sun.COM (void) clist_deregister(xdrp->xp_conn, 288*7387SRobert.Gordon@Sun.COM xdrp->xp_wcl, CLIST_REG_DST); 289*7387SRobert.Gordon@Sun.COM rdma_buf_free(xdrp->xp_conn, 290*7387SRobert.Gordon@Sun.COM &xdrp->xp_wcl->rb_longbuf); 291*7387SRobert.Gordon@Sun.COM } 292*7387SRobert.Gordon@Sun.COM clist_free(xdrp->xp_wcl); 293*7387SRobert.Gordon@Sun.COM } 294*7387SRobert.Gordon@Sun.COM 295*7387SRobert.Gordon@Sun.COM if (xdrp->xp_rcl) { 296*7387SRobert.Gordon@Sun.COM if (xdrp->xp_flags & XDR_RDMA_RLIST_REG) { 297*7387SRobert.Gordon@Sun.COM (void) clist_deregister(xdrp->xp_conn, 298*7387SRobert.Gordon@Sun.COM xdrp->xp_rcl, CLIST_REG_SOURCE); 299*7387SRobert.Gordon@Sun.COM rdma_buf_free(xdrp->xp_conn, 300*7387SRobert.Gordon@Sun.COM &xdrp->xp_rcl->rb_longbuf); 301*7387SRobert.Gordon@Sun.COM } 302*7387SRobert.Gordon@Sun.COM clist_free(xdrp->xp_rcl); 303*7387SRobert.Gordon@Sun.COM } 304*7387SRobert.Gordon@Sun.COM 305*7387SRobert.Gordon@Sun.COM (void) kmem_free(xdrs->x_private, sizeof (xrdma_private_t)); 306*7387SRobert.Gordon@Sun.COM xdrs->x_private = NULL; 3070Sstevel@tonic-gate } 3080Sstevel@tonic-gate 309*7387SRobert.Gordon@Sun.COM static bool_t 3100Sstevel@tonic-gate xdrrdma_getint32(XDR *xdrs, int32_t *int32p) 3110Sstevel@tonic-gate { 312*7387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate if ((xdrs->x_handy -= (int)sizeof (int32_t)) < 0) 3150Sstevel@tonic-gate return (FALSE); 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate /* LINTED pointer alignment */ 3180Sstevel@tonic-gate *int32p = (int32_t)ntohl((uint32_t)(*((int32_t *)(xdrp->xp_offp)))); 3190Sstevel@tonic-gate xdrp->xp_offp += sizeof (int32_t); 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate return (TRUE); 3220Sstevel@tonic-gate } 3230Sstevel@tonic-gate 324*7387SRobert.Gordon@Sun.COM static bool_t 3250Sstevel@tonic-gate xdrrdma_putint32(XDR *xdrs, int32_t *int32p) 3260Sstevel@tonic-gate { 327*7387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate if ((xdrs->x_handy -= (int)sizeof (int32_t)) < 0) 3300Sstevel@tonic-gate return (FALSE); 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate /* LINTED pointer alignment */ 3330Sstevel@tonic-gate *(int32_t *)xdrp->xp_offp = (int32_t)htonl((uint32_t)(*int32p)); 3340Sstevel@tonic-gate xdrp->xp_offp += sizeof (int32_t); 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate return (TRUE); 3370Sstevel@tonic-gate } 3380Sstevel@tonic-gate 3390Sstevel@tonic-gate /* 340*7387SRobert.Gordon@Sun.COM * DECODE bytes from XDR stream for rdma. 341*7387SRobert.Gordon@Sun.COM * If the XDR stream contains a read chunk list, 342*7387SRobert.Gordon@Sun.COM * it will go through xdrrdma_getrdmablk instead. 3430Sstevel@tonic-gate */ 344*7387SRobert.Gordon@Sun.COM static bool_t 3450Sstevel@tonic-gate xdrrdma_getbytes(XDR *xdrs, caddr_t addr, int len) 3460Sstevel@tonic-gate { 347*7387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 348*7387SRobert.Gordon@Sun.COM struct clist *cle = *(xdrp->xp_rcl_next); 349*7387SRobert.Gordon@Sun.COM struct clist *cls = *(xdrp->xp_rcl_next); 350*7387SRobert.Gordon@Sun.COM struct clist cl; 351*7387SRobert.Gordon@Sun.COM bool_t retval = TRUE; 352*7387SRobert.Gordon@Sun.COM uint32_t total_len = len; 353*7387SRobert.Gordon@Sun.COM uint32_t cur_offset = 0; 354*7387SRobert.Gordon@Sun.COM uint32_t total_segments = 0; 355*7387SRobert.Gordon@Sun.COM uint32_t actual_segments = 0; 356*7387SRobert.Gordon@Sun.COM uint32_t status; 357*7387SRobert.Gordon@Sun.COM uint32_t alen; 3580Sstevel@tonic-gate 359*7387SRobert.Gordon@Sun.COM while (cle) { 360*7387SRobert.Gordon@Sun.COM total_segments++; 361*7387SRobert.Gordon@Sun.COM cle = cle->c_next; 362*7387SRobert.Gordon@Sun.COM } 363*7387SRobert.Gordon@Sun.COM 364*7387SRobert.Gordon@Sun.COM cle = *(xdrp->xp_rcl_next); 3650Sstevel@tonic-gate /* 366*7387SRobert.Gordon@Sun.COM * If there was a chunk at the current offset, then setup a read 367*7387SRobert.Gordon@Sun.COM * chunk list which records the destination address and length 368*7387SRobert.Gordon@Sun.COM * and will RDMA READ the data in later. 3690Sstevel@tonic-gate */ 370*7387SRobert.Gordon@Sun.COM 3710Sstevel@tonic-gate if (cle != NULL && 372*7387SRobert.Gordon@Sun.COM cle->c_xdroff == (xdrp->xp_offp - xdrs->x_base)) { 373*7387SRobert.Gordon@Sun.COM for (actual_segments = 0; 374*7387SRobert.Gordon@Sun.COM actual_segments < total_segments; actual_segments++) { 375*7387SRobert.Gordon@Sun.COM if (total_len <= 0) 376*7387SRobert.Gordon@Sun.COM break; 377*7387SRobert.Gordon@Sun.COM cle->u.c_daddr = (uint64)(uintptr_t)addr + cur_offset; 378*7387SRobert.Gordon@Sun.COM alen = 0; 379*7387SRobert.Gordon@Sun.COM if (cle->c_len > total_len) { 380*7387SRobert.Gordon@Sun.COM alen = cle->c_len; 381*7387SRobert.Gordon@Sun.COM cle->c_len = total_len; 382*7387SRobert.Gordon@Sun.COM } 383*7387SRobert.Gordon@Sun.COM if (!alen) 384*7387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &cle->c_next; 385*7387SRobert.Gordon@Sun.COM 386*7387SRobert.Gordon@Sun.COM cur_offset += cle->c_len; 387*7387SRobert.Gordon@Sun.COM total_len -= cle->c_len; 388*7387SRobert.Gordon@Sun.COM 389*7387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) == 0 && 390*7387SRobert.Gordon@Sun.COM total_len > 0) { 391*7387SRobert.Gordon@Sun.COM DTRACE_PROBE( 392*7387SRobert.Gordon@Sun.COM krpc__e__xdrrdma_getbytes_chunktooshort); 393*7387SRobert.Gordon@Sun.COM retval = FALSE; 394*7387SRobert.Gordon@Sun.COM } 395*7387SRobert.Gordon@Sun.COM 396*7387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) > 0 && 397*7387SRobert.Gordon@Sun.COM total_len == 0) { 398*7387SRobert.Gordon@Sun.COM DTRACE_PROBE2(krpc__e__xdrrdma_getbytes_toobig, 399*7387SRobert.Gordon@Sun.COM int, total_segments, int, actual_segments); 400*7387SRobert.Gordon@Sun.COM } 4010Sstevel@tonic-gate 402*7387SRobert.Gordon@Sun.COM /* 403*7387SRobert.Gordon@Sun.COM * RDMA READ the chunk data from the remote end. 404*7387SRobert.Gordon@Sun.COM * First prep the destination buffer by registering 405*7387SRobert.Gordon@Sun.COM * it, then RDMA READ the chunk data. Since we are 406*7387SRobert.Gordon@Sun.COM * doing streaming memory, sync the destination 407*7387SRobert.Gordon@Sun.COM * buffer to CPU and deregister the buffer. 408*7387SRobert.Gordon@Sun.COM */ 409*7387SRobert.Gordon@Sun.COM if (xdrp->xp_conn == NULL) { 410*7387SRobert.Gordon@Sun.COM return (FALSE); 411*7387SRobert.Gordon@Sun.COM } 412*7387SRobert.Gordon@Sun.COM cl = *cle; 413*7387SRobert.Gordon@Sun.COM cl.c_next = NULL; 414*7387SRobert.Gordon@Sun.COM if (clist_register(xdrp->xp_conn, &cl, CLIST_REG_DST) 415*7387SRobert.Gordon@Sun.COM != RDMA_SUCCESS) { 416*7387SRobert.Gordon@Sun.COM return (FALSE); 417*7387SRobert.Gordon@Sun.COM } 418*7387SRobert.Gordon@Sun.COM cle->c_dmemhandle = cl.c_dmemhandle; 419*7387SRobert.Gordon@Sun.COM cle->c_dsynchandle = cl.c_dsynchandle; 4200Sstevel@tonic-gate 421*7387SRobert.Gordon@Sun.COM /* 422*7387SRobert.Gordon@Sun.COM * Now read the chunk in 423*7387SRobert.Gordon@Sun.COM */ 424*7387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) == 0 || 425*7387SRobert.Gordon@Sun.COM total_len == 0) { 426*7387SRobert.Gordon@Sun.COM status = RDMA_READ(xdrp->xp_conn, &cl, WAIT); 427*7387SRobert.Gordon@Sun.COM } else { 428*7387SRobert.Gordon@Sun.COM status = RDMA_READ(xdrp->xp_conn, &cl, NOWAIT); 429*7387SRobert.Gordon@Sun.COM } 430*7387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 431*7387SRobert.Gordon@Sun.COM DTRACE_PROBE1( 432*7387SRobert.Gordon@Sun.COM krpc__i__xdrrdma_getblk_readfailed, 433*7387SRobert.Gordon@Sun.COM int, status); 434*7387SRobert.Gordon@Sun.COM retval = FALSE; 435*7387SRobert.Gordon@Sun.COM goto out; 436*7387SRobert.Gordon@Sun.COM } 437*7387SRobert.Gordon@Sun.COM cle = cle->c_next; 4380Sstevel@tonic-gate } 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate /* 4410Sstevel@tonic-gate * sync the memory for cpu 4420Sstevel@tonic-gate */ 443*7387SRobert.Gordon@Sun.COM cl = *cls; 444*7387SRobert.Gordon@Sun.COM cl.c_next = NULL; 445*7387SRobert.Gordon@Sun.COM cl.c_len = cur_offset; 4460Sstevel@tonic-gate if (clist_syncmem(xdrp->xp_conn, &cl, 0) != RDMA_SUCCESS) { 4470Sstevel@tonic-gate retval = FALSE; 4480Sstevel@tonic-gate } 4490Sstevel@tonic-gate out: 4500Sstevel@tonic-gate /* 4510Sstevel@tonic-gate * Deregister the chunks 4520Sstevel@tonic-gate */ 453*7387SRobert.Gordon@Sun.COM cle = cls; 454*7387SRobert.Gordon@Sun.COM cl = *cle; 455*7387SRobert.Gordon@Sun.COM cl.c_next = NULL; 456*7387SRobert.Gordon@Sun.COM cl.c_len = cur_offset; 457*7387SRobert.Gordon@Sun.COM (void) clist_deregister(xdrp->xp_conn, &cl, CLIST_REG_DST); 458*7387SRobert.Gordon@Sun.COM if (alen) { 459*7387SRobert.Gordon@Sun.COM cle->w.c_saddr = 460*7387SRobert.Gordon@Sun.COM (uint64)(uintptr_t)cle->w.c_saddr + cle->c_len; 461*7387SRobert.Gordon@Sun.COM cle->c_len = alen - cle->c_len; 462*7387SRobert.Gordon@Sun.COM } 4630Sstevel@tonic-gate return (retval); 4640Sstevel@tonic-gate } 4650Sstevel@tonic-gate if ((xdrs->x_handy -= len) < 0) 4660Sstevel@tonic-gate return (FALSE); 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate bcopy(xdrp->xp_offp, addr, len); 4690Sstevel@tonic-gate xdrp->xp_offp += len; 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate return (TRUE); 4720Sstevel@tonic-gate } 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate /* 475*7387SRobert.Gordon@Sun.COM * ENCODE some bytes into an XDR stream xp_min_chunk = 0, means the stream of 476*7387SRobert.Gordon@Sun.COM * bytes contain no chunks to seperate out, and if the bytes do not fit in 477*7387SRobert.Gordon@Sun.COM * the supplied buffer, grow the buffer and free the old buffer. 4780Sstevel@tonic-gate */ 479*7387SRobert.Gordon@Sun.COM static bool_t 4800Sstevel@tonic-gate xdrrdma_putbytes(XDR *xdrs, caddr_t addr, int len) 4810Sstevel@tonic-gate { 482*7387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 4830Sstevel@tonic-gate /* 484*7387SRobert.Gordon@Sun.COM * Is this stream accepting chunks? 485*7387SRobert.Gordon@Sun.COM * If so, does the either of the two following conditions exist? 486*7387SRobert.Gordon@Sun.COM * - length of bytes to encode is greater than the min chunk size? 487*7387SRobert.Gordon@Sun.COM * - remaining space in this stream is shorter than length of 488*7387SRobert.Gordon@Sun.COM * bytes to encode? 489*7387SRobert.Gordon@Sun.COM * 490*7387SRobert.Gordon@Sun.COM * If the above exists, then create a chunk for this encoding 491*7387SRobert.Gordon@Sun.COM * and save the addresses, etc. 4920Sstevel@tonic-gate */ 493*7387SRobert.Gordon@Sun.COM if (xdrp->xp_flags & XDR_RDMA_CHUNK && 494*7387SRobert.Gordon@Sun.COM ((xdrp->xp_min_chunk != 0 && 495*7387SRobert.Gordon@Sun.COM len >= xdrp->xp_min_chunk) || 496*7387SRobert.Gordon@Sun.COM (xdrs->x_handy - len < 0))) { 497*7387SRobert.Gordon@Sun.COM struct clist *cle; 498*7387SRobert.Gordon@Sun.COM int offset = xdrp->xp_offp - xdrs->x_base; 4990Sstevel@tonic-gate 500*7387SRobert.Gordon@Sun.COM cle = clist_alloc(); 5010Sstevel@tonic-gate cle->c_xdroff = offset; 502*7387SRobert.Gordon@Sun.COM cle->c_len = len; 503*7387SRobert.Gordon@Sun.COM cle->w.c_saddr = (uint64)(uintptr_t)addr; 5040Sstevel@tonic-gate cle->c_next = NULL; 5050Sstevel@tonic-gate 506*7387SRobert.Gordon@Sun.COM *(xdrp->xp_rcl_next) = cle; 507*7387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &(cle->c_next); 5080Sstevel@tonic-gate 5090Sstevel@tonic-gate return (TRUE); 5100Sstevel@tonic-gate } 511*7387SRobert.Gordon@Sun.COM /* Is there enough space to encode what is left? */ 5120Sstevel@tonic-gate if ((xdrs->x_handy -= len) < 0) { 513*7387SRobert.Gordon@Sun.COM return (FALSE); 5140Sstevel@tonic-gate } 5150Sstevel@tonic-gate bcopy(addr, xdrp->xp_offp, len); 5160Sstevel@tonic-gate xdrp->xp_offp += len; 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate return (TRUE); 5190Sstevel@tonic-gate } 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate uint_t 5220Sstevel@tonic-gate xdrrdma_getpos(XDR *xdrs) 5230Sstevel@tonic-gate { 524*7387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 5250Sstevel@tonic-gate 5260Sstevel@tonic-gate return ((uint_t)((uintptr_t)xdrp->xp_offp - (uintptr_t)xdrs->x_base)); 5270Sstevel@tonic-gate } 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate bool_t 5300Sstevel@tonic-gate xdrrdma_setpos(XDR *xdrs, uint_t pos) 5310Sstevel@tonic-gate { 532*7387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 5330Sstevel@tonic-gate 534*7387SRobert.Gordon@Sun.COM caddr_t newaddr = xdrs->x_base + pos; 535*7387SRobert.Gordon@Sun.COM caddr_t lastaddr = xdrp->xp_offp + xdrs->x_handy; 536*7387SRobert.Gordon@Sun.COM ptrdiff_t diff; 5370Sstevel@tonic-gate 5380Sstevel@tonic-gate if (newaddr > lastaddr) 5390Sstevel@tonic-gate return (FALSE); 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate xdrp->xp_offp = newaddr; 5420Sstevel@tonic-gate diff = lastaddr - newaddr; 5430Sstevel@tonic-gate xdrs->x_handy = (int)diff; 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate return (TRUE); 5460Sstevel@tonic-gate } 5470Sstevel@tonic-gate 5480Sstevel@tonic-gate /* ARGSUSED */ 5490Sstevel@tonic-gate static rpc_inline_t * 5500Sstevel@tonic-gate xdrrdma_inline(XDR *xdrs, int len) 5510Sstevel@tonic-gate { 552*7387SRobert.Gordon@Sun.COM rpc_inline_t *buf = NULL; 553*7387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 554*7387SRobert.Gordon@Sun.COM struct clist *cle = *(xdrp->xp_rcl_next); 5550Sstevel@tonic-gate 5560Sstevel@tonic-gate if (xdrs->x_op == XDR_DECODE) { 5570Sstevel@tonic-gate /* 558*7387SRobert.Gordon@Sun.COM * Since chunks aren't in-line, check to see whether there is 559*7387SRobert.Gordon@Sun.COM * a chunk in the inline range. 5600Sstevel@tonic-gate */ 5610Sstevel@tonic-gate if (cle != NULL && 562*7387SRobert.Gordon@Sun.COM cle->c_xdroff <= (xdrp->xp_offp - xdrs->x_base + len)) 563*7387SRobert.Gordon@Sun.COM return (NULL); 564*7387SRobert.Gordon@Sun.COM } 565*7387SRobert.Gordon@Sun.COM 566*7387SRobert.Gordon@Sun.COM /* LINTED pointer alignment */ 567*7387SRobert.Gordon@Sun.COM buf = (rpc_inline_t *)xdrp->xp_offp; 568*7387SRobert.Gordon@Sun.COM if (!IS_P2ALIGNED(buf, sizeof (int32_t))) 5690Sstevel@tonic-gate return (NULL); 5700Sstevel@tonic-gate 5710Sstevel@tonic-gate if ((xdrs->x_handy < len) || (xdrp->xp_min_chunk != 0 && 5720Sstevel@tonic-gate len >= xdrp->xp_min_chunk)) { 5730Sstevel@tonic-gate return (NULL); 5740Sstevel@tonic-gate } else { 5750Sstevel@tonic-gate xdrs->x_handy -= len; 5760Sstevel@tonic-gate xdrp->xp_offp += len; 5770Sstevel@tonic-gate return (buf); 5780Sstevel@tonic-gate } 5790Sstevel@tonic-gate } 5800Sstevel@tonic-gate 581*7387SRobert.Gordon@Sun.COM static bool_t 5820Sstevel@tonic-gate xdrrdma_control(XDR *xdrs, int request, void *info) 5830Sstevel@tonic-gate { 584*7387SRobert.Gordon@Sun.COM int32_t *int32p; 585*7387SRobert.Gordon@Sun.COM int len, i; 586*7387SRobert.Gordon@Sun.COM uint_t in_flags; 587*7387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 588*7387SRobert.Gordon@Sun.COM rdma_chunkinfo_t *rcip = NULL; 589*7387SRobert.Gordon@Sun.COM rdma_wlist_conn_info_t *rwcip = NULL; 590*7387SRobert.Gordon@Sun.COM rdma_chunkinfo_lengths_t *rcilp = NULL; 591*7387SRobert.Gordon@Sun.COM struct uio *uiop; 592*7387SRobert.Gordon@Sun.COM struct clist *rwl = NULL; 593*7387SRobert.Gordon@Sun.COM struct clist *prev = NULL; 5940Sstevel@tonic-gate 5950Sstevel@tonic-gate switch (request) { 5960Sstevel@tonic-gate case XDR_PEEK: 5970Sstevel@tonic-gate /* 5980Sstevel@tonic-gate * Return the next 4 byte unit in the XDR stream. 5990Sstevel@tonic-gate */ 6000Sstevel@tonic-gate if (xdrs->x_handy < sizeof (int32_t)) 6010Sstevel@tonic-gate return (FALSE); 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate int32p = (int32_t *)info; 6040Sstevel@tonic-gate *int32p = (int32_t)ntohl((uint32_t) 6050Sstevel@tonic-gate (*((int32_t *)(xdrp->xp_offp)))); 6060Sstevel@tonic-gate 6070Sstevel@tonic-gate return (TRUE); 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate case XDR_SKIPBYTES: 6100Sstevel@tonic-gate /* 6110Sstevel@tonic-gate * Skip the next N bytes in the XDR stream. 6120Sstevel@tonic-gate */ 6130Sstevel@tonic-gate int32p = (int32_t *)info; 6140Sstevel@tonic-gate len = RNDUP((int)(*int32p)); 6150Sstevel@tonic-gate if ((xdrs->x_handy -= len) < 0) 6160Sstevel@tonic-gate return (FALSE); 6170Sstevel@tonic-gate xdrp->xp_offp += len; 6180Sstevel@tonic-gate 6190Sstevel@tonic-gate return (TRUE); 6200Sstevel@tonic-gate 621*7387SRobert.Gordon@Sun.COM case XDR_RDMA_SET_FLAGS: 6220Sstevel@tonic-gate /* 623*7387SRobert.Gordon@Sun.COM * Set the flags provided in the *info in xp_flags for rdma 624*7387SRobert.Gordon@Sun.COM * xdr stream control. 6250Sstevel@tonic-gate */ 6260Sstevel@tonic-gate int32p = (int32_t *)info; 6270Sstevel@tonic-gate in_flags = (uint_t)(*int32p); 6280Sstevel@tonic-gate 6290Sstevel@tonic-gate xdrp->xp_flags |= in_flags; 6300Sstevel@tonic-gate return (TRUE); 6310Sstevel@tonic-gate 632*7387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_FLAGS: 6330Sstevel@tonic-gate /* 6340Sstevel@tonic-gate * Get the flags provided in xp_flags return through *info 6350Sstevel@tonic-gate */ 6360Sstevel@tonic-gate int32p = (int32_t *)info; 6370Sstevel@tonic-gate 6380Sstevel@tonic-gate *int32p = (int32_t)xdrp->xp_flags; 6390Sstevel@tonic-gate return (TRUE); 6400Sstevel@tonic-gate 641*7387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_CHUNK_LEN: 642*7387SRobert.Gordon@Sun.COM rcilp = (rdma_chunkinfo_lengths_t *)info; 643*7387SRobert.Gordon@Sun.COM rcilp->rcil_len = xdrp->xp_reply_chunk_len; 644*7387SRobert.Gordon@Sun.COM rcilp->rcil_len_alt = xdrp->xp_reply_chunk_len_alt; 645*7387SRobert.Gordon@Sun.COM 646*7387SRobert.Gordon@Sun.COM return (TRUE); 647*7387SRobert.Gordon@Sun.COM 648*7387SRobert.Gordon@Sun.COM case XDR_RDMA_ADD_CHUNK: 649*7387SRobert.Gordon@Sun.COM /* 650*7387SRobert.Gordon@Sun.COM * Store wlist information 651*7387SRobert.Gordon@Sun.COM */ 652*7387SRobert.Gordon@Sun.COM 653*7387SRobert.Gordon@Sun.COM rcip = (rdma_chunkinfo_t *)info; 654*7387SRobert.Gordon@Sun.COM 655*7387SRobert.Gordon@Sun.COM switch (rcip->rci_type) { 656*7387SRobert.Gordon@Sun.COM case RCI_WRITE_UIO_CHUNK: 657*7387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len_alt += rcip->rci_len; 658*7387SRobert.Gordon@Sun.COM 659*7387SRobert.Gordon@Sun.COM if (rcip->rci_len < xdrp->xp_min_chunk) { 660*7387SRobert.Gordon@Sun.COM xdrp->xp_wcl = NULL; 661*7387SRobert.Gordon@Sun.COM *(rcip->rci_clpp) = NULL; 662*7387SRobert.Gordon@Sun.COM return (TRUE); 663*7387SRobert.Gordon@Sun.COM } 664*7387SRobert.Gordon@Sun.COM uiop = rcip->rci_a.rci_uiop; 665*7387SRobert.Gordon@Sun.COM 666*7387SRobert.Gordon@Sun.COM for (i = 0; i < uiop->uio_iovcnt; i++) { 667*7387SRobert.Gordon@Sun.COM rwl = clist_alloc(); 668*7387SRobert.Gordon@Sun.COM rwl->c_len = uiop->uio_iov[i].iov_len; 669*7387SRobert.Gordon@Sun.COM rwl->u.c_daddr = 670*7387SRobert.Gordon@Sun.COM (uint64)(uintptr_t) 671*7387SRobert.Gordon@Sun.COM (uiop->uio_iov[i].iov_base); 672*7387SRobert.Gordon@Sun.COM /* 673*7387SRobert.Gordon@Sun.COM * if userspace address, put adspace ptr in 674*7387SRobert.Gordon@Sun.COM * clist. If not, then do nothing since it's 675*7387SRobert.Gordon@Sun.COM * already set to NULL (from kmem_zalloc) 676*7387SRobert.Gordon@Sun.COM */ 677*7387SRobert.Gordon@Sun.COM if (uiop->uio_segflg == UIO_USERSPACE) { 678*7387SRobert.Gordon@Sun.COM rwl->c_adspc = ttoproc(curthread)->p_as; 679*7387SRobert.Gordon@Sun.COM } 680*7387SRobert.Gordon@Sun.COM 681*7387SRobert.Gordon@Sun.COM if (prev == NULL) 682*7387SRobert.Gordon@Sun.COM prev = rwl; 683*7387SRobert.Gordon@Sun.COM else { 684*7387SRobert.Gordon@Sun.COM prev->c_next = rwl; 685*7387SRobert.Gordon@Sun.COM prev = rwl; 686*7387SRobert.Gordon@Sun.COM } 687*7387SRobert.Gordon@Sun.COM } 688*7387SRobert.Gordon@Sun.COM 689*7387SRobert.Gordon@Sun.COM rwl->c_next = NULL; 690*7387SRobert.Gordon@Sun.COM xdrp->xp_wcl = rwl; 691*7387SRobert.Gordon@Sun.COM *(rcip->rci_clpp) = rwl; 692*7387SRobert.Gordon@Sun.COM 693*7387SRobert.Gordon@Sun.COM break; 694*7387SRobert.Gordon@Sun.COM 695*7387SRobert.Gordon@Sun.COM case RCI_WRITE_ADDR_CHUNK: 696*7387SRobert.Gordon@Sun.COM rwl = clist_alloc(); 697*7387SRobert.Gordon@Sun.COM 698*7387SRobert.Gordon@Sun.COM rwl->c_len = rcip->rci_len; 699*7387SRobert.Gordon@Sun.COM rwl->u.c_daddr3 = rcip->rci_a.rci_addr; 700*7387SRobert.Gordon@Sun.COM rwl->c_next = NULL; 701*7387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len_alt += rcip->rci_len; 702*7387SRobert.Gordon@Sun.COM 703*7387SRobert.Gordon@Sun.COM xdrp->xp_wcl = rwl; 704*7387SRobert.Gordon@Sun.COM *(rcip->rci_clpp) = rwl; 705*7387SRobert.Gordon@Sun.COM 706*7387SRobert.Gordon@Sun.COM break; 707*7387SRobert.Gordon@Sun.COM 708*7387SRobert.Gordon@Sun.COM case RCI_REPLY_CHUNK: 709*7387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len += rcip->rci_len; 710*7387SRobert.Gordon@Sun.COM break; 711*7387SRobert.Gordon@Sun.COM } 712*7387SRobert.Gordon@Sun.COM return (TRUE); 713*7387SRobert.Gordon@Sun.COM 714*7387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_WLIST: 715*7387SRobert.Gordon@Sun.COM *((struct clist **)info) = xdrp->xp_wcl; 716*7387SRobert.Gordon@Sun.COM return (TRUE); 717*7387SRobert.Gordon@Sun.COM 718*7387SRobert.Gordon@Sun.COM case XDR_RDMA_SET_WLIST: 719*7387SRobert.Gordon@Sun.COM xdrp->xp_wcl = (struct clist *)info; 720*7387SRobert.Gordon@Sun.COM return (TRUE); 721*7387SRobert.Gordon@Sun.COM 722*7387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_RLIST: 723*7387SRobert.Gordon@Sun.COM *((struct clist **)info) = xdrp->xp_rcl; 724*7387SRobert.Gordon@Sun.COM return (TRUE); 725*7387SRobert.Gordon@Sun.COM 726*7387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_WCINFO: 727*7387SRobert.Gordon@Sun.COM rwcip = (rdma_wlist_conn_info_t *)info; 728*7387SRobert.Gordon@Sun.COM 729*7387SRobert.Gordon@Sun.COM rwcip->rwci_wlist = xdrp->xp_wcl; 730*7387SRobert.Gordon@Sun.COM rwcip->rwci_conn = xdrp->xp_conn; 731*7387SRobert.Gordon@Sun.COM 732*7387SRobert.Gordon@Sun.COM return (TRUE); 733*7387SRobert.Gordon@Sun.COM 7340Sstevel@tonic-gate default: 7350Sstevel@tonic-gate return (FALSE); 7360Sstevel@tonic-gate } 7370Sstevel@tonic-gate } 7380Sstevel@tonic-gate 739*7387SRobert.Gordon@Sun.COM bool_t xdr_do_clist(XDR *, clist **); 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate /* 742*7387SRobert.Gordon@Sun.COM * Not all fields in struct clist are interesting to the RPC over RDMA 743*7387SRobert.Gordon@Sun.COM * protocol. Only XDR the interesting fields. 7440Sstevel@tonic-gate */ 7450Sstevel@tonic-gate bool_t 7460Sstevel@tonic-gate xdr_clist(XDR *xdrs, clist *objp) 7470Sstevel@tonic-gate { 7480Sstevel@tonic-gate if (!xdr_uint32(xdrs, &objp->c_xdroff)) 7490Sstevel@tonic-gate return (FALSE); 750*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &objp->c_smemhandle.mrc_rmr)) 751*7387SRobert.Gordon@Sun.COM return (FALSE); 7520Sstevel@tonic-gate if (!xdr_uint32(xdrs, &objp->c_len)) 7530Sstevel@tonic-gate return (FALSE); 754*7387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &objp->w.c_saddr)) 7550Sstevel@tonic-gate return (FALSE); 756*7387SRobert.Gordon@Sun.COM if (!xdr_do_clist(xdrs, &objp->c_next)) 7570Sstevel@tonic-gate return (FALSE); 7580Sstevel@tonic-gate return (TRUE); 7590Sstevel@tonic-gate } 7600Sstevel@tonic-gate 761*7387SRobert.Gordon@Sun.COM /* 762*7387SRobert.Gordon@Sun.COM * The following two functions are forms of xdr_pointer() 763*7387SRobert.Gordon@Sun.COM * and xdr_reference(). Since the generic versions just 764*7387SRobert.Gordon@Sun.COM * kmem_alloc() a new clist, we actually want to use the 765*7387SRobert.Gordon@Sun.COM * rdma_clist kmem_cache. 766*7387SRobert.Gordon@Sun.COM */ 767*7387SRobert.Gordon@Sun.COM 768*7387SRobert.Gordon@Sun.COM /* 769*7387SRobert.Gordon@Sun.COM * Generate or free a clist structure from the 770*7387SRobert.Gordon@Sun.COM * kmem_cache "rdma_clist" 771*7387SRobert.Gordon@Sun.COM */ 7720Sstevel@tonic-gate bool_t 773*7387SRobert.Gordon@Sun.COM xdr_ref_clist(XDR *xdrs, caddr_t *pp) 7740Sstevel@tonic-gate { 775*7387SRobert.Gordon@Sun.COM caddr_t loc = *pp; 776*7387SRobert.Gordon@Sun.COM bool_t stat; 777*7387SRobert.Gordon@Sun.COM 778*7387SRobert.Gordon@Sun.COM if (loc == NULL) { 779*7387SRobert.Gordon@Sun.COM switch (xdrs->x_op) { 780*7387SRobert.Gordon@Sun.COM case XDR_FREE: 781*7387SRobert.Gordon@Sun.COM return (TRUE); 782*7387SRobert.Gordon@Sun.COM 783*7387SRobert.Gordon@Sun.COM case XDR_DECODE: 784*7387SRobert.Gordon@Sun.COM *pp = loc = (caddr_t)clist_alloc(); 785*7387SRobert.Gordon@Sun.COM break; 786*7387SRobert.Gordon@Sun.COM 787*7387SRobert.Gordon@Sun.COM case XDR_ENCODE: 788*7387SRobert.Gordon@Sun.COM ASSERT(loc); 789*7387SRobert.Gordon@Sun.COM break; 790*7387SRobert.Gordon@Sun.COM } 791*7387SRobert.Gordon@Sun.COM } 792*7387SRobert.Gordon@Sun.COM 793*7387SRobert.Gordon@Sun.COM stat = xdr_clist(xdrs, (struct clist *)loc); 794*7387SRobert.Gordon@Sun.COM 795*7387SRobert.Gordon@Sun.COM if (xdrs->x_op == XDR_FREE) { 796*7387SRobert.Gordon@Sun.COM kmem_cache_free(clist_cache, loc); 797*7387SRobert.Gordon@Sun.COM *pp = NULL; 798*7387SRobert.Gordon@Sun.COM } 799*7387SRobert.Gordon@Sun.COM return (stat); 800*7387SRobert.Gordon@Sun.COM } 801*7387SRobert.Gordon@Sun.COM 802*7387SRobert.Gordon@Sun.COM /* 803*7387SRobert.Gordon@Sun.COM * XDR a pointer to a possibly recursive clist. This differs 804*7387SRobert.Gordon@Sun.COM * with xdr_reference in that it can serialize/deserialiaze 805*7387SRobert.Gordon@Sun.COM * trees correctly. 806*7387SRobert.Gordon@Sun.COM * 807*7387SRobert.Gordon@Sun.COM * What is sent is actually a union: 808*7387SRobert.Gordon@Sun.COM * 809*7387SRobert.Gordon@Sun.COM * union object_pointer switch (boolean b) { 810*7387SRobert.Gordon@Sun.COM * case TRUE: object_data data; 811*7387SRobert.Gordon@Sun.COM * case FALSE: void nothing; 812*7387SRobert.Gordon@Sun.COM * } 813*7387SRobert.Gordon@Sun.COM * 814*7387SRobert.Gordon@Sun.COM * > objpp: Pointer to the pointer to the object. 815*7387SRobert.Gordon@Sun.COM * 816*7387SRobert.Gordon@Sun.COM */ 817*7387SRobert.Gordon@Sun.COM 818*7387SRobert.Gordon@Sun.COM bool_t 819*7387SRobert.Gordon@Sun.COM xdr_do_clist(XDR *xdrs, clist **objpp) 820*7387SRobert.Gordon@Sun.COM { 821*7387SRobert.Gordon@Sun.COM bool_t more_data; 822*7387SRobert.Gordon@Sun.COM 823*7387SRobert.Gordon@Sun.COM more_data = (*objpp != NULL); 824*7387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more_data)) 825*7387SRobert.Gordon@Sun.COM return (FALSE); 826*7387SRobert.Gordon@Sun.COM if (!more_data) { 827*7387SRobert.Gordon@Sun.COM *objpp = NULL; 828*7387SRobert.Gordon@Sun.COM return (TRUE); 829*7387SRobert.Gordon@Sun.COM } 830*7387SRobert.Gordon@Sun.COM return (xdr_ref_clist(xdrs, (caddr_t *)objpp)); 8310Sstevel@tonic-gate } 8320Sstevel@tonic-gate 8330Sstevel@tonic-gate uint_t 8340Sstevel@tonic-gate xdr_getbufsize(XDR *xdrs) 8350Sstevel@tonic-gate { 836*7387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 8370Sstevel@tonic-gate 8380Sstevel@tonic-gate return ((uint_t)xdrp->xp_buf_size); 8390Sstevel@tonic-gate } 840*7387SRobert.Gordon@Sun.COM 841*7387SRobert.Gordon@Sun.COM /* ARGSUSED */ 842*7387SRobert.Gordon@Sun.COM bool_t 843*7387SRobert.Gordon@Sun.COM xdr_encode_rlist_svc(XDR *xdrs, clist *rlist) 844*7387SRobert.Gordon@Sun.COM { 845*7387SRobert.Gordon@Sun.COM bool_t vfalse = FALSE; 846*7387SRobert.Gordon@Sun.COM 847*7387SRobert.Gordon@Sun.COM ASSERT(rlist == NULL); 848*7387SRobert.Gordon@Sun.COM return (xdr_bool(xdrs, &vfalse)); 849*7387SRobert.Gordon@Sun.COM } 850*7387SRobert.Gordon@Sun.COM 851*7387SRobert.Gordon@Sun.COM bool_t 852*7387SRobert.Gordon@Sun.COM xdr_encode_wlist(XDR *xdrs, clist *w) 853*7387SRobert.Gordon@Sun.COM { 854*7387SRobert.Gordon@Sun.COM bool_t vfalse = FALSE, vtrue = TRUE; 855*7387SRobert.Gordon@Sun.COM int i; 856*7387SRobert.Gordon@Sun.COM uint_t num_segment = 0; 857*7387SRobert.Gordon@Sun.COM struct clist *cl; 858*7387SRobert.Gordon@Sun.COM 859*7387SRobert.Gordon@Sun.COM /* does a wlist exist? */ 860*7387SRobert.Gordon@Sun.COM if (w == NULL) { 861*7387SRobert.Gordon@Sun.COM return (xdr_bool(xdrs, &vfalse)); 862*7387SRobert.Gordon@Sun.COM } 863*7387SRobert.Gordon@Sun.COM /* Encode N consecutive segments, 1, N, HLOO, ..., HLOO, 0 */ 864*7387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &vtrue)) 865*7387SRobert.Gordon@Sun.COM return (FALSE); 866*7387SRobert.Gordon@Sun.COM 867*7387SRobert.Gordon@Sun.COM for (cl = w; cl != NULL; cl = cl->c_next) { 868*7387SRobert.Gordon@Sun.COM num_segment++; 869*7387SRobert.Gordon@Sun.COM } 870*7387SRobert.Gordon@Sun.COM 871*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &num_segment)) 872*7387SRobert.Gordon@Sun.COM return (FALSE); 873*7387SRobert.Gordon@Sun.COM for (i = 0; i < num_segment; i++) { 874*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &w->c_dmemhandle.mrc_rmr)) 875*7387SRobert.Gordon@Sun.COM return (FALSE); 876*7387SRobert.Gordon@Sun.COM 877*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &w->c_len)) 878*7387SRobert.Gordon@Sun.COM return (FALSE); 879*7387SRobert.Gordon@Sun.COM 880*7387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &w->u.c_daddr)) 881*7387SRobert.Gordon@Sun.COM return (FALSE); 882*7387SRobert.Gordon@Sun.COM 883*7387SRobert.Gordon@Sun.COM w = w->c_next; 884*7387SRobert.Gordon@Sun.COM } 885*7387SRobert.Gordon@Sun.COM 886*7387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &vfalse)) 887*7387SRobert.Gordon@Sun.COM return (FALSE); 888*7387SRobert.Gordon@Sun.COM 889*7387SRobert.Gordon@Sun.COM return (TRUE); 890*7387SRobert.Gordon@Sun.COM } 891*7387SRobert.Gordon@Sun.COM 892*7387SRobert.Gordon@Sun.COM 893*7387SRobert.Gordon@Sun.COM /* 894*7387SRobert.Gordon@Sun.COM * Conditionally decode a RDMA WRITE chunk list from XDR stream. 895*7387SRobert.Gordon@Sun.COM * 896*7387SRobert.Gordon@Sun.COM * If the next boolean in the XDR stream is false there is no 897*7387SRobert.Gordon@Sun.COM * RDMA WRITE chunk list present. Otherwise iterate over the 898*7387SRobert.Gordon@Sun.COM * array and for each entry: allocate a struct clist and decode. 899*7387SRobert.Gordon@Sun.COM * Pass back an indication via wlist_exists if we have seen a 900*7387SRobert.Gordon@Sun.COM * RDMA WRITE chunk list. 901*7387SRobert.Gordon@Sun.COM */ 902*7387SRobert.Gordon@Sun.COM bool_t 903*7387SRobert.Gordon@Sun.COM xdr_decode_wlist(XDR *xdrs, struct clist **w, bool_t *wlist_exists) 904*7387SRobert.Gordon@Sun.COM { 905*7387SRobert.Gordon@Sun.COM struct clist *tmp; 906*7387SRobert.Gordon@Sun.COM bool_t more = FALSE; 907*7387SRobert.Gordon@Sun.COM uint32_t seg_array_len; 908*7387SRobert.Gordon@Sun.COM uint32_t i; 909*7387SRobert.Gordon@Sun.COM 910*7387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more)) 911*7387SRobert.Gordon@Sun.COM return (FALSE); 912*7387SRobert.Gordon@Sun.COM 913*7387SRobert.Gordon@Sun.COM /* is there a wlist? */ 914*7387SRobert.Gordon@Sun.COM if (more == FALSE) { 915*7387SRobert.Gordon@Sun.COM *wlist_exists = FALSE; 916*7387SRobert.Gordon@Sun.COM return (TRUE); 917*7387SRobert.Gordon@Sun.COM } 918*7387SRobert.Gordon@Sun.COM *wlist_exists = TRUE; 919*7387SRobert.Gordon@Sun.COM 920*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &seg_array_len)) 921*7387SRobert.Gordon@Sun.COM return (FALSE); 922*7387SRobert.Gordon@Sun.COM 923*7387SRobert.Gordon@Sun.COM tmp = *w = clist_alloc(); 924*7387SRobert.Gordon@Sun.COM for (i = 0; i < seg_array_len; i++) { 925*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &tmp->c_dmemhandle.mrc_rmr)) 926*7387SRobert.Gordon@Sun.COM return (FALSE); 927*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &tmp->c_len)) 928*7387SRobert.Gordon@Sun.COM return (FALSE); 929*7387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &tmp->u.c_daddr)) 930*7387SRobert.Gordon@Sun.COM return (FALSE); 931*7387SRobert.Gordon@Sun.COM if (i < seg_array_len - 1) { 932*7387SRobert.Gordon@Sun.COM tmp->c_next = clist_alloc(); 933*7387SRobert.Gordon@Sun.COM tmp = tmp->c_next; 934*7387SRobert.Gordon@Sun.COM } else { 935*7387SRobert.Gordon@Sun.COM tmp->c_next = NULL; 936*7387SRobert.Gordon@Sun.COM } 937*7387SRobert.Gordon@Sun.COM } 938*7387SRobert.Gordon@Sun.COM 939*7387SRobert.Gordon@Sun.COM more = FALSE; 940*7387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more)) 941*7387SRobert.Gordon@Sun.COM return (FALSE); 942*7387SRobert.Gordon@Sun.COM 943*7387SRobert.Gordon@Sun.COM return (TRUE); 944*7387SRobert.Gordon@Sun.COM } 945*7387SRobert.Gordon@Sun.COM 946*7387SRobert.Gordon@Sun.COM /* 947*7387SRobert.Gordon@Sun.COM * Server side RDMA WRITE list decode. 948*7387SRobert.Gordon@Sun.COM * XDR context is memory ops 949*7387SRobert.Gordon@Sun.COM */ 950*7387SRobert.Gordon@Sun.COM bool_t 951*7387SRobert.Gordon@Sun.COM xdr_decode_wlist_svc(XDR *xdrs, struct clist **wclp, bool_t *wwl, 952*7387SRobert.Gordon@Sun.COM uint32_t *total_length, CONN *conn) 953*7387SRobert.Gordon@Sun.COM { 954*7387SRobert.Gordon@Sun.COM struct clist *first, *ncl; 955*7387SRobert.Gordon@Sun.COM char *memp; 956*7387SRobert.Gordon@Sun.COM uint32_t num_wclist; 957*7387SRobert.Gordon@Sun.COM uint32_t wcl_length = 0; 958*7387SRobert.Gordon@Sun.COM uint32_t i; 959*7387SRobert.Gordon@Sun.COM bool_t more = FALSE; 960*7387SRobert.Gordon@Sun.COM 961*7387SRobert.Gordon@Sun.COM *wclp = NULL; 962*7387SRobert.Gordon@Sun.COM *wwl = FALSE; 963*7387SRobert.Gordon@Sun.COM *total_length = 0; 964*7387SRobert.Gordon@Sun.COM 965*7387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more)) { 966*7387SRobert.Gordon@Sun.COM return (FALSE); 967*7387SRobert.Gordon@Sun.COM } 968*7387SRobert.Gordon@Sun.COM 969*7387SRobert.Gordon@Sun.COM if (more == FALSE) { 970*7387SRobert.Gordon@Sun.COM return (TRUE); 971*7387SRobert.Gordon@Sun.COM } 972*7387SRobert.Gordon@Sun.COM 973*7387SRobert.Gordon@Sun.COM *wwl = TRUE; 974*7387SRobert.Gordon@Sun.COM 975*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &num_wclist)) { 976*7387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__xdrrdma__wlistsvc__listlength); 977*7387SRobert.Gordon@Sun.COM return (FALSE); 978*7387SRobert.Gordon@Sun.COM } 979*7387SRobert.Gordon@Sun.COM 980*7387SRobert.Gordon@Sun.COM first = ncl = clist_alloc(); 981*7387SRobert.Gordon@Sun.COM 982*7387SRobert.Gordon@Sun.COM for (i = 0; i < num_wclist; i++) { 983*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &ncl->c_dmemhandle.mrc_rmr)) 984*7387SRobert.Gordon@Sun.COM goto err_out; 985*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &ncl->c_len)) 986*7387SRobert.Gordon@Sun.COM goto err_out; 987*7387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &ncl->u.c_daddr)) 988*7387SRobert.Gordon@Sun.COM goto err_out; 989*7387SRobert.Gordon@Sun.COM 990*7387SRobert.Gordon@Sun.COM if (ncl->c_len > MAX_SVC_XFER_SIZE) { 991*7387SRobert.Gordon@Sun.COM DTRACE_PROBE( 992*7387SRobert.Gordon@Sun.COM krpc__e__xdrrdma__wlistsvc__chunklist_toobig); 993*7387SRobert.Gordon@Sun.COM ncl->c_len = MAX_SVC_XFER_SIZE; 994*7387SRobert.Gordon@Sun.COM } 995*7387SRobert.Gordon@Sun.COM 996*7387SRobert.Gordon@Sun.COM wcl_length += ncl->c_len; 997*7387SRobert.Gordon@Sun.COM 998*7387SRobert.Gordon@Sun.COM if (i < num_wclist - 1) { 999*7387SRobert.Gordon@Sun.COM ncl->c_next = clist_alloc(); 1000*7387SRobert.Gordon@Sun.COM ncl = ncl->c_next; 1001*7387SRobert.Gordon@Sun.COM } 1002*7387SRobert.Gordon@Sun.COM } 1003*7387SRobert.Gordon@Sun.COM 1004*7387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more)) 1005*7387SRobert.Gordon@Sun.COM goto err_out; 1006*7387SRobert.Gordon@Sun.COM 1007*7387SRobert.Gordon@Sun.COM first->rb_longbuf.type = RDMA_LONG_BUFFER; 1008*7387SRobert.Gordon@Sun.COM first->rb_longbuf.len = 1009*7387SRobert.Gordon@Sun.COM wcl_length > WCL_BUF_LEN ? wcl_length : WCL_BUF_LEN; 1010*7387SRobert.Gordon@Sun.COM 1011*7387SRobert.Gordon@Sun.COM if (rdma_buf_alloc(conn, &first->rb_longbuf)) { 1012*7387SRobert.Gordon@Sun.COM clist_free(first); 1013*7387SRobert.Gordon@Sun.COM return (FALSE); 1014*7387SRobert.Gordon@Sun.COM } 1015*7387SRobert.Gordon@Sun.COM 1016*7387SRobert.Gordon@Sun.COM memp = first->rb_longbuf.addr; 1017*7387SRobert.Gordon@Sun.COM 1018*7387SRobert.Gordon@Sun.COM ncl = first; 1019*7387SRobert.Gordon@Sun.COM for (i = 0; i < num_wclist; i++) { 1020*7387SRobert.Gordon@Sun.COM ncl->w.c_saddr3 = (caddr_t)memp; 1021*7387SRobert.Gordon@Sun.COM memp += ncl->c_len; 1022*7387SRobert.Gordon@Sun.COM ncl = ncl->c_next; 1023*7387SRobert.Gordon@Sun.COM } 1024*7387SRobert.Gordon@Sun.COM 1025*7387SRobert.Gordon@Sun.COM *wclp = first; 1026*7387SRobert.Gordon@Sun.COM *total_length = wcl_length; 1027*7387SRobert.Gordon@Sun.COM return (TRUE); 1028*7387SRobert.Gordon@Sun.COM 1029*7387SRobert.Gordon@Sun.COM err_out: 1030*7387SRobert.Gordon@Sun.COM clist_free(first); 1031*7387SRobert.Gordon@Sun.COM return (FALSE); 1032*7387SRobert.Gordon@Sun.COM } 1033*7387SRobert.Gordon@Sun.COM 1034*7387SRobert.Gordon@Sun.COM /* 1035*7387SRobert.Gordon@Sun.COM * XDR decode the long reply write chunk. 1036*7387SRobert.Gordon@Sun.COM */ 1037*7387SRobert.Gordon@Sun.COM bool_t 1038*7387SRobert.Gordon@Sun.COM xdr_decode_reply_wchunk(XDR *xdrs, struct clist **clist) 1039*7387SRobert.Gordon@Sun.COM { 1040*7387SRobert.Gordon@Sun.COM bool_t have_rchunk = FALSE; 1041*7387SRobert.Gordon@Sun.COM struct clist *first = NULL, *ncl = NULL; 1042*7387SRobert.Gordon@Sun.COM uint32_t num_wclist; 1043*7387SRobert.Gordon@Sun.COM uint32_t i; 1044*7387SRobert.Gordon@Sun.COM 1045*7387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &have_rchunk)) 1046*7387SRobert.Gordon@Sun.COM return (FALSE); 1047*7387SRobert.Gordon@Sun.COM 1048*7387SRobert.Gordon@Sun.COM if (have_rchunk == FALSE) 1049*7387SRobert.Gordon@Sun.COM return (TRUE); 1050*7387SRobert.Gordon@Sun.COM 1051*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &num_wclist)) { 1052*7387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__xdrrdma__replywchunk__listlength); 1053*7387SRobert.Gordon@Sun.COM return (FALSE); 1054*7387SRobert.Gordon@Sun.COM } 1055*7387SRobert.Gordon@Sun.COM 1056*7387SRobert.Gordon@Sun.COM if (num_wclist == 0) { 1057*7387SRobert.Gordon@Sun.COM return (FALSE); 1058*7387SRobert.Gordon@Sun.COM } 1059*7387SRobert.Gordon@Sun.COM 1060*7387SRobert.Gordon@Sun.COM first = ncl = clist_alloc(); 1061*7387SRobert.Gordon@Sun.COM 1062*7387SRobert.Gordon@Sun.COM for (i = 0; i < num_wclist; i++) { 1063*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &ncl->c_dmemhandle.mrc_rmr)) 1064*7387SRobert.Gordon@Sun.COM goto err_out; 1065*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &ncl->c_len)) 1066*7387SRobert.Gordon@Sun.COM goto err_out; 1067*7387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &ncl->u.c_daddr)) 1068*7387SRobert.Gordon@Sun.COM goto err_out; 1069*7387SRobert.Gordon@Sun.COM 1070*7387SRobert.Gordon@Sun.COM if (ncl->c_len > MAX_SVC_XFER_SIZE) { 1071*7387SRobert.Gordon@Sun.COM DTRACE_PROBE( 1072*7387SRobert.Gordon@Sun.COM krpc__e__xdrrdma__replywchunk__chunklist_toobig); 1073*7387SRobert.Gordon@Sun.COM ncl->c_len = MAX_SVC_XFER_SIZE; 1074*7387SRobert.Gordon@Sun.COM } 1075*7387SRobert.Gordon@Sun.COM if (!(ncl->c_dmemhandle.mrc_rmr && 1076*7387SRobert.Gordon@Sun.COM (ncl->c_len > 0) && ncl->u.c_daddr)) 1077*7387SRobert.Gordon@Sun.COM DTRACE_PROBE( 1078*7387SRobert.Gordon@Sun.COM krpc__e__xdrrdma__replywchunk__invalid_segaddr); 1079*7387SRobert.Gordon@Sun.COM 1080*7387SRobert.Gordon@Sun.COM if (i > 0) { 1081*7387SRobert.Gordon@Sun.COM ncl->c_next = clist_alloc(); 1082*7387SRobert.Gordon@Sun.COM ncl = ncl->c_next; 1083*7387SRobert.Gordon@Sun.COM } 1084*7387SRobert.Gordon@Sun.COM } 1085*7387SRobert.Gordon@Sun.COM *clist = first; 1086*7387SRobert.Gordon@Sun.COM return (TRUE); 1087*7387SRobert.Gordon@Sun.COM 1088*7387SRobert.Gordon@Sun.COM err_out: 1089*7387SRobert.Gordon@Sun.COM clist_free(first); 1090*7387SRobert.Gordon@Sun.COM return (FALSE); 1091*7387SRobert.Gordon@Sun.COM } 1092*7387SRobert.Gordon@Sun.COM 1093*7387SRobert.Gordon@Sun.COM 1094*7387SRobert.Gordon@Sun.COM bool_t 1095*7387SRobert.Gordon@Sun.COM xdr_encode_reply_wchunk(XDR *xdrs, 1096*7387SRobert.Gordon@Sun.COM struct clist *cl_longreply, uint32_t seg_array_len) 1097*7387SRobert.Gordon@Sun.COM { 1098*7387SRobert.Gordon@Sun.COM int i; 1099*7387SRobert.Gordon@Sun.COM bool_t long_reply_exists = TRUE; 1100*7387SRobert.Gordon@Sun.COM uint32_t length; 1101*7387SRobert.Gordon@Sun.COM uint64 offset; 1102*7387SRobert.Gordon@Sun.COM 1103*7387SRobert.Gordon@Sun.COM if (seg_array_len > 0) { 1104*7387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &long_reply_exists)) 1105*7387SRobert.Gordon@Sun.COM return (FALSE); 1106*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &seg_array_len)) 1107*7387SRobert.Gordon@Sun.COM return (FALSE); 1108*7387SRobert.Gordon@Sun.COM 1109*7387SRobert.Gordon@Sun.COM for (i = 0; i < seg_array_len; i++) { 1110*7387SRobert.Gordon@Sun.COM if (!cl_longreply) 1111*7387SRobert.Gordon@Sun.COM return (FALSE); 1112*7387SRobert.Gordon@Sun.COM length = cl_longreply->c_len; 1113*7387SRobert.Gordon@Sun.COM offset = (uint64) cl_longreply->u.c_daddr; 1114*7387SRobert.Gordon@Sun.COM 1115*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, 1116*7387SRobert.Gordon@Sun.COM &cl_longreply->c_dmemhandle.mrc_rmr)) 1117*7387SRobert.Gordon@Sun.COM return (FALSE); 1118*7387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &length)) 1119*7387SRobert.Gordon@Sun.COM return (FALSE); 1120*7387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &offset)) 1121*7387SRobert.Gordon@Sun.COM return (FALSE); 1122*7387SRobert.Gordon@Sun.COM cl_longreply = cl_longreply->c_next; 1123*7387SRobert.Gordon@Sun.COM } 1124*7387SRobert.Gordon@Sun.COM } else { 1125*7387SRobert.Gordon@Sun.COM long_reply_exists = FALSE; 1126*7387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &long_reply_exists)) 1127*7387SRobert.Gordon@Sun.COM return (FALSE); 1128*7387SRobert.Gordon@Sun.COM } 1129*7387SRobert.Gordon@Sun.COM return (TRUE); 1130*7387SRobert.Gordon@Sun.COM } 1131*7387SRobert.Gordon@Sun.COM bool_t 1132*7387SRobert.Gordon@Sun.COM xdrrdma_read_from_client(struct clist **rlist, CONN **conn, uint_t count) 1133*7387SRobert.Gordon@Sun.COM { 1134*7387SRobert.Gordon@Sun.COM struct clist *rdclist; 1135*7387SRobert.Gordon@Sun.COM struct clist cl; 1136*7387SRobert.Gordon@Sun.COM uint_t total_len = 0; 1137*7387SRobert.Gordon@Sun.COM uint32_t status; 1138*7387SRobert.Gordon@Sun.COM bool_t retval = TRUE; 1139*7387SRobert.Gordon@Sun.COM 1140*7387SRobert.Gordon@Sun.COM (*rlist)->rb_longbuf.type = RDMA_LONG_BUFFER; 1141*7387SRobert.Gordon@Sun.COM (*rlist)->rb_longbuf.len = 1142*7387SRobert.Gordon@Sun.COM count > RCL_BUF_LEN ? count : RCL_BUF_LEN; 1143*7387SRobert.Gordon@Sun.COM 1144*7387SRobert.Gordon@Sun.COM if (rdma_buf_alloc(*conn, &(*rlist)->rb_longbuf)) { 1145*7387SRobert.Gordon@Sun.COM return (FALSE); 1146*7387SRobert.Gordon@Sun.COM } 1147*7387SRobert.Gordon@Sun.COM 1148*7387SRobert.Gordon@Sun.COM for (rdclist = *rlist; 1149*7387SRobert.Gordon@Sun.COM rdclist != NULL; rdclist = rdclist->c_next) { 1150*7387SRobert.Gordon@Sun.COM total_len += rdclist->c_len; 1151*7387SRobert.Gordon@Sun.COM #if (defined(OBJ32)||defined(DEBUG32)) 1152*7387SRobert.Gordon@Sun.COM rdclist->u.c_daddr3 = 1153*7387SRobert.Gordon@Sun.COM (caddr_t)((char *)(*rlist)->rb_longbuf.addr + 1154*7387SRobert.Gordon@Sun.COM (uint32) rdclist->u.c_daddr3); 1155*7387SRobert.Gordon@Sun.COM #else 1156*7387SRobert.Gordon@Sun.COM rdclist->u.c_daddr3 = 1157*7387SRobert.Gordon@Sun.COM (caddr_t)((char *)(*rlist)->rb_longbuf.addr + 1158*7387SRobert.Gordon@Sun.COM (uint64) rdclist->u.c_daddr); 1159*7387SRobert.Gordon@Sun.COM 1160*7387SRobert.Gordon@Sun.COM #endif 1161*7387SRobert.Gordon@Sun.COM cl = (*rdclist); 1162*7387SRobert.Gordon@Sun.COM cl.c_next = NULL; 1163*7387SRobert.Gordon@Sun.COM 1164*7387SRobert.Gordon@Sun.COM if (clist_register(*conn, &cl, CLIST_REG_DST) != RDMA_SUCCESS) { 1165*7387SRobert.Gordon@Sun.COM rdma_buf_free(*conn, &(*rlist)->rb_longbuf); 1166*7387SRobert.Gordon@Sun.COM DTRACE_PROBE( 1167*7387SRobert.Gordon@Sun.COM krpc__e__xdrrdma__readfromclient__clist__reg); 1168*7387SRobert.Gordon@Sun.COM return (FALSE); 1169*7387SRobert.Gordon@Sun.COM } 1170*7387SRobert.Gordon@Sun.COM 1171*7387SRobert.Gordon@Sun.COM DTRACE_PROBE1(krpc__i__xdrrdma__readfromclient__buflen, 1172*7387SRobert.Gordon@Sun.COM int, rdclist->c_len); 1173*7387SRobert.Gordon@Sun.COM 1174*7387SRobert.Gordon@Sun.COM /* 1175*7387SRobert.Gordon@Sun.COM * Now read the chunk in 1176*7387SRobert.Gordon@Sun.COM */ 1177*7387SRobert.Gordon@Sun.COM if (rdclist->c_next == NULL) { 1178*7387SRobert.Gordon@Sun.COM status = RDMA_READ(*conn, &cl, WAIT); 1179*7387SRobert.Gordon@Sun.COM } else { 1180*7387SRobert.Gordon@Sun.COM status = RDMA_READ(*conn, &cl, NOWAIT); 1181*7387SRobert.Gordon@Sun.COM } 1182*7387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 1183*7387SRobert.Gordon@Sun.COM DTRACE_PROBE( 1184*7387SRobert.Gordon@Sun.COM krpc__e__xdrrdma__readfromclient__readfailed); 1185*7387SRobert.Gordon@Sun.COM rdma_buf_free(*conn, &(*rlist)->rb_longbuf); 1186*7387SRobert.Gordon@Sun.COM return (FALSE); 1187*7387SRobert.Gordon@Sun.COM } 1188*7387SRobert.Gordon@Sun.COM } 1189*7387SRobert.Gordon@Sun.COM 1190*7387SRobert.Gordon@Sun.COM cl = (*(*rlist)); 1191*7387SRobert.Gordon@Sun.COM cl.c_next = NULL; 1192*7387SRobert.Gordon@Sun.COM cl.c_len = total_len; 1193*7387SRobert.Gordon@Sun.COM if (clist_syncmem(*conn, &cl, 0) != RDMA_SUCCESS) { 1194*7387SRobert.Gordon@Sun.COM retval = FALSE; 1195*7387SRobert.Gordon@Sun.COM } 1196*7387SRobert.Gordon@Sun.COM return (retval); 1197*7387SRobert.Gordon@Sun.COM } 1198*7387SRobert.Gordon@Sun.COM 1199*7387SRobert.Gordon@Sun.COM bool_t 1200*7387SRobert.Gordon@Sun.COM xdrrdma_free_clist(CONN *conn, struct clist *clp) 1201*7387SRobert.Gordon@Sun.COM { 1202*7387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &clp->rb_longbuf); 1203*7387SRobert.Gordon@Sun.COM clist_free(clp); 1204*7387SRobert.Gordon@Sun.COM return (TRUE); 1205*7387SRobert.Gordon@Sun.COM } 1206*7387SRobert.Gordon@Sun.COM 1207*7387SRobert.Gordon@Sun.COM bool_t 1208*7387SRobert.Gordon@Sun.COM xdrrdma_send_read_data(XDR *xdrs, struct clist *wcl) 1209*7387SRobert.Gordon@Sun.COM { 1210*7387SRobert.Gordon@Sun.COM int status; 1211*7387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 1212*7387SRobert.Gordon@Sun.COM struct xdr_ops *xops = xdrrdma_xops(); 1213*7387SRobert.Gordon@Sun.COM 1214*7387SRobert.Gordon@Sun.COM /* caller is doing a sizeof */ 1215*7387SRobert.Gordon@Sun.COM if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_ops == xops) 1216*7387SRobert.Gordon@Sun.COM return (TRUE); 1217*7387SRobert.Gordon@Sun.COM 1218*7387SRobert.Gordon@Sun.COM status = clist_register(xdrp->xp_conn, wcl, CLIST_REG_SOURCE); 1219*7387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 1220*7387SRobert.Gordon@Sun.COM return (FALSE); 1221*7387SRobert.Gordon@Sun.COM } 1222*7387SRobert.Gordon@Sun.COM 1223*7387SRobert.Gordon@Sun.COM status = clist_syncmem(xdrp->xp_conn, wcl, CLIST_REG_SOURCE); 1224*7387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 1225*7387SRobert.Gordon@Sun.COM return (FALSE); 1226*7387SRobert.Gordon@Sun.COM } 1227*7387SRobert.Gordon@Sun.COM 1228*7387SRobert.Gordon@Sun.COM status = RDMA_WRITE(xdrp->xp_conn, wcl, WAIT); 1229*7387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 1230*7387SRobert.Gordon@Sun.COM return (FALSE); 1231*7387SRobert.Gordon@Sun.COM } 1232*7387SRobert.Gordon@Sun.COM 1233*7387SRobert.Gordon@Sun.COM return (TRUE); 1234*7387SRobert.Gordon@Sun.COM } 1235