1bbc000e5SAnders Persson /* 2bbc000e5SAnders Persson * CDDL HEADER START 3bbc000e5SAnders Persson * 4bbc000e5SAnders Persson * The contents of this file are subject to the terms of the 5bbc000e5SAnders Persson * Common Development and Distribution License (the "License"). 6bbc000e5SAnders Persson * You may not use this file except in compliance with the License. 7bbc000e5SAnders Persson * 8bbc000e5SAnders Persson * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9bbc000e5SAnders Persson * or http://www.opensolaris.org/os/licensing. 10bbc000e5SAnders Persson * See the License for the specific language governing permissions 11bbc000e5SAnders Persson * and limitations under the License. 12bbc000e5SAnders Persson * 13bbc000e5SAnders Persson * When distributing Covered Code, include this CDDL HEADER in each 14bbc000e5SAnders Persson * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15bbc000e5SAnders Persson * If applicable, add the following below this CDDL HEADER, with the 16bbc000e5SAnders Persson * fields enclosed by brackets "[]" replaced with your own identifying 17bbc000e5SAnders Persson * information: Portions Copyright [yyyy] [name of copyright owner] 18bbc000e5SAnders Persson * 19bbc000e5SAnders Persson * CDDL HEADER END 20bbc000e5SAnders Persson */ 21bbc000e5SAnders Persson 22bbc000e5SAnders Persson /* 23*3e95bd4aSAnders Persson * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24bbc000e5SAnders Persson */ 25bbc000e5SAnders Persson 26bbc000e5SAnders Persson #include <sys/types.h> 27bbc000e5SAnders Persson #include <sys/param.h> 28bbc000e5SAnders Persson #include <sys/cmn_err.h> 29bbc000e5SAnders Persson #include <sys/uio.h> 30bbc000e5SAnders Persson #include <sys/stropts.h> 31bbc000e5SAnders Persson #include <sys/strsun.h> 32bbc000e5SAnders Persson #include <sys/systm.h> 33bbc000e5SAnders Persson #include <sys/socketvar.h> 34bbc000e5SAnders Persson #include <fs/sockfs/sodirect.h> 35bbc000e5SAnders Persson 36bbc000e5SAnders Persson /* 37bbc000e5SAnders Persson * In support of on-board asynchronous DMA hardware (e.g. Intel I/OAT) 38bbc000e5SAnders Persson * we use a consolidation private KAPI to allow the protocol to start 39bbc000e5SAnders Persson * an asynchronous copyout to a user-land receive-side buffer (uioa) 40bbc000e5SAnders Persson * when a blocking socket read (e.g. read, recv, ...) is pending. 41bbc000e5SAnders Persson * 42bbc000e5SAnders Persson * In some broad strokes, this is what happens. When recv is called, 43bbc000e5SAnders Persson * we first determine whether it would be beneficial to use uioa, and 44bbc000e5SAnders Persson * if so set up the required state (all done by sod_rcv_init()). 45bbc000e5SAnders Persson * The protocol can only initiate asynchronous copyout if the receive 46bbc000e5SAnders Persson * queue is empty, so the first thing we do is drain any previously 47bbc000e5SAnders Persson * queued data (using sod_uioa_so_init()). Once the copyouts (if any) 48bbc000e5SAnders Persson * have been scheduled we wait for the receive to be satisfied. During 49bbc000e5SAnders Persson * that time any new mblks that are enqueued will be scheduled to be 50bbc000e5SAnders Persson * copied out asynchronously (sod_uioa_mblk_init()). When the receive 51bbc000e5SAnders Persson * has been satisfied we wait for all scheduled copyout operations to 52bbc000e5SAnders Persson * complete before we return to the user (sod_rcv_done()) 53bbc000e5SAnders Persson */ 54bbc000e5SAnders Persson 55bbc000e5SAnders Persson static struct kmem_cache *sock_sod_cache; 56bbc000e5SAnders Persson 57bbc000e5SAnders Persson /* 58bbc000e5SAnders Persson * This function is called at the beginning of recvmsg(). 59bbc000e5SAnders Persson * 60bbc000e5SAnders Persson * If I/OAT is enabled on this sonode, initialize the uioa state machine 61bbc000e5SAnders Persson * with state UIOA_ALLOC. 62bbc000e5SAnders Persson */ 63bbc000e5SAnders Persson uio_t * 64bbc000e5SAnders Persson sod_rcv_init(struct sonode *so, int flags, struct uio **uiopp) 65bbc000e5SAnders Persson { 66bbc000e5SAnders Persson struct uio *suiop; 67bbc000e5SAnders Persson struct uio *uiop; 68bbc000e5SAnders Persson sodirect_t *sodp = so->so_direct; 69bbc000e5SAnders Persson 70bbc000e5SAnders Persson if (sodp == NULL) 71bbc000e5SAnders Persson return (NULL); 72bbc000e5SAnders Persson 73bbc000e5SAnders Persson suiop = NULL; 74bbc000e5SAnders Persson uiop = *uiopp; 75bbc000e5SAnders Persson 76bbc000e5SAnders Persson mutex_enter(&so->so_lock); 77bbc000e5SAnders Persson if (uiop->uio_resid >= uioasync.mincnt && 78bbc000e5SAnders Persson sodp != NULL && sodp->sod_enabled && 79bbc000e5SAnders Persson uioasync.enabled && !(flags & MSG_PEEK) && 80*3e95bd4aSAnders Persson !so->so_proto_props.sopp_loopback && so->so_filter_active == 0 && 81bbc000e5SAnders Persson !(so->so_state & SS_CANTRCVMORE)) { 82bbc000e5SAnders Persson /* 83bbc000e5SAnders Persson * Big enough I/O for uioa min setup and an sodirect socket 84bbc000e5SAnders Persson * and sodirect enabled and uioa enabled and I/O will be done 85bbc000e5SAnders Persson * and not EOF so initialize the sodirect_t uioa_t with "uiop". 86bbc000e5SAnders Persson */ 87bbc000e5SAnders Persson if (!uioainit(uiop, &sodp->sod_uioa)) { 88bbc000e5SAnders Persson /* 89bbc000e5SAnders Persson * Successful uioainit() so the uio_t part of the 90bbc000e5SAnders Persson * uioa_t will be used for all uio_t work to follow, 91bbc000e5SAnders Persson * we return the original "uiop" in "suiop". 92bbc000e5SAnders Persson */ 93bbc000e5SAnders Persson suiop = uiop; 94bbc000e5SAnders Persson *uiopp = (uio_t *)&sodp->sod_uioa; 95bbc000e5SAnders Persson /* 96bbc000e5SAnders Persson * Before returning to the caller the passed in uio_t 97bbc000e5SAnders Persson * "uiop" will be updated via a call to uioafini() 98bbc000e5SAnders Persson * below. 99bbc000e5SAnders Persson * 100bbc000e5SAnders Persson * Note, the uioa.uioa_state isn't set to UIOA_ENABLED 101bbc000e5SAnders Persson * here as first we have to uioamove() any currently 102bbc000e5SAnders Persson * queued M_DATA mblk_t(s) so it will be done later. 103bbc000e5SAnders Persson */ 104bbc000e5SAnders Persson } 105bbc000e5SAnders Persson } 106bbc000e5SAnders Persson mutex_exit(&so->so_lock); 107bbc000e5SAnders Persson 108bbc000e5SAnders Persson return (suiop); 109bbc000e5SAnders Persson } 110bbc000e5SAnders Persson 111bbc000e5SAnders Persson /* 112bbc000e5SAnders Persson * This function is called at the end of recvmsg(), it finializes all the I/OAT 113bbc000e5SAnders Persson * operations, and reset the uioa state to UIOA_ALLOC. 114bbc000e5SAnders Persson */ 115bbc000e5SAnders Persson int 116bbc000e5SAnders Persson sod_rcv_done(struct sonode *so, struct uio *suiop, struct uio *uiop) 117bbc000e5SAnders Persson { 118bbc000e5SAnders Persson int error = 0; 119bbc000e5SAnders Persson sodirect_t *sodp = so->so_direct; 120bbc000e5SAnders Persson mblk_t *mp; 121bbc000e5SAnders Persson 122bbc000e5SAnders Persson if (sodp == NULL) { 123bbc000e5SAnders Persson return (0); 124bbc000e5SAnders Persson } 125bbc000e5SAnders Persson 126bbc000e5SAnders Persson ASSERT(MUTEX_HELD(&so->so_lock)); 127bbc000e5SAnders Persson /* Finish any sodirect and uioa processing */ 128bbc000e5SAnders Persson if (suiop != NULL) { 129bbc000e5SAnders Persson /* Finish any uioa_t processing */ 130bbc000e5SAnders Persson 131bbc000e5SAnders Persson ASSERT(uiop == (uio_t *)&sodp->sod_uioa); 132bbc000e5SAnders Persson error = uioafini(suiop, (uioa_t *)uiop); 133bbc000e5SAnders Persson if ((mp = sodp->sod_uioafh) != NULL) { 134bbc000e5SAnders Persson sodp->sod_uioafh = NULL; 135bbc000e5SAnders Persson sodp->sod_uioaft = NULL; 136bbc000e5SAnders Persson freemsg(mp); 137bbc000e5SAnders Persson } 138bbc000e5SAnders Persson } 139bbc000e5SAnders Persson ASSERT(sodp->sod_uioafh == NULL); 140bbc000e5SAnders Persson 141bbc000e5SAnders Persson return (error); 142bbc000e5SAnders Persson } 143bbc000e5SAnders Persson 144bbc000e5SAnders Persson /* 145bbc000e5SAnders Persson * Schedule a uioamove() on a mblk. This is done as mblks are enqueued 146bbc000e5SAnders Persson * by the protocol on the socket's rcv queue. 147bbc000e5SAnders Persson * 148bbc000e5SAnders Persson * Caller must be holding so_lock. 149bbc000e5SAnders Persson */ 150bbc000e5SAnders Persson void 151bbc000e5SAnders Persson sod_uioa_mblk_init(struct sodirect_s *sodp, mblk_t *mp, size_t msg_size) 152bbc000e5SAnders Persson { 153bbc000e5SAnders Persson uioa_t *uioap = &sodp->sod_uioa; 154bbc000e5SAnders Persson mblk_t *mp1 = mp; 155bbc000e5SAnders Persson mblk_t *lmp = NULL; 156bbc000e5SAnders Persson 157bbc000e5SAnders Persson ASSERT(DB_TYPE(mp) == M_DATA); 158bbc000e5SAnders Persson ASSERT(msg_size == msgdsize(mp)); 159bbc000e5SAnders Persson 160bbc000e5SAnders Persson if (uioap->uioa_state & UIOA_ENABLED) { 161bbc000e5SAnders Persson /* Uioa is enabled */ 162bbc000e5SAnders Persson 163bbc000e5SAnders Persson if (msg_size > uioap->uio_resid) { 164bbc000e5SAnders Persson /* 165bbc000e5SAnders Persson * There isn't enough uio space for the mblk_t chain 166bbc000e5SAnders Persson * so disable uioa such that this and any additional 167bbc000e5SAnders Persson * mblk_t data is handled by the socket and schedule 168bbc000e5SAnders Persson * the socket for wakeup to finish this uioa. 169bbc000e5SAnders Persson */ 170bbc000e5SAnders Persson uioap->uioa_state &= UIOA_CLR; 171bbc000e5SAnders Persson uioap->uioa_state |= UIOA_FINI; 172bbc000e5SAnders Persson return; 173bbc000e5SAnders Persson } 174bbc000e5SAnders Persson do { 175bbc000e5SAnders Persson uint32_t len = MBLKL(mp1); 176bbc000e5SAnders Persson 177bbc000e5SAnders Persson if (!uioamove(mp1->b_rptr, len, UIO_READ, uioap)) { 178bbc000e5SAnders Persson /* Scheduled, mark dblk_t as such */ 179bbc000e5SAnders Persson DB_FLAGS(mp1) |= DBLK_UIOA; 180bbc000e5SAnders Persson } else { 181bbc000e5SAnders Persson /* Error, turn off async processing */ 182bbc000e5SAnders Persson uioap->uioa_state &= UIOA_CLR; 183bbc000e5SAnders Persson uioap->uioa_state |= UIOA_FINI; 184bbc000e5SAnders Persson break; 185bbc000e5SAnders Persson } 186bbc000e5SAnders Persson lmp = mp1; 187bbc000e5SAnders Persson } while ((mp1 = mp1->b_cont) != NULL); 188bbc000e5SAnders Persson 189bbc000e5SAnders Persson if (mp1 != NULL || uioap->uio_resid == 0) { 190bbc000e5SAnders Persson /* Break the mblk chain if neccessary. */ 191bbc000e5SAnders Persson if (mp1 != NULL && lmp != NULL) { 192bbc000e5SAnders Persson mp->b_next = mp1; 193bbc000e5SAnders Persson lmp->b_cont = NULL; 194bbc000e5SAnders Persson } 195bbc000e5SAnders Persson } 196bbc000e5SAnders Persson } 197bbc000e5SAnders Persson } 198bbc000e5SAnders Persson 199bbc000e5SAnders Persson /* 200bbc000e5SAnders Persson * This function is called on a mblk that thas been successfully uioamoved(). 201bbc000e5SAnders Persson */ 202bbc000e5SAnders Persson void 203bbc000e5SAnders Persson sod_uioa_mblk_done(sodirect_t *sodp, mblk_t *bp) 204bbc000e5SAnders Persson { 205bbc000e5SAnders Persson if (bp != NULL && (bp->b_datap->db_flags & DBLK_UIOA)) { 206bbc000e5SAnders Persson /* 207bbc000e5SAnders Persson * A uioa flaged mblk_t chain, already uio processed, 208bbc000e5SAnders Persson * add it to the sodirect uioa pending free list. 209bbc000e5SAnders Persson * 210bbc000e5SAnders Persson * Note, a b_cont chain headed by a DBLK_UIOA enable 211bbc000e5SAnders Persson * mblk_t must have all mblk_t(s) DBLK_UIOA enabled. 212bbc000e5SAnders Persson */ 213bbc000e5SAnders Persson mblk_t *bpt = sodp->sod_uioaft; 214bbc000e5SAnders Persson 215bbc000e5SAnders Persson ASSERT(sodp != NULL); 216bbc000e5SAnders Persson 217bbc000e5SAnders Persson /* 218bbc000e5SAnders Persson * Add first mblk_t of "bp" chain to current sodirect uioa 219bbc000e5SAnders Persson * free list tail mblk_t, if any, else empty list so new head. 220bbc000e5SAnders Persson */ 221bbc000e5SAnders Persson if (bpt == NULL) 222bbc000e5SAnders Persson sodp->sod_uioafh = bp; 223bbc000e5SAnders Persson else 224bbc000e5SAnders Persson bpt->b_cont = bp; 225bbc000e5SAnders Persson 226bbc000e5SAnders Persson /* 227bbc000e5SAnders Persson * Walk mblk_t "bp" chain to find tail and adjust rptr of 228bbc000e5SAnders Persson * each to reflect that uioamove() has consumed all data. 229bbc000e5SAnders Persson */ 230bbc000e5SAnders Persson bpt = bp; 231bbc000e5SAnders Persson for (;;) { 232bbc000e5SAnders Persson ASSERT(bpt->b_datap->db_flags & DBLK_UIOA); 233bbc000e5SAnders Persson 234bbc000e5SAnders Persson bpt->b_rptr = bpt->b_wptr; 235bbc000e5SAnders Persson if (bpt->b_cont == NULL) 236bbc000e5SAnders Persson break; 237bbc000e5SAnders Persson bpt = bpt->b_cont; 238bbc000e5SAnders Persson } 239bbc000e5SAnders Persson /* New sodirect uioa free list tail */ 240bbc000e5SAnders Persson sodp->sod_uioaft = bpt; 241bbc000e5SAnders Persson 242bbc000e5SAnders Persson /* Only dequeue once with data returned per uioa_t */ 243bbc000e5SAnders Persson if (sodp->sod_uioa.uioa_state & UIOA_ENABLED) { 244bbc000e5SAnders Persson sodp->sod_uioa.uioa_state &= UIOA_CLR; 245bbc000e5SAnders Persson sodp->sod_uioa.uioa_state |= UIOA_FINI; 246bbc000e5SAnders Persson } 247bbc000e5SAnders Persson } 248bbc000e5SAnders Persson } 249bbc000e5SAnders Persson 250bbc000e5SAnders Persson /* 251bbc000e5SAnders Persson * When transit from UIOA_INIT state to UIOA_ENABLE state in recvmsg(), call 252bbc000e5SAnders Persson * this function on a non-STREAMS socket to schedule uioamove() on the data 253bbc000e5SAnders Persson * that has already queued in this socket. 254bbc000e5SAnders Persson */ 255bbc000e5SAnders Persson void 256bbc000e5SAnders Persson sod_uioa_so_init(struct sonode *so, struct sodirect_s *sodp, struct uio *uiop) 257bbc000e5SAnders Persson { 258bbc000e5SAnders Persson uioa_t *uioap = (uioa_t *)uiop; 259bbc000e5SAnders Persson mblk_t *lbp; 260bbc000e5SAnders Persson mblk_t *wbp; 261bbc000e5SAnders Persson mblk_t *bp; 262bbc000e5SAnders Persson int len; 263bbc000e5SAnders Persson int error; 264bbc000e5SAnders Persson boolean_t in_rcv_q = B_TRUE; 265bbc000e5SAnders Persson 266bbc000e5SAnders Persson ASSERT(MUTEX_HELD(&so->so_lock)); 267bbc000e5SAnders Persson ASSERT(&sodp->sod_uioa == uioap); 268bbc000e5SAnders Persson 269bbc000e5SAnders Persson /* 270bbc000e5SAnders Persson * Walk first b_cont chain in sod_q 271bbc000e5SAnders Persson * and schedule any M_DATA mblk_t's for uio asynchronous move. 272bbc000e5SAnders Persson */ 273bbc000e5SAnders Persson bp = so->so_rcv_q_head; 274bbc000e5SAnders Persson 275bbc000e5SAnders Persson again: 276bbc000e5SAnders Persson /* Walk the chain */ 277bbc000e5SAnders Persson lbp = NULL; 278bbc000e5SAnders Persson wbp = bp; 279bbc000e5SAnders Persson 280bbc000e5SAnders Persson do { 281bbc000e5SAnders Persson if (bp == NULL) 282bbc000e5SAnders Persson break; 283bbc000e5SAnders Persson 284bbc000e5SAnders Persson if (wbp->b_datap->db_type != M_DATA) { 285bbc000e5SAnders Persson /* Not M_DATA, no more uioa */ 286bbc000e5SAnders Persson goto nouioa; 287bbc000e5SAnders Persson } 288bbc000e5SAnders Persson if ((len = wbp->b_wptr - wbp->b_rptr) > 0) { 289bbc000e5SAnders Persson /* Have a M_DATA mblk_t with data */ 290bbc000e5SAnders Persson if (len > uioap->uio_resid || (so->so_oobmark > 0 && 291bbc000e5SAnders Persson len + uioap->uioa_mbytes >= so->so_oobmark)) { 292bbc000e5SAnders Persson /* Not enough uio sapce, or beyond oobmark */ 293bbc000e5SAnders Persson goto nouioa; 294bbc000e5SAnders Persson } 295bbc000e5SAnders Persson ASSERT(!(wbp->b_datap->db_flags & DBLK_UIOA)); 296bbc000e5SAnders Persson error = uioamove(wbp->b_rptr, len, 297bbc000e5SAnders Persson UIO_READ, uioap); 298bbc000e5SAnders Persson if (!error) { 299bbc000e5SAnders Persson /* Scheduled, mark dblk_t as such */ 300bbc000e5SAnders Persson wbp->b_datap->db_flags |= DBLK_UIOA; 301bbc000e5SAnders Persson } else { 302bbc000e5SAnders Persson /* Break the mblk chain */ 303bbc000e5SAnders Persson goto nouioa; 304bbc000e5SAnders Persson } 305bbc000e5SAnders Persson } 306bbc000e5SAnders Persson /* Save last wbp processed */ 307bbc000e5SAnders Persson lbp = wbp; 308bbc000e5SAnders Persson } while ((wbp = wbp->b_cont) != NULL); 309bbc000e5SAnders Persson 310bbc000e5SAnders Persson if (in_rcv_q && (bp == NULL || bp->b_next == NULL)) { 311bbc000e5SAnders Persson /* 312bbc000e5SAnders Persson * We get here only once to process the sonode dump area 313bbc000e5SAnders Persson * if so_rcv_q_head is NULL or all the mblks have been 314bbc000e5SAnders Persson * successfully uioamoved()ed. 315bbc000e5SAnders Persson */ 316bbc000e5SAnders Persson in_rcv_q = B_FALSE; 317bbc000e5SAnders Persson 318bbc000e5SAnders Persson /* move to dump area */ 319bbc000e5SAnders Persson bp = so->so_rcv_head; 320bbc000e5SAnders Persson goto again; 321bbc000e5SAnders Persson } 322bbc000e5SAnders Persson 323bbc000e5SAnders Persson return; 324bbc000e5SAnders Persson 325bbc000e5SAnders Persson nouioa: 326bbc000e5SAnders Persson /* No more uioa */ 327bbc000e5SAnders Persson uioap->uioa_state &= UIOA_CLR; 328bbc000e5SAnders Persson uioap->uioa_state |= UIOA_FINI; 329bbc000e5SAnders Persson 330bbc000e5SAnders Persson /* 331bbc000e5SAnders Persson * If we processed 1 or more mblk_t(s) then we need to split the 332bbc000e5SAnders Persson * current mblk_t chain in 2 so that all the uioamove()ed mblk_t(s) 333bbc000e5SAnders Persson * are in the current chain and the rest are in the following new 334bbc000e5SAnders Persson * chain. 335bbc000e5SAnders Persson */ 336bbc000e5SAnders Persson if (lbp != NULL) { 337bbc000e5SAnders Persson /* New end of current chain */ 338bbc000e5SAnders Persson lbp->b_cont = NULL; 339bbc000e5SAnders Persson 340bbc000e5SAnders Persson /* Insert new chain wbp after bp */ 341bbc000e5SAnders Persson if ((wbp->b_next = bp->b_next) == NULL) { 342bbc000e5SAnders Persson if (in_rcv_q) 343bbc000e5SAnders Persson so->so_rcv_q_last_head = wbp; 344bbc000e5SAnders Persson else 345bbc000e5SAnders Persson so->so_rcv_last_head = wbp; 346bbc000e5SAnders Persson } 347bbc000e5SAnders Persson bp->b_next = wbp; 348bbc000e5SAnders Persson bp->b_next->b_prev = bp->b_prev; 349bbc000e5SAnders Persson bp->b_prev = lbp; 350bbc000e5SAnders Persson } 351bbc000e5SAnders Persson } 352bbc000e5SAnders Persson 353bbc000e5SAnders Persson /* 354bbc000e5SAnders Persson * Initialize sodirect data structures on a socket. 355bbc000e5SAnders Persson */ 356bbc000e5SAnders Persson void 357bbc000e5SAnders Persson sod_sock_init(struct sonode *so) 358bbc000e5SAnders Persson { 359bbc000e5SAnders Persson sodirect_t *sodp; 360bbc000e5SAnders Persson 361bbc000e5SAnders Persson ASSERT(so->so_direct == NULL); 362bbc000e5SAnders Persson 363bbc000e5SAnders Persson so->so_state |= SS_SODIRECT; 364bbc000e5SAnders Persson 365bbc000e5SAnders Persson sodp = kmem_cache_alloc(sock_sod_cache, KM_SLEEP); 366bbc000e5SAnders Persson sodp->sod_enabled = B_TRUE; 367bbc000e5SAnders Persson sodp->sod_uioafh = NULL; 368bbc000e5SAnders Persson sodp->sod_uioaft = NULL; 369bbc000e5SAnders Persson /* 370bbc000e5SAnders Persson * Remainder of the sod_uioa members are left uninitialized 371bbc000e5SAnders Persson * but will be initialized later by uioainit() before uioa 372bbc000e5SAnders Persson * is enabled. 373bbc000e5SAnders Persson */ 374bbc000e5SAnders Persson sodp->sod_uioa.uioa_state = UIOA_ALLOC; 375bbc000e5SAnders Persson so->so_direct = sodp; 376bbc000e5SAnders Persson } 377bbc000e5SAnders Persson 378bbc000e5SAnders Persson void 379bbc000e5SAnders Persson sod_sock_fini(struct sonode *so) 380bbc000e5SAnders Persson { 381bbc000e5SAnders Persson sodirect_t *sodp = so->so_direct; 382bbc000e5SAnders Persson 383bbc000e5SAnders Persson ASSERT(sodp->sod_uioafh == NULL); 384bbc000e5SAnders Persson 385bbc000e5SAnders Persson so->so_direct = NULL; 386bbc000e5SAnders Persson kmem_cache_free(sock_sod_cache, sodp); 387bbc000e5SAnders Persson } 388bbc000e5SAnders Persson 389bbc000e5SAnders Persson /* 390bbc000e5SAnders Persson * Init the sodirect kmem cache while sockfs is loading. 391bbc000e5SAnders Persson */ 392bbc000e5SAnders Persson int 393bbc000e5SAnders Persson sod_init() 394bbc000e5SAnders Persson { 395bbc000e5SAnders Persson /* Allocate sodirect_t kmem_cache */ 396bbc000e5SAnders Persson sock_sod_cache = kmem_cache_create("sock_sod_cache", 397bbc000e5SAnders Persson sizeof (sodirect_t), 0, NULL, NULL, NULL, NULL, NULL, 0); 398bbc000e5SAnders Persson 399bbc000e5SAnders Persson return (0); 400bbc000e5SAnders Persson } 401bbc000e5SAnders Persson 402bbc000e5SAnders Persson ssize_t 403bbc000e5SAnders Persson sod_uioa_mblk(struct sonode *so, mblk_t *mp) 404bbc000e5SAnders Persson { 405bbc000e5SAnders Persson sodirect_t *sodp = so->so_direct; 406bbc000e5SAnders Persson 407bbc000e5SAnders Persson ASSERT(sodp != NULL); 408bbc000e5SAnders Persson ASSERT(MUTEX_HELD(&so->so_lock)); 409bbc000e5SAnders Persson 410bbc000e5SAnders Persson ASSERT(sodp->sod_enabled); 411bbc000e5SAnders Persson ASSERT(sodp->sod_uioa.uioa_state != (UIOA_ALLOC|UIOA_INIT)); 412bbc000e5SAnders Persson 413bbc000e5SAnders Persson ASSERT(sodp->sod_uioa.uioa_state & (UIOA_ENABLED|UIOA_FINI)); 414bbc000e5SAnders Persson 415bbc000e5SAnders Persson if (mp == NULL && so->so_rcv_q_head != NULL) { 416bbc000e5SAnders Persson mp = so->so_rcv_q_head; 417bbc000e5SAnders Persson ASSERT(mp->b_prev != NULL); 418bbc000e5SAnders Persson mp->b_prev = NULL; 419bbc000e5SAnders Persson so->so_rcv_q_head = mp->b_next; 420bbc000e5SAnders Persson if (so->so_rcv_q_head == NULL) { 421bbc000e5SAnders Persson so->so_rcv_q_last_head = NULL; 422bbc000e5SAnders Persson } 423bbc000e5SAnders Persson mp->b_next = NULL; 424bbc000e5SAnders Persson } 425bbc000e5SAnders Persson 426bbc000e5SAnders Persson sod_uioa_mblk_done(sodp, mp); 427bbc000e5SAnders Persson 428bbc000e5SAnders Persson if (so->so_rcv_q_head == NULL && so->so_rcv_head != NULL && 429bbc000e5SAnders Persson DB_TYPE(so->so_rcv_head) == M_DATA && 430bbc000e5SAnders Persson (DB_FLAGS(so->so_rcv_head) & DBLK_UIOA)) { 431bbc000e5SAnders Persson /* more arrived */ 432bbc000e5SAnders Persson ASSERT(so->so_rcv_q_head == NULL); 433bbc000e5SAnders Persson mp = so->so_rcv_head; 434bbc000e5SAnders Persson so->so_rcv_head = mp->b_next; 435bbc000e5SAnders Persson if (so->so_rcv_head == NULL) 436bbc000e5SAnders Persson so->so_rcv_last_head = NULL; 437bbc000e5SAnders Persson mp->b_prev = mp->b_next = NULL; 438bbc000e5SAnders Persson sod_uioa_mblk_done(sodp, mp); 439bbc000e5SAnders Persson } 440bbc000e5SAnders Persson 441bbc000e5SAnders Persson #ifdef DEBUG 442bbc000e5SAnders Persson if (so->so_rcv_q_head != NULL) { 443bbc000e5SAnders Persson mblk_t *m = so->so_rcv_q_head; 444bbc000e5SAnders Persson while (m != NULL) { 445bbc000e5SAnders Persson if (DB_FLAGS(m) & DBLK_UIOA) { 446bbc000e5SAnders Persson cmn_err(CE_PANIC, "Unexpected I/OAT mblk %p" 447bbc000e5SAnders Persson " in so_rcv_q_head.\n", (void *)m); 448bbc000e5SAnders Persson } 449bbc000e5SAnders Persson m = m->b_next; 450bbc000e5SAnders Persson } 451bbc000e5SAnders Persson } 452bbc000e5SAnders Persson if (so->so_rcv_head != NULL) { 453bbc000e5SAnders Persson mblk_t *m = so->so_rcv_head; 454bbc000e5SAnders Persson while (m != NULL) { 455bbc000e5SAnders Persson if (DB_FLAGS(m) & DBLK_UIOA) { 456bbc000e5SAnders Persson cmn_err(CE_PANIC, "Unexpected I/OAT mblk %p" 457bbc000e5SAnders Persson " in so_rcv_head.\n", (void *)m); 458bbc000e5SAnders Persson } 459bbc000e5SAnders Persson m = m->b_next; 460bbc000e5SAnders Persson } 461bbc000e5SAnders Persson } 462bbc000e5SAnders Persson #endif 463bbc000e5SAnders Persson return (sodp->sod_uioa.uioa_mbytes); 464bbc000e5SAnders Persson } 465