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 /* 2212553SKaren.Rochford@Sun.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 230Sstevel@tonic-gate */ 240Sstevel@tonic-gate 257387SRobert.Gordon@Sun.COM /* 267387SRobert.Gordon@Sun.COM * Copyright (c) 2007, The Ohio State University. All rights reserved. 277387SRobert.Gordon@Sun.COM * 287387SRobert.Gordon@Sun.COM * Portions of this source code is developed by the team members of 297387SRobert.Gordon@Sun.COM * The Ohio State University's Network-Based Computing Laboratory (NBCL), 307387SRobert.Gordon@Sun.COM * headed by Professor Dhabaleswar K. (DK) Panda. 317387SRobert.Gordon@Sun.COM * 327387SRobert.Gordon@Sun.COM * Acknowledgements to contributions from developors: 337387SRobert.Gordon@Sun.COM * Ranjit Noronha: noronha@cse.ohio-state.edu 347387SRobert.Gordon@Sun.COM * Lei Chai : chail@cse.ohio-state.edu 357387SRobert.Gordon@Sun.COM * Weikuan Yu : yuw@cse.ohio-state.edu 367387SRobert.Gordon@Sun.COM * 377387SRobert.Gordon@Sun.COM */ 380Sstevel@tonic-gate 390Sstevel@tonic-gate /* 400Sstevel@tonic-gate * xdr_rdma.c, XDR implementation using RDMA to move large chunks 410Sstevel@tonic-gate */ 420Sstevel@tonic-gate 430Sstevel@tonic-gate #include <sys/param.h> 440Sstevel@tonic-gate #include <sys/types.h> 450Sstevel@tonic-gate #include <sys/systm.h> 460Sstevel@tonic-gate #include <sys/kmem.h> 477387SRobert.Gordon@Sun.COM #include <sys/sdt.h> 487387SRobert.Gordon@Sun.COM #include <sys/debug.h> 490Sstevel@tonic-gate 500Sstevel@tonic-gate #include <rpc/types.h> 510Sstevel@tonic-gate #include <rpc/xdr.h> 520Sstevel@tonic-gate #include <sys/cmn_err.h> 530Sstevel@tonic-gate #include <rpc/rpc_sztypes.h> 540Sstevel@tonic-gate #include <rpc/rpc_rdma.h> 557387SRobert.Gordon@Sun.COM #include <sys/sysmacros.h> 560Sstevel@tonic-gate 5712553SKaren.Rochford@Sun.COM /* 5812553SKaren.Rochford@Sun.COM * RCP header and xdr encoding overhead. The number was determined by 5912553SKaren.Rochford@Sun.COM * tracing the msglen in svc_rdma_ksend for sec=sys,krb5,krb5i and krb5p. 6012553SKaren.Rochford@Sun.COM * If the XDR_RDMA_BUF_OVERHEAD is not large enough the result is the trigger 6112553SKaren.Rochford@Sun.COM * of the dtrace probe on the server "krpc-e-svcrdma-ksend-noreplycl" from 6212553SKaren.Rochford@Sun.COM * svc_rdma_ksend. 6312553SKaren.Rochford@Sun.COM */ 6412553SKaren.Rochford@Sun.COM #define XDR_RDMA_BUF_OVERHEAD 300 6512553SKaren.Rochford@Sun.COM 667387SRobert.Gordon@Sun.COM static bool_t xdrrdma_getint32(XDR *, int32_t *); 677387SRobert.Gordon@Sun.COM static bool_t xdrrdma_putint32(XDR *, int32_t *); 687387SRobert.Gordon@Sun.COM static bool_t xdrrdma_getbytes(XDR *, caddr_t, int); 697387SRobert.Gordon@Sun.COM static bool_t xdrrdma_putbytes(XDR *, caddr_t, int); 707387SRobert.Gordon@Sun.COM uint_t xdrrdma_getpos(XDR *); 717387SRobert.Gordon@Sun.COM bool_t xdrrdma_setpos(XDR *, uint_t); 727387SRobert.Gordon@Sun.COM static rpc_inline_t *xdrrdma_inline(XDR *, int); 737387SRobert.Gordon@Sun.COM void xdrrdma_destroy(XDR *); 747387SRobert.Gordon@Sun.COM static bool_t xdrrdma_control(XDR *, int, void *); 759348SSiddheshwar.Mahesh@Sun.COM static bool_t xdrrdma_read_a_chunk(XDR *, CONN **); 769348SSiddheshwar.Mahesh@Sun.COM static void xdrrdma_free_xdr_chunks(CONN *, struct clist *); 777387SRobert.Gordon@Sun.COM 787387SRobert.Gordon@Sun.COM struct xdr_ops xdrrdmablk_ops = { 797387SRobert.Gordon@Sun.COM xdrrdma_getbytes, 807387SRobert.Gordon@Sun.COM xdrrdma_putbytes, 817387SRobert.Gordon@Sun.COM xdrrdma_getpos, 827387SRobert.Gordon@Sun.COM xdrrdma_setpos, 837387SRobert.Gordon@Sun.COM xdrrdma_inline, 847387SRobert.Gordon@Sun.COM xdrrdma_destroy, 857387SRobert.Gordon@Sun.COM xdrrdma_control, 867387SRobert.Gordon@Sun.COM xdrrdma_getint32, 877387SRobert.Gordon@Sun.COM xdrrdma_putint32 887387SRobert.Gordon@Sun.COM }; 897387SRobert.Gordon@Sun.COM 907387SRobert.Gordon@Sun.COM struct xdr_ops xdrrdma_ops = { 917387SRobert.Gordon@Sun.COM xdrrdma_getbytes, 927387SRobert.Gordon@Sun.COM xdrrdma_putbytes, 937387SRobert.Gordon@Sun.COM xdrrdma_getpos, 947387SRobert.Gordon@Sun.COM xdrrdma_setpos, 957387SRobert.Gordon@Sun.COM xdrrdma_inline, 967387SRobert.Gordon@Sun.COM xdrrdma_destroy, 977387SRobert.Gordon@Sun.COM xdrrdma_control, 987387SRobert.Gordon@Sun.COM xdrrdma_getint32, 997387SRobert.Gordon@Sun.COM xdrrdma_putint32 1007387SRobert.Gordon@Sun.COM }; 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate /* 1037387SRobert.Gordon@Sun.COM * A chunk list entry identifies a chunk of opaque data to be moved 1047387SRobert.Gordon@Sun.COM * separately from the rest of the RPC message. xp_min_chunk = 0, is a 1057387SRobert.Gordon@Sun.COM * special case for ENCODING, which means do not chunk the incoming stream of 1067387SRobert.Gordon@Sun.COM * data. 1079348SSiddheshwar.Mahesh@Sun.COM * 1089348SSiddheshwar.Mahesh@Sun.COM * A read chunk can contain part of the RPC message in addition to the 1099348SSiddheshwar.Mahesh@Sun.COM * inline message. In such a case, (xp_offp - x_base) will not provide 1109348SSiddheshwar.Mahesh@Sun.COM * the correct xdr offset of the entire message. xp_off is used in such 1119348SSiddheshwar.Mahesh@Sun.COM * a case to denote the offset or current position in the overall message 1129348SSiddheshwar.Mahesh@Sun.COM * covering both the inline and the chunk. This is used only in the case 1139348SSiddheshwar.Mahesh@Sun.COM * of decoding and useful to compare read chunk 'c_xdroff' offsets. 1149348SSiddheshwar.Mahesh@Sun.COM * 1159348SSiddheshwar.Mahesh@Sun.COM * An example for a read chunk containing an XDR message: 1169348SSiddheshwar.Mahesh@Sun.COM * An NFSv4 compound as following: 1179348SSiddheshwar.Mahesh@Sun.COM * 1189348SSiddheshwar.Mahesh@Sun.COM * PUTFH 1199348SSiddheshwar.Mahesh@Sun.COM * WRITE [4109 bytes] 1209348SSiddheshwar.Mahesh@Sun.COM * GETATTR 1219348SSiddheshwar.Mahesh@Sun.COM * 1229348SSiddheshwar.Mahesh@Sun.COM * Solaris Encoding is: 1239348SSiddheshwar.Mahesh@Sun.COM * ------------------- 1249348SSiddheshwar.Mahesh@Sun.COM * 1259348SSiddheshwar.Mahesh@Sun.COM * <Inline message>: [PUTFH WRITE4args GETATTR] 1269348SSiddheshwar.Mahesh@Sun.COM * | 1279348SSiddheshwar.Mahesh@Sun.COM * v 1289348SSiddheshwar.Mahesh@Sun.COM * [RDMA_READ chunks]: [write data] 1299348SSiddheshwar.Mahesh@Sun.COM * 1309348SSiddheshwar.Mahesh@Sun.COM * 1319348SSiddheshwar.Mahesh@Sun.COM * Linux encoding is: 1329348SSiddheshwar.Mahesh@Sun.COM * ----------------- 1339348SSiddheshwar.Mahesh@Sun.COM * 1349348SSiddheshwar.Mahesh@Sun.COM * <Inline message>: [PUTFH WRITE4args] 1359348SSiddheshwar.Mahesh@Sun.COM * | 1369348SSiddheshwar.Mahesh@Sun.COM * v 1379348SSiddheshwar.Mahesh@Sun.COM * [RDMA_READ chunks]: [Write data] [Write data2] [Getattr chunk] 1389348SSiddheshwar.Mahesh@Sun.COM * chunk1 chunk2 chunk3 1399348SSiddheshwar.Mahesh@Sun.COM * 1409348SSiddheshwar.Mahesh@Sun.COM * where the READ chunks are as: 1419348SSiddheshwar.Mahesh@Sun.COM * 1429348SSiddheshwar.Mahesh@Sun.COM * - chunk1 - 4k 1439348SSiddheshwar.Mahesh@Sun.COM * write data | 1449348SSiddheshwar.Mahesh@Sun.COM * - chunk2 - 13 bytes(4109 - 4k) 1459348SSiddheshwar.Mahesh@Sun.COM * getattr op - chunk3 - 19 bytes 1469348SSiddheshwar.Mahesh@Sun.COM * (getattr op starts at byte 4 after 3 bytes of roundup) 1479348SSiddheshwar.Mahesh@Sun.COM * 1480Sstevel@tonic-gate */ 1490Sstevel@tonic-gate 1507387SRobert.Gordon@Sun.COM typedef struct { 1510Sstevel@tonic-gate caddr_t xp_offp; 1520Sstevel@tonic-gate int xp_min_chunk; 1530Sstevel@tonic-gate uint_t xp_flags; /* Controls setting for rdma xdr */ 1547387SRobert.Gordon@Sun.COM int xp_buf_size; /* size of xdr buffer */ 1559348SSiddheshwar.Mahesh@Sun.COM int xp_off; /* overall offset */ 1569348SSiddheshwar.Mahesh@Sun.COM struct clist *xp_rcl; /* head of chunk list */ 1577387SRobert.Gordon@Sun.COM struct clist **xp_rcl_next; /* location to place/find next chunk */ 1589348SSiddheshwar.Mahesh@Sun.COM struct clist *xp_rcl_xdr; /* copy of rcl containing RPC message */ 1597387SRobert.Gordon@Sun.COM struct clist *xp_wcl; /* head of write chunk list */ 1600Sstevel@tonic-gate CONN *xp_conn; /* connection for chunk data xfer */ 1617387SRobert.Gordon@Sun.COM uint_t xp_reply_chunk_len; 1627387SRobert.Gordon@Sun.COM /* used to track length for security modes: integrity/privacy */ 1637387SRobert.Gordon@Sun.COM uint_t xp_reply_chunk_len_alt; 1647387SRobert.Gordon@Sun.COM } xrdma_private_t; 1657387SRobert.Gordon@Sun.COM 1667387SRobert.Gordon@Sun.COM extern kmem_cache_t *clist_cache; 1677387SRobert.Gordon@Sun.COM 1687387SRobert.Gordon@Sun.COM bool_t 1697387SRobert.Gordon@Sun.COM xdrrdma_getrdmablk(XDR *xdrs, struct clist **rlist, uint_t *sizep, 1707387SRobert.Gordon@Sun.COM CONN **conn, const uint_t maxsize) 1717387SRobert.Gordon@Sun.COM { 1727387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 1737387SRobert.Gordon@Sun.COM struct clist *cle = *(xdrp->xp_rcl_next); 1747387SRobert.Gordon@Sun.COM struct clist *rdclist = NULL, *prev = NULL; 1757387SRobert.Gordon@Sun.COM bool_t retval = TRUE; 1767387SRobert.Gordon@Sun.COM uint32_t cur_offset = 0; 1777387SRobert.Gordon@Sun.COM uint32_t total_segments = 0; 1787387SRobert.Gordon@Sun.COM uint32_t actual_segments = 0; 1797387SRobert.Gordon@Sun.COM uint32_t alen; 1807387SRobert.Gordon@Sun.COM uint_t total_len; 1817387SRobert.Gordon@Sun.COM 1827387SRobert.Gordon@Sun.COM ASSERT(xdrs->x_op != XDR_FREE); 1837387SRobert.Gordon@Sun.COM 1847387SRobert.Gordon@Sun.COM /* 1857387SRobert.Gordon@Sun.COM * first deal with the length since xdr bytes are counted 1867387SRobert.Gordon@Sun.COM */ 1877387SRobert.Gordon@Sun.COM if (!xdr_u_int(xdrs, sizep)) { 1887387SRobert.Gordon@Sun.COM DTRACE_PROBE(xdr__e__getrdmablk_sizep_fail); 1897387SRobert.Gordon@Sun.COM return (FALSE); 1907387SRobert.Gordon@Sun.COM } 1917387SRobert.Gordon@Sun.COM total_len = *sizep; 1927387SRobert.Gordon@Sun.COM if (total_len > maxsize) { 1937387SRobert.Gordon@Sun.COM DTRACE_PROBE2(xdr__e__getrdmablk_bad_size, 1947387SRobert.Gordon@Sun.COM int, total_len, int, maxsize); 1957387SRobert.Gordon@Sun.COM return (FALSE); 1967387SRobert.Gordon@Sun.COM } 1977387SRobert.Gordon@Sun.COM (*conn) = xdrp->xp_conn; 1987387SRobert.Gordon@Sun.COM 1997387SRobert.Gordon@Sun.COM /* 2007387SRobert.Gordon@Sun.COM * if no data we are done 2017387SRobert.Gordon@Sun.COM */ 2027387SRobert.Gordon@Sun.COM if (total_len == 0) 2037387SRobert.Gordon@Sun.COM return (TRUE); 2047387SRobert.Gordon@Sun.COM 2057387SRobert.Gordon@Sun.COM while (cle) { 2067387SRobert.Gordon@Sun.COM total_segments++; 2077387SRobert.Gordon@Sun.COM cle = cle->c_next; 2087387SRobert.Gordon@Sun.COM } 2097387SRobert.Gordon@Sun.COM 2107387SRobert.Gordon@Sun.COM cle = *(xdrp->xp_rcl_next); 2117387SRobert.Gordon@Sun.COM 2127387SRobert.Gordon@Sun.COM /* 2137387SRobert.Gordon@Sun.COM * If there was a chunk at the current offset, then setup a read 2147387SRobert.Gordon@Sun.COM * chunk list which records the destination address and length 2157387SRobert.Gordon@Sun.COM * and will RDMA READ the data in later. 2167387SRobert.Gordon@Sun.COM */ 2177387SRobert.Gordon@Sun.COM if (cle == NULL) 2187387SRobert.Gordon@Sun.COM return (FALSE); 2190Sstevel@tonic-gate 2207387SRobert.Gordon@Sun.COM if (cle->c_xdroff != (xdrp->xp_offp - xdrs->x_base)) 2217387SRobert.Gordon@Sun.COM return (FALSE); 2227387SRobert.Gordon@Sun.COM 2237387SRobert.Gordon@Sun.COM /* 2247387SRobert.Gordon@Sun.COM * Setup the chunk list with appropriate 2257387SRobert.Gordon@Sun.COM * address (offset) and length 2267387SRobert.Gordon@Sun.COM */ 2277387SRobert.Gordon@Sun.COM for (actual_segments = 0; 2287387SRobert.Gordon@Sun.COM actual_segments < total_segments; actual_segments++) { 2299348SSiddheshwar.Mahesh@Sun.COM 2309348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE3(krpc__i__xdrrdma_getrdmablk, uint32_t, cle->c_len, 2319348SSiddheshwar.Mahesh@Sun.COM uint32_t, total_len, uint32_t, cle->c_xdroff); 2329348SSiddheshwar.Mahesh@Sun.COM 2337387SRobert.Gordon@Sun.COM if (total_len <= 0) 2347387SRobert.Gordon@Sun.COM break; 2359348SSiddheshwar.Mahesh@Sun.COM 2369348SSiddheshwar.Mahesh@Sun.COM /* 2379348SSiddheshwar.Mahesh@Sun.COM * not the first time in the loop 2389348SSiddheshwar.Mahesh@Sun.COM */ 2399348SSiddheshwar.Mahesh@Sun.COM if (actual_segments > 0) 2409348SSiddheshwar.Mahesh@Sun.COM cle = cle->c_next; 2419348SSiddheshwar.Mahesh@Sun.COM 2427387SRobert.Gordon@Sun.COM cle->u.c_daddr = (uint64) cur_offset; 2437387SRobert.Gordon@Sun.COM alen = 0; 2447387SRobert.Gordon@Sun.COM if (cle->c_len > total_len) { 2457387SRobert.Gordon@Sun.COM alen = cle->c_len; 2467387SRobert.Gordon@Sun.COM cle->c_len = total_len; 2477387SRobert.Gordon@Sun.COM } 2487387SRobert.Gordon@Sun.COM if (!alen) 2497387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &cle->c_next; 2507387SRobert.Gordon@Sun.COM 2517387SRobert.Gordon@Sun.COM cur_offset += cle->c_len; 2527387SRobert.Gordon@Sun.COM total_len -= cle->c_len; 2537387SRobert.Gordon@Sun.COM 2547387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) == 0 && 2557387SRobert.Gordon@Sun.COM total_len > 0) { 2567387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__xdrrdma_getblk_chunktooshort); 2577387SRobert.Gordon@Sun.COM retval = FALSE; 2587387SRobert.Gordon@Sun.COM } 2597387SRobert.Gordon@Sun.COM 2607387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) > 0 && 2617387SRobert.Gordon@Sun.COM total_len == 0) { 2627387SRobert.Gordon@Sun.COM DTRACE_PROBE2(krpc__e__xdrrdma_getblk_toobig, 2637387SRobert.Gordon@Sun.COM int, total_segments, int, actual_segments); 2647387SRobert.Gordon@Sun.COM } 2657387SRobert.Gordon@Sun.COM 2667387SRobert.Gordon@Sun.COM rdclist = clist_alloc(); 2677387SRobert.Gordon@Sun.COM (*rdclist) = (*cle); 2687387SRobert.Gordon@Sun.COM if ((*rlist) == NULL) 2697387SRobert.Gordon@Sun.COM (*rlist) = rdclist; 2707387SRobert.Gordon@Sun.COM if (prev == NULL) 2717387SRobert.Gordon@Sun.COM prev = rdclist; 2727387SRobert.Gordon@Sun.COM else { 2737387SRobert.Gordon@Sun.COM prev->c_next = rdclist; 2747387SRobert.Gordon@Sun.COM prev = rdclist; 2757387SRobert.Gordon@Sun.COM } 2767387SRobert.Gordon@Sun.COM 2777387SRobert.Gordon@Sun.COM } 2787387SRobert.Gordon@Sun.COM 2797387SRobert.Gordon@Sun.COM out: 2807387SRobert.Gordon@Sun.COM if (prev != NULL) 2817387SRobert.Gordon@Sun.COM prev->c_next = NULL; 2827387SRobert.Gordon@Sun.COM 2839348SSiddheshwar.Mahesh@Sun.COM /* 2849348SSiddheshwar.Mahesh@Sun.COM * Adjust the chunk length, if we read only a part of 2859348SSiddheshwar.Mahesh@Sun.COM * a chunk. 2869348SSiddheshwar.Mahesh@Sun.COM */ 2879348SSiddheshwar.Mahesh@Sun.COM 2887387SRobert.Gordon@Sun.COM if (alen) { 2897387SRobert.Gordon@Sun.COM cle->w.c_saddr = 2907387SRobert.Gordon@Sun.COM (uint64)(uintptr_t)cle->w.c_saddr + cle->c_len; 2917387SRobert.Gordon@Sun.COM cle->c_len = alen - cle->c_len; 2927387SRobert.Gordon@Sun.COM } 2937387SRobert.Gordon@Sun.COM 2947387SRobert.Gordon@Sun.COM return (retval); 2957387SRobert.Gordon@Sun.COM } 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate /* 2987387SRobert.Gordon@Sun.COM * The procedure xdrrdma_create initializes a stream descriptor for a memory 2997387SRobert.Gordon@Sun.COM * buffer. 3000Sstevel@tonic-gate */ 3010Sstevel@tonic-gate void 3020Sstevel@tonic-gate xdrrdma_create(XDR *xdrs, caddr_t addr, uint_t size, 3037387SRobert.Gordon@Sun.COM int min_chunk, struct clist *cl, enum xdr_op op, CONN *conn) 3040Sstevel@tonic-gate { 3057387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp; 3067387SRobert.Gordon@Sun.COM struct clist *cle; 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate xdrs->x_op = op; 3097387SRobert.Gordon@Sun.COM xdrs->x_ops = &xdrrdma_ops; 3100Sstevel@tonic-gate xdrs->x_base = addr; 3110Sstevel@tonic-gate xdrs->x_handy = size; 3120Sstevel@tonic-gate xdrs->x_public = NULL; 3130Sstevel@tonic-gate 3147387SRobert.Gordon@Sun.COM xdrp = (xrdma_private_t *)kmem_zalloc(sizeof (xrdma_private_t), 3157387SRobert.Gordon@Sun.COM KM_SLEEP); 3160Sstevel@tonic-gate xdrs->x_private = (caddr_t)xdrp; 3170Sstevel@tonic-gate xdrp->xp_offp = addr; 3180Sstevel@tonic-gate xdrp->xp_min_chunk = min_chunk; 3190Sstevel@tonic-gate xdrp->xp_flags = 0; 3200Sstevel@tonic-gate xdrp->xp_buf_size = size; 3217387SRobert.Gordon@Sun.COM xdrp->xp_rcl = cl; 3227387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len = 0; 3237387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len_alt = 0; 3247387SRobert.Gordon@Sun.COM 3250Sstevel@tonic-gate if (op == XDR_ENCODE && cl != NULL) { 3267387SRobert.Gordon@Sun.COM /* Find last element in chunk list and set xp_rcl_next */ 3277387SRobert.Gordon@Sun.COM for (cle = cl; cle->c_next != NULL; cle = cle->c_next) 3287387SRobert.Gordon@Sun.COM continue; 3297387SRobert.Gordon@Sun.COM 3307387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &(cle->c_next); 3317387SRobert.Gordon@Sun.COM } else { 3327387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &(xdrp->xp_rcl); 3337387SRobert.Gordon@Sun.COM } 3347387SRobert.Gordon@Sun.COM 3357387SRobert.Gordon@Sun.COM xdrp->xp_wcl = NULL; 3367387SRobert.Gordon@Sun.COM 3370Sstevel@tonic-gate xdrp->xp_conn = conn; 3387387SRobert.Gordon@Sun.COM if (xdrp->xp_min_chunk != 0) 3397387SRobert.Gordon@Sun.COM xdrp->xp_flags |= XDR_RDMA_CHUNK; 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate /* ARGSUSED */ 3430Sstevel@tonic-gate void 3447387SRobert.Gordon@Sun.COM xdrrdma_destroy(XDR * xdrs) 3450Sstevel@tonic-gate { 3467387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 3477387SRobert.Gordon@Sun.COM 3487387SRobert.Gordon@Sun.COM if (xdrp == NULL) 3497387SRobert.Gordon@Sun.COM return; 3507387SRobert.Gordon@Sun.COM 3517387SRobert.Gordon@Sun.COM if (xdrp->xp_wcl) { 3527387SRobert.Gordon@Sun.COM if (xdrp->xp_flags & XDR_RDMA_WLIST_REG) { 3539348SSiddheshwar.Mahesh@Sun.COM (void) clist_deregister(xdrp->xp_conn, xdrp->xp_wcl); 3547387SRobert.Gordon@Sun.COM rdma_buf_free(xdrp->xp_conn, 3557387SRobert.Gordon@Sun.COM &xdrp->xp_wcl->rb_longbuf); 3567387SRobert.Gordon@Sun.COM } 3577387SRobert.Gordon@Sun.COM clist_free(xdrp->xp_wcl); 3587387SRobert.Gordon@Sun.COM } 3597387SRobert.Gordon@Sun.COM 3607387SRobert.Gordon@Sun.COM if (xdrp->xp_rcl) { 3617387SRobert.Gordon@Sun.COM if (xdrp->xp_flags & XDR_RDMA_RLIST_REG) { 3629348SSiddheshwar.Mahesh@Sun.COM (void) clist_deregister(xdrp->xp_conn, xdrp->xp_rcl); 3637387SRobert.Gordon@Sun.COM rdma_buf_free(xdrp->xp_conn, 3647387SRobert.Gordon@Sun.COM &xdrp->xp_rcl->rb_longbuf); 3657387SRobert.Gordon@Sun.COM } 3667387SRobert.Gordon@Sun.COM clist_free(xdrp->xp_rcl); 3677387SRobert.Gordon@Sun.COM } 3687387SRobert.Gordon@Sun.COM 3699348SSiddheshwar.Mahesh@Sun.COM if (xdrp->xp_rcl_xdr) 3709348SSiddheshwar.Mahesh@Sun.COM xdrrdma_free_xdr_chunks(xdrp->xp_conn, xdrp->xp_rcl_xdr); 3719348SSiddheshwar.Mahesh@Sun.COM 3727387SRobert.Gordon@Sun.COM (void) kmem_free(xdrs->x_private, sizeof (xrdma_private_t)); 3737387SRobert.Gordon@Sun.COM xdrs->x_private = NULL; 3740Sstevel@tonic-gate } 3750Sstevel@tonic-gate 3767387SRobert.Gordon@Sun.COM static bool_t 3770Sstevel@tonic-gate xdrrdma_getint32(XDR *xdrs, int32_t *int32p) 3780Sstevel@tonic-gate { 3797387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 3809348SSiddheshwar.Mahesh@Sun.COM int chunked = 0; 3810Sstevel@tonic-gate 3829348SSiddheshwar.Mahesh@Sun.COM if ((xdrs->x_handy -= (int)sizeof (int32_t)) < 0) { 3839348SSiddheshwar.Mahesh@Sun.COM /* 3849348SSiddheshwar.Mahesh@Sun.COM * check if rest of the rpc message is in a chunk 3859348SSiddheshwar.Mahesh@Sun.COM */ 3869348SSiddheshwar.Mahesh@Sun.COM if (!xdrrdma_read_a_chunk(xdrs, &xdrp->xp_conn)) { 3879348SSiddheshwar.Mahesh@Sun.COM return (FALSE); 3889348SSiddheshwar.Mahesh@Sun.COM } 3899348SSiddheshwar.Mahesh@Sun.COM chunked = 1; 3909348SSiddheshwar.Mahesh@Sun.COM } 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate /* LINTED pointer alignment */ 3930Sstevel@tonic-gate *int32p = (int32_t)ntohl((uint32_t)(*((int32_t *)(xdrp->xp_offp)))); 3949348SSiddheshwar.Mahesh@Sun.COM 3959348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE1(krpc__i__xdrrdma_getint32, int32_t, *int32p); 3969348SSiddheshwar.Mahesh@Sun.COM 3970Sstevel@tonic-gate xdrp->xp_offp += sizeof (int32_t); 3980Sstevel@tonic-gate 3999348SSiddheshwar.Mahesh@Sun.COM if (chunked) 4009348SSiddheshwar.Mahesh@Sun.COM xdrs->x_handy -= (int)sizeof (int32_t); 4019348SSiddheshwar.Mahesh@Sun.COM 4029348SSiddheshwar.Mahesh@Sun.COM if (xdrp->xp_off != 0) { 4039348SSiddheshwar.Mahesh@Sun.COM xdrp->xp_off += sizeof (int32_t); 4049348SSiddheshwar.Mahesh@Sun.COM } 4059348SSiddheshwar.Mahesh@Sun.COM 4060Sstevel@tonic-gate return (TRUE); 4070Sstevel@tonic-gate } 4080Sstevel@tonic-gate 4097387SRobert.Gordon@Sun.COM static bool_t 4100Sstevel@tonic-gate xdrrdma_putint32(XDR *xdrs, int32_t *int32p) 4110Sstevel@tonic-gate { 4127387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate if ((xdrs->x_handy -= (int)sizeof (int32_t)) < 0) 4150Sstevel@tonic-gate return (FALSE); 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate /* LINTED pointer alignment */ 4180Sstevel@tonic-gate *(int32_t *)xdrp->xp_offp = (int32_t)htonl((uint32_t)(*int32p)); 4190Sstevel@tonic-gate xdrp->xp_offp += sizeof (int32_t); 4200Sstevel@tonic-gate 4210Sstevel@tonic-gate return (TRUE); 4220Sstevel@tonic-gate } 4230Sstevel@tonic-gate 4240Sstevel@tonic-gate /* 4257387SRobert.Gordon@Sun.COM * DECODE bytes from XDR stream for rdma. 4267387SRobert.Gordon@Sun.COM * If the XDR stream contains a read chunk list, 4277387SRobert.Gordon@Sun.COM * it will go through xdrrdma_getrdmablk instead. 4280Sstevel@tonic-gate */ 4297387SRobert.Gordon@Sun.COM static bool_t 4300Sstevel@tonic-gate xdrrdma_getbytes(XDR *xdrs, caddr_t addr, int len) 4310Sstevel@tonic-gate { 4327387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 4337387SRobert.Gordon@Sun.COM struct clist *cle = *(xdrp->xp_rcl_next); 4347387SRobert.Gordon@Sun.COM struct clist *cls = *(xdrp->xp_rcl_next); 4357387SRobert.Gordon@Sun.COM struct clist cl; 4367387SRobert.Gordon@Sun.COM bool_t retval = TRUE; 4377387SRobert.Gordon@Sun.COM uint32_t total_len = len; 4387387SRobert.Gordon@Sun.COM uint32_t cur_offset = 0; 4397387SRobert.Gordon@Sun.COM uint32_t total_segments = 0; 4407387SRobert.Gordon@Sun.COM uint32_t actual_segments = 0; 4419803SSiddheshwar.Mahesh@Sun.COM uint32_t status = RDMA_SUCCESS; 4429803SSiddheshwar.Mahesh@Sun.COM uint32_t alen = 0; 4439348SSiddheshwar.Mahesh@Sun.COM uint32_t xpoff; 4440Sstevel@tonic-gate 4457387SRobert.Gordon@Sun.COM while (cle) { 4467387SRobert.Gordon@Sun.COM total_segments++; 4477387SRobert.Gordon@Sun.COM cle = cle->c_next; 4487387SRobert.Gordon@Sun.COM } 4497387SRobert.Gordon@Sun.COM 4507387SRobert.Gordon@Sun.COM cle = *(xdrp->xp_rcl_next); 4519348SSiddheshwar.Mahesh@Sun.COM 4529348SSiddheshwar.Mahesh@Sun.COM if (xdrp->xp_off) { 4539348SSiddheshwar.Mahesh@Sun.COM xpoff = xdrp->xp_off; 4549348SSiddheshwar.Mahesh@Sun.COM } else { 4559348SSiddheshwar.Mahesh@Sun.COM xpoff = (xdrp->xp_offp - xdrs->x_base); 4569348SSiddheshwar.Mahesh@Sun.COM } 4579348SSiddheshwar.Mahesh@Sun.COM 4580Sstevel@tonic-gate /* 4597387SRobert.Gordon@Sun.COM * If there was a chunk at the current offset, then setup a read 4607387SRobert.Gordon@Sun.COM * chunk list which records the destination address and length 4617387SRobert.Gordon@Sun.COM * and will RDMA READ the data in later. 4620Sstevel@tonic-gate */ 4637387SRobert.Gordon@Sun.COM 4649348SSiddheshwar.Mahesh@Sun.COM if (cle != NULL && cle->c_xdroff == xpoff) { 4657387SRobert.Gordon@Sun.COM for (actual_segments = 0; 4667387SRobert.Gordon@Sun.COM actual_segments < total_segments; actual_segments++) { 4679803SSiddheshwar.Mahesh@Sun.COM 4687387SRobert.Gordon@Sun.COM if (total_len <= 0) 4697387SRobert.Gordon@Sun.COM break; 4709803SSiddheshwar.Mahesh@Sun.COM 4719803SSiddheshwar.Mahesh@Sun.COM if (status != RDMA_SUCCESS) 4729803SSiddheshwar.Mahesh@Sun.COM goto out; 4739803SSiddheshwar.Mahesh@Sun.COM 4747387SRobert.Gordon@Sun.COM cle->u.c_daddr = (uint64)(uintptr_t)addr + cur_offset; 4757387SRobert.Gordon@Sun.COM alen = 0; 4767387SRobert.Gordon@Sun.COM if (cle->c_len > total_len) { 4777387SRobert.Gordon@Sun.COM alen = cle->c_len; 4787387SRobert.Gordon@Sun.COM cle->c_len = total_len; 4797387SRobert.Gordon@Sun.COM } 4807387SRobert.Gordon@Sun.COM if (!alen) 4817387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &cle->c_next; 4827387SRobert.Gordon@Sun.COM 4837387SRobert.Gordon@Sun.COM cur_offset += cle->c_len; 4847387SRobert.Gordon@Sun.COM total_len -= cle->c_len; 4857387SRobert.Gordon@Sun.COM 4867387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) == 0 && 4877387SRobert.Gordon@Sun.COM total_len > 0) { 4887387SRobert.Gordon@Sun.COM DTRACE_PROBE( 4897387SRobert.Gordon@Sun.COM krpc__e__xdrrdma_getbytes_chunktooshort); 4907387SRobert.Gordon@Sun.COM retval = FALSE; 4917387SRobert.Gordon@Sun.COM } 4927387SRobert.Gordon@Sun.COM 4937387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) > 0 && 4947387SRobert.Gordon@Sun.COM total_len == 0) { 4957387SRobert.Gordon@Sun.COM DTRACE_PROBE2(krpc__e__xdrrdma_getbytes_toobig, 4967387SRobert.Gordon@Sun.COM int, total_segments, int, actual_segments); 4977387SRobert.Gordon@Sun.COM } 4980Sstevel@tonic-gate 4997387SRobert.Gordon@Sun.COM /* 5007387SRobert.Gordon@Sun.COM * RDMA READ the chunk data from the remote end. 5017387SRobert.Gordon@Sun.COM * First prep the destination buffer by registering 5027387SRobert.Gordon@Sun.COM * it, then RDMA READ the chunk data. Since we are 5037387SRobert.Gordon@Sun.COM * doing streaming memory, sync the destination 5047387SRobert.Gordon@Sun.COM * buffer to CPU and deregister the buffer. 5057387SRobert.Gordon@Sun.COM */ 5067387SRobert.Gordon@Sun.COM if (xdrp->xp_conn == NULL) { 5077387SRobert.Gordon@Sun.COM return (FALSE); 5087387SRobert.Gordon@Sun.COM } 5097387SRobert.Gordon@Sun.COM cl = *cle; 5107387SRobert.Gordon@Sun.COM cl.c_next = NULL; 5119803SSiddheshwar.Mahesh@Sun.COM status = clist_register(xdrp->xp_conn, &cl, 5129803SSiddheshwar.Mahesh@Sun.COM CLIST_REG_DST); 5139803SSiddheshwar.Mahesh@Sun.COM if (status != RDMA_SUCCESS) { 5149803SSiddheshwar.Mahesh@Sun.COM retval = FALSE; 5159803SSiddheshwar.Mahesh@Sun.COM /* 5169803SSiddheshwar.Mahesh@Sun.COM * Deregister the previous chunks 5179803SSiddheshwar.Mahesh@Sun.COM * before return 5189803SSiddheshwar.Mahesh@Sun.COM */ 5199803SSiddheshwar.Mahesh@Sun.COM goto out; 5207387SRobert.Gordon@Sun.COM } 5219803SSiddheshwar.Mahesh@Sun.COM 5227387SRobert.Gordon@Sun.COM cle->c_dmemhandle = cl.c_dmemhandle; 5237387SRobert.Gordon@Sun.COM cle->c_dsynchandle = cl.c_dsynchandle; 5240Sstevel@tonic-gate 5257387SRobert.Gordon@Sun.COM /* 5267387SRobert.Gordon@Sun.COM * Now read the chunk in 5277387SRobert.Gordon@Sun.COM */ 5287387SRobert.Gordon@Sun.COM if ((total_segments - actual_segments - 1) == 0 || 5297387SRobert.Gordon@Sun.COM total_len == 0) { 5307387SRobert.Gordon@Sun.COM status = RDMA_READ(xdrp->xp_conn, &cl, WAIT); 5317387SRobert.Gordon@Sun.COM } else { 5327387SRobert.Gordon@Sun.COM status = RDMA_READ(xdrp->xp_conn, &cl, NOWAIT); 5337387SRobert.Gordon@Sun.COM } 5347387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 5357387SRobert.Gordon@Sun.COM DTRACE_PROBE1( 5367387SRobert.Gordon@Sun.COM krpc__i__xdrrdma_getblk_readfailed, 5377387SRobert.Gordon@Sun.COM int, status); 5387387SRobert.Gordon@Sun.COM retval = FALSE; 5397387SRobert.Gordon@Sun.COM } 5409803SSiddheshwar.Mahesh@Sun.COM 5417387SRobert.Gordon@Sun.COM cle = cle->c_next; 5429803SSiddheshwar.Mahesh@Sun.COM 5430Sstevel@tonic-gate } 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate /* 5460Sstevel@tonic-gate * sync the memory for cpu 5470Sstevel@tonic-gate */ 5487387SRobert.Gordon@Sun.COM cl = *cls; 5497387SRobert.Gordon@Sun.COM cl.c_next = NULL; 5507387SRobert.Gordon@Sun.COM cl.c_len = cur_offset; 5519348SSiddheshwar.Mahesh@Sun.COM if (clist_syncmem( 5529348SSiddheshwar.Mahesh@Sun.COM xdrp->xp_conn, &cl, CLIST_REG_DST) != RDMA_SUCCESS) { 5530Sstevel@tonic-gate retval = FALSE; 5540Sstevel@tonic-gate } 5550Sstevel@tonic-gate out: 5569803SSiddheshwar.Mahesh@Sun.COM 5570Sstevel@tonic-gate /* 5580Sstevel@tonic-gate * Deregister the chunks 5590Sstevel@tonic-gate */ 5607387SRobert.Gordon@Sun.COM cle = cls; 5619803SSiddheshwar.Mahesh@Sun.COM while (actual_segments != 0) { 5629803SSiddheshwar.Mahesh@Sun.COM cl = *cle; 5639803SSiddheshwar.Mahesh@Sun.COM cl.c_next = NULL; 5649803SSiddheshwar.Mahesh@Sun.COM 5659803SSiddheshwar.Mahesh@Sun.COM cl.c_regtype = CLIST_REG_DST; 5669803SSiddheshwar.Mahesh@Sun.COM (void) clist_deregister(xdrp->xp_conn, &cl); 5679803SSiddheshwar.Mahesh@Sun.COM 5689803SSiddheshwar.Mahesh@Sun.COM cle = cle->c_next; 5699803SSiddheshwar.Mahesh@Sun.COM actual_segments--; 5709803SSiddheshwar.Mahesh@Sun.COM } 5719803SSiddheshwar.Mahesh@Sun.COM 5727387SRobert.Gordon@Sun.COM if (alen) { 5739803SSiddheshwar.Mahesh@Sun.COM cle = *(xdrp->xp_rcl_next); 5747387SRobert.Gordon@Sun.COM cle->w.c_saddr = 5757387SRobert.Gordon@Sun.COM (uint64)(uintptr_t)cle->w.c_saddr + cle->c_len; 5767387SRobert.Gordon@Sun.COM cle->c_len = alen - cle->c_len; 5777387SRobert.Gordon@Sun.COM } 5789803SSiddheshwar.Mahesh@Sun.COM 5790Sstevel@tonic-gate return (retval); 5800Sstevel@tonic-gate } 5819348SSiddheshwar.Mahesh@Sun.COM 5820Sstevel@tonic-gate if ((xdrs->x_handy -= len) < 0) 5830Sstevel@tonic-gate return (FALSE); 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate bcopy(xdrp->xp_offp, addr, len); 5869348SSiddheshwar.Mahesh@Sun.COM 5870Sstevel@tonic-gate xdrp->xp_offp += len; 5880Sstevel@tonic-gate 5899348SSiddheshwar.Mahesh@Sun.COM if (xdrp->xp_off != 0) 5909348SSiddheshwar.Mahesh@Sun.COM xdrp->xp_off += len; 5919348SSiddheshwar.Mahesh@Sun.COM 5920Sstevel@tonic-gate return (TRUE); 5930Sstevel@tonic-gate } 5940Sstevel@tonic-gate 5950Sstevel@tonic-gate /* 5967387SRobert.Gordon@Sun.COM * ENCODE some bytes into an XDR stream xp_min_chunk = 0, means the stream of 5977387SRobert.Gordon@Sun.COM * bytes contain no chunks to seperate out, and if the bytes do not fit in 5987387SRobert.Gordon@Sun.COM * the supplied buffer, grow the buffer and free the old buffer. 5990Sstevel@tonic-gate */ 6007387SRobert.Gordon@Sun.COM static bool_t 6010Sstevel@tonic-gate xdrrdma_putbytes(XDR *xdrs, caddr_t addr, int len) 6020Sstevel@tonic-gate { 6037387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 6040Sstevel@tonic-gate /* 6057387SRobert.Gordon@Sun.COM * Is this stream accepting chunks? 6067387SRobert.Gordon@Sun.COM * If so, does the either of the two following conditions exist? 6077387SRobert.Gordon@Sun.COM * - length of bytes to encode is greater than the min chunk size? 6087387SRobert.Gordon@Sun.COM * - remaining space in this stream is shorter than length of 6097387SRobert.Gordon@Sun.COM * bytes to encode? 6107387SRobert.Gordon@Sun.COM * 6117387SRobert.Gordon@Sun.COM * If the above exists, then create a chunk for this encoding 6127387SRobert.Gordon@Sun.COM * and save the addresses, etc. 6130Sstevel@tonic-gate */ 6147387SRobert.Gordon@Sun.COM if (xdrp->xp_flags & XDR_RDMA_CHUNK && 6157387SRobert.Gordon@Sun.COM ((xdrp->xp_min_chunk != 0 && 6167387SRobert.Gordon@Sun.COM len >= xdrp->xp_min_chunk) || 6177387SRobert.Gordon@Sun.COM (xdrs->x_handy - len < 0))) { 6187387SRobert.Gordon@Sun.COM struct clist *cle; 6197387SRobert.Gordon@Sun.COM int offset = xdrp->xp_offp - xdrs->x_base; 6200Sstevel@tonic-gate 6217387SRobert.Gordon@Sun.COM cle = clist_alloc(); 6220Sstevel@tonic-gate cle->c_xdroff = offset; 6237387SRobert.Gordon@Sun.COM cle->c_len = len; 6247387SRobert.Gordon@Sun.COM cle->w.c_saddr = (uint64)(uintptr_t)addr; 6250Sstevel@tonic-gate cle->c_next = NULL; 6260Sstevel@tonic-gate 6277387SRobert.Gordon@Sun.COM *(xdrp->xp_rcl_next) = cle; 6287387SRobert.Gordon@Sun.COM xdrp->xp_rcl_next = &(cle->c_next); 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate return (TRUE); 6310Sstevel@tonic-gate } 6327387SRobert.Gordon@Sun.COM /* Is there enough space to encode what is left? */ 6330Sstevel@tonic-gate if ((xdrs->x_handy -= len) < 0) { 6347387SRobert.Gordon@Sun.COM return (FALSE); 6350Sstevel@tonic-gate } 6360Sstevel@tonic-gate bcopy(addr, xdrp->xp_offp, len); 6370Sstevel@tonic-gate xdrp->xp_offp += len; 6380Sstevel@tonic-gate 6390Sstevel@tonic-gate return (TRUE); 6400Sstevel@tonic-gate } 6410Sstevel@tonic-gate 6420Sstevel@tonic-gate uint_t 6430Sstevel@tonic-gate xdrrdma_getpos(XDR *xdrs) 6440Sstevel@tonic-gate { 6457387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 6460Sstevel@tonic-gate 6470Sstevel@tonic-gate return ((uint_t)((uintptr_t)xdrp->xp_offp - (uintptr_t)xdrs->x_base)); 6480Sstevel@tonic-gate } 6490Sstevel@tonic-gate 6500Sstevel@tonic-gate bool_t 6510Sstevel@tonic-gate xdrrdma_setpos(XDR *xdrs, uint_t pos) 6520Sstevel@tonic-gate { 6537387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 6540Sstevel@tonic-gate 6557387SRobert.Gordon@Sun.COM caddr_t newaddr = xdrs->x_base + pos; 6567387SRobert.Gordon@Sun.COM caddr_t lastaddr = xdrp->xp_offp + xdrs->x_handy; 6577387SRobert.Gordon@Sun.COM ptrdiff_t diff; 6580Sstevel@tonic-gate 6590Sstevel@tonic-gate if (newaddr > lastaddr) 6600Sstevel@tonic-gate return (FALSE); 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate xdrp->xp_offp = newaddr; 6630Sstevel@tonic-gate diff = lastaddr - newaddr; 6640Sstevel@tonic-gate xdrs->x_handy = (int)diff; 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate return (TRUE); 6670Sstevel@tonic-gate } 6680Sstevel@tonic-gate 6690Sstevel@tonic-gate /* ARGSUSED */ 6700Sstevel@tonic-gate static rpc_inline_t * 6710Sstevel@tonic-gate xdrrdma_inline(XDR *xdrs, int len) 6720Sstevel@tonic-gate { 6737387SRobert.Gordon@Sun.COM rpc_inline_t *buf = NULL; 6747387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 6757387SRobert.Gordon@Sun.COM struct clist *cle = *(xdrp->xp_rcl_next); 6760Sstevel@tonic-gate 6770Sstevel@tonic-gate if (xdrs->x_op == XDR_DECODE) { 6780Sstevel@tonic-gate /* 6797387SRobert.Gordon@Sun.COM * Since chunks aren't in-line, check to see whether there is 6807387SRobert.Gordon@Sun.COM * a chunk in the inline range. 6810Sstevel@tonic-gate */ 6820Sstevel@tonic-gate if (cle != NULL && 6837387SRobert.Gordon@Sun.COM cle->c_xdroff <= (xdrp->xp_offp - xdrs->x_base + len)) 6847387SRobert.Gordon@Sun.COM return (NULL); 6857387SRobert.Gordon@Sun.COM } 6867387SRobert.Gordon@Sun.COM 6877387SRobert.Gordon@Sun.COM /* LINTED pointer alignment */ 6887387SRobert.Gordon@Sun.COM buf = (rpc_inline_t *)xdrp->xp_offp; 6897387SRobert.Gordon@Sun.COM if (!IS_P2ALIGNED(buf, sizeof (int32_t))) 6900Sstevel@tonic-gate return (NULL); 6910Sstevel@tonic-gate 6920Sstevel@tonic-gate if ((xdrs->x_handy < len) || (xdrp->xp_min_chunk != 0 && 6930Sstevel@tonic-gate len >= xdrp->xp_min_chunk)) { 6940Sstevel@tonic-gate return (NULL); 6950Sstevel@tonic-gate } else { 6960Sstevel@tonic-gate xdrs->x_handy -= len; 6970Sstevel@tonic-gate xdrp->xp_offp += len; 6980Sstevel@tonic-gate return (buf); 6990Sstevel@tonic-gate } 7000Sstevel@tonic-gate } 7010Sstevel@tonic-gate 7027387SRobert.Gordon@Sun.COM static bool_t 7030Sstevel@tonic-gate xdrrdma_control(XDR *xdrs, int request, void *info) 7040Sstevel@tonic-gate { 7057387SRobert.Gordon@Sun.COM int32_t *int32p; 7067387SRobert.Gordon@Sun.COM int len, i; 7077387SRobert.Gordon@Sun.COM uint_t in_flags; 7087387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 7097387SRobert.Gordon@Sun.COM rdma_chunkinfo_t *rcip = NULL; 7107387SRobert.Gordon@Sun.COM rdma_wlist_conn_info_t *rwcip = NULL; 7117387SRobert.Gordon@Sun.COM rdma_chunkinfo_lengths_t *rcilp = NULL; 7127387SRobert.Gordon@Sun.COM struct uio *uiop; 713*13002SKaren.Rochford@Sun.COM struct clist *rwl = NULL, *first = NULL; 7147387SRobert.Gordon@Sun.COM struct clist *prev = NULL; 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate switch (request) { 7170Sstevel@tonic-gate case XDR_PEEK: 7180Sstevel@tonic-gate /* 7190Sstevel@tonic-gate * Return the next 4 byte unit in the XDR stream. 7200Sstevel@tonic-gate */ 7210Sstevel@tonic-gate if (xdrs->x_handy < sizeof (int32_t)) 7220Sstevel@tonic-gate return (FALSE); 7230Sstevel@tonic-gate 7240Sstevel@tonic-gate int32p = (int32_t *)info; 7250Sstevel@tonic-gate *int32p = (int32_t)ntohl((uint32_t) 7260Sstevel@tonic-gate (*((int32_t *)(xdrp->xp_offp)))); 7270Sstevel@tonic-gate 7280Sstevel@tonic-gate return (TRUE); 7290Sstevel@tonic-gate 7300Sstevel@tonic-gate case XDR_SKIPBYTES: 7310Sstevel@tonic-gate /* 7320Sstevel@tonic-gate * Skip the next N bytes in the XDR stream. 7330Sstevel@tonic-gate */ 7340Sstevel@tonic-gate int32p = (int32_t *)info; 7350Sstevel@tonic-gate len = RNDUP((int)(*int32p)); 7360Sstevel@tonic-gate if ((xdrs->x_handy -= len) < 0) 7370Sstevel@tonic-gate return (FALSE); 7380Sstevel@tonic-gate xdrp->xp_offp += len; 7390Sstevel@tonic-gate 7400Sstevel@tonic-gate return (TRUE); 7410Sstevel@tonic-gate 7427387SRobert.Gordon@Sun.COM case XDR_RDMA_SET_FLAGS: 7430Sstevel@tonic-gate /* 7447387SRobert.Gordon@Sun.COM * Set the flags provided in the *info in xp_flags for rdma 7457387SRobert.Gordon@Sun.COM * xdr stream control. 7460Sstevel@tonic-gate */ 7470Sstevel@tonic-gate int32p = (int32_t *)info; 7480Sstevel@tonic-gate in_flags = (uint_t)(*int32p); 7490Sstevel@tonic-gate 7500Sstevel@tonic-gate xdrp->xp_flags |= in_flags; 7510Sstevel@tonic-gate return (TRUE); 7520Sstevel@tonic-gate 7537387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_FLAGS: 7540Sstevel@tonic-gate /* 7550Sstevel@tonic-gate * Get the flags provided in xp_flags return through *info 7560Sstevel@tonic-gate */ 7570Sstevel@tonic-gate int32p = (int32_t *)info; 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate *int32p = (int32_t)xdrp->xp_flags; 7600Sstevel@tonic-gate return (TRUE); 7610Sstevel@tonic-gate 7627387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_CHUNK_LEN: 7637387SRobert.Gordon@Sun.COM rcilp = (rdma_chunkinfo_lengths_t *)info; 7647387SRobert.Gordon@Sun.COM rcilp->rcil_len = xdrp->xp_reply_chunk_len; 7657387SRobert.Gordon@Sun.COM rcilp->rcil_len_alt = xdrp->xp_reply_chunk_len_alt; 7667387SRobert.Gordon@Sun.COM 7677387SRobert.Gordon@Sun.COM return (TRUE); 7687387SRobert.Gordon@Sun.COM 7697387SRobert.Gordon@Sun.COM case XDR_RDMA_ADD_CHUNK: 7707387SRobert.Gordon@Sun.COM /* 7717387SRobert.Gordon@Sun.COM * Store wlist information 7727387SRobert.Gordon@Sun.COM */ 7737387SRobert.Gordon@Sun.COM 7747387SRobert.Gordon@Sun.COM rcip = (rdma_chunkinfo_t *)info; 7757387SRobert.Gordon@Sun.COM 77611591SFaramarz.Jalalian@Sun.COM DTRACE_PROBE2(krpc__i__xdrrdma__control__add__chunk, 77711591SFaramarz.Jalalian@Sun.COM rci_type_t, rcip->rci_type, uint32, rcip->rci_len); 7787387SRobert.Gordon@Sun.COM switch (rcip->rci_type) { 7797387SRobert.Gordon@Sun.COM case RCI_WRITE_UIO_CHUNK: 7807387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len_alt += rcip->rci_len; 7817387SRobert.Gordon@Sun.COM 78212553SKaren.Rochford@Sun.COM if ((rcip->rci_len + XDR_RDMA_BUF_OVERHEAD) < 78312553SKaren.Rochford@Sun.COM xdrp->xp_min_chunk) { 7847387SRobert.Gordon@Sun.COM xdrp->xp_wcl = NULL; 7857387SRobert.Gordon@Sun.COM *(rcip->rci_clpp) = NULL; 7867387SRobert.Gordon@Sun.COM return (TRUE); 7877387SRobert.Gordon@Sun.COM } 7887387SRobert.Gordon@Sun.COM uiop = rcip->rci_a.rci_uiop; 7897387SRobert.Gordon@Sun.COM 7907387SRobert.Gordon@Sun.COM for (i = 0; i < uiop->uio_iovcnt; i++) { 7917387SRobert.Gordon@Sun.COM rwl = clist_alloc(); 792*13002SKaren.Rochford@Sun.COM if (first == NULL) 793*13002SKaren.Rochford@Sun.COM first = rwl; 7947387SRobert.Gordon@Sun.COM rwl->c_len = uiop->uio_iov[i].iov_len; 7957387SRobert.Gordon@Sun.COM rwl->u.c_daddr = 7967387SRobert.Gordon@Sun.COM (uint64)(uintptr_t) 7977387SRobert.Gordon@Sun.COM (uiop->uio_iov[i].iov_base); 7987387SRobert.Gordon@Sun.COM /* 7997387SRobert.Gordon@Sun.COM * if userspace address, put adspace ptr in 8007387SRobert.Gordon@Sun.COM * clist. If not, then do nothing since it's 8017387SRobert.Gordon@Sun.COM * already set to NULL (from kmem_zalloc) 8027387SRobert.Gordon@Sun.COM */ 8037387SRobert.Gordon@Sun.COM if (uiop->uio_segflg == UIO_USERSPACE) { 8047387SRobert.Gordon@Sun.COM rwl->c_adspc = ttoproc(curthread)->p_as; 8057387SRobert.Gordon@Sun.COM } 8067387SRobert.Gordon@Sun.COM 8077387SRobert.Gordon@Sun.COM if (prev == NULL) 8087387SRobert.Gordon@Sun.COM prev = rwl; 8097387SRobert.Gordon@Sun.COM else { 8107387SRobert.Gordon@Sun.COM prev->c_next = rwl; 8117387SRobert.Gordon@Sun.COM prev = rwl; 8127387SRobert.Gordon@Sun.COM } 8137387SRobert.Gordon@Sun.COM } 8147387SRobert.Gordon@Sun.COM 8157387SRobert.Gordon@Sun.COM rwl->c_next = NULL; 816*13002SKaren.Rochford@Sun.COM xdrp->xp_wcl = first; 817*13002SKaren.Rochford@Sun.COM *(rcip->rci_clpp) = first; 8187387SRobert.Gordon@Sun.COM 8197387SRobert.Gordon@Sun.COM break; 8207387SRobert.Gordon@Sun.COM 8217387SRobert.Gordon@Sun.COM case RCI_WRITE_ADDR_CHUNK: 8227387SRobert.Gordon@Sun.COM rwl = clist_alloc(); 8237387SRobert.Gordon@Sun.COM 8247387SRobert.Gordon@Sun.COM rwl->c_len = rcip->rci_len; 8257387SRobert.Gordon@Sun.COM rwl->u.c_daddr3 = rcip->rci_a.rci_addr; 8267387SRobert.Gordon@Sun.COM rwl->c_next = NULL; 8277387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len_alt += rcip->rci_len; 8287387SRobert.Gordon@Sun.COM 8297387SRobert.Gordon@Sun.COM xdrp->xp_wcl = rwl; 8307387SRobert.Gordon@Sun.COM *(rcip->rci_clpp) = rwl; 8317387SRobert.Gordon@Sun.COM 8327387SRobert.Gordon@Sun.COM break; 8337387SRobert.Gordon@Sun.COM 8347387SRobert.Gordon@Sun.COM case RCI_REPLY_CHUNK: 8357387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len += rcip->rci_len; 8367387SRobert.Gordon@Sun.COM break; 8377387SRobert.Gordon@Sun.COM } 8387387SRobert.Gordon@Sun.COM return (TRUE); 8397387SRobert.Gordon@Sun.COM 8407387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_WLIST: 8417387SRobert.Gordon@Sun.COM *((struct clist **)info) = xdrp->xp_wcl; 8427387SRobert.Gordon@Sun.COM return (TRUE); 8437387SRobert.Gordon@Sun.COM 8447387SRobert.Gordon@Sun.COM case XDR_RDMA_SET_WLIST: 8457387SRobert.Gordon@Sun.COM xdrp->xp_wcl = (struct clist *)info; 8467387SRobert.Gordon@Sun.COM return (TRUE); 8477387SRobert.Gordon@Sun.COM 8487387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_RLIST: 8497387SRobert.Gordon@Sun.COM *((struct clist **)info) = xdrp->xp_rcl; 8507387SRobert.Gordon@Sun.COM return (TRUE); 8517387SRobert.Gordon@Sun.COM 8527387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_WCINFO: 8537387SRobert.Gordon@Sun.COM rwcip = (rdma_wlist_conn_info_t *)info; 8547387SRobert.Gordon@Sun.COM 8557387SRobert.Gordon@Sun.COM rwcip->rwci_wlist = xdrp->xp_wcl; 8567387SRobert.Gordon@Sun.COM rwcip->rwci_conn = xdrp->xp_conn; 8577387SRobert.Gordon@Sun.COM 8587387SRobert.Gordon@Sun.COM return (TRUE); 8597387SRobert.Gordon@Sun.COM 8600Sstevel@tonic-gate default: 8610Sstevel@tonic-gate return (FALSE); 8620Sstevel@tonic-gate } 8630Sstevel@tonic-gate } 8640Sstevel@tonic-gate 8657387SRobert.Gordon@Sun.COM bool_t xdr_do_clist(XDR *, clist **); 8660Sstevel@tonic-gate 8670Sstevel@tonic-gate /* 8687387SRobert.Gordon@Sun.COM * Not all fields in struct clist are interesting to the RPC over RDMA 8697387SRobert.Gordon@Sun.COM * protocol. Only XDR the interesting fields. 8700Sstevel@tonic-gate */ 8710Sstevel@tonic-gate bool_t 8720Sstevel@tonic-gate xdr_clist(XDR *xdrs, clist *objp) 8730Sstevel@tonic-gate { 8740Sstevel@tonic-gate if (!xdr_uint32(xdrs, &objp->c_xdroff)) 8750Sstevel@tonic-gate return (FALSE); 8767387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &objp->c_smemhandle.mrc_rmr)) 8777387SRobert.Gordon@Sun.COM return (FALSE); 8780Sstevel@tonic-gate if (!xdr_uint32(xdrs, &objp->c_len)) 8790Sstevel@tonic-gate return (FALSE); 8807387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &objp->w.c_saddr)) 8810Sstevel@tonic-gate return (FALSE); 8827387SRobert.Gordon@Sun.COM if (!xdr_do_clist(xdrs, &objp->c_next)) 8830Sstevel@tonic-gate return (FALSE); 8840Sstevel@tonic-gate return (TRUE); 8850Sstevel@tonic-gate } 8860Sstevel@tonic-gate 8877387SRobert.Gordon@Sun.COM /* 8887387SRobert.Gordon@Sun.COM * The following two functions are forms of xdr_pointer() 8897387SRobert.Gordon@Sun.COM * and xdr_reference(). Since the generic versions just 8907387SRobert.Gordon@Sun.COM * kmem_alloc() a new clist, we actually want to use the 8917387SRobert.Gordon@Sun.COM * rdma_clist kmem_cache. 8927387SRobert.Gordon@Sun.COM */ 8937387SRobert.Gordon@Sun.COM 8947387SRobert.Gordon@Sun.COM /* 8957387SRobert.Gordon@Sun.COM * Generate or free a clist structure from the 8967387SRobert.Gordon@Sun.COM * kmem_cache "rdma_clist" 8977387SRobert.Gordon@Sun.COM */ 8980Sstevel@tonic-gate bool_t 8997387SRobert.Gordon@Sun.COM xdr_ref_clist(XDR *xdrs, caddr_t *pp) 9000Sstevel@tonic-gate { 9017387SRobert.Gordon@Sun.COM caddr_t loc = *pp; 9027387SRobert.Gordon@Sun.COM bool_t stat; 9037387SRobert.Gordon@Sun.COM 9047387SRobert.Gordon@Sun.COM if (loc == NULL) { 9057387SRobert.Gordon@Sun.COM switch (xdrs->x_op) { 9067387SRobert.Gordon@Sun.COM case XDR_FREE: 9077387SRobert.Gordon@Sun.COM return (TRUE); 9087387SRobert.Gordon@Sun.COM 9097387SRobert.Gordon@Sun.COM case XDR_DECODE: 9107387SRobert.Gordon@Sun.COM *pp = loc = (caddr_t)clist_alloc(); 9117387SRobert.Gordon@Sun.COM break; 9127387SRobert.Gordon@Sun.COM 9137387SRobert.Gordon@Sun.COM case XDR_ENCODE: 9147387SRobert.Gordon@Sun.COM ASSERT(loc); 9157387SRobert.Gordon@Sun.COM break; 9167387SRobert.Gordon@Sun.COM } 9177387SRobert.Gordon@Sun.COM } 9187387SRobert.Gordon@Sun.COM 9197387SRobert.Gordon@Sun.COM stat = xdr_clist(xdrs, (struct clist *)loc); 9207387SRobert.Gordon@Sun.COM 9217387SRobert.Gordon@Sun.COM if (xdrs->x_op == XDR_FREE) { 9227387SRobert.Gordon@Sun.COM kmem_cache_free(clist_cache, loc); 9237387SRobert.Gordon@Sun.COM *pp = NULL; 9247387SRobert.Gordon@Sun.COM } 9257387SRobert.Gordon@Sun.COM return (stat); 9267387SRobert.Gordon@Sun.COM } 9277387SRobert.Gordon@Sun.COM 9287387SRobert.Gordon@Sun.COM /* 9297387SRobert.Gordon@Sun.COM * XDR a pointer to a possibly recursive clist. This differs 9307387SRobert.Gordon@Sun.COM * with xdr_reference in that it can serialize/deserialiaze 9317387SRobert.Gordon@Sun.COM * trees correctly. 9327387SRobert.Gordon@Sun.COM * 9337387SRobert.Gordon@Sun.COM * What is sent is actually a union: 9347387SRobert.Gordon@Sun.COM * 9357387SRobert.Gordon@Sun.COM * union object_pointer switch (boolean b) { 9367387SRobert.Gordon@Sun.COM * case TRUE: object_data data; 9377387SRobert.Gordon@Sun.COM * case FALSE: void nothing; 9387387SRobert.Gordon@Sun.COM * } 9397387SRobert.Gordon@Sun.COM * 9407387SRobert.Gordon@Sun.COM * > objpp: Pointer to the pointer to the object. 9417387SRobert.Gordon@Sun.COM * 9427387SRobert.Gordon@Sun.COM */ 9437387SRobert.Gordon@Sun.COM 9447387SRobert.Gordon@Sun.COM bool_t 9457387SRobert.Gordon@Sun.COM xdr_do_clist(XDR *xdrs, clist **objpp) 9467387SRobert.Gordon@Sun.COM { 9477387SRobert.Gordon@Sun.COM bool_t more_data; 9487387SRobert.Gordon@Sun.COM 9497387SRobert.Gordon@Sun.COM more_data = (*objpp != NULL); 9507387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more_data)) 9517387SRobert.Gordon@Sun.COM return (FALSE); 9527387SRobert.Gordon@Sun.COM if (!more_data) { 9537387SRobert.Gordon@Sun.COM *objpp = NULL; 9547387SRobert.Gordon@Sun.COM return (TRUE); 9557387SRobert.Gordon@Sun.COM } 9567387SRobert.Gordon@Sun.COM return (xdr_ref_clist(xdrs, (caddr_t *)objpp)); 9570Sstevel@tonic-gate } 9580Sstevel@tonic-gate 9590Sstevel@tonic-gate uint_t 9600Sstevel@tonic-gate xdr_getbufsize(XDR *xdrs) 9610Sstevel@tonic-gate { 9627387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 9630Sstevel@tonic-gate 9640Sstevel@tonic-gate return ((uint_t)xdrp->xp_buf_size); 9650Sstevel@tonic-gate } 9667387SRobert.Gordon@Sun.COM 9677387SRobert.Gordon@Sun.COM /* ARGSUSED */ 9687387SRobert.Gordon@Sun.COM bool_t 9697387SRobert.Gordon@Sun.COM xdr_encode_rlist_svc(XDR *xdrs, clist *rlist) 9707387SRobert.Gordon@Sun.COM { 9717387SRobert.Gordon@Sun.COM bool_t vfalse = FALSE; 9727387SRobert.Gordon@Sun.COM 9737387SRobert.Gordon@Sun.COM ASSERT(rlist == NULL); 9747387SRobert.Gordon@Sun.COM return (xdr_bool(xdrs, &vfalse)); 9757387SRobert.Gordon@Sun.COM } 9767387SRobert.Gordon@Sun.COM 9777387SRobert.Gordon@Sun.COM bool_t 9787387SRobert.Gordon@Sun.COM xdr_encode_wlist(XDR *xdrs, clist *w) 9797387SRobert.Gordon@Sun.COM { 9807387SRobert.Gordon@Sun.COM bool_t vfalse = FALSE, vtrue = TRUE; 9817387SRobert.Gordon@Sun.COM int i; 9827387SRobert.Gordon@Sun.COM uint_t num_segment = 0; 9837387SRobert.Gordon@Sun.COM struct clist *cl; 9847387SRobert.Gordon@Sun.COM 9857387SRobert.Gordon@Sun.COM /* does a wlist exist? */ 9867387SRobert.Gordon@Sun.COM if (w == NULL) { 9877387SRobert.Gordon@Sun.COM return (xdr_bool(xdrs, &vfalse)); 9887387SRobert.Gordon@Sun.COM } 9897387SRobert.Gordon@Sun.COM /* Encode N consecutive segments, 1, N, HLOO, ..., HLOO, 0 */ 9907387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &vtrue)) 9917387SRobert.Gordon@Sun.COM return (FALSE); 9927387SRobert.Gordon@Sun.COM 9937387SRobert.Gordon@Sun.COM for (cl = w; cl != NULL; cl = cl->c_next) { 9947387SRobert.Gordon@Sun.COM num_segment++; 9957387SRobert.Gordon@Sun.COM } 9967387SRobert.Gordon@Sun.COM 9977387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &num_segment)) 9987387SRobert.Gordon@Sun.COM return (FALSE); 9997387SRobert.Gordon@Sun.COM for (i = 0; i < num_segment; i++) { 10009348SSiddheshwar.Mahesh@Sun.COM 10019348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE1(krpc__i__xdr_encode_wlist_len, uint_t, w->c_len); 10029348SSiddheshwar.Mahesh@Sun.COM 10037387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &w->c_dmemhandle.mrc_rmr)) 10047387SRobert.Gordon@Sun.COM return (FALSE); 10057387SRobert.Gordon@Sun.COM 10067387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &w->c_len)) 10077387SRobert.Gordon@Sun.COM return (FALSE); 10087387SRobert.Gordon@Sun.COM 10097387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &w->u.c_daddr)) 10107387SRobert.Gordon@Sun.COM return (FALSE); 10117387SRobert.Gordon@Sun.COM 10127387SRobert.Gordon@Sun.COM w = w->c_next; 10137387SRobert.Gordon@Sun.COM } 10147387SRobert.Gordon@Sun.COM 10157387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &vfalse)) 10167387SRobert.Gordon@Sun.COM return (FALSE); 10177387SRobert.Gordon@Sun.COM 10187387SRobert.Gordon@Sun.COM return (TRUE); 10197387SRobert.Gordon@Sun.COM } 10207387SRobert.Gordon@Sun.COM 10217387SRobert.Gordon@Sun.COM 10227387SRobert.Gordon@Sun.COM /* 10237387SRobert.Gordon@Sun.COM * Conditionally decode a RDMA WRITE chunk list from XDR stream. 10247387SRobert.Gordon@Sun.COM * 10257387SRobert.Gordon@Sun.COM * If the next boolean in the XDR stream is false there is no 10267387SRobert.Gordon@Sun.COM * RDMA WRITE chunk list present. Otherwise iterate over the 10277387SRobert.Gordon@Sun.COM * array and for each entry: allocate a struct clist and decode. 10287387SRobert.Gordon@Sun.COM * Pass back an indication via wlist_exists if we have seen a 10297387SRobert.Gordon@Sun.COM * RDMA WRITE chunk list. 10307387SRobert.Gordon@Sun.COM */ 10317387SRobert.Gordon@Sun.COM bool_t 10327387SRobert.Gordon@Sun.COM xdr_decode_wlist(XDR *xdrs, struct clist **w, bool_t *wlist_exists) 10337387SRobert.Gordon@Sun.COM { 10347387SRobert.Gordon@Sun.COM struct clist *tmp; 10357387SRobert.Gordon@Sun.COM bool_t more = FALSE; 10367387SRobert.Gordon@Sun.COM uint32_t seg_array_len; 10377387SRobert.Gordon@Sun.COM uint32_t i; 10387387SRobert.Gordon@Sun.COM 10397387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more)) 10407387SRobert.Gordon@Sun.COM return (FALSE); 10417387SRobert.Gordon@Sun.COM 10427387SRobert.Gordon@Sun.COM /* is there a wlist? */ 10437387SRobert.Gordon@Sun.COM if (more == FALSE) { 10447387SRobert.Gordon@Sun.COM *wlist_exists = FALSE; 10457387SRobert.Gordon@Sun.COM return (TRUE); 10467387SRobert.Gordon@Sun.COM } 10477387SRobert.Gordon@Sun.COM *wlist_exists = TRUE; 10487387SRobert.Gordon@Sun.COM 10497387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &seg_array_len)) 10507387SRobert.Gordon@Sun.COM return (FALSE); 10517387SRobert.Gordon@Sun.COM 10527387SRobert.Gordon@Sun.COM tmp = *w = clist_alloc(); 10537387SRobert.Gordon@Sun.COM for (i = 0; i < seg_array_len; i++) { 10549348SSiddheshwar.Mahesh@Sun.COM 10557387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &tmp->c_dmemhandle.mrc_rmr)) 10567387SRobert.Gordon@Sun.COM return (FALSE); 10577387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &tmp->c_len)) 10587387SRobert.Gordon@Sun.COM return (FALSE); 10599348SSiddheshwar.Mahesh@Sun.COM 10609348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE1(krpc__i__xdr_decode_wlist_len, 10619348SSiddheshwar.Mahesh@Sun.COM uint_t, tmp->c_len); 10629348SSiddheshwar.Mahesh@Sun.COM 10637387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &tmp->u.c_daddr)) 10647387SRobert.Gordon@Sun.COM return (FALSE); 10657387SRobert.Gordon@Sun.COM if (i < seg_array_len - 1) { 10667387SRobert.Gordon@Sun.COM tmp->c_next = clist_alloc(); 10677387SRobert.Gordon@Sun.COM tmp = tmp->c_next; 10687387SRobert.Gordon@Sun.COM } else { 10697387SRobert.Gordon@Sun.COM tmp->c_next = NULL; 10707387SRobert.Gordon@Sun.COM } 10717387SRobert.Gordon@Sun.COM } 10727387SRobert.Gordon@Sun.COM 10737387SRobert.Gordon@Sun.COM more = FALSE; 10747387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more)) 10757387SRobert.Gordon@Sun.COM return (FALSE); 10767387SRobert.Gordon@Sun.COM 10777387SRobert.Gordon@Sun.COM return (TRUE); 10787387SRobert.Gordon@Sun.COM } 10797387SRobert.Gordon@Sun.COM 10807387SRobert.Gordon@Sun.COM /* 10817387SRobert.Gordon@Sun.COM * Server side RDMA WRITE list decode. 10827387SRobert.Gordon@Sun.COM * XDR context is memory ops 10837387SRobert.Gordon@Sun.COM */ 10847387SRobert.Gordon@Sun.COM bool_t 10857387SRobert.Gordon@Sun.COM xdr_decode_wlist_svc(XDR *xdrs, struct clist **wclp, bool_t *wwl, 10867387SRobert.Gordon@Sun.COM uint32_t *total_length, CONN *conn) 10877387SRobert.Gordon@Sun.COM { 10887387SRobert.Gordon@Sun.COM struct clist *first, *ncl; 10897387SRobert.Gordon@Sun.COM char *memp; 10907387SRobert.Gordon@Sun.COM uint32_t num_wclist; 10917387SRobert.Gordon@Sun.COM uint32_t wcl_length = 0; 10927387SRobert.Gordon@Sun.COM uint32_t i; 10937387SRobert.Gordon@Sun.COM bool_t more = FALSE; 10947387SRobert.Gordon@Sun.COM 10957387SRobert.Gordon@Sun.COM *wclp = NULL; 10967387SRobert.Gordon@Sun.COM *wwl = FALSE; 10977387SRobert.Gordon@Sun.COM *total_length = 0; 10987387SRobert.Gordon@Sun.COM 10997387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more)) { 11007387SRobert.Gordon@Sun.COM return (FALSE); 11017387SRobert.Gordon@Sun.COM } 11027387SRobert.Gordon@Sun.COM 11037387SRobert.Gordon@Sun.COM if (more == FALSE) { 11047387SRobert.Gordon@Sun.COM return (TRUE); 11057387SRobert.Gordon@Sun.COM } 11067387SRobert.Gordon@Sun.COM 11077387SRobert.Gordon@Sun.COM *wwl = TRUE; 11087387SRobert.Gordon@Sun.COM 11097387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &num_wclist)) { 11107387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__xdrrdma__wlistsvc__listlength); 11117387SRobert.Gordon@Sun.COM return (FALSE); 11127387SRobert.Gordon@Sun.COM } 11137387SRobert.Gordon@Sun.COM 11147387SRobert.Gordon@Sun.COM first = ncl = clist_alloc(); 11157387SRobert.Gordon@Sun.COM 11167387SRobert.Gordon@Sun.COM for (i = 0; i < num_wclist; i++) { 11179348SSiddheshwar.Mahesh@Sun.COM 11187387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &ncl->c_dmemhandle.mrc_rmr)) 11197387SRobert.Gordon@Sun.COM goto err_out; 11207387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &ncl->c_len)) 11217387SRobert.Gordon@Sun.COM goto err_out; 11227387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &ncl->u.c_daddr)) 11237387SRobert.Gordon@Sun.COM goto err_out; 11247387SRobert.Gordon@Sun.COM 11257387SRobert.Gordon@Sun.COM if (ncl->c_len > MAX_SVC_XFER_SIZE) { 11267387SRobert.Gordon@Sun.COM DTRACE_PROBE( 11277387SRobert.Gordon@Sun.COM krpc__e__xdrrdma__wlistsvc__chunklist_toobig); 11287387SRobert.Gordon@Sun.COM ncl->c_len = MAX_SVC_XFER_SIZE; 11297387SRobert.Gordon@Sun.COM } 11307387SRobert.Gordon@Sun.COM 11319348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE1(krpc__i__xdr_decode_wlist_svc_len, 11329348SSiddheshwar.Mahesh@Sun.COM uint_t, ncl->c_len); 11339348SSiddheshwar.Mahesh@Sun.COM 11347387SRobert.Gordon@Sun.COM wcl_length += ncl->c_len; 11357387SRobert.Gordon@Sun.COM 11367387SRobert.Gordon@Sun.COM if (i < num_wclist - 1) { 11377387SRobert.Gordon@Sun.COM ncl->c_next = clist_alloc(); 11387387SRobert.Gordon@Sun.COM ncl = ncl->c_next; 11397387SRobert.Gordon@Sun.COM } 11407387SRobert.Gordon@Sun.COM } 11417387SRobert.Gordon@Sun.COM 11427387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &more)) 11437387SRobert.Gordon@Sun.COM goto err_out; 11447387SRobert.Gordon@Sun.COM 11457387SRobert.Gordon@Sun.COM first->rb_longbuf.type = RDMA_LONG_BUFFER; 11467387SRobert.Gordon@Sun.COM first->rb_longbuf.len = 11477387SRobert.Gordon@Sun.COM wcl_length > WCL_BUF_LEN ? wcl_length : WCL_BUF_LEN; 11487387SRobert.Gordon@Sun.COM 11497387SRobert.Gordon@Sun.COM if (rdma_buf_alloc(conn, &first->rb_longbuf)) { 11507387SRobert.Gordon@Sun.COM clist_free(first); 11517387SRobert.Gordon@Sun.COM return (FALSE); 11527387SRobert.Gordon@Sun.COM } 11537387SRobert.Gordon@Sun.COM 11547387SRobert.Gordon@Sun.COM memp = first->rb_longbuf.addr; 11557387SRobert.Gordon@Sun.COM 11567387SRobert.Gordon@Sun.COM ncl = first; 11577387SRobert.Gordon@Sun.COM for (i = 0; i < num_wclist; i++) { 11587387SRobert.Gordon@Sun.COM ncl->w.c_saddr3 = (caddr_t)memp; 11597387SRobert.Gordon@Sun.COM memp += ncl->c_len; 11607387SRobert.Gordon@Sun.COM ncl = ncl->c_next; 11617387SRobert.Gordon@Sun.COM } 11627387SRobert.Gordon@Sun.COM 11637387SRobert.Gordon@Sun.COM *wclp = first; 11647387SRobert.Gordon@Sun.COM *total_length = wcl_length; 11657387SRobert.Gordon@Sun.COM return (TRUE); 11667387SRobert.Gordon@Sun.COM 11677387SRobert.Gordon@Sun.COM err_out: 11687387SRobert.Gordon@Sun.COM clist_free(first); 11697387SRobert.Gordon@Sun.COM return (FALSE); 11707387SRobert.Gordon@Sun.COM } 11717387SRobert.Gordon@Sun.COM 11727387SRobert.Gordon@Sun.COM /* 11737387SRobert.Gordon@Sun.COM * XDR decode the long reply write chunk. 11747387SRobert.Gordon@Sun.COM */ 11757387SRobert.Gordon@Sun.COM bool_t 11767387SRobert.Gordon@Sun.COM xdr_decode_reply_wchunk(XDR *xdrs, struct clist **clist) 11777387SRobert.Gordon@Sun.COM { 11787387SRobert.Gordon@Sun.COM bool_t have_rchunk = FALSE; 11797387SRobert.Gordon@Sun.COM struct clist *first = NULL, *ncl = NULL; 11807387SRobert.Gordon@Sun.COM uint32_t num_wclist; 11817387SRobert.Gordon@Sun.COM uint32_t i; 11827387SRobert.Gordon@Sun.COM 11837387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &have_rchunk)) 11847387SRobert.Gordon@Sun.COM return (FALSE); 11857387SRobert.Gordon@Sun.COM 11867387SRobert.Gordon@Sun.COM if (have_rchunk == FALSE) 11877387SRobert.Gordon@Sun.COM return (TRUE); 11887387SRobert.Gordon@Sun.COM 11897387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &num_wclist)) { 11907387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__xdrrdma__replywchunk__listlength); 11917387SRobert.Gordon@Sun.COM return (FALSE); 11927387SRobert.Gordon@Sun.COM } 11937387SRobert.Gordon@Sun.COM 11947387SRobert.Gordon@Sun.COM if (num_wclist == 0) { 11957387SRobert.Gordon@Sun.COM return (FALSE); 11967387SRobert.Gordon@Sun.COM } 11977387SRobert.Gordon@Sun.COM 11987387SRobert.Gordon@Sun.COM first = ncl = clist_alloc(); 11997387SRobert.Gordon@Sun.COM 12007387SRobert.Gordon@Sun.COM for (i = 0; i < num_wclist; i++) { 12019348SSiddheshwar.Mahesh@Sun.COM 12029348SSiddheshwar.Mahesh@Sun.COM if (i > 0) { 12039348SSiddheshwar.Mahesh@Sun.COM ncl->c_next = clist_alloc(); 12049348SSiddheshwar.Mahesh@Sun.COM ncl = ncl->c_next; 12059348SSiddheshwar.Mahesh@Sun.COM } 12069348SSiddheshwar.Mahesh@Sun.COM 12077387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &ncl->c_dmemhandle.mrc_rmr)) 12087387SRobert.Gordon@Sun.COM goto err_out; 12097387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &ncl->c_len)) 12107387SRobert.Gordon@Sun.COM goto err_out; 12117387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &ncl->u.c_daddr)) 12127387SRobert.Gordon@Sun.COM goto err_out; 12137387SRobert.Gordon@Sun.COM 12147387SRobert.Gordon@Sun.COM if (ncl->c_len > MAX_SVC_XFER_SIZE) { 12157387SRobert.Gordon@Sun.COM DTRACE_PROBE( 12167387SRobert.Gordon@Sun.COM krpc__e__xdrrdma__replywchunk__chunklist_toobig); 12177387SRobert.Gordon@Sun.COM ncl->c_len = MAX_SVC_XFER_SIZE; 12187387SRobert.Gordon@Sun.COM } 12197387SRobert.Gordon@Sun.COM if (!(ncl->c_dmemhandle.mrc_rmr && 12207387SRobert.Gordon@Sun.COM (ncl->c_len > 0) && ncl->u.c_daddr)) 12217387SRobert.Gordon@Sun.COM DTRACE_PROBE( 12227387SRobert.Gordon@Sun.COM krpc__e__xdrrdma__replywchunk__invalid_segaddr); 12237387SRobert.Gordon@Sun.COM 12249348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE1(krpc__i__xdr_decode_reply_wchunk_c_len, 12259348SSiddheshwar.Mahesh@Sun.COM uint32_t, ncl->c_len); 12269348SSiddheshwar.Mahesh@Sun.COM 12277387SRobert.Gordon@Sun.COM } 12287387SRobert.Gordon@Sun.COM *clist = first; 12297387SRobert.Gordon@Sun.COM return (TRUE); 12307387SRobert.Gordon@Sun.COM 12317387SRobert.Gordon@Sun.COM err_out: 12327387SRobert.Gordon@Sun.COM clist_free(first); 12337387SRobert.Gordon@Sun.COM return (FALSE); 12347387SRobert.Gordon@Sun.COM } 12357387SRobert.Gordon@Sun.COM 12367387SRobert.Gordon@Sun.COM 12377387SRobert.Gordon@Sun.COM bool_t 12387387SRobert.Gordon@Sun.COM xdr_encode_reply_wchunk(XDR *xdrs, 12397387SRobert.Gordon@Sun.COM struct clist *cl_longreply, uint32_t seg_array_len) 12407387SRobert.Gordon@Sun.COM { 12417387SRobert.Gordon@Sun.COM int i; 12427387SRobert.Gordon@Sun.COM bool_t long_reply_exists = TRUE; 12437387SRobert.Gordon@Sun.COM uint32_t length; 12447387SRobert.Gordon@Sun.COM uint64 offset; 12457387SRobert.Gordon@Sun.COM 12467387SRobert.Gordon@Sun.COM if (seg_array_len > 0) { 12477387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &long_reply_exists)) 12487387SRobert.Gordon@Sun.COM return (FALSE); 12497387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &seg_array_len)) 12507387SRobert.Gordon@Sun.COM return (FALSE); 12517387SRobert.Gordon@Sun.COM 12527387SRobert.Gordon@Sun.COM for (i = 0; i < seg_array_len; i++) { 12537387SRobert.Gordon@Sun.COM if (!cl_longreply) 12547387SRobert.Gordon@Sun.COM return (FALSE); 12557387SRobert.Gordon@Sun.COM length = cl_longreply->c_len; 12567387SRobert.Gordon@Sun.COM offset = (uint64) cl_longreply->u.c_daddr; 12577387SRobert.Gordon@Sun.COM 12589348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE1( 12599348SSiddheshwar.Mahesh@Sun.COM krpc__i__xdr_encode_reply_wchunk_c_len, 12609348SSiddheshwar.Mahesh@Sun.COM uint32_t, length); 12619348SSiddheshwar.Mahesh@Sun.COM 12627387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, 12637387SRobert.Gordon@Sun.COM &cl_longreply->c_dmemhandle.mrc_rmr)) 12647387SRobert.Gordon@Sun.COM return (FALSE); 12657387SRobert.Gordon@Sun.COM if (!xdr_uint32(xdrs, &length)) 12667387SRobert.Gordon@Sun.COM return (FALSE); 12677387SRobert.Gordon@Sun.COM if (!xdr_uint64(xdrs, &offset)) 12687387SRobert.Gordon@Sun.COM return (FALSE); 12697387SRobert.Gordon@Sun.COM cl_longreply = cl_longreply->c_next; 12707387SRobert.Gordon@Sun.COM } 12717387SRobert.Gordon@Sun.COM } else { 12727387SRobert.Gordon@Sun.COM long_reply_exists = FALSE; 12737387SRobert.Gordon@Sun.COM if (!xdr_bool(xdrs, &long_reply_exists)) 12747387SRobert.Gordon@Sun.COM return (FALSE); 12757387SRobert.Gordon@Sun.COM } 12767387SRobert.Gordon@Sun.COM return (TRUE); 12777387SRobert.Gordon@Sun.COM } 12787387SRobert.Gordon@Sun.COM bool_t 12799348SSiddheshwar.Mahesh@Sun.COM xdrrdma_read_from_client(struct clist *rlist, CONN **conn, uint_t count) 12807387SRobert.Gordon@Sun.COM { 12817387SRobert.Gordon@Sun.COM struct clist *rdclist; 12827387SRobert.Gordon@Sun.COM struct clist cl; 12837387SRobert.Gordon@Sun.COM uint_t total_len = 0; 12847387SRobert.Gordon@Sun.COM uint32_t status; 12857387SRobert.Gordon@Sun.COM bool_t retval = TRUE; 12867387SRobert.Gordon@Sun.COM 12879348SSiddheshwar.Mahesh@Sun.COM rlist->rb_longbuf.type = RDMA_LONG_BUFFER; 12889348SSiddheshwar.Mahesh@Sun.COM rlist->rb_longbuf.len = 12897387SRobert.Gordon@Sun.COM count > RCL_BUF_LEN ? count : RCL_BUF_LEN; 12907387SRobert.Gordon@Sun.COM 12919348SSiddheshwar.Mahesh@Sun.COM if (rdma_buf_alloc(*conn, &rlist->rb_longbuf)) { 12927387SRobert.Gordon@Sun.COM return (FALSE); 12937387SRobert.Gordon@Sun.COM } 12947387SRobert.Gordon@Sun.COM 12959348SSiddheshwar.Mahesh@Sun.COM /* 12969348SSiddheshwar.Mahesh@Sun.COM * The entire buffer is registered with the first chunk. 12979348SSiddheshwar.Mahesh@Sun.COM * Later chunks will use the same registered memory handle. 12989348SSiddheshwar.Mahesh@Sun.COM */ 12999348SSiddheshwar.Mahesh@Sun.COM 13009348SSiddheshwar.Mahesh@Sun.COM cl = *rlist; 13019348SSiddheshwar.Mahesh@Sun.COM cl.c_next = NULL; 13029348SSiddheshwar.Mahesh@Sun.COM if (clist_register(*conn, &cl, CLIST_REG_DST) != RDMA_SUCCESS) { 13039348SSiddheshwar.Mahesh@Sun.COM rdma_buf_free(*conn, &rlist->rb_longbuf); 13049348SSiddheshwar.Mahesh@Sun.COM DTRACE_PROBE( 13059348SSiddheshwar.Mahesh@Sun.COM krpc__e__xdrrdma__readfromclient__clist__reg); 13069348SSiddheshwar.Mahesh@Sun.COM return (FALSE); 13079348SSiddheshwar.Mahesh@Sun.COM } 13089348SSiddheshwar.Mahesh@Sun.COM 13099348SSiddheshwar.Mahesh@Sun.COM rlist->c_regtype = CLIST_REG_DST; 13109348SSiddheshwar.Mahesh@Sun.COM rlist->c_dmemhandle = cl.c_dmemhandle; 13119348SSiddheshwar.Mahesh@Sun.COM rlist->c_dsynchandle = cl.c_dsynchandle; 13129348SSiddheshwar.Mahesh@Sun.COM 13139348SSiddheshwar.Mahesh@Sun.COM for (rdclist = rlist; 13147387SRobert.Gordon@Sun.COM rdclist != NULL; rdclist = rdclist->c_next) { 13157387SRobert.Gordon@Sun.COM total_len += rdclist->c_len; 13167387SRobert.Gordon@Sun.COM #if (defined(OBJ32)||defined(DEBUG32)) 13177387SRobert.Gordon@Sun.COM rdclist->u.c_daddr3 = 13189348SSiddheshwar.Mahesh@Sun.COM (caddr_t)((char *)rlist->rb_longbuf.addr + 13197387SRobert.Gordon@Sun.COM (uint32) rdclist->u.c_daddr3); 13207387SRobert.Gordon@Sun.COM #else 13217387SRobert.Gordon@Sun.COM rdclist->u.c_daddr3 = 13229348SSiddheshwar.Mahesh@Sun.COM (caddr_t)((char *)rlist->rb_longbuf.addr + 13237387SRobert.Gordon@Sun.COM (uint64) rdclist->u.c_daddr); 13247387SRobert.Gordon@Sun.COM 13257387SRobert.Gordon@Sun.COM #endif 13267387SRobert.Gordon@Sun.COM cl = (*rdclist); 13277387SRobert.Gordon@Sun.COM cl.c_next = NULL; 13287387SRobert.Gordon@Sun.COM 13299348SSiddheshwar.Mahesh@Sun.COM /* 13309348SSiddheshwar.Mahesh@Sun.COM * Use the same memory handle for all the chunks 13319348SSiddheshwar.Mahesh@Sun.COM */ 13329348SSiddheshwar.Mahesh@Sun.COM cl.c_dmemhandle = rlist->c_dmemhandle; 13339348SSiddheshwar.Mahesh@Sun.COM cl.c_dsynchandle = rlist->c_dsynchandle; 13349348SSiddheshwar.Mahesh@Sun.COM 13357387SRobert.Gordon@Sun.COM 13367387SRobert.Gordon@Sun.COM DTRACE_PROBE1(krpc__i__xdrrdma__readfromclient__buflen, 13377387SRobert.Gordon@Sun.COM int, rdclist->c_len); 13387387SRobert.Gordon@Sun.COM 13397387SRobert.Gordon@Sun.COM /* 13407387SRobert.Gordon@Sun.COM * Now read the chunk in 13417387SRobert.Gordon@Sun.COM */ 13427387SRobert.Gordon@Sun.COM if (rdclist->c_next == NULL) { 13437387SRobert.Gordon@Sun.COM status = RDMA_READ(*conn, &cl, WAIT); 13447387SRobert.Gordon@Sun.COM } else { 13457387SRobert.Gordon@Sun.COM status = RDMA_READ(*conn, &cl, NOWAIT); 13467387SRobert.Gordon@Sun.COM } 13477387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 13487387SRobert.Gordon@Sun.COM DTRACE_PROBE( 13497387SRobert.Gordon@Sun.COM krpc__e__xdrrdma__readfromclient__readfailed); 13509348SSiddheshwar.Mahesh@Sun.COM rdma_buf_free(*conn, &rlist->rb_longbuf); 13517387SRobert.Gordon@Sun.COM return (FALSE); 13527387SRobert.Gordon@Sun.COM } 13537387SRobert.Gordon@Sun.COM } 13547387SRobert.Gordon@Sun.COM 13559348SSiddheshwar.Mahesh@Sun.COM cl = (*rlist); 13567387SRobert.Gordon@Sun.COM cl.c_next = NULL; 13577387SRobert.Gordon@Sun.COM cl.c_len = total_len; 13589348SSiddheshwar.Mahesh@Sun.COM if (clist_syncmem(*conn, &cl, CLIST_REG_DST) != RDMA_SUCCESS) { 13597387SRobert.Gordon@Sun.COM retval = FALSE; 13607387SRobert.Gordon@Sun.COM } 13617387SRobert.Gordon@Sun.COM return (retval); 13627387SRobert.Gordon@Sun.COM } 13637387SRobert.Gordon@Sun.COM 13647387SRobert.Gordon@Sun.COM bool_t 13657387SRobert.Gordon@Sun.COM xdrrdma_free_clist(CONN *conn, struct clist *clp) 13667387SRobert.Gordon@Sun.COM { 13677387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &clp->rb_longbuf); 13687387SRobert.Gordon@Sun.COM clist_free(clp); 13697387SRobert.Gordon@Sun.COM return (TRUE); 13707387SRobert.Gordon@Sun.COM } 13717387SRobert.Gordon@Sun.COM 13727387SRobert.Gordon@Sun.COM bool_t 13739348SSiddheshwar.Mahesh@Sun.COM xdrrdma_send_read_data(XDR *xdrs, uint_t data_len, struct clist *wcl) 13747387SRobert.Gordon@Sun.COM { 13757387SRobert.Gordon@Sun.COM int status; 13767387SRobert.Gordon@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 13777387SRobert.Gordon@Sun.COM struct xdr_ops *xops = xdrrdma_xops(); 13789348SSiddheshwar.Mahesh@Sun.COM struct clist *tcl, *wrcl, *cl; 13799348SSiddheshwar.Mahesh@Sun.COM struct clist fcl; 13809348SSiddheshwar.Mahesh@Sun.COM int rndup_present, rnduplen; 13819348SSiddheshwar.Mahesh@Sun.COM 13829348SSiddheshwar.Mahesh@Sun.COM rndup_present = 0; 13839348SSiddheshwar.Mahesh@Sun.COM wrcl = NULL; 13847387SRobert.Gordon@Sun.COM 13857387SRobert.Gordon@Sun.COM /* caller is doing a sizeof */ 13867387SRobert.Gordon@Sun.COM if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_ops == xops) 13877387SRobert.Gordon@Sun.COM return (TRUE); 13887387SRobert.Gordon@Sun.COM 13899348SSiddheshwar.Mahesh@Sun.COM /* copy of the first chunk */ 13909348SSiddheshwar.Mahesh@Sun.COM fcl = *wcl; 13919348SSiddheshwar.Mahesh@Sun.COM fcl.c_next = NULL; 13929348SSiddheshwar.Mahesh@Sun.COM 13939348SSiddheshwar.Mahesh@Sun.COM /* 13949348SSiddheshwar.Mahesh@Sun.COM * The entire buffer is registered with the first chunk. 13959348SSiddheshwar.Mahesh@Sun.COM * Later chunks will use the same registered memory handle. 13969348SSiddheshwar.Mahesh@Sun.COM */ 13979348SSiddheshwar.Mahesh@Sun.COM 13989348SSiddheshwar.Mahesh@Sun.COM status = clist_register(xdrp->xp_conn, &fcl, CLIST_REG_SOURCE); 13997387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 14007387SRobert.Gordon@Sun.COM return (FALSE); 14017387SRobert.Gordon@Sun.COM } 14027387SRobert.Gordon@Sun.COM 14039348SSiddheshwar.Mahesh@Sun.COM wcl->c_regtype = CLIST_REG_SOURCE; 14049348SSiddheshwar.Mahesh@Sun.COM wcl->c_smemhandle = fcl.c_smemhandle; 14059348SSiddheshwar.Mahesh@Sun.COM wcl->c_ssynchandle = fcl.c_ssynchandle; 14069348SSiddheshwar.Mahesh@Sun.COM 14079348SSiddheshwar.Mahesh@Sun.COM /* 14089348SSiddheshwar.Mahesh@Sun.COM * Only transfer the read data ignoring any trailing 14099348SSiddheshwar.Mahesh@Sun.COM * roundup chunks. A bit of work, but it saves an 14109348SSiddheshwar.Mahesh@Sun.COM * unnecessary extra RDMA_WRITE containing only 14119348SSiddheshwar.Mahesh@Sun.COM * roundup bytes. 14129348SSiddheshwar.Mahesh@Sun.COM */ 14139348SSiddheshwar.Mahesh@Sun.COM 14149348SSiddheshwar.Mahesh@Sun.COM rnduplen = clist_len(wcl) - data_len; 14159348SSiddheshwar.Mahesh@Sun.COM 14169348SSiddheshwar.Mahesh@Sun.COM if (rnduplen) { 14179348SSiddheshwar.Mahesh@Sun.COM 14189348SSiddheshwar.Mahesh@Sun.COM tcl = wcl->c_next; 14199348SSiddheshwar.Mahesh@Sun.COM 14209348SSiddheshwar.Mahesh@Sun.COM /* 14219348SSiddheshwar.Mahesh@Sun.COM * Check if there is a trailing roundup chunk 14229348SSiddheshwar.Mahesh@Sun.COM */ 14239348SSiddheshwar.Mahesh@Sun.COM while (tcl) { 14249348SSiddheshwar.Mahesh@Sun.COM if ((tcl->c_next == NULL) && (tcl->c_len == rnduplen)) { 14259348SSiddheshwar.Mahesh@Sun.COM rndup_present = 1; 14269348SSiddheshwar.Mahesh@Sun.COM break; 14279348SSiddheshwar.Mahesh@Sun.COM } 14289348SSiddheshwar.Mahesh@Sun.COM tcl = tcl->c_next; 14299348SSiddheshwar.Mahesh@Sun.COM } 14309348SSiddheshwar.Mahesh@Sun.COM 14319348SSiddheshwar.Mahesh@Sun.COM /* 14329348SSiddheshwar.Mahesh@Sun.COM * Make a copy chunk list skipping the last chunk 14339348SSiddheshwar.Mahesh@Sun.COM */ 14349348SSiddheshwar.Mahesh@Sun.COM if (rndup_present) { 14359348SSiddheshwar.Mahesh@Sun.COM cl = wcl; 14369348SSiddheshwar.Mahesh@Sun.COM tcl = NULL; 14379348SSiddheshwar.Mahesh@Sun.COM while (cl) { 14389348SSiddheshwar.Mahesh@Sun.COM if (tcl == NULL) { 14399348SSiddheshwar.Mahesh@Sun.COM tcl = clist_alloc(); 14409348SSiddheshwar.Mahesh@Sun.COM wrcl = tcl; 14419348SSiddheshwar.Mahesh@Sun.COM } else { 14429348SSiddheshwar.Mahesh@Sun.COM tcl->c_next = clist_alloc(); 14439348SSiddheshwar.Mahesh@Sun.COM tcl = tcl->c_next; 14449348SSiddheshwar.Mahesh@Sun.COM } 14459348SSiddheshwar.Mahesh@Sun.COM 14469348SSiddheshwar.Mahesh@Sun.COM *tcl = *cl; 14479348SSiddheshwar.Mahesh@Sun.COM cl = cl->c_next; 14489348SSiddheshwar.Mahesh@Sun.COM /* last chunk */ 14499348SSiddheshwar.Mahesh@Sun.COM if (cl->c_next == NULL) 14509348SSiddheshwar.Mahesh@Sun.COM break; 14519348SSiddheshwar.Mahesh@Sun.COM } 14529348SSiddheshwar.Mahesh@Sun.COM tcl->c_next = NULL; 14539348SSiddheshwar.Mahesh@Sun.COM } 14549348SSiddheshwar.Mahesh@Sun.COM } 14559348SSiddheshwar.Mahesh@Sun.COM 14569348SSiddheshwar.Mahesh@Sun.COM if (wrcl == NULL) { 14579348SSiddheshwar.Mahesh@Sun.COM /* No roundup chunks */ 14589348SSiddheshwar.Mahesh@Sun.COM wrcl = wcl; 14599348SSiddheshwar.Mahesh@Sun.COM } 14609348SSiddheshwar.Mahesh@Sun.COM 14619348SSiddheshwar.Mahesh@Sun.COM /* 14629348SSiddheshwar.Mahesh@Sun.COM * Set the registered memory handles for the 14639348SSiddheshwar.Mahesh@Sun.COM * rest of the chunks same as the first chunk. 14649348SSiddheshwar.Mahesh@Sun.COM */ 14659348SSiddheshwar.Mahesh@Sun.COM tcl = wrcl->c_next; 14669348SSiddheshwar.Mahesh@Sun.COM while (tcl) { 14679348SSiddheshwar.Mahesh@Sun.COM tcl->c_smemhandle = fcl.c_smemhandle; 14689348SSiddheshwar.Mahesh@Sun.COM tcl->c_ssynchandle = fcl.c_ssynchandle; 14699348SSiddheshwar.Mahesh@Sun.COM tcl = tcl->c_next; 14709348SSiddheshwar.Mahesh@Sun.COM } 14719348SSiddheshwar.Mahesh@Sun.COM 14729348SSiddheshwar.Mahesh@Sun.COM /* 14739348SSiddheshwar.Mahesh@Sun.COM * Sync the total len beginning from the first chunk. 14749348SSiddheshwar.Mahesh@Sun.COM */ 14759348SSiddheshwar.Mahesh@Sun.COM fcl.c_len = clist_len(wrcl); 14769348SSiddheshwar.Mahesh@Sun.COM status = clist_syncmem(xdrp->xp_conn, &fcl, CLIST_REG_SOURCE); 14777387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 14787387SRobert.Gordon@Sun.COM return (FALSE); 14797387SRobert.Gordon@Sun.COM } 14807387SRobert.Gordon@Sun.COM 14819348SSiddheshwar.Mahesh@Sun.COM status = RDMA_WRITE(xdrp->xp_conn, wrcl, WAIT); 14829348SSiddheshwar.Mahesh@Sun.COM 14839348SSiddheshwar.Mahesh@Sun.COM if (rndup_present) 14849348SSiddheshwar.Mahesh@Sun.COM clist_free(wrcl); 14859348SSiddheshwar.Mahesh@Sun.COM 14867387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) { 14877387SRobert.Gordon@Sun.COM return (FALSE); 14887387SRobert.Gordon@Sun.COM } 14897387SRobert.Gordon@Sun.COM 14907387SRobert.Gordon@Sun.COM return (TRUE); 14917387SRobert.Gordon@Sun.COM } 14929348SSiddheshwar.Mahesh@Sun.COM 14939348SSiddheshwar.Mahesh@Sun.COM 14949348SSiddheshwar.Mahesh@Sun.COM /* 14959348SSiddheshwar.Mahesh@Sun.COM * Reads one chunk at a time 14969348SSiddheshwar.Mahesh@Sun.COM */ 14979348SSiddheshwar.Mahesh@Sun.COM 14989348SSiddheshwar.Mahesh@Sun.COM static bool_t 14999348SSiddheshwar.Mahesh@Sun.COM xdrrdma_read_a_chunk(XDR *xdrs, CONN **conn) 15009348SSiddheshwar.Mahesh@Sun.COM { 15019348SSiddheshwar.Mahesh@Sun.COM int status; 15029348SSiddheshwar.Mahesh@Sun.COM int32_t len = 0; 15039348SSiddheshwar.Mahesh@Sun.COM xrdma_private_t *xdrp = (xrdma_private_t *)(xdrs->x_private); 15049348SSiddheshwar.Mahesh@Sun.COM struct clist *cle = *(xdrp->xp_rcl_next); 15059348SSiddheshwar.Mahesh@Sun.COM struct clist *rclp = xdrp->xp_rcl; 15069348SSiddheshwar.Mahesh@Sun.COM struct clist *clp; 15079348SSiddheshwar.Mahesh@Sun.COM 15089348SSiddheshwar.Mahesh@Sun.COM /* 15099348SSiddheshwar.Mahesh@Sun.COM * len is used later to decide xdr offset in 15109348SSiddheshwar.Mahesh@Sun.COM * the chunk factoring any 4-byte XDR alignment 15119348SSiddheshwar.Mahesh@Sun.COM * (See read chunk example top of this file) 15129348SSiddheshwar.Mahesh@Sun.COM */ 15139348SSiddheshwar.Mahesh@Sun.COM while (rclp != cle) { 15149348SSiddheshwar.Mahesh@Sun.COM len += rclp->c_len; 15159348SSiddheshwar.Mahesh@Sun.COM rclp = rclp->c_next; 15169348SSiddheshwar.Mahesh@Sun.COM } 15179348SSiddheshwar.Mahesh@Sun.COM 15189348SSiddheshwar.Mahesh@Sun.COM len = RNDUP(len) - len; 15199348SSiddheshwar.Mahesh@Sun.COM 15209348SSiddheshwar.Mahesh@Sun.COM ASSERT(xdrs->x_handy <= 0); 15219348SSiddheshwar.Mahesh@Sun.COM 15229348SSiddheshwar.Mahesh@Sun.COM /* 15239348SSiddheshwar.Mahesh@Sun.COM * If this is the first chunk to contain the RPC 15249348SSiddheshwar.Mahesh@Sun.COM * message set xp_off to the xdr offset of the 15259348SSiddheshwar.Mahesh@Sun.COM * inline message. 15269348SSiddheshwar.Mahesh@Sun.COM */ 15279348SSiddheshwar.Mahesh@Sun.COM if (xdrp->xp_off == 0) 15289348SSiddheshwar.Mahesh@Sun.COM xdrp->xp_off = (xdrp->xp_offp - xdrs->x_base); 15299348SSiddheshwar.Mahesh@Sun.COM 15309348SSiddheshwar.Mahesh@Sun.COM if (cle == NULL || (cle->c_xdroff != xdrp->xp_off)) 15319348SSiddheshwar.Mahesh@Sun.COM return (FALSE); 15329348SSiddheshwar.Mahesh@Sun.COM 15339348SSiddheshwar.Mahesh@Sun.COM /* 15349348SSiddheshwar.Mahesh@Sun.COM * Make a copy of the chunk to read from client. 15359348SSiddheshwar.Mahesh@Sun.COM * Chunks are read on demand, so read only one 15369348SSiddheshwar.Mahesh@Sun.COM * for now. 15379348SSiddheshwar.Mahesh@Sun.COM */ 15389348SSiddheshwar.Mahesh@Sun.COM 15399348SSiddheshwar.Mahesh@Sun.COM rclp = clist_alloc(); 15409348SSiddheshwar.Mahesh@Sun.COM *rclp = *cle; 15419348SSiddheshwar.Mahesh@Sun.COM rclp->c_next = NULL; 15429348SSiddheshwar.Mahesh@Sun.COM 15439348SSiddheshwar.Mahesh@Sun.COM xdrp->xp_rcl_next = &cle->c_next; 15449348SSiddheshwar.Mahesh@Sun.COM 15459348SSiddheshwar.Mahesh@Sun.COM /* 15469348SSiddheshwar.Mahesh@Sun.COM * If there is a roundup present, then skip those 15479348SSiddheshwar.Mahesh@Sun.COM * bytes when reading. 15489348SSiddheshwar.Mahesh@Sun.COM */ 15499348SSiddheshwar.Mahesh@Sun.COM if (len) { 15509348SSiddheshwar.Mahesh@Sun.COM rclp->w.c_saddr = 15519348SSiddheshwar.Mahesh@Sun.COM (uint64)(uintptr_t)rclp->w.c_saddr + len; 15529348SSiddheshwar.Mahesh@Sun.COM rclp->c_len = rclp->c_len - len; 15539348SSiddheshwar.Mahesh@Sun.COM } 15549348SSiddheshwar.Mahesh@Sun.COM 15559348SSiddheshwar.Mahesh@Sun.COM status = xdrrdma_read_from_client(rclp, conn, rclp->c_len); 15569348SSiddheshwar.Mahesh@Sun.COM 15579348SSiddheshwar.Mahesh@Sun.COM if (status == FALSE) { 15589348SSiddheshwar.Mahesh@Sun.COM clist_free(rclp); 15599348SSiddheshwar.Mahesh@Sun.COM return (status); 15609348SSiddheshwar.Mahesh@Sun.COM } 15619348SSiddheshwar.Mahesh@Sun.COM 15629348SSiddheshwar.Mahesh@Sun.COM xdrp->xp_offp = rclp->rb_longbuf.addr; 15639348SSiddheshwar.Mahesh@Sun.COM xdrs->x_base = xdrp->xp_offp; 15649348SSiddheshwar.Mahesh@Sun.COM xdrs->x_handy = rclp->c_len; 15659348SSiddheshwar.Mahesh@Sun.COM 15669348SSiddheshwar.Mahesh@Sun.COM /* 15679348SSiddheshwar.Mahesh@Sun.COM * This copy of read chunks containing the XDR 15689348SSiddheshwar.Mahesh@Sun.COM * message is freed later in xdrrdma_destroy() 15699348SSiddheshwar.Mahesh@Sun.COM */ 15709348SSiddheshwar.Mahesh@Sun.COM 15719348SSiddheshwar.Mahesh@Sun.COM if (xdrp->xp_rcl_xdr) { 15729348SSiddheshwar.Mahesh@Sun.COM /* Add the chunk to end of the list */ 15739348SSiddheshwar.Mahesh@Sun.COM clp = xdrp->xp_rcl_xdr; 15749348SSiddheshwar.Mahesh@Sun.COM while (clp->c_next != NULL) 15759348SSiddheshwar.Mahesh@Sun.COM clp = clp->c_next; 15769348SSiddheshwar.Mahesh@Sun.COM clp->c_next = rclp; 15779348SSiddheshwar.Mahesh@Sun.COM } else { 15789348SSiddheshwar.Mahesh@Sun.COM xdrp->xp_rcl_xdr = rclp; 15799348SSiddheshwar.Mahesh@Sun.COM } 15809348SSiddheshwar.Mahesh@Sun.COM return (TRUE); 15819348SSiddheshwar.Mahesh@Sun.COM } 15829348SSiddheshwar.Mahesh@Sun.COM 15839348SSiddheshwar.Mahesh@Sun.COM static void 15849348SSiddheshwar.Mahesh@Sun.COM xdrrdma_free_xdr_chunks(CONN *conn, struct clist *xdr_rcl) 15859348SSiddheshwar.Mahesh@Sun.COM { 15869348SSiddheshwar.Mahesh@Sun.COM struct clist *cl; 15879348SSiddheshwar.Mahesh@Sun.COM 15889348SSiddheshwar.Mahesh@Sun.COM (void) clist_deregister(conn, xdr_rcl); 15899348SSiddheshwar.Mahesh@Sun.COM 15909348SSiddheshwar.Mahesh@Sun.COM /* 15919348SSiddheshwar.Mahesh@Sun.COM * Read chunks containing parts XDR message are 15929348SSiddheshwar.Mahesh@Sun.COM * special: in case of multiple chunks each has 15939348SSiddheshwar.Mahesh@Sun.COM * its own buffer. 15949348SSiddheshwar.Mahesh@Sun.COM */ 15959348SSiddheshwar.Mahesh@Sun.COM 15969348SSiddheshwar.Mahesh@Sun.COM cl = xdr_rcl; 15979348SSiddheshwar.Mahesh@Sun.COM while (cl) { 15989348SSiddheshwar.Mahesh@Sun.COM rdma_buf_free(conn, &cl->rb_longbuf); 15999348SSiddheshwar.Mahesh@Sun.COM cl = cl->c_next; 16009348SSiddheshwar.Mahesh@Sun.COM } 16019348SSiddheshwar.Mahesh@Sun.COM 16029348SSiddheshwar.Mahesh@Sun.COM clist_free(xdr_rcl); 16039348SSiddheshwar.Mahesh@Sun.COM } 1604