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 /* 22*11591SFaramarz.Jalalian@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 267387SRobert.Gordon@Sun.COM /* 277387SRobert.Gordon@Sun.COM * Copyright (c) 2007, The Ohio State University. All rights reserved. 287387SRobert.Gordon@Sun.COM * 297387SRobert.Gordon@Sun.COM * Portions of this source code is developed by the team members of 307387SRobert.Gordon@Sun.COM * The Ohio State University's Network-Based Computing Laboratory (NBCL), 317387SRobert.Gordon@Sun.COM * headed by Professor Dhabaleswar K. (DK) Panda. 327387SRobert.Gordon@Sun.COM * 337387SRobert.Gordon@Sun.COM * Acknowledgements to contributions from developors: 347387SRobert.Gordon@Sun.COM * Ranjit Noronha: noronha@cse.ohio-state.edu 357387SRobert.Gordon@Sun.COM * Lei Chai : chail@cse.ohio-state.edu 367387SRobert.Gordon@Sun.COM * Weikuan Yu : yuw@cse.ohio-state.edu 377387SRobert.Gordon@Sun.COM * 387387SRobert.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> 487387SRobert.Gordon@Sun.COM #include <sys/sdt.h> 497387SRobert.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> 567387SRobert.Gordon@Sun.COM #include <sys/sysmacros.h> 570Sstevel@tonic-gate 587387SRobert.Gordon@Sun.COM static bool_t xdrrdma_getint32(XDR *, int32_t *); 597387SRobert.Gordon@Sun.COM static bool_t xdrrdma_putint32(XDR *, int32_t *); 607387SRobert.Gordon@Sun.COM static bool_t xdrrdma_getbytes(XDR *, caddr_t, int); 617387SRobert.Gordon@Sun.COM static bool_t xdrrdma_putbytes(XDR *, caddr_t, int); 627387SRobert.Gordon@Sun.COM uint_t xdrrdma_getpos(XDR *); 637387SRobert.Gordon@Sun.COM bool_t xdrrdma_setpos(XDR *, uint_t); 647387SRobert.Gordon@Sun.COM static rpc_inline_t *xdrrdma_inline(XDR *, int); 657387SRobert.Gordon@Sun.COM void xdrrdma_destroy(XDR *); 667387SRobert.Gordon@Sun.COM static bool_t xdrrdma_control(XDR *, int, void *); 679348SSiddheshwar.Mahesh@Sun.COM static bool_t xdrrdma_read_a_chunk(XDR *, CONN **); 689348SSiddheshwar.Mahesh@Sun.COM static void xdrrdma_free_xdr_chunks(CONN *, struct clist *); 697387SRobert.Gordon@Sun.COM 707387SRobert.Gordon@Sun.COM struct xdr_ops xdrrdmablk_ops = { 717387SRobert.Gordon@Sun.COM xdrrdma_getbytes, 727387SRobert.Gordon@Sun.COM xdrrdma_putbytes, 737387SRobert.Gordon@Sun.COM xdrrdma_getpos, 747387SRobert.Gordon@Sun.COM xdrrdma_setpos, 757387SRobert.Gordon@Sun.COM xdrrdma_inline, 767387SRobert.Gordon@Sun.COM xdrrdma_destroy, 777387SRobert.Gordon@Sun.COM xdrrdma_control, 787387SRobert.Gordon@Sun.COM xdrrdma_getint32, 797387SRobert.Gordon@Sun.COM xdrrdma_putint32 807387SRobert.Gordon@Sun.COM }; 817387SRobert.Gordon@Sun.COM 827387SRobert.Gordon@Sun.COM struct xdr_ops xdrrdma_ops = { 837387SRobert.Gordon@Sun.COM xdrrdma_getbytes, 847387SRobert.Gordon@Sun.COM xdrrdma_putbytes, 857387SRobert.Gordon@Sun.COM xdrrdma_getpos, 867387SRobert.Gordon@Sun.COM xdrrdma_setpos, 877387SRobert.Gordon@Sun.COM xdrrdma_inline, 887387SRobert.Gordon@Sun.COM xdrrdma_destroy, 897387SRobert.Gordon@Sun.COM xdrrdma_control, 907387SRobert.Gordon@Sun.COM xdrrdma_getint32, 917387SRobert.Gordon@Sun.COM xdrrdma_putint32 927387SRobert.Gordon@Sun.COM }; 930Sstevel@tonic-gate 940Sstevel@tonic-gate /* 957387SRobert.Gordon@Sun.COM * A chunk list entry identifies a chunk of opaque data to be moved 967387SRobert.Gordon@Sun.COM * separately from the rest of the RPC message. xp_min_chunk = 0, is a 977387SRobert.Gordon@Sun.COM * special case for ENCODING, which means do not chunk the incoming stream of 987387SRobert.Gordon@Sun.COM * data. 999348SSiddheshwar.Mahesh@Sun.COM * 1009348SSiddheshwar.Mahesh@Sun.COM * A read chunk can contain part of the RPC message in addition to the 1019348SSiddheshwar.Mahesh@Sun.COM * inline message. In such a case, (xp_offp - x_base) will not provide 1029348SSiddheshwar.Mahesh@Sun.COM * the correct xdr offset of the entire message. xp_off is used in such 1039348SSiddheshwar.Mahesh@Sun.COM * a case to denote the offset or current position in the overall message 1049348SSiddheshwar.Mahesh@Sun.COM * covering both the inline and the chunk. This is used only in the case 1059348SSiddheshwar.Mahesh@Sun.COM * of decoding and useful to compare read chunk 'c_xdroff' offsets. 1069348SSiddheshwar.Mahesh@Sun.COM * 1079348SSiddheshwar.Mahesh@Sun.COM * An example for a read chunk containing an XDR message: 1089348SSiddheshwar.Mahesh@Sun.COM * An NFSv4 compound as following: 1099348SSiddheshwar.Mahesh@Sun.COM * 1109348SSiddheshwar.Mahesh@Sun.COM * PUTFH 1119348SSiddheshwar.Mahesh@Sun.COM * WRITE [4109 bytes] 1129348SSiddheshwar.Mahesh@Sun.COM * GETATTR 1139348SSiddheshwar.Mahesh@Sun.COM * 1149348SSiddheshwar.Mahesh@Sun.COM * Solaris Encoding is: 1159348SSiddheshwar.Mahesh@Sun.COM * ------------------- 1169348SSiddheshwar.Mahesh@Sun.COM * 1179348SSiddheshwar.Mahesh@Sun.COM * <Inline message>: [PUTFH WRITE4args GETATTR] 1189348SSiddheshwar.Mahesh@Sun.COM * | 1199348SSiddheshwar.Mahesh@Sun.COM * v 1209348SSiddheshwar.Mahesh@Sun.COM * [RDMA_READ chunks]: [write data] 1219348SSiddheshwar.Mahesh@Sun.COM * 1229348SSiddheshwar.Mahesh@Sun.COM * 1239348SSiddheshwar.Mahesh@Sun.COM * Linux encoding is: 1249348SSiddheshwar.Mahesh@Sun.COM * ----------------- 1259348SSiddheshwar.Mahesh@Sun.COM * 1269348SSiddheshwar.Mahesh@Sun.COM * <Inline message>: [PUTFH WRITE4args] 1279348SSiddheshwar.Mahesh@Sun.COM * | 1289348SSiddheshwar.Mahesh@Sun.COM * v 1299348SSiddheshwar.Mahesh@Sun.COM * [RDMA_READ chunks]: [Write data] [Write data2] [Getattr chunk] 1309348SSiddheshwar.Mahesh@Sun.COM * chunk1 chunk2 chunk3 1319348SSiddheshwar.Mahesh@Sun.COM * 1329348SSiddheshwar.Mahesh@Sun.COM * where the READ chunks are as: 1339348SSiddheshwar.Mahesh@Sun.COM * 1349348SSiddheshwar.Mahesh@Sun.COM * - chunk1 - 4k 1359348SSiddheshwar.Mahesh@Sun.COM * write data | 1369348SSiddheshwar.Mahesh@Sun.COM * - chunk2 - 13 bytes(4109 - 4k) 1379348SSiddheshwar.Mahesh@Sun.COM * getattr op - chunk3 - 19 bytes 1389348SSiddheshwar.Mahesh@Sun.COM * (getattr op starts at byte 4 after 3 bytes of roundup) 1399348SSiddheshwar.Mahesh@Sun.COM * 1400Sstevel@tonic-gate */ 1410Sstevel@tonic-gate 1427387SRobert.Gordon@Sun.COM typedef struct { 1430Sstevel@tonic-gate caddr_t xp_offp; 1440Sstevel@tonic-gate int xp_min_chunk; 1450Sstevel@tonic-gate uint_t xp_flags; /* Controls setting for rdma xdr */ 1467387SRobert.Gordon@Sun.COM int xp_buf_size; /* size of xdr buffer */ 1479348SSiddheshwar.Mahesh@Sun.COM int xp_off; /* overall offset */ 1489348SSiddheshwar.Mahesh@Sun.COM struct clist *xp_rcl; /* head of chunk list */ 1497387SRobert.Gordon@Sun.COM struct clist **xp_rcl_next; /* location to place/find next chunk */ 1509348SSiddheshwar.Mahesh@Sun.COM struct clist *xp_rcl_xdr; /* copy of rcl containing RPC message */ 1517387SRobert.Gordon@Sun.COM struct clist *xp_wcl; /* head of write chunk list */ 1520Sstevel@tonic-gate CONN *xp_conn; /* connection for chunk data xfer */ 1537387SRobert.Gordon@Sun.COM uint_t xp_reply_chunk_len; 1547387SRobert.Gordon@Sun.COM /* used to track length for security modes: integrity/privacy */ 1557387SRobert.Gordon@Sun.COM uint_t xp_reply_chunk_len_alt; 1567387SRobert.Gordon@Sun.COM } xrdma_private_t; 1577387SRobert.Gordon@Sun.COM 1587387SRobert.Gordon@Sun.COM extern kmem_cache_t *clist_cache; 1597387SRobert.Gordon@Sun.COM 1607387SRobert.Gordon@Sun.COM bool_t 1617387SRobert.Gordon@Sun.COM xdrrdma_getrdmablk(XDR *xdrs, struct clist **rlist, uint_t *sizep, 1627387SRobert.Gordon@Sun.COM CONN **conn, const uint_t maxsize) 1637387SRobert.Gordon@Sun.COM { 1647387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 1657387SRobert.Gordon@Sun.COM struct clist *cle = *(xdrp->xp_rcl_next); 1667387SRobert.Gordon@Sun.COM struct clist *rdclist = NULL, *prev = NULL; 1677387SRobert.Gordon@Sun.COM bool_t retval = TRUE; 1687387SRobert.Gordon@Sun.COM uint32_t cur_offset = 0; 1697387SRobert.Gordon@Sun.COM uint32_t total_segments = 0; 1707387SRobert.Gordon@Sun.COM uint32_t actual_segments = 0; 1717387SRobert.Gordon@Sun.COM uint32_t alen; 1727387SRobert.Gordon@Sun.COM uint_t total_len; 1737387SRobert.Gordon@Sun.COM 1747387SRobert.Gordon@Sun.COM ASSERT(xdrs->x_op != XDR_FREE); 1757387SRobert.Gordon@Sun.COM 1767387SRobert.Gordon@Sun.COM /* 1777387SRobert.Gordon@Sun.COM * first deal with the length since xdr bytes are counted 1787387SRobert.Gordon@Sun.COM */ 1797387SRobert.Gordon@Sun.COM if (!xdr_u_int(xdrs, sizep)) { 1807387SRobert.Gordon@Sun.COM DTRACE_PROBE(xdr__e__getrdmablk_sizep_fail); 1817387SRobert.Gordon@Sun.COM return (FALSE); 1827387SRobert.Gordon@Sun.COM } 1837387SRobert.Gordon@Sun.COM total_len = *sizep; 1847387SRobert.Gordon@Sun.COM if (total_len > maxsize) { 1857387SRobert.Gordon@Sun.COM DTRACE_PROBE2(xdr__e__getrdmablk_bad_size, 1867387SRobert.Gordon@Sun.COM int, total_len, int, maxsize); 1877387SRobert.Gordon@Sun.COM return (FALSE); 1887387SRobert.Gordon@Sun.COM } 1897387SRobert.Gordon@Sun.COM (*conn) = xdrp->xp_conn; 1907387SRobert.Gordon@Sun.COM 1917387SRobert.Gordon@Sun.COM /* 1927387SRobert.Gordon@Sun.COM * if no data we are done 1937387SRobert.Gordon@Sun.COM */ 1947387SRobert.Gordon@Sun.COM if (total_len == 0) 1957387SRobert.Gordon@Sun.COM return (TRUE); 1967387SRobert.Gordon@Sun.COM 1977387SRobert.Gordon@Sun.COM while (cle) { 1987387SRobert.Gordon@Sun.COM total_segments++; 1997387SRobert.Gordon@Sun.COM cle = cle->c_next; 2007387SRobert.Gordon@Sun.COM } 2017387SRobert.Gordon@Sun.COM 2027387SRobert.Gordon@Sun.COM cle = *(xdrp->xp_rcl_next); 2037387SRobert.Gordon@Sun.COM 2047387SRobert.Gordon@Sun.COM /* 2057387SRobert.Gordon@Sun.COM * If there was a chunk at the current offset, then setup a read 2067387SRobert.Gordon@Sun.COM * chunk list which records the destination address and length 2077387SRobert.Gordon@Sun.COM * and will RDMA READ the data in later. 2087387SRobert.Gordon@Sun.COM */ 2097387SRobert.Gordon@Sun.COM if (cle == NULL) 2107387SRobert.Gordon@Sun.COM return (FALSE); 2110Sstevel@tonic-gate 2127387SRobert.Gordon@Sun.COM if (cle->c_xdroff != (xdrp->xp_offp - xdrs->x_base)) 2137387SRobert.Gordon@Sun.COM return (FALSE); 2147387SRobert.Gordon@Sun.COM 2157387SRobert.Gordon@Sun.COM /* 2167387SRobert.Gordon@Sun.COM * Setup the chunk list with appropriate 2177387SRobert.Gordon@Sun.COM * address (offset) and length 2187387SRobert.Gordon@Sun.COM */ 2197387SRobert.Gordon@Sun.COM for (actual_segments = 0; 2207387SRobert.Gordon@Sun.COM actual_segments < total_segments; actual_segments++) { 2219348SSiddheshwar.Mahesh@Sun.COM 2229348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE3(krpc__i__xdrrdma_getrdmablk, uint32_t, cle->c_len, 2239348SSiddheshwar.Mahesh@Sun.COM uint32_t, total_len, uint32_t, cle->c_xdroff); 2249348SSiddheshwar.Mahesh@Sun.COM 2257387SRobert.Gordon@Sun.COM if (total_len <= 0) 2267387SRobert.Gordon@Sun.COM break; 2279348SSiddheshwar.Mahesh@Sun.COM 2289348SSiddheshwar.Mahesh@Sun.COM /* 2299348SSiddheshwar.Mahesh@Sun.COM * not the first time in the loop 2309348SSiddheshwar.Mahesh@Sun.COM */ 2319348SSiddheshwar.Mahesh@Sun.COM if (actual_segments > 0) 2329348SSiddheshwar.Mahesh@Sun.COM cle = cle->c_next; 2339348SSiddheshwar.Mahesh@Sun.COM 2347387SRobert.Gordon@Sun.COM cle->u.c_daddr = (uint64) cur_offset; 2357387SRobert.Gordon@Sun.COM alen = 0; 2367387SRobert.Gordon@Sun.COM if (cle->c_len > total_len) { 2377387SRobert.Gordon@Sun.COM alen = cle->c_len; 2387387SRobert.Gordon@Sun.COM cle->c_len = total_len; 2397387SRobert.Gordon@Sun.COM } 2407387SRobert.Gordon@Sun.COM if (!alen) 2417387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &cle->c_next; 2427387SRobert.Gordon@Sun.COM 2437387SRobert.Gordon@Sun.COM cur_offset += cle->c_len; 2447387SRobert.Gordon@Sun.COM total_len -= cle->c_len; 2457387SRobert.Gordon@Sun.COM 2467387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) == 0 && 2477387SRobert.Gordon@Sun.COM total_len > 0) { 2487387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__xdrrdma_getblk_chunktooshort); 2497387SRobert.Gordon@Sun.COM retval = FALSE; 2507387SRobert.Gordon@Sun.COM } 2517387SRobert.Gordon@Sun.COM 2527387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) > 0 && 2537387SRobert.Gordon@Sun.COM total_len == 0) { 2547387SRobert.Gordon@Sun.COM DTRACE_PROBE2(krpc__e__xdrrdma_getblk_toobig, 2557387SRobert.Gordon@Sun.COM int, total_segments, int, actual_segments); 2567387SRobert.Gordon@Sun.COM } 2577387SRobert.Gordon@Sun.COM 2587387SRobert.Gordon@Sun.COM rdclist = clist_alloc(); 2597387SRobert.Gordon@Sun.COM (*rdclist) = (*cle); 2607387SRobert.Gordon@Sun.COM if ((*rlist) == NULL) 2617387SRobert.Gordon@Sun.COM (*rlist) = rdclist; 2627387SRobert.Gordon@Sun.COM if (prev == NULL) 2637387SRobert.Gordon@Sun.COM prev = rdclist; 2647387SRobert.Gordon@Sun.COM else { 2657387SRobert.Gordon@Sun.COM prev->c_next = rdclist; 2667387SRobert.Gordon@Sun.COM prev = rdclist; 2677387SRobert.Gordon@Sun.COM } 2687387SRobert.Gordon@Sun.COM 2697387SRobert.Gordon@Sun.COM } 2707387SRobert.Gordon@Sun.COM 2717387SRobert.Gordon@Sun.COM out: 2727387SRobert.Gordon@Sun.COM if (prev != NULL) 2737387SRobert.Gordon@Sun.COM prev->c_next = NULL; 2747387SRobert.Gordon@Sun.COM 2759348SSiddheshwar.Mahesh@Sun.COM /* 2769348SSiddheshwar.Mahesh@Sun.COM * Adjust the chunk length, if we read only a part of 2779348SSiddheshwar.Mahesh@Sun.COM * a chunk. 2789348SSiddheshwar.Mahesh@Sun.COM */ 2799348SSiddheshwar.Mahesh@Sun.COM 2807387SRobert.Gordon@Sun.COM if (alen) { 2817387SRobert.Gordon@Sun.COM cle->w.c_saddr = 2827387SRobert.Gordon@Sun.COM (uint64)(uintptr_t)cle->w.c_saddr + cle->c_len; 2837387SRobert.Gordon@Sun.COM cle->c_len = alen - cle->c_len; 2847387SRobert.Gordon@Sun.COM } 2857387SRobert.Gordon@Sun.COM 2867387SRobert.Gordon@Sun.COM return (retval); 2877387SRobert.Gordon@Sun.COM } 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate /* 2907387SRobert.Gordon@Sun.COM * The procedure xdrrdma_create initializes a stream descriptor for a memory 2917387SRobert.Gordon@Sun.COM * buffer. 2920Sstevel@tonic-gate */ 2930Sstevel@tonic-gate void 2940Sstevel@tonic-gate xdrrdma_create(XDR *xdrs, caddr_t addr, uint_t size, 2957387SRobert.Gordon@Sun.COM int min_chunk, struct clist *cl, enum xdr_op op, CONN *conn) 2960Sstevel@tonic-gate { 2977387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp; 2987387SRobert.Gordon@Sun.COM struct clist *cle; 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate xdrs->x_op = op; 3017387SRobert.Gordon@Sun.COM xdrs->x_ops = &xdrrdma_ops; 3020Sstevel@tonic-gate xdrs->x_base = addr; 3030Sstevel@tonic-gate xdrs->x_handy = size; 3040Sstevel@tonic-gate xdrs->x_public = NULL; 3050Sstevel@tonic-gate 3067387SRobert.Gordon@Sun.COM xdrp = (xrdma_private_t *)kmem_zalloc(sizeof (xrdma_private_t), 3077387SRobert.Gordon@Sun.COM KM_SLEEP); 3080Sstevel@tonic-gate xdrs->x_private = (caddr_t)xdrp; 3090Sstevel@tonic-gate xdrp->xp_offp = addr; 3100Sstevel@tonic-gate xdrp->xp_min_chunk = min_chunk; 3110Sstevel@tonic-gate xdrp->xp_flags = 0; 3120Sstevel@tonic-gate xdrp->xp_buf_size = size; 3137387SRobert.Gordon@Sun.COM xdrp->xp_rcl = cl; 3147387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len = 0; 3157387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len_alt = 0; 3167387SRobert.Gordon@Sun.COM 3170Sstevel@tonic-gate if (op == XDR_ENCODE && cl != NULL) { 3187387SRobert.Gordon@Sun.COM /* Find last element in chunk list and set xp_rcl_next */ 3197387SRobert.Gordon@Sun.COM for (cle = cl; cle->c_next != NULL; cle = cle->c_next) 3207387SRobert.Gordon@Sun.COM continue; 3217387SRobert.Gordon@Sun.COM 3227387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &(cle->c_next); 3237387SRobert.Gordon@Sun.COM } else { 3247387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &(xdrp->xp_rcl); 3257387SRobert.Gordon@Sun.COM } 3267387SRobert.Gordon@Sun.COM 3277387SRobert.Gordon@Sun.COM xdrp->xp_wcl = NULL; 3287387SRobert.Gordon@Sun.COM 3290Sstevel@tonic-gate xdrp->xp_conn = conn; 3307387SRobert.Gordon@Sun.COM if (xdrp->xp_min_chunk != 0) 3317387SRobert.Gordon@Sun.COM xdrp->xp_flags |= XDR_RDMA_CHUNK; 3320Sstevel@tonic-gate } 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate /* ARGSUSED */ 3350Sstevel@tonic-gate void 3367387SRobert.Gordon@Sun.COM xdrrdma_destroy(XDR * xdrs) 3370Sstevel@tonic-gate { 3387387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 3397387SRobert.Gordon@Sun.COM 3407387SRobert.Gordon@Sun.COM if (xdrp == NULL) 3417387SRobert.Gordon@Sun.COM return; 3427387SRobert.Gordon@Sun.COM 3437387SRobert.Gordon@Sun.COM if (xdrp->xp_wcl) { 3447387SRobert.Gordon@Sun.COM if (xdrp->xp_flags & XDR_RDMA_WLIST_REG) { 3459348SSiddheshwar.Mahesh@Sun.COM (void) clist_deregister(xdrp->xp_conn, xdrp->xp_wcl); 3467387SRobert.Gordon@Sun.COM rdma_buf_free(xdrp->xp_conn, 3477387SRobert.Gordon@Sun.COM &xdrp->xp_wcl->rb_longbuf); 3487387SRobert.Gordon@Sun.COM } 3497387SRobert.Gordon@Sun.COM clist_free(xdrp->xp_wcl); 3507387SRobert.Gordon@Sun.COM } 3517387SRobert.Gordon@Sun.COM 3527387SRobert.Gordon@Sun.COM if (xdrp->xp_rcl) { 3537387SRobert.Gordon@Sun.COM if (xdrp->xp_flags & XDR_RDMA_RLIST_REG) { 3549348SSiddheshwar.Mahesh@Sun.COM (void) clist_deregister(xdrp->xp_conn, xdrp->xp_rcl); 3557387SRobert.Gordon@Sun.COM rdma_buf_free(xdrp->xp_conn, 3567387SRobert.Gordon@Sun.COM &xdrp->xp_rcl->rb_longbuf); 3577387SRobert.Gordon@Sun.COM } 3587387SRobert.Gordon@Sun.COM clist_free(xdrp->xp_rcl); 3597387SRobert.Gordon@Sun.COM } 3607387SRobert.Gordon@Sun.COM 3619348SSiddheshwar.Mahesh@Sun.COM if (xdrp->xp_rcl_xdr) 3629348SSiddheshwar.Mahesh@Sun.COM xdrrdma_free_xdr_chunks(xdrp->xp_conn, xdrp->xp_rcl_xdr); 3639348SSiddheshwar.Mahesh@Sun.COM 3647387SRobert.Gordon@Sun.COM (void) kmem_free(xdrs->x_private, sizeof (xrdma_private_t)); 3657387SRobert.Gordon@Sun.COM xdrs->x_private = NULL; 3660Sstevel@tonic-gate } 3670Sstevel@tonic-gate 3687387SRobert.Gordon@Sun.COM static bool_t 3690Sstevel@tonic-gate xdrrdma_getint32(XDR *xdrs, int32_t *int32p) 3700Sstevel@tonic-gate { 3717387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 3729348SSiddheshwar.Mahesh@Sun.COM int chunked = 0; 3730Sstevel@tonic-gate 3749348SSiddheshwar.Mahesh@Sun.COM if ((xdrs->x_handy -= (int)sizeof (int32_t)) < 0) { 3759348SSiddheshwar.Mahesh@Sun.COM /* 3769348SSiddheshwar.Mahesh@Sun.COM * check if rest of the rpc message is in a chunk 3779348SSiddheshwar.Mahesh@Sun.COM */ 3789348SSiddheshwar.Mahesh@Sun.COM if (!xdrrdma_read_a_chunk(xdrs, &xdrp->xp_conn)) { 3799348SSiddheshwar.Mahesh@Sun.COM return (FALSE); 3809348SSiddheshwar.Mahesh@Sun.COM } 3819348SSiddheshwar.Mahesh@Sun.COM chunked = 1; 3829348SSiddheshwar.Mahesh@Sun.COM } 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate /* LINTED pointer alignment */ 3850Sstevel@tonic-gate *int32p = (int32_t)ntohl((uint32_t)(*((int32_t *)(xdrp->xp_offp)))); 3869348SSiddheshwar.Mahesh@Sun.COM 3879348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE1(krpc__i__xdrrdma_getint32, int32_t, *int32p); 3889348SSiddheshwar.Mahesh@Sun.COM 3890Sstevel@tonic-gate xdrp->xp_offp += sizeof (int32_t); 3900Sstevel@tonic-gate 3919348SSiddheshwar.Mahesh@Sun.COM if (chunked) 3929348SSiddheshwar.Mahesh@Sun.COM xdrs->x_handy -= (int)sizeof (int32_t); 3939348SSiddheshwar.Mahesh@Sun.COM 3949348SSiddheshwar.Mahesh@Sun.COM if (xdrp->xp_off != 0) { 3959348SSiddheshwar.Mahesh@Sun.COM xdrp->xp_off += sizeof (int32_t); 3969348SSiddheshwar.Mahesh@Sun.COM } 3979348SSiddheshwar.Mahesh@Sun.COM 3980Sstevel@tonic-gate return (TRUE); 3990Sstevel@tonic-gate } 4000Sstevel@tonic-gate 4017387SRobert.Gordon@Sun.COM static bool_t 4020Sstevel@tonic-gate xdrrdma_putint32(XDR *xdrs, int32_t *int32p) 4030Sstevel@tonic-gate { 4047387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate if ((xdrs->x_handy -= (int)sizeof (int32_t)) < 0) 4070Sstevel@tonic-gate return (FALSE); 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate /* LINTED pointer alignment */ 4100Sstevel@tonic-gate *(int32_t *)xdrp->xp_offp = (int32_t)htonl((uint32_t)(*int32p)); 4110Sstevel@tonic-gate xdrp->xp_offp += sizeof (int32_t); 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate return (TRUE); 4140Sstevel@tonic-gate } 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate /* 4177387SRobert.Gordon@Sun.COM * DECODE bytes from XDR stream for rdma. 4187387SRobert.Gordon@Sun.COM * If the XDR stream contains a read chunk list, 4197387SRobert.Gordon@Sun.COM * it will go through xdrrdma_getrdmablk instead. 4200Sstevel@tonic-gate */ 4217387SRobert.Gordon@Sun.COM static bool_t 4220Sstevel@tonic-gate xdrrdma_getbytes(XDR *xdrs, caddr_t addr, int len) 4230Sstevel@tonic-gate { 4247387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 4257387SRobert.Gordon@Sun.COM struct clist *cle = *(xdrp->xp_rcl_next); 4267387SRobert.Gordon@Sun.COM struct clist *cls = *(xdrp->xp_rcl_next); 4277387SRobert.Gordon@Sun.COM struct clist cl; 4287387SRobert.Gordon@Sun.COM bool_t retval = TRUE; 4297387SRobert.Gordon@Sun.COM uint32_t total_len = len; 4307387SRobert.Gordon@Sun.COM uint32_t cur_offset = 0; 4317387SRobert.Gordon@Sun.COM uint32_t total_segments = 0; 4327387SRobert.Gordon@Sun.COM uint32_t actual_segments = 0; 4339803SSiddheshwar.Mahesh@Sun.COM uint32_t status = RDMA_SUCCESS; 4349803SSiddheshwar.Mahesh@Sun.COM uint32_t alen = 0; 4359348SSiddheshwar.Mahesh@Sun.COM uint32_t xpoff; 4360Sstevel@tonic-gate 4377387SRobert.Gordon@Sun.COM while (cle) { 4387387SRobert.Gordon@Sun.COM total_segments++; 4397387SRobert.Gordon@Sun.COM cle = cle->c_next; 4407387SRobert.Gordon@Sun.COM } 4417387SRobert.Gordon@Sun.COM 4427387SRobert.Gordon@Sun.COM cle = *(xdrp->xp_rcl_next); 4439348SSiddheshwar.Mahesh@Sun.COM 4449348SSiddheshwar.Mahesh@Sun.COM if (xdrp->xp_off) { 4459348SSiddheshwar.Mahesh@Sun.COM xpoff = xdrp->xp_off; 4469348SSiddheshwar.Mahesh@Sun.COM } else { 4479348SSiddheshwar.Mahesh@Sun.COM xpoff = (xdrp->xp_offp - xdrs->x_base); 4489348SSiddheshwar.Mahesh@Sun.COM } 4499348SSiddheshwar.Mahesh@Sun.COM 4500Sstevel@tonic-gate /* 4517387SRobert.Gordon@Sun.COM * If there was a chunk at the current offset, then setup a read 4527387SRobert.Gordon@Sun.COM * chunk list which records the destination address and length 4537387SRobert.Gordon@Sun.COM * and will RDMA READ the data in later. 4540Sstevel@tonic-gate */ 4557387SRobert.Gordon@Sun.COM 4569348SSiddheshwar.Mahesh@Sun.COM if (cle != NULL && cle->c_xdroff == xpoff) { 4577387SRobert.Gordon@Sun.COM for (actual_segments = 0; 4587387SRobert.Gordon@Sun.COM actual_segments < total_segments; actual_segments++) { 4599803SSiddheshwar.Mahesh@Sun.COM 4607387SRobert.Gordon@Sun.COM if (total_len <= 0) 4617387SRobert.Gordon@Sun.COM break; 4629803SSiddheshwar.Mahesh@Sun.COM 4639803SSiddheshwar.Mahesh@Sun.COM if (status != RDMA_SUCCESS) 4649803SSiddheshwar.Mahesh@Sun.COM goto out; 4659803SSiddheshwar.Mahesh@Sun.COM 4667387SRobert.Gordon@Sun.COM cle->u.c_daddr = (uint64)(uintptr_t)addr + cur_offset; 4677387SRobert.Gordon@Sun.COM alen = 0; 4687387SRobert.Gordon@Sun.COM if (cle->c_len > total_len) { 4697387SRobert.Gordon@Sun.COM alen = cle->c_len; 4707387SRobert.Gordon@Sun.COM cle->c_len = total_len; 4717387SRobert.Gordon@Sun.COM } 4727387SRobert.Gordon@Sun.COM if (!alen) 4737387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &cle->c_next; 4747387SRobert.Gordon@Sun.COM 4757387SRobert.Gordon@Sun.COM cur_offset += cle->c_len; 4767387SRobert.Gordon@Sun.COM total_len -= cle->c_len; 4777387SRobert.Gordon@Sun.COM 4787387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) == 0 && 4797387SRobert.Gordon@Sun.COM total_len > 0) { 4807387SRobert.Gordon@Sun.COM DTRACE_PROBE( 4817387SRobert.Gordon@Sun.COM krpc__e__xdrrdma_getbytes_chunktooshort); 4827387SRobert.Gordon@Sun.COM retval = FALSE; 4837387SRobert.Gordon@Sun.COM } 4847387SRobert.Gordon@Sun.COM 4857387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) > 0 && 4867387SRobert.Gordon@Sun.COM total_len == 0) { 4877387SRobert.Gordon@Sun.COM DTRACE_PROBE2(krpc__e__xdrrdma_getbytes_toobig, 4887387SRobert.Gordon@Sun.COM int, total_segments, int, actual_segments); 4897387SRobert.Gordon@Sun.COM } 4900Sstevel@tonic-gate 4917387SRobert.Gordon@Sun.COM /* 4927387SRobert.Gordon@Sun.COM * RDMA READ the chunk data from the remote end. 4937387SRobert.Gordon@Sun.COM * First prep the destination buffer by registering 4947387SRobert.Gordon@Sun.COM * it, then RDMA READ the chunk data. Since we are 4957387SRobert.Gordon@Sun.COM * doing streaming memory, sync the destination 4967387SRobert.Gordon@Sun.COM * buffer to CPU and deregister the buffer. 4977387SRobert.Gordon@Sun.COM */ 4987387SRobert.Gordon@Sun.COM if (xdrp->xp_conn == NULL) { 4997387SRobert.Gordon@Sun.COM return (FALSE); 5007387SRobert.Gordon@Sun.COM } 5017387SRobert.Gordon@Sun.COM cl = *cle; 5027387SRobert.Gordon@Sun.COM cl.c_next = NULL; 5039803SSiddheshwar.Mahesh@Sun.COM status = clist_register(xdrp->xp_conn, &cl, 5049803SSiddheshwar.Mahesh@Sun.COM CLIST_REG_DST); 5059803SSiddheshwar.Mahesh@Sun.COM if (status != RDMA_SUCCESS) { 5069803SSiddheshwar.Mahesh@Sun.COM retval = FALSE; 5079803SSiddheshwar.Mahesh@Sun.COM /* 5089803SSiddheshwar.Mahesh@Sun.COM * Deregister the previous chunks 5099803SSiddheshwar.Mahesh@Sun.COM * before return 5109803SSiddheshwar.Mahesh@Sun.COM */ 5119803SSiddheshwar.Mahesh@Sun.COM goto out; 5127387SRobert.Gordon@Sun.COM } 5139803SSiddheshwar.Mahesh@Sun.COM 5147387SRobert.Gordon@Sun.COM cle->c_dmemhandle = cl.c_dmemhandle; 5157387SRobert.Gordon@Sun.COM cle->c_dsynchandle = cl.c_dsynchandle; 5160Sstevel@tonic-gate 5177387SRobert.Gordon@Sun.COM /* 5187387SRobert.Gordon@Sun.COM * Now read the chunk in 5197387SRobert.Gordon@Sun.COM */ 5207387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) == 0 || 5217387SRobert.Gordon@Sun.COM total_len == 0) { 5227387SRobert.Gordon@Sun.COM status = RDMA_READ(xdrp->xp_conn, &cl, WAIT); 5237387SRobert.Gordon@Sun.COM } else { 5247387SRobert.Gordon@Sun.COM status = RDMA_READ(xdrp->xp_conn, &cl, NOWAIT); 5257387SRobert.Gordon@Sun.COM } 5267387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 5277387SRobert.Gordon@Sun.COM DTRACE_PROBE1( 5287387SRobert.Gordon@Sun.COM krpc__i__xdrrdma_getblk_readfailed, 5297387SRobert.Gordon@Sun.COM int, status); 5307387SRobert.Gordon@Sun.COM retval = FALSE; 5317387SRobert.Gordon@Sun.COM } 5329803SSiddheshwar.Mahesh@Sun.COM 5337387SRobert.Gordon@Sun.COM cle = cle->c_next; 5349803SSiddheshwar.Mahesh@Sun.COM 5350Sstevel@tonic-gate } 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate /* 5380Sstevel@tonic-gate * sync the memory for cpu 5390Sstevel@tonic-gate */ 5407387SRobert.Gordon@Sun.COM cl = *cls; 5417387SRobert.Gordon@Sun.COM cl.c_next = NULL; 5427387SRobert.Gordon@Sun.COM cl.c_len = cur_offset; 5439348SSiddheshwar.Mahesh@Sun.COM if (clist_syncmem( 5449348SSiddheshwar.Mahesh@Sun.COM xdrp->xp_conn, &cl, CLIST_REG_DST) != RDMA_SUCCESS) { 5450Sstevel@tonic-gate retval = FALSE; 5460Sstevel@tonic-gate } 5470Sstevel@tonic-gate out: 5489803SSiddheshwar.Mahesh@Sun.COM 5490Sstevel@tonic-gate /* 5500Sstevel@tonic-gate * Deregister the chunks 5510Sstevel@tonic-gate */ 5527387SRobert.Gordon@Sun.COM cle = cls; 5539803SSiddheshwar.Mahesh@Sun.COM while (actual_segments != 0) { 5549803SSiddheshwar.Mahesh@Sun.COM cl = *cle; 5559803SSiddheshwar.Mahesh@Sun.COM cl.c_next = NULL; 5569803SSiddheshwar.Mahesh@Sun.COM 5579803SSiddheshwar.Mahesh@Sun.COM cl.c_regtype = CLIST_REG_DST; 5589803SSiddheshwar.Mahesh@Sun.COM (void) clist_deregister(xdrp->xp_conn, &cl); 5599803SSiddheshwar.Mahesh@Sun.COM 5609803SSiddheshwar.Mahesh@Sun.COM cle = cle->c_next; 5619803SSiddheshwar.Mahesh@Sun.COM actual_segments--; 5629803SSiddheshwar.Mahesh@Sun.COM } 5639803SSiddheshwar.Mahesh@Sun.COM 5647387SRobert.Gordon@Sun.COM if (alen) { 5659803SSiddheshwar.Mahesh@Sun.COM cle = *(xdrp->xp_rcl_next); 5667387SRobert.Gordon@Sun.COM cle->w.c_saddr = 5677387SRobert.Gordon@Sun.COM (uint64)(uintptr_t)cle->w.c_saddr + cle->c_len; 5687387SRobert.Gordon@Sun.COM cle->c_len = alen - cle->c_len; 5697387SRobert.Gordon@Sun.COM } 5709803SSiddheshwar.Mahesh@Sun.COM 5710Sstevel@tonic-gate return (retval); 5720Sstevel@tonic-gate } 5739348SSiddheshwar.Mahesh@Sun.COM 5740Sstevel@tonic-gate if ((xdrs->x_handy -= len) < 0) 5750Sstevel@tonic-gate return (FALSE); 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate bcopy(xdrp->xp_offp, addr, len); 5789348SSiddheshwar.Mahesh@Sun.COM 5790Sstevel@tonic-gate xdrp->xp_offp += len; 5800Sstevel@tonic-gate 5819348SSiddheshwar.Mahesh@Sun.COM if (xdrp->xp_off != 0) 5829348SSiddheshwar.Mahesh@Sun.COM xdrp->xp_off += len; 5839348SSiddheshwar.Mahesh@Sun.COM 5840Sstevel@tonic-gate return (TRUE); 5850Sstevel@tonic-gate } 5860Sstevel@tonic-gate 5870Sstevel@tonic-gate /* 5887387SRobert.Gordon@Sun.COM * ENCODE some bytes into an XDR stream xp_min_chunk = 0, means the stream of 5897387SRobert.Gordon@Sun.COM * bytes contain no chunks to seperate out, and if the bytes do not fit in 5907387SRobert.Gordon@Sun.COM * the supplied buffer, grow the buffer and free the old buffer. 5910Sstevel@tonic-gate */ 5927387SRobert.Gordon@Sun.COM static bool_t 5930Sstevel@tonic-gate xdrrdma_putbytes(XDR *xdrs, caddr_t addr, int len) 5940Sstevel@tonic-gate { 5957387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 5960Sstevel@tonic-gate /* 5977387SRobert.Gordon@Sun.COM * Is this stream accepting chunks? 5987387SRobert.Gordon@Sun.COM * If so, does the either of the two following conditions exist? 5997387SRobert.Gordon@Sun.COM * - length of bytes to encode is greater than the min chunk size? 6007387SRobert.Gordon@Sun.COM * - remaining space in this stream is shorter than length of 6017387SRobert.Gordon@Sun.COM * bytes to encode? 6027387SRobert.Gordon@Sun.COM * 6037387SRobert.Gordon@Sun.COM * If the above exists, then create a chunk for this encoding 6047387SRobert.Gordon@Sun.COM * and save the addresses, etc. 6050Sstevel@tonic-gate */ 6067387SRobert.Gordon@Sun.COM if (xdrp->xp_flags & XDR_RDMA_CHUNK && 6077387SRobert.Gordon@Sun.COM ((xdrp->xp_min_chunk != 0 && 6087387SRobert.Gordon@Sun.COM len >= xdrp->xp_min_chunk) || 6097387SRobert.Gordon@Sun.COM (xdrs->x_handy - len < 0))) { 6107387SRobert.Gordon@Sun.COM struct clist *cle; 6117387SRobert.Gordon@Sun.COM int offset = xdrp->xp_offp - xdrs->x_base; 6120Sstevel@tonic-gate 6137387SRobert.Gordon@Sun.COM cle = clist_alloc(); 6140Sstevel@tonic-gate cle->c_xdroff = offset; 6157387SRobert.Gordon@Sun.COM cle->c_len = len; 6167387SRobert.Gordon@Sun.COM cle->w.c_saddr = (uint64)(uintptr_t)addr; 6170Sstevel@tonic-gate cle->c_next = NULL; 6180Sstevel@tonic-gate 6197387SRobert.Gordon@Sun.COM *(xdrp->xp_rcl_next) = cle; 6207387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &(cle->c_next); 6210Sstevel@tonic-gate 6220Sstevel@tonic-gate return (TRUE); 6230Sstevel@tonic-gate } 6247387SRobert.Gordon@Sun.COM /* Is there enough space to encode what is left? */ 6250Sstevel@tonic-gate if ((xdrs->x_handy -= len) < 0) { 6267387SRobert.Gordon@Sun.COM return (FALSE); 6270Sstevel@tonic-gate } 6280Sstevel@tonic-gate bcopy(addr, xdrp->xp_offp, len); 6290Sstevel@tonic-gate xdrp->xp_offp += len; 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate return (TRUE); 6320Sstevel@tonic-gate } 6330Sstevel@tonic-gate 6340Sstevel@tonic-gate uint_t 6350Sstevel@tonic-gate xdrrdma_getpos(XDR *xdrs) 6360Sstevel@tonic-gate { 6377387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 6380Sstevel@tonic-gate 6390Sstevel@tonic-gate return ((uint_t)((uintptr_t)xdrp->xp_offp - (uintptr_t)xdrs->x_base)); 6400Sstevel@tonic-gate } 6410Sstevel@tonic-gate 6420Sstevel@tonic-gate bool_t 6430Sstevel@tonic-gate xdrrdma_setpos(XDR *xdrs, uint_t pos) 6440Sstevel@tonic-gate { 6457387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 6460Sstevel@tonic-gate 6477387SRobert.Gordon@Sun.COM caddr_t newaddr = xdrs->x_base + pos; 6487387SRobert.Gordon@Sun.COM caddr_t lastaddr = xdrp->xp_offp + xdrs->x_handy; 6497387SRobert.Gordon@Sun.COM ptrdiff_t diff; 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate if (newaddr > lastaddr) 6520Sstevel@tonic-gate return (FALSE); 6530Sstevel@tonic-gate 6540Sstevel@tonic-gate xdrp->xp_offp = newaddr; 6550Sstevel@tonic-gate diff = lastaddr - newaddr; 6560Sstevel@tonic-gate xdrs->x_handy = (int)diff; 6570Sstevel@tonic-gate 6580Sstevel@tonic-gate return (TRUE); 6590Sstevel@tonic-gate } 6600Sstevel@tonic-gate 6610Sstevel@tonic-gate /* ARGSUSED */ 6620Sstevel@tonic-gate static rpc_inline_t * 6630Sstevel@tonic-gate xdrrdma_inline(XDR *xdrs, int len) 6640Sstevel@tonic-gate { 6657387SRobert.Gordon@Sun.COM rpc_inline_t *buf = NULL; 6667387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 6677387SRobert.Gordon@Sun.COM struct clist *cle = *(xdrp->xp_rcl_next); 6680Sstevel@tonic-gate 6690Sstevel@tonic-gate if (xdrs->x_op == XDR_DECODE) { 6700Sstevel@tonic-gate /* 6717387SRobert.Gordon@Sun.COM * Since chunks aren't in-line, check to see whether there is 6727387SRobert.Gordon@Sun.COM * a chunk in the inline range. 6730Sstevel@tonic-gate */ 6740Sstevel@tonic-gate if (cle != NULL && 6757387SRobert.Gordon@Sun.COM cle->c_xdroff <= (xdrp->xp_offp - xdrs->x_base + len)) 6767387SRobert.Gordon@Sun.COM return (NULL); 6777387SRobert.Gordon@Sun.COM } 6787387SRobert.Gordon@Sun.COM 6797387SRobert.Gordon@Sun.COM /* LINTED pointer alignment */ 6807387SRobert.Gordon@Sun.COM buf = (rpc_inline_t *)xdrp->xp_offp; 6817387SRobert.Gordon@Sun.COM if (!IS_P2ALIGNED(buf, sizeof (int32_t))) 6820Sstevel@tonic-gate return (NULL); 6830Sstevel@tonic-gate 6840Sstevel@tonic-gate if ((xdrs->x_handy < len) || (xdrp->xp_min_chunk != 0 && 6850Sstevel@tonic-gate len >= xdrp->xp_min_chunk)) { 6860Sstevel@tonic-gate return (NULL); 6870Sstevel@tonic-gate } else { 6880Sstevel@tonic-gate xdrs->x_handy -= len; 6890Sstevel@tonic-gate xdrp->xp_offp += len; 6900Sstevel@tonic-gate return (buf); 6910Sstevel@tonic-gate } 6920Sstevel@tonic-gate } 6930Sstevel@tonic-gate 6947387SRobert.Gordon@Sun.COM static bool_t 6950Sstevel@tonic-gate xdrrdma_control(XDR *xdrs, int request, void *info) 6960Sstevel@tonic-gate { 6977387SRobert.Gordon@Sun.COM int32_t *int32p; 6987387SRobert.Gordon@Sun.COM int len, i; 6997387SRobert.Gordon@Sun.COM uint_t in_flags; 7007387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 7017387SRobert.Gordon@Sun.COM rdma_chunkinfo_t *rcip = NULL; 7027387SRobert.Gordon@Sun.COM rdma_wlist_conn_info_t *rwcip = NULL; 7037387SRobert.Gordon@Sun.COM rdma_chunkinfo_lengths_t *rcilp = NULL; 7047387SRobert.Gordon@Sun.COM struct uio *uiop; 7057387SRobert.Gordon@Sun.COM struct clist *rwl = NULL; 7067387SRobert.Gordon@Sun.COM struct clist *prev = NULL; 7070Sstevel@tonic-gate 7080Sstevel@tonic-gate switch (request) { 7090Sstevel@tonic-gate case XDR_PEEK: 7100Sstevel@tonic-gate /* 7110Sstevel@tonic-gate * Return the next 4 byte unit in the XDR stream. 7120Sstevel@tonic-gate */ 7130Sstevel@tonic-gate if (xdrs->x_handy < sizeof (int32_t)) 7140Sstevel@tonic-gate return (FALSE); 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate int32p = (int32_t *)info; 7170Sstevel@tonic-gate *int32p = (int32_t)ntohl((uint32_t) 7180Sstevel@tonic-gate (*((int32_t *)(xdrp->xp_offp)))); 7190Sstevel@tonic-gate 7200Sstevel@tonic-gate return (TRUE); 7210Sstevel@tonic-gate 7220Sstevel@tonic-gate case XDR_SKIPBYTES: 7230Sstevel@tonic-gate /* 7240Sstevel@tonic-gate * Skip the next N bytes in the XDR stream. 7250Sstevel@tonic-gate */ 7260Sstevel@tonic-gate int32p = (int32_t *)info; 7270Sstevel@tonic-gate len = RNDUP((int)(*int32p)); 7280Sstevel@tonic-gate if ((xdrs->x_handy -= len) < 0) 7290Sstevel@tonic-gate return (FALSE); 7300Sstevel@tonic-gate xdrp->xp_offp += len; 7310Sstevel@tonic-gate 7320Sstevel@tonic-gate return (TRUE); 7330Sstevel@tonic-gate 7347387SRobert.Gordon@Sun.COM case XDR_RDMA_SET_FLAGS: 7350Sstevel@tonic-gate /* 7367387SRobert.Gordon@Sun.COM * Set the flags provided in the *info in xp_flags for rdma 7377387SRobert.Gordon@Sun.COM * xdr stream control. 7380Sstevel@tonic-gate */ 7390Sstevel@tonic-gate int32p = (int32_t *)info; 7400Sstevel@tonic-gate in_flags = (uint_t)(*int32p); 7410Sstevel@tonic-gate 7420Sstevel@tonic-gate xdrp->xp_flags |= in_flags; 7430Sstevel@tonic-gate return (TRUE); 7440Sstevel@tonic-gate 7457387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_FLAGS: 7460Sstevel@tonic-gate /* 7470Sstevel@tonic-gate * Get the flags provided in xp_flags return through *info 7480Sstevel@tonic-gate */ 7490Sstevel@tonic-gate int32p = (int32_t *)info; 7500Sstevel@tonic-gate 7510Sstevel@tonic-gate *int32p = (int32_t)xdrp->xp_flags; 7520Sstevel@tonic-gate return (TRUE); 7530Sstevel@tonic-gate 7547387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_CHUNK_LEN: 7557387SRobert.Gordon@Sun.COM rcilp = (rdma_chunkinfo_lengths_t *)info; 7567387SRobert.Gordon@Sun.COM rcilp->rcil_len = xdrp->xp_reply_chunk_len; 7577387SRobert.Gordon@Sun.COM rcilp->rcil_len_alt = xdrp->xp_reply_chunk_len_alt; 7587387SRobert.Gordon@Sun.COM 7597387SRobert.Gordon@Sun.COM return (TRUE); 7607387SRobert.Gordon@Sun.COM 7617387SRobert.Gordon@Sun.COM case XDR_RDMA_ADD_CHUNK: 7627387SRobert.Gordon@Sun.COM /* 7637387SRobert.Gordon@Sun.COM * Store wlist information 7647387SRobert.Gordon@Sun.COM */ 7657387SRobert.Gordon@Sun.COM 7667387SRobert.Gordon@Sun.COM rcip = (rdma_chunkinfo_t *)info; 7677387SRobert.Gordon@Sun.COM 768*11591SFaramarz.Jalalian@Sun.COM DTRACE_PROBE2(krpc__i__xdrrdma__control__add__chunk, 769*11591SFaramarz.Jalalian@Sun.COM rci_type_t, rcip->rci_type, uint32, rcip->rci_len); 7707387SRobert.Gordon@Sun.COM switch (rcip->rci_type) { 7717387SRobert.Gordon@Sun.COM case RCI_WRITE_UIO_CHUNK: 7727387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len_alt += rcip->rci_len; 7737387SRobert.Gordon@Sun.COM 7747387SRobert.Gordon@Sun.COM if (rcip->rci_len < xdrp->xp_min_chunk) { 7757387SRobert.Gordon@Sun.COM xdrp->xp_wcl = NULL; 7767387SRobert.Gordon@Sun.COM *(rcip->rci_clpp) = NULL; 7777387SRobert.Gordon@Sun.COM return (TRUE); 7787387SRobert.Gordon@Sun.COM } 7797387SRobert.Gordon@Sun.COM uiop = rcip->rci_a.rci_uiop; 7807387SRobert.Gordon@Sun.COM 7817387SRobert.Gordon@Sun.COM for (i = 0; i < uiop->uio_iovcnt; i++) { 7827387SRobert.Gordon@Sun.COM rwl = clist_alloc(); 7837387SRobert.Gordon@Sun.COM rwl->c_len = uiop->uio_iov[i].iov_len; 7847387SRobert.Gordon@Sun.COM rwl->u.c_daddr = 7857387SRobert.Gordon@Sun.COM (uint64)(uintptr_t) 7867387SRobert.Gordon@Sun.COM (uiop->uio_iov[i].iov_base); 7877387SRobert.Gordon@Sun.COM /* 7887387SRobert.Gordon@Sun.COM * if userspace address, put adspace ptr in 7897387SRobert.Gordon@Sun.COM * clist. If not, then do nothing since it's 7907387SRobert.Gordon@Sun.COM * already set to NULL (from kmem_zalloc) 7917387SRobert.Gordon@Sun.COM */ 7927387SRobert.Gordon@Sun.COM if (uiop->uio_segflg == UIO_USERSPACE) { 7937387SRobert.Gordon@Sun.COM rwl->c_adspc = ttoproc(curthread)->p_as; 7947387SRobert.Gordon@Sun.COM } 7957387SRobert.Gordon@Sun.COM 7967387SRobert.Gordon@Sun.COM if (prev == NULL) 7977387SRobert.Gordon@Sun.COM prev = rwl; 7987387SRobert.Gordon@Sun.COM else { 7997387SRobert.Gordon@Sun.COM prev->c_next = rwl; 8007387SRobert.Gordon@Sun.COM prev = rwl; 8017387SRobert.Gordon@Sun.COM } 8027387SRobert.Gordon@Sun.COM } 8037387SRobert.Gordon@Sun.COM 8047387SRobert.Gordon@Sun.COM rwl->c_next = NULL; 8057387SRobert.Gordon@Sun.COM xdrp->xp_wcl = rwl; 8067387SRobert.Gordon@Sun.COM *(rcip->rci_clpp) = rwl; 8077387SRobert.Gordon@Sun.COM 8087387SRobert.Gordon@Sun.COM break; 8097387SRobert.Gordon@Sun.COM 8107387SRobert.Gordon@Sun.COM case RCI_WRITE_ADDR_CHUNK: 8117387SRobert.Gordon@Sun.COM rwl = clist_alloc(); 8127387SRobert.Gordon@Sun.COM 8137387SRobert.Gordon@Sun.COM rwl->c_len = rcip->rci_len; 8147387SRobert.Gordon@Sun.COM rwl->u.c_daddr3 = rcip->rci_a.rci_addr; 8157387SRobert.Gordon@Sun.COM rwl->c_next = NULL; 8167387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len_alt += rcip->rci_len; 8177387SRobert.Gordon@Sun.COM 8187387SRobert.Gordon@Sun.COM xdrp->xp_wcl = rwl; 8197387SRobert.Gordon@Sun.COM *(rcip->rci_clpp) = rwl; 8207387SRobert.Gordon@Sun.COM 8217387SRobert.Gordon@Sun.COM break; 8227387SRobert.Gordon@Sun.COM 8237387SRobert.Gordon@Sun.COM case RCI_REPLY_CHUNK: 8247387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len += rcip->rci_len; 8257387SRobert.Gordon@Sun.COM break; 8267387SRobert.Gordon@Sun.COM } 8277387SRobert.Gordon@Sun.COM return (TRUE); 8287387SRobert.Gordon@Sun.COM 8297387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_WLIST: 8307387SRobert.Gordon@Sun.COM *((struct clist **)info) = xdrp->xp_wcl; 8317387SRobert.Gordon@Sun.COM return (TRUE); 8327387SRobert.Gordon@Sun.COM 8337387SRobert.Gordon@Sun.COM case XDR_RDMA_SET_WLIST: 8347387SRobert.Gordon@Sun.COM xdrp->xp_wcl = (struct clist *)info; 8357387SRobert.Gordon@Sun.COM return (TRUE); 8367387SRobert.Gordon@Sun.COM 8377387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_RLIST: 8387387SRobert.Gordon@Sun.COM *((struct clist **)info) = xdrp->xp_rcl; 8397387SRobert.Gordon@Sun.COM return (TRUE); 8407387SRobert.Gordon@Sun.COM 8417387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_WCINFO: 8427387SRobert.Gordon@Sun.COM rwcip = (rdma_wlist_conn_info_t *)info; 8437387SRobert.Gordon@Sun.COM 8447387SRobert.Gordon@Sun.COM rwcip->rwci_wlist = xdrp->xp_wcl; 8457387SRobert.Gordon@Sun.COM rwcip->rwci_conn = xdrp->xp_conn; 8467387SRobert.Gordon@Sun.COM 8477387SRobert.Gordon@Sun.COM return (TRUE); 8487387SRobert.Gordon@Sun.COM 8490Sstevel@tonic-gate default: 8500Sstevel@tonic-gate return (FALSE); 8510Sstevel@tonic-gate } 8520Sstevel@tonic-gate } 8530Sstevel@tonic-gate 8547387SRobert.Gordon@Sun.COM bool_t xdr_do_clist(XDR *, clist **); 8550Sstevel@tonic-gate 8560Sstevel@tonic-gate /* 8577387SRobert.Gordon@Sun.COM * Not all fields in struct clist are interesting to the RPC over RDMA 8587387SRobert.Gordon@Sun.COM * protocol. Only XDR the interesting fields. 8590Sstevel@tonic-gate */ 8600Sstevel@tonic-gate bool_t 8610Sstevel@tonic-gate xdr_clist(XDR *xdrs, clist *objp) 8620Sstevel@tonic-gate { 8630Sstevel@tonic-gate if (!xdr_uint32(xdrs, &objp->c_xdroff)) 8640Sstevel@tonic-gate return (FALSE); 8657387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &objp->c_smemhandle.mrc_rmr)) 8667387SRobert.Gordon@Sun.COM return (FALSE); 8670Sstevel@tonic-gate if (!xdr_uint32(xdrs, &objp->c_len)) 8680Sstevel@tonic-gate return (FALSE); 8697387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &objp->w.c_saddr)) 8700Sstevel@tonic-gate return (FALSE); 8717387SRobert.Gordon@Sun.COM if (!xdr_do_clist(xdrs, &objp->c_next)) 8720Sstevel@tonic-gate return (FALSE); 8730Sstevel@tonic-gate return (TRUE); 8740Sstevel@tonic-gate } 8750Sstevel@tonic-gate 8767387SRobert.Gordon@Sun.COM /* 8777387SRobert.Gordon@Sun.COM * The following two functions are forms of xdr_pointer() 8787387SRobert.Gordon@Sun.COM * and xdr_reference(). Since the generic versions just 8797387SRobert.Gordon@Sun.COM * kmem_alloc() a new clist, we actually want to use the 8807387SRobert.Gordon@Sun.COM * rdma_clist kmem_cache. 8817387SRobert.Gordon@Sun.COM */ 8827387SRobert.Gordon@Sun.COM 8837387SRobert.Gordon@Sun.COM /* 8847387SRobert.Gordon@Sun.COM * Generate or free a clist structure from the 8857387SRobert.Gordon@Sun.COM * kmem_cache "rdma_clist" 8867387SRobert.Gordon@Sun.COM */ 8870Sstevel@tonic-gate bool_t 8887387SRobert.Gordon@Sun.COM xdr_ref_clist(XDR *xdrs, caddr_t *pp) 8890Sstevel@tonic-gate { 8907387SRobert.Gordon@Sun.COM caddr_t loc = *pp; 8917387SRobert.Gordon@Sun.COM bool_t stat; 8927387SRobert.Gordon@Sun.COM 8937387SRobert.Gordon@Sun.COM if (loc == NULL) { 8947387SRobert.Gordon@Sun.COM switch (xdrs->x_op) { 8957387SRobert.Gordon@Sun.COM case XDR_FREE: 8967387SRobert.Gordon@Sun.COM return (TRUE); 8977387SRobert.Gordon@Sun.COM 8987387SRobert.Gordon@Sun.COM case XDR_DECODE: 8997387SRobert.Gordon@Sun.COM *pp = loc = (caddr_t)clist_alloc(); 9007387SRobert.Gordon@Sun.COM break; 9017387SRobert.Gordon@Sun.COM 9027387SRobert.Gordon@Sun.COM case XDR_ENCODE: 9037387SRobert.Gordon@Sun.COM ASSERT(loc); 9047387SRobert.Gordon@Sun.COM break; 9057387SRobert.Gordon@Sun.COM } 9067387SRobert.Gordon@Sun.COM } 9077387SRobert.Gordon@Sun.COM 9087387SRobert.Gordon@Sun.COM stat = xdr_clist(xdrs, (struct clist *)loc); 9097387SRobert.Gordon@Sun.COM 9107387SRobert.Gordon@Sun.COM if (xdrs->x_op == XDR_FREE) { 9117387SRobert.Gordon@Sun.COM kmem_cache_free(clist_cache, loc); 9127387SRobert.Gordon@Sun.COM *pp = NULL; 9137387SRobert.Gordon@Sun.COM } 9147387SRobert.Gordon@Sun.COM return (stat); 9157387SRobert.Gordon@Sun.COM } 9167387SRobert.Gordon@Sun.COM 9177387SRobert.Gordon@Sun.COM /* 9187387SRobert.Gordon@Sun.COM * XDR a pointer to a possibly recursive clist. This differs 9197387SRobert.Gordon@Sun.COM * with xdr_reference in that it can serialize/deserialiaze 9207387SRobert.Gordon@Sun.COM * trees correctly. 9217387SRobert.Gordon@Sun.COM * 9227387SRobert.Gordon@Sun.COM * What is sent is actually a union: 9237387SRobert.Gordon@Sun.COM * 9247387SRobert.Gordon@Sun.COM * union object_pointer switch (boolean b) { 9257387SRobert.Gordon@Sun.COM * case TRUE: object_data data; 9267387SRobert.Gordon@Sun.COM * case FALSE: void nothing; 9277387SRobert.Gordon@Sun.COM * } 9287387SRobert.Gordon@Sun.COM * 9297387SRobert.Gordon@Sun.COM * > objpp: Pointer to the pointer to the object. 9307387SRobert.Gordon@Sun.COM * 9317387SRobert.Gordon@Sun.COM */ 9327387SRobert.Gordon@Sun.COM 9337387SRobert.Gordon@Sun.COM bool_t 9347387SRobert.Gordon@Sun.COM xdr_do_clist(XDR *xdrs, clist **objpp) 9357387SRobert.Gordon@Sun.COM { 9367387SRobert.Gordon@Sun.COM bool_t more_data; 9377387SRobert.Gordon@Sun.COM 9387387SRobert.Gordon@Sun.COM more_data = (*objpp != NULL); 9397387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more_data)) 9407387SRobert.Gordon@Sun.COM return (FALSE); 9417387SRobert.Gordon@Sun.COM if (!more_data) { 9427387SRobert.Gordon@Sun.COM *objpp = NULL; 9437387SRobert.Gordon@Sun.COM return (TRUE); 9447387SRobert.Gordon@Sun.COM } 9457387SRobert.Gordon@Sun.COM return (xdr_ref_clist(xdrs, (caddr_t *)objpp)); 9460Sstevel@tonic-gate } 9470Sstevel@tonic-gate 9480Sstevel@tonic-gate uint_t 9490Sstevel@tonic-gate xdr_getbufsize(XDR *xdrs) 9500Sstevel@tonic-gate { 9517387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 9520Sstevel@tonic-gate 9530Sstevel@tonic-gate return ((uint_t)xdrp->xp_buf_size); 9540Sstevel@tonic-gate } 9557387SRobert.Gordon@Sun.COM 9567387SRobert.Gordon@Sun.COM /* ARGSUSED */ 9577387SRobert.Gordon@Sun.COM bool_t 9587387SRobert.Gordon@Sun.COM xdr_encode_rlist_svc(XDR *xdrs, clist *rlist) 9597387SRobert.Gordon@Sun.COM { 9607387SRobert.Gordon@Sun.COM bool_t vfalse = FALSE; 9617387SRobert.Gordon@Sun.COM 9627387SRobert.Gordon@Sun.COM ASSERT(rlist == NULL); 9637387SRobert.Gordon@Sun.COM return (xdr_bool(xdrs, &vfalse)); 9647387SRobert.Gordon@Sun.COM } 9657387SRobert.Gordon@Sun.COM 9667387SRobert.Gordon@Sun.COM bool_t 9677387SRobert.Gordon@Sun.COM xdr_encode_wlist(XDR *xdrs, clist *w) 9687387SRobert.Gordon@Sun.COM { 9697387SRobert.Gordon@Sun.COM bool_t vfalse = FALSE, vtrue = TRUE; 9707387SRobert.Gordon@Sun.COM int i; 9717387SRobert.Gordon@Sun.COM uint_t num_segment = 0; 9727387SRobert.Gordon@Sun.COM struct clist *cl; 9737387SRobert.Gordon@Sun.COM 9747387SRobert.Gordon@Sun.COM /* does a wlist exist? */ 9757387SRobert.Gordon@Sun.COM if (w == NULL) { 9767387SRobert.Gordon@Sun.COM return (xdr_bool(xdrs, &vfalse)); 9777387SRobert.Gordon@Sun.COM } 9787387SRobert.Gordon@Sun.COM /* Encode N consecutive segments, 1, N, HLOO, ..., HLOO, 0 */ 9797387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &vtrue)) 9807387SRobert.Gordon@Sun.COM return (FALSE); 9817387SRobert.Gordon@Sun.COM 9827387SRobert.Gordon@Sun.COM for (cl = w; cl != NULL; cl = cl->c_next) { 9837387SRobert.Gordon@Sun.COM num_segment++; 9847387SRobert.Gordon@Sun.COM } 9857387SRobert.Gordon@Sun.COM 9867387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &num_segment)) 9877387SRobert.Gordon@Sun.COM return (FALSE); 9887387SRobert.Gordon@Sun.COM for (i = 0; i < num_segment; i++) { 9899348SSiddheshwar.Mahesh@Sun.COM 9909348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE1(krpc__i__xdr_encode_wlist_len, uint_t, w->c_len); 9919348SSiddheshwar.Mahesh@Sun.COM 9927387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &w->c_dmemhandle.mrc_rmr)) 9937387SRobert.Gordon@Sun.COM return (FALSE); 9947387SRobert.Gordon@Sun.COM 9957387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &w->c_len)) 9967387SRobert.Gordon@Sun.COM return (FALSE); 9977387SRobert.Gordon@Sun.COM 9987387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &w->u.c_daddr)) 9997387SRobert.Gordon@Sun.COM return (FALSE); 10007387SRobert.Gordon@Sun.COM 10017387SRobert.Gordon@Sun.COM w = w->c_next; 10027387SRobert.Gordon@Sun.COM } 10037387SRobert.Gordon@Sun.COM 10047387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &vfalse)) 10057387SRobert.Gordon@Sun.COM return (FALSE); 10067387SRobert.Gordon@Sun.COM 10077387SRobert.Gordon@Sun.COM return (TRUE); 10087387SRobert.Gordon@Sun.COM } 10097387SRobert.Gordon@Sun.COM 10107387SRobert.Gordon@Sun.COM 10117387SRobert.Gordon@Sun.COM /* 10127387SRobert.Gordon@Sun.COM * Conditionally decode a RDMA WRITE chunk list from XDR stream. 10137387SRobert.Gordon@Sun.COM * 10147387SRobert.Gordon@Sun.COM * If the next boolean in the XDR stream is false there is no 10157387SRobert.Gordon@Sun.COM * RDMA WRITE chunk list present. Otherwise iterate over the 10167387SRobert.Gordon@Sun.COM * array and for each entry: allocate a struct clist and decode. 10177387SRobert.Gordon@Sun.COM * Pass back an indication via wlist_exists if we have seen a 10187387SRobert.Gordon@Sun.COM * RDMA WRITE chunk list. 10197387SRobert.Gordon@Sun.COM */ 10207387SRobert.Gordon@Sun.COM bool_t 10217387SRobert.Gordon@Sun.COM xdr_decode_wlist(XDR *xdrs, struct clist **w, bool_t *wlist_exists) 10227387SRobert.Gordon@Sun.COM { 10237387SRobert.Gordon@Sun.COM struct clist *tmp; 10247387SRobert.Gordon@Sun.COM bool_t more = FALSE; 10257387SRobert.Gordon@Sun.COM uint32_t seg_array_len; 10267387SRobert.Gordon@Sun.COM uint32_t i; 10277387SRobert.Gordon@Sun.COM 10287387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more)) 10297387SRobert.Gordon@Sun.COM return (FALSE); 10307387SRobert.Gordon@Sun.COM 10317387SRobert.Gordon@Sun.COM /* is there a wlist? */ 10327387SRobert.Gordon@Sun.COM if (more == FALSE) { 10337387SRobert.Gordon@Sun.COM *wlist_exists = FALSE; 10347387SRobert.Gordon@Sun.COM return (TRUE); 10357387SRobert.Gordon@Sun.COM } 10367387SRobert.Gordon@Sun.COM *wlist_exists = TRUE; 10377387SRobert.Gordon@Sun.COM 10387387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &seg_array_len)) 10397387SRobert.Gordon@Sun.COM return (FALSE); 10407387SRobert.Gordon@Sun.COM 10417387SRobert.Gordon@Sun.COM tmp = *w = clist_alloc(); 10427387SRobert.Gordon@Sun.COM for (i = 0; i < seg_array_len; i++) { 10439348SSiddheshwar.Mahesh@Sun.COM 10447387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &tmp->c_dmemhandle.mrc_rmr)) 10457387SRobert.Gordon@Sun.COM return (FALSE); 10467387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &tmp->c_len)) 10477387SRobert.Gordon@Sun.COM return (FALSE); 10489348SSiddheshwar.Mahesh@Sun.COM 10499348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE1(krpc__i__xdr_decode_wlist_len, 10509348SSiddheshwar.Mahesh@Sun.COM uint_t, tmp->c_len); 10519348SSiddheshwar.Mahesh@Sun.COM 10527387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &tmp->u.c_daddr)) 10537387SRobert.Gordon@Sun.COM return (FALSE); 10547387SRobert.Gordon@Sun.COM if (i < seg_array_len - 1) { 10557387SRobert.Gordon@Sun.COM tmp->c_next = clist_alloc(); 10567387SRobert.Gordon@Sun.COM tmp = tmp->c_next; 10577387SRobert.Gordon@Sun.COM } else { 10587387SRobert.Gordon@Sun.COM tmp->c_next = NULL; 10597387SRobert.Gordon@Sun.COM } 10607387SRobert.Gordon@Sun.COM } 10617387SRobert.Gordon@Sun.COM 10627387SRobert.Gordon@Sun.COM more = FALSE; 10637387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more)) 10647387SRobert.Gordon@Sun.COM return (FALSE); 10657387SRobert.Gordon@Sun.COM 10667387SRobert.Gordon@Sun.COM return (TRUE); 10677387SRobert.Gordon@Sun.COM } 10687387SRobert.Gordon@Sun.COM 10697387SRobert.Gordon@Sun.COM /* 10707387SRobert.Gordon@Sun.COM * Server side RDMA WRITE list decode. 10717387SRobert.Gordon@Sun.COM * XDR context is memory ops 10727387SRobert.Gordon@Sun.COM */ 10737387SRobert.Gordon@Sun.COM bool_t 10747387SRobert.Gordon@Sun.COM xdr_decode_wlist_svc(XDR *xdrs, struct clist **wclp, bool_t *wwl, 10757387SRobert.Gordon@Sun.COM uint32_t *total_length, CONN *conn) 10767387SRobert.Gordon@Sun.COM { 10777387SRobert.Gordon@Sun.COM struct clist *first, *ncl; 10787387SRobert.Gordon@Sun.COM char *memp; 10797387SRobert.Gordon@Sun.COM uint32_t num_wclist; 10807387SRobert.Gordon@Sun.COM uint32_t wcl_length = 0; 10817387SRobert.Gordon@Sun.COM uint32_t i; 10827387SRobert.Gordon@Sun.COM bool_t more = FALSE; 10837387SRobert.Gordon@Sun.COM 10847387SRobert.Gordon@Sun.COM *wclp = NULL; 10857387SRobert.Gordon@Sun.COM *wwl = FALSE; 10867387SRobert.Gordon@Sun.COM *total_length = 0; 10877387SRobert.Gordon@Sun.COM 10887387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more)) { 10897387SRobert.Gordon@Sun.COM return (FALSE); 10907387SRobert.Gordon@Sun.COM } 10917387SRobert.Gordon@Sun.COM 10927387SRobert.Gordon@Sun.COM if (more == FALSE) { 10937387SRobert.Gordon@Sun.COM return (TRUE); 10947387SRobert.Gordon@Sun.COM } 10957387SRobert.Gordon@Sun.COM 10967387SRobert.Gordon@Sun.COM *wwl = TRUE; 10977387SRobert.Gordon@Sun.COM 10987387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &num_wclist)) { 10997387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__xdrrdma__wlistsvc__listlength); 11007387SRobert.Gordon@Sun.COM return (FALSE); 11017387SRobert.Gordon@Sun.COM } 11027387SRobert.Gordon@Sun.COM 11037387SRobert.Gordon@Sun.COM first = ncl = clist_alloc(); 11047387SRobert.Gordon@Sun.COM 11057387SRobert.Gordon@Sun.COM for (i = 0; i < num_wclist; i++) { 11069348SSiddheshwar.Mahesh@Sun.COM 11077387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &ncl->c_dmemhandle.mrc_rmr)) 11087387SRobert.Gordon@Sun.COM goto err_out; 11097387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &ncl->c_len)) 11107387SRobert.Gordon@Sun.COM goto err_out; 11117387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &ncl->u.c_daddr)) 11127387SRobert.Gordon@Sun.COM goto err_out; 11137387SRobert.Gordon@Sun.COM 11147387SRobert.Gordon@Sun.COM if (ncl->c_len > MAX_SVC_XFER_SIZE) { 11157387SRobert.Gordon@Sun.COM DTRACE_PROBE( 11167387SRobert.Gordon@Sun.COM krpc__e__xdrrdma__wlistsvc__chunklist_toobig); 11177387SRobert.Gordon@Sun.COM ncl->c_len = MAX_SVC_XFER_SIZE; 11187387SRobert.Gordon@Sun.COM } 11197387SRobert.Gordon@Sun.COM 11209348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE1(krpc__i__xdr_decode_wlist_svc_len, 11219348SSiddheshwar.Mahesh@Sun.COM uint_t, ncl->c_len); 11229348SSiddheshwar.Mahesh@Sun.COM 11237387SRobert.Gordon@Sun.COM wcl_length += ncl->c_len; 11247387SRobert.Gordon@Sun.COM 11257387SRobert.Gordon@Sun.COM if (i < num_wclist - 1) { 11267387SRobert.Gordon@Sun.COM ncl->c_next = clist_alloc(); 11277387SRobert.Gordon@Sun.COM ncl = ncl->c_next; 11287387SRobert.Gordon@Sun.COM } 11297387SRobert.Gordon@Sun.COM } 11307387SRobert.Gordon@Sun.COM 11317387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more)) 11327387SRobert.Gordon@Sun.COM goto err_out; 11337387SRobert.Gordon@Sun.COM 11347387SRobert.Gordon@Sun.COM first->rb_longbuf.type = RDMA_LONG_BUFFER; 11357387SRobert.Gordon@Sun.COM first->rb_longbuf.len = 11367387SRobert.Gordon@Sun.COM wcl_length > WCL_BUF_LEN ? wcl_length : WCL_BUF_LEN; 11377387SRobert.Gordon@Sun.COM 11387387SRobert.Gordon@Sun.COM if (rdma_buf_alloc(conn, &first->rb_longbuf)) { 11397387SRobert.Gordon@Sun.COM clist_free(first); 11407387SRobert.Gordon@Sun.COM return (FALSE); 11417387SRobert.Gordon@Sun.COM } 11427387SRobert.Gordon@Sun.COM 11437387SRobert.Gordon@Sun.COM memp = first->rb_longbuf.addr; 11447387SRobert.Gordon@Sun.COM 11457387SRobert.Gordon@Sun.COM ncl = first; 11467387SRobert.Gordon@Sun.COM for (i = 0; i < num_wclist; i++) { 11477387SRobert.Gordon@Sun.COM ncl->w.c_saddr3 = (caddr_t)memp; 11487387SRobert.Gordon@Sun.COM memp += ncl->c_len; 11497387SRobert.Gordon@Sun.COM ncl = ncl->c_next; 11507387SRobert.Gordon@Sun.COM } 11517387SRobert.Gordon@Sun.COM 11527387SRobert.Gordon@Sun.COM *wclp = first; 11537387SRobert.Gordon@Sun.COM *total_length = wcl_length; 11547387SRobert.Gordon@Sun.COM return (TRUE); 11557387SRobert.Gordon@Sun.COM 11567387SRobert.Gordon@Sun.COM err_out: 11577387SRobert.Gordon@Sun.COM clist_free(first); 11587387SRobert.Gordon@Sun.COM return (FALSE); 11597387SRobert.Gordon@Sun.COM } 11607387SRobert.Gordon@Sun.COM 11617387SRobert.Gordon@Sun.COM /* 11627387SRobert.Gordon@Sun.COM * XDR decode the long reply write chunk. 11637387SRobert.Gordon@Sun.COM */ 11647387SRobert.Gordon@Sun.COM bool_t 11657387SRobert.Gordon@Sun.COM xdr_decode_reply_wchunk(XDR *xdrs, struct clist **clist) 11667387SRobert.Gordon@Sun.COM { 11677387SRobert.Gordon@Sun.COM bool_t have_rchunk = FALSE; 11687387SRobert.Gordon@Sun.COM struct clist *first = NULL, *ncl = NULL; 11697387SRobert.Gordon@Sun.COM uint32_t num_wclist; 11707387SRobert.Gordon@Sun.COM uint32_t i; 11717387SRobert.Gordon@Sun.COM 11727387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &have_rchunk)) 11737387SRobert.Gordon@Sun.COM return (FALSE); 11747387SRobert.Gordon@Sun.COM 11757387SRobert.Gordon@Sun.COM if (have_rchunk == FALSE) 11767387SRobert.Gordon@Sun.COM return (TRUE); 11777387SRobert.Gordon@Sun.COM 11787387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &num_wclist)) { 11797387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__xdrrdma__replywchunk__listlength); 11807387SRobert.Gordon@Sun.COM return (FALSE); 11817387SRobert.Gordon@Sun.COM } 11827387SRobert.Gordon@Sun.COM 11837387SRobert.Gordon@Sun.COM if (num_wclist == 0) { 11847387SRobert.Gordon@Sun.COM return (FALSE); 11857387SRobert.Gordon@Sun.COM } 11867387SRobert.Gordon@Sun.COM 11877387SRobert.Gordon@Sun.COM first = ncl = clist_alloc(); 11887387SRobert.Gordon@Sun.COM 11897387SRobert.Gordon@Sun.COM for (i = 0; i < num_wclist; i++) { 11909348SSiddheshwar.Mahesh@Sun.COM 11919348SSiddheshwar.Mahesh@Sun.COM if (i > 0) { 11929348SSiddheshwar.Mahesh@Sun.COM ncl->c_next = clist_alloc(); 11939348SSiddheshwar.Mahesh@Sun.COM ncl = ncl->c_next; 11949348SSiddheshwar.Mahesh@Sun.COM } 11959348SSiddheshwar.Mahesh@Sun.COM 11967387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &ncl->c_dmemhandle.mrc_rmr)) 11977387SRobert.Gordon@Sun.COM goto err_out; 11987387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &ncl->c_len)) 11997387SRobert.Gordon@Sun.COM goto err_out; 12007387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &ncl->u.c_daddr)) 12017387SRobert.Gordon@Sun.COM goto err_out; 12027387SRobert.Gordon@Sun.COM 12037387SRobert.Gordon@Sun.COM if (ncl->c_len > MAX_SVC_XFER_SIZE) { 12047387SRobert.Gordon@Sun.COM DTRACE_PROBE( 12057387SRobert.Gordon@Sun.COM krpc__e__xdrrdma__replywchunk__chunklist_toobig); 12067387SRobert.Gordon@Sun.COM ncl->c_len = MAX_SVC_XFER_SIZE; 12077387SRobert.Gordon@Sun.COM } 12087387SRobert.Gordon@Sun.COM if (!(ncl->c_dmemhandle.mrc_rmr && 12097387SRobert.Gordon@Sun.COM (ncl->c_len > 0) && ncl->u.c_daddr)) 12107387SRobert.Gordon@Sun.COM DTRACE_PROBE( 12117387SRobert.Gordon@Sun.COM krpc__e__xdrrdma__replywchunk__invalid_segaddr); 12127387SRobert.Gordon@Sun.COM 12139348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE1(krpc__i__xdr_decode_reply_wchunk_c_len, 12149348SSiddheshwar.Mahesh@Sun.COM uint32_t, ncl->c_len); 12159348SSiddheshwar.Mahesh@Sun.COM 12167387SRobert.Gordon@Sun.COM } 12177387SRobert.Gordon@Sun.COM *clist = first; 12187387SRobert.Gordon@Sun.COM return (TRUE); 12197387SRobert.Gordon@Sun.COM 12207387SRobert.Gordon@Sun.COM err_out: 12217387SRobert.Gordon@Sun.COM clist_free(first); 12227387SRobert.Gordon@Sun.COM return (FALSE); 12237387SRobert.Gordon@Sun.COM } 12247387SRobert.Gordon@Sun.COM 12257387SRobert.Gordon@Sun.COM 12267387SRobert.Gordon@Sun.COM bool_t 12277387SRobert.Gordon@Sun.COM xdr_encode_reply_wchunk(XDR *xdrs, 12287387SRobert.Gordon@Sun.COM struct clist *cl_longreply, uint32_t seg_array_len) 12297387SRobert.Gordon@Sun.COM { 12307387SRobert.Gordon@Sun.COM int i; 12317387SRobert.Gordon@Sun.COM bool_t long_reply_exists = TRUE; 12327387SRobert.Gordon@Sun.COM uint32_t length; 12337387SRobert.Gordon@Sun.COM uint64 offset; 12347387SRobert.Gordon@Sun.COM 12357387SRobert.Gordon@Sun.COM if (seg_array_len > 0) { 12367387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &long_reply_exists)) 12377387SRobert.Gordon@Sun.COM return (FALSE); 12387387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &seg_array_len)) 12397387SRobert.Gordon@Sun.COM return (FALSE); 12407387SRobert.Gordon@Sun.COM 12417387SRobert.Gordon@Sun.COM for (i = 0; i < seg_array_len; i++) { 12427387SRobert.Gordon@Sun.COM if (!cl_longreply) 12437387SRobert.Gordon@Sun.COM return (FALSE); 12447387SRobert.Gordon@Sun.COM length = cl_longreply->c_len; 12457387SRobert.Gordon@Sun.COM offset = (uint64) cl_longreply->u.c_daddr; 12467387SRobert.Gordon@Sun.COM 12479348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE1( 12489348SSiddheshwar.Mahesh@Sun.COM krpc__i__xdr_encode_reply_wchunk_c_len, 12499348SSiddheshwar.Mahesh@Sun.COM uint32_t, length); 12509348SSiddheshwar.Mahesh@Sun.COM 12517387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, 12527387SRobert.Gordon@Sun.COM &cl_longreply->c_dmemhandle.mrc_rmr)) 12537387SRobert.Gordon@Sun.COM return (FALSE); 12547387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &length)) 12557387SRobert.Gordon@Sun.COM return (FALSE); 12567387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &offset)) 12577387SRobert.Gordon@Sun.COM return (FALSE); 12587387SRobert.Gordon@Sun.COM cl_longreply = cl_longreply->c_next; 12597387SRobert.Gordon@Sun.COM } 12607387SRobert.Gordon@Sun.COM } else { 12617387SRobert.Gordon@Sun.COM long_reply_exists = FALSE; 12627387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &long_reply_exists)) 12637387SRobert.Gordon@Sun.COM return (FALSE); 12647387SRobert.Gordon@Sun.COM } 12657387SRobert.Gordon@Sun.COM return (TRUE); 12667387SRobert.Gordon@Sun.COM } 12677387SRobert.Gordon@Sun.COM bool_t 12689348SSiddheshwar.Mahesh@Sun.COM xdrrdma_read_from_client(struct clist *rlist, CONN **conn, uint_t count) 12697387SRobert.Gordon@Sun.COM { 12707387SRobert.Gordon@Sun.COM struct clist *rdclist; 12717387SRobert.Gordon@Sun.COM struct clist cl; 12727387SRobert.Gordon@Sun.COM uint_t total_len = 0; 12737387SRobert.Gordon@Sun.COM uint32_t status; 12747387SRobert.Gordon@Sun.COM bool_t retval = TRUE; 12757387SRobert.Gordon@Sun.COM 12769348SSiddheshwar.Mahesh@Sun.COM rlist->rb_longbuf.type = RDMA_LONG_BUFFER; 12779348SSiddheshwar.Mahesh@Sun.COM rlist->rb_longbuf.len = 12787387SRobert.Gordon@Sun.COM count > RCL_BUF_LEN ? count : RCL_BUF_LEN; 12797387SRobert.Gordon@Sun.COM 12809348SSiddheshwar.Mahesh@Sun.COM if (rdma_buf_alloc(*conn, &rlist->rb_longbuf)) { 12817387SRobert.Gordon@Sun.COM return (FALSE); 12827387SRobert.Gordon@Sun.COM } 12837387SRobert.Gordon@Sun.COM 12849348SSiddheshwar.Mahesh@Sun.COM /* 12859348SSiddheshwar.Mahesh@Sun.COM * The entire buffer is registered with the first chunk. 12869348SSiddheshwar.Mahesh@Sun.COM * Later chunks will use the same registered memory handle. 12879348SSiddheshwar.Mahesh@Sun.COM */ 12889348SSiddheshwar.Mahesh@Sun.COM 12899348SSiddheshwar.Mahesh@Sun.COM cl = *rlist; 12909348SSiddheshwar.Mahesh@Sun.COM cl.c_next = NULL; 12919348SSiddheshwar.Mahesh@Sun.COM if (clist_register(*conn, &cl, CLIST_REG_DST) != RDMA_SUCCESS) { 12929348SSiddheshwar.Mahesh@Sun.COM rdma_buf_free(*conn, &rlist->rb_longbuf); 12939348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE( 12949348SSiddheshwar.Mahesh@Sun.COM krpc__e__xdrrdma__readfromclient__clist__reg); 12959348SSiddheshwar.Mahesh@Sun.COM return (FALSE); 12969348SSiddheshwar.Mahesh@Sun.COM } 12979348SSiddheshwar.Mahesh@Sun.COM 12989348SSiddheshwar.Mahesh@Sun.COM rlist->c_regtype = CLIST_REG_DST; 12999348SSiddheshwar.Mahesh@Sun.COM rlist->c_dmemhandle = cl.c_dmemhandle; 13009348SSiddheshwar.Mahesh@Sun.COM rlist->c_dsynchandle = cl.c_dsynchandle; 13019348SSiddheshwar.Mahesh@Sun.COM 13029348SSiddheshwar.Mahesh@Sun.COM for (rdclist = rlist; 13037387SRobert.Gordon@Sun.COM rdclist != NULL; rdclist = rdclist->c_next) { 13047387SRobert.Gordon@Sun.COM total_len += rdclist->c_len; 13057387SRobert.Gordon@Sun.COM #if (defined(OBJ32)||defined(DEBUG32)) 13067387SRobert.Gordon@Sun.COM rdclist->u.c_daddr3 = 13079348SSiddheshwar.Mahesh@Sun.COM (caddr_t)((char *)rlist->rb_longbuf.addr + 13087387SRobert.Gordon@Sun.COM (uint32) rdclist->u.c_daddr3); 13097387SRobert.Gordon@Sun.COM #else 13107387SRobert.Gordon@Sun.COM rdclist->u.c_daddr3 = 13119348SSiddheshwar.Mahesh@Sun.COM (caddr_t)((char *)rlist->rb_longbuf.addr + 13127387SRobert.Gordon@Sun.COM (uint64) rdclist->u.c_daddr); 13137387SRobert.Gordon@Sun.COM 13147387SRobert.Gordon@Sun.COM #endif 13157387SRobert.Gordon@Sun.COM cl = (*rdclist); 13167387SRobert.Gordon@Sun.COM cl.c_next = NULL; 13177387SRobert.Gordon@Sun.COM 13189348SSiddheshwar.Mahesh@Sun.COM /* 13199348SSiddheshwar.Mahesh@Sun.COM * Use the same memory handle for all the chunks 13209348SSiddheshwar.Mahesh@Sun.COM */ 13219348SSiddheshwar.Mahesh@Sun.COM cl.c_dmemhandle = rlist->c_dmemhandle; 13229348SSiddheshwar.Mahesh@Sun.COM cl.c_dsynchandle = rlist->c_dsynchandle; 13239348SSiddheshwar.Mahesh@Sun.COM 13247387SRobert.Gordon@Sun.COM 13257387SRobert.Gordon@Sun.COM DTRACE_PROBE1(krpc__i__xdrrdma__readfromclient__buflen, 13267387SRobert.Gordon@Sun.COM int, rdclist->c_len); 13277387SRobert.Gordon@Sun.COM 13287387SRobert.Gordon@Sun.COM /* 13297387SRobert.Gordon@Sun.COM * Now read the chunk in 13307387SRobert.Gordon@Sun.COM */ 13317387SRobert.Gordon@Sun.COM if (rdclist->c_next == NULL) { 13327387SRobert.Gordon@Sun.COM status = RDMA_READ(*conn, &cl, WAIT); 13337387SRobert.Gordon@Sun.COM } else { 13347387SRobert.Gordon@Sun.COM status = RDMA_READ(*conn, &cl, NOWAIT); 13357387SRobert.Gordon@Sun.COM } 13367387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 13377387SRobert.Gordon@Sun.COM DTRACE_PROBE( 13387387SRobert.Gordon@Sun.COM krpc__e__xdrrdma__readfromclient__readfailed); 13399348SSiddheshwar.Mahesh@Sun.COM rdma_buf_free(*conn, &rlist->rb_longbuf); 13407387SRobert.Gordon@Sun.COM return (FALSE); 13417387SRobert.Gordon@Sun.COM } 13427387SRobert.Gordon@Sun.COM } 13437387SRobert.Gordon@Sun.COM 13449348SSiddheshwar.Mahesh@Sun.COM cl = (*rlist); 13457387SRobert.Gordon@Sun.COM cl.c_next = NULL; 13467387SRobert.Gordon@Sun.COM cl.c_len = total_len; 13479348SSiddheshwar.Mahesh@Sun.COM if (clist_syncmem(*conn, &cl, CLIST_REG_DST) != RDMA_SUCCESS) { 13487387SRobert.Gordon@Sun.COM retval = FALSE; 13497387SRobert.Gordon@Sun.COM } 13507387SRobert.Gordon@Sun.COM return (retval); 13517387SRobert.Gordon@Sun.COM } 13527387SRobert.Gordon@Sun.COM 13537387SRobert.Gordon@Sun.COM bool_t 13547387SRobert.Gordon@Sun.COM xdrrdma_free_clist(CONN *conn, struct clist *clp) 13557387SRobert.Gordon@Sun.COM { 13567387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &clp->rb_longbuf); 13577387SRobert.Gordon@Sun.COM clist_free(clp); 13587387SRobert.Gordon@Sun.COM return (TRUE); 13597387SRobert.Gordon@Sun.COM } 13607387SRobert.Gordon@Sun.COM 13617387SRobert.Gordon@Sun.COM bool_t 13629348SSiddheshwar.Mahesh@Sun.COM xdrrdma_send_read_data(XDR *xdrs, uint_t data_len, struct clist *wcl) 13637387SRobert.Gordon@Sun.COM { 13647387SRobert.Gordon@Sun.COM int status; 13657387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 13667387SRobert.Gordon@Sun.COM struct xdr_ops *xops = xdrrdma_xops(); 13679348SSiddheshwar.Mahesh@Sun.COM struct clist *tcl, *wrcl, *cl; 13689348SSiddheshwar.Mahesh@Sun.COM struct clist fcl; 13699348SSiddheshwar.Mahesh@Sun.COM int rndup_present, rnduplen; 13709348SSiddheshwar.Mahesh@Sun.COM 13719348SSiddheshwar.Mahesh@Sun.COM rndup_present = 0; 13729348SSiddheshwar.Mahesh@Sun.COM wrcl = NULL; 13737387SRobert.Gordon@Sun.COM 13747387SRobert.Gordon@Sun.COM /* caller is doing a sizeof */ 13757387SRobert.Gordon@Sun.COM if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_ops == xops) 13767387SRobert.Gordon@Sun.COM return (TRUE); 13777387SRobert.Gordon@Sun.COM 13789348SSiddheshwar.Mahesh@Sun.COM /* copy of the first chunk */ 13799348SSiddheshwar.Mahesh@Sun.COM fcl = *wcl; 13809348SSiddheshwar.Mahesh@Sun.COM fcl.c_next = NULL; 13819348SSiddheshwar.Mahesh@Sun.COM 13829348SSiddheshwar.Mahesh@Sun.COM /* 13839348SSiddheshwar.Mahesh@Sun.COM * The entire buffer is registered with the first chunk. 13849348SSiddheshwar.Mahesh@Sun.COM * Later chunks will use the same registered memory handle. 13859348SSiddheshwar.Mahesh@Sun.COM */ 13869348SSiddheshwar.Mahesh@Sun.COM 13879348SSiddheshwar.Mahesh@Sun.COM status = clist_register(xdrp->xp_conn, &fcl, CLIST_REG_SOURCE); 13887387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 13897387SRobert.Gordon@Sun.COM return (FALSE); 13907387SRobert.Gordon@Sun.COM } 13917387SRobert.Gordon@Sun.COM 13929348SSiddheshwar.Mahesh@Sun.COM wcl->c_regtype = CLIST_REG_SOURCE; 13939348SSiddheshwar.Mahesh@Sun.COM wcl->c_smemhandle = fcl.c_smemhandle; 13949348SSiddheshwar.Mahesh@Sun.COM wcl->c_ssynchandle = fcl.c_ssynchandle; 13959348SSiddheshwar.Mahesh@Sun.COM 13969348SSiddheshwar.Mahesh@Sun.COM /* 13979348SSiddheshwar.Mahesh@Sun.COM * Only transfer the read data ignoring any trailing 13989348SSiddheshwar.Mahesh@Sun.COM * roundup chunks. A bit of work, but it saves an 13999348SSiddheshwar.Mahesh@Sun.COM * unnecessary extra RDMA_WRITE containing only 14009348SSiddheshwar.Mahesh@Sun.COM * roundup bytes. 14019348SSiddheshwar.Mahesh@Sun.COM */ 14029348SSiddheshwar.Mahesh@Sun.COM 14039348SSiddheshwar.Mahesh@Sun.COM rnduplen = clist_len(wcl) - data_len; 14049348SSiddheshwar.Mahesh@Sun.COM 14059348SSiddheshwar.Mahesh@Sun.COM if (rnduplen) { 14069348SSiddheshwar.Mahesh@Sun.COM 14079348SSiddheshwar.Mahesh@Sun.COM tcl = wcl->c_next; 14089348SSiddheshwar.Mahesh@Sun.COM 14099348SSiddheshwar.Mahesh@Sun.COM /* 14109348SSiddheshwar.Mahesh@Sun.COM * Check if there is a trailing roundup chunk 14119348SSiddheshwar.Mahesh@Sun.COM */ 14129348SSiddheshwar.Mahesh@Sun.COM while (tcl) { 14139348SSiddheshwar.Mahesh@Sun.COM if ((tcl->c_next == NULL) && (tcl->c_len == rnduplen)) { 14149348SSiddheshwar.Mahesh@Sun.COM rndup_present = 1; 14159348SSiddheshwar.Mahesh@Sun.COM break; 14169348SSiddheshwar.Mahesh@Sun.COM } 14179348SSiddheshwar.Mahesh@Sun.COM tcl = tcl->c_next; 14189348SSiddheshwar.Mahesh@Sun.COM } 14199348SSiddheshwar.Mahesh@Sun.COM 14209348SSiddheshwar.Mahesh@Sun.COM /* 14219348SSiddheshwar.Mahesh@Sun.COM * Make a copy chunk list skipping the last chunk 14229348SSiddheshwar.Mahesh@Sun.COM */ 14239348SSiddheshwar.Mahesh@Sun.COM if (rndup_present) { 14249348SSiddheshwar.Mahesh@Sun.COM cl = wcl; 14259348SSiddheshwar.Mahesh@Sun.COM tcl = NULL; 14269348SSiddheshwar.Mahesh@Sun.COM while (cl) { 14279348SSiddheshwar.Mahesh@Sun.COM if (tcl == NULL) { 14289348SSiddheshwar.Mahesh@Sun.COM tcl = clist_alloc(); 14299348SSiddheshwar.Mahesh@Sun.COM wrcl = tcl; 14309348SSiddheshwar.Mahesh@Sun.COM } else { 14319348SSiddheshwar.Mahesh@Sun.COM tcl->c_next = clist_alloc(); 14329348SSiddheshwar.Mahesh@Sun.COM tcl = tcl->c_next; 14339348SSiddheshwar.Mahesh@Sun.COM } 14349348SSiddheshwar.Mahesh@Sun.COM 14359348SSiddheshwar.Mahesh@Sun.COM *tcl = *cl; 14369348SSiddheshwar.Mahesh@Sun.COM cl = cl->c_next; 14379348SSiddheshwar.Mahesh@Sun.COM /* last chunk */ 14389348SSiddheshwar.Mahesh@Sun.COM if (cl->c_next == NULL) 14399348SSiddheshwar.Mahesh@Sun.COM break; 14409348SSiddheshwar.Mahesh@Sun.COM } 14419348SSiddheshwar.Mahesh@Sun.COM tcl->c_next = NULL; 14429348SSiddheshwar.Mahesh@Sun.COM } 14439348SSiddheshwar.Mahesh@Sun.COM } 14449348SSiddheshwar.Mahesh@Sun.COM 14459348SSiddheshwar.Mahesh@Sun.COM if (wrcl == NULL) { 14469348SSiddheshwar.Mahesh@Sun.COM /* No roundup chunks */ 14479348SSiddheshwar.Mahesh@Sun.COM wrcl = wcl; 14489348SSiddheshwar.Mahesh@Sun.COM } 14499348SSiddheshwar.Mahesh@Sun.COM 14509348SSiddheshwar.Mahesh@Sun.COM /* 14519348SSiddheshwar.Mahesh@Sun.COM * Set the registered memory handles for the 14529348SSiddheshwar.Mahesh@Sun.COM * rest of the chunks same as the first chunk. 14539348SSiddheshwar.Mahesh@Sun.COM */ 14549348SSiddheshwar.Mahesh@Sun.COM tcl = wrcl->c_next; 14559348SSiddheshwar.Mahesh@Sun.COM while (tcl) { 14569348SSiddheshwar.Mahesh@Sun.COM tcl->c_smemhandle = fcl.c_smemhandle; 14579348SSiddheshwar.Mahesh@Sun.COM tcl->c_ssynchandle = fcl.c_ssynchandle; 14589348SSiddheshwar.Mahesh@Sun.COM tcl = tcl->c_next; 14599348SSiddheshwar.Mahesh@Sun.COM } 14609348SSiddheshwar.Mahesh@Sun.COM 14619348SSiddheshwar.Mahesh@Sun.COM /* 14629348SSiddheshwar.Mahesh@Sun.COM * Sync the total len beginning from the first chunk. 14639348SSiddheshwar.Mahesh@Sun.COM */ 14649348SSiddheshwar.Mahesh@Sun.COM fcl.c_len = clist_len(wrcl); 14659348SSiddheshwar.Mahesh@Sun.COM status = clist_syncmem(xdrp->xp_conn, &fcl, CLIST_REG_SOURCE); 14667387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 14677387SRobert.Gordon@Sun.COM return (FALSE); 14687387SRobert.Gordon@Sun.COM } 14697387SRobert.Gordon@Sun.COM 14709348SSiddheshwar.Mahesh@Sun.COM status = RDMA_WRITE(xdrp->xp_conn, wrcl, WAIT); 14719348SSiddheshwar.Mahesh@Sun.COM 14729348SSiddheshwar.Mahesh@Sun.COM if (rndup_present) 14739348SSiddheshwar.Mahesh@Sun.COM clist_free(wrcl); 14749348SSiddheshwar.Mahesh@Sun.COM 14757387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 14767387SRobert.Gordon@Sun.COM return (FALSE); 14777387SRobert.Gordon@Sun.COM } 14787387SRobert.Gordon@Sun.COM 14797387SRobert.Gordon@Sun.COM return (TRUE); 14807387SRobert.Gordon@Sun.COM } 14819348SSiddheshwar.Mahesh@Sun.COM 14829348SSiddheshwar.Mahesh@Sun.COM 14839348SSiddheshwar.Mahesh@Sun.COM /* 14849348SSiddheshwar.Mahesh@Sun.COM * Reads one chunk at a time 14859348SSiddheshwar.Mahesh@Sun.COM */ 14869348SSiddheshwar.Mahesh@Sun.COM 14879348SSiddheshwar.Mahesh@Sun.COM static bool_t 14889348SSiddheshwar.Mahesh@Sun.COM xdrrdma_read_a_chunk(XDR *xdrs, CONN **conn) 14899348SSiddheshwar.Mahesh@Sun.COM { 14909348SSiddheshwar.Mahesh@Sun.COM int status; 14919348SSiddheshwar.Mahesh@Sun.COM int32_t len = 0; 14929348SSiddheshwar.Mahesh@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 14939348SSiddheshwar.Mahesh@Sun.COM struct clist *cle = *(xdrp->xp_rcl_next); 14949348SSiddheshwar.Mahesh@Sun.COM struct clist *rclp = xdrp->xp_rcl; 14959348SSiddheshwar.Mahesh@Sun.COM struct clist *clp; 14969348SSiddheshwar.Mahesh@Sun.COM 14979348SSiddheshwar.Mahesh@Sun.COM /* 14989348SSiddheshwar.Mahesh@Sun.COM * len is used later to decide xdr offset in 14999348SSiddheshwar.Mahesh@Sun.COM * the chunk factoring any 4-byte XDR alignment 15009348SSiddheshwar.Mahesh@Sun.COM * (See read chunk example top of this file) 15019348SSiddheshwar.Mahesh@Sun.COM */ 15029348SSiddheshwar.Mahesh@Sun.COM while (rclp != cle) { 15039348SSiddheshwar.Mahesh@Sun.COM len += rclp->c_len; 15049348SSiddheshwar.Mahesh@Sun.COM rclp = rclp->c_next; 15059348SSiddheshwar.Mahesh@Sun.COM } 15069348SSiddheshwar.Mahesh@Sun.COM 15079348SSiddheshwar.Mahesh@Sun.COM len = RNDUP(len) - len; 15089348SSiddheshwar.Mahesh@Sun.COM 15099348SSiddheshwar.Mahesh@Sun.COM ASSERT(xdrs->x_handy <= 0); 15109348SSiddheshwar.Mahesh@Sun.COM 15119348SSiddheshwar.Mahesh@Sun.COM /* 15129348SSiddheshwar.Mahesh@Sun.COM * If this is the first chunk to contain the RPC 15139348SSiddheshwar.Mahesh@Sun.COM * message set xp_off to the xdr offset of the 15149348SSiddheshwar.Mahesh@Sun.COM * inline message. 15159348SSiddheshwar.Mahesh@Sun.COM */ 15169348SSiddheshwar.Mahesh@Sun.COM if (xdrp->xp_off == 0) 15179348SSiddheshwar.Mahesh@Sun.COM xdrp->xp_off = (xdrp->xp_offp - xdrs->x_base); 15189348SSiddheshwar.Mahesh@Sun.COM 15199348SSiddheshwar.Mahesh@Sun.COM if (cle == NULL || (cle->c_xdroff != xdrp->xp_off)) 15209348SSiddheshwar.Mahesh@Sun.COM return (FALSE); 15219348SSiddheshwar.Mahesh@Sun.COM 15229348SSiddheshwar.Mahesh@Sun.COM /* 15239348SSiddheshwar.Mahesh@Sun.COM * Make a copy of the chunk to read from client. 15249348SSiddheshwar.Mahesh@Sun.COM * Chunks are read on demand, so read only one 15259348SSiddheshwar.Mahesh@Sun.COM * for now. 15269348SSiddheshwar.Mahesh@Sun.COM */ 15279348SSiddheshwar.Mahesh@Sun.COM 15289348SSiddheshwar.Mahesh@Sun.COM rclp = clist_alloc(); 15299348SSiddheshwar.Mahesh@Sun.COM *rclp = *cle; 15309348SSiddheshwar.Mahesh@Sun.COM rclp->c_next = NULL; 15319348SSiddheshwar.Mahesh@Sun.COM 15329348SSiddheshwar.Mahesh@Sun.COM xdrp->xp_rcl_next = &cle->c_next; 15339348SSiddheshwar.Mahesh@Sun.COM 15349348SSiddheshwar.Mahesh@Sun.COM /* 15359348SSiddheshwar.Mahesh@Sun.COM * If there is a roundup present, then skip those 15369348SSiddheshwar.Mahesh@Sun.COM * bytes when reading. 15379348SSiddheshwar.Mahesh@Sun.COM */ 15389348SSiddheshwar.Mahesh@Sun.COM if (len) { 15399348SSiddheshwar.Mahesh@Sun.COM rclp->w.c_saddr = 15409348SSiddheshwar.Mahesh@Sun.COM (uint64)(uintptr_t)rclp->w.c_saddr + len; 15419348SSiddheshwar.Mahesh@Sun.COM rclp->c_len = rclp->c_len - len; 15429348SSiddheshwar.Mahesh@Sun.COM } 15439348SSiddheshwar.Mahesh@Sun.COM 15449348SSiddheshwar.Mahesh@Sun.COM status = xdrrdma_read_from_client(rclp, conn, rclp->c_len); 15459348SSiddheshwar.Mahesh@Sun.COM 15469348SSiddheshwar.Mahesh@Sun.COM if (status == FALSE) { 15479348SSiddheshwar.Mahesh@Sun.COM clist_free(rclp); 15489348SSiddheshwar.Mahesh@Sun.COM return (status); 15499348SSiddheshwar.Mahesh@Sun.COM } 15509348SSiddheshwar.Mahesh@Sun.COM 15519348SSiddheshwar.Mahesh@Sun.COM xdrp->xp_offp = rclp->rb_longbuf.addr; 15529348SSiddheshwar.Mahesh@Sun.COM xdrs->x_base = xdrp->xp_offp; 15539348SSiddheshwar.Mahesh@Sun.COM xdrs->x_handy = rclp->c_len; 15549348SSiddheshwar.Mahesh@Sun.COM 15559348SSiddheshwar.Mahesh@Sun.COM /* 15569348SSiddheshwar.Mahesh@Sun.COM * This copy of read chunks containing the XDR 15579348SSiddheshwar.Mahesh@Sun.COM * message is freed later in xdrrdma_destroy() 15589348SSiddheshwar.Mahesh@Sun.COM */ 15599348SSiddheshwar.Mahesh@Sun.COM 15609348SSiddheshwar.Mahesh@Sun.COM if (xdrp->xp_rcl_xdr) { 15619348SSiddheshwar.Mahesh@Sun.COM /* Add the chunk to end of the list */ 15629348SSiddheshwar.Mahesh@Sun.COM clp = xdrp->xp_rcl_xdr; 15639348SSiddheshwar.Mahesh@Sun.COM while (clp->c_next != NULL) 15649348SSiddheshwar.Mahesh@Sun.COM clp = clp->c_next; 15659348SSiddheshwar.Mahesh@Sun.COM clp->c_next = rclp; 15669348SSiddheshwar.Mahesh@Sun.COM } else { 15679348SSiddheshwar.Mahesh@Sun.COM xdrp->xp_rcl_xdr = rclp; 15689348SSiddheshwar.Mahesh@Sun.COM } 15699348SSiddheshwar.Mahesh@Sun.COM return (TRUE); 15709348SSiddheshwar.Mahesh@Sun.COM } 15719348SSiddheshwar.Mahesh@Sun.COM 15729348SSiddheshwar.Mahesh@Sun.COM static void 15739348SSiddheshwar.Mahesh@Sun.COM xdrrdma_free_xdr_chunks(CONN *conn, struct clist *xdr_rcl) 15749348SSiddheshwar.Mahesh@Sun.COM { 15759348SSiddheshwar.Mahesh@Sun.COM struct clist *cl; 15769348SSiddheshwar.Mahesh@Sun.COM 15779348SSiddheshwar.Mahesh@Sun.COM (void) clist_deregister(conn, xdr_rcl); 15789348SSiddheshwar.Mahesh@Sun.COM 15799348SSiddheshwar.Mahesh@Sun.COM /* 15809348SSiddheshwar.Mahesh@Sun.COM * Read chunks containing parts XDR message are 15819348SSiddheshwar.Mahesh@Sun.COM * special: in case of multiple chunks each has 15829348SSiddheshwar.Mahesh@Sun.COM * its own buffer. 15839348SSiddheshwar.Mahesh@Sun.COM */ 15849348SSiddheshwar.Mahesh@Sun.COM 15859348SSiddheshwar.Mahesh@Sun.COM cl = xdr_rcl; 15869348SSiddheshwar.Mahesh@Sun.COM while (cl) { 15879348SSiddheshwar.Mahesh@Sun.COM rdma_buf_free(conn, &cl->rb_longbuf); 15889348SSiddheshwar.Mahesh@Sun.COM cl = cl->c_next; 15899348SSiddheshwar.Mahesh@Sun.COM } 15909348SSiddheshwar.Mahesh@Sun.COM 15919348SSiddheshwar.Mahesh@Sun.COM clist_free(xdr_rcl); 15929348SSiddheshwar.Mahesh@Sun.COM } 1593