1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1998,2001 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate * 26*7c478bd9Sstevel@tonic-gate */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include <sys/fdbuffer.h> 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 40*7c478bd9Sstevel@tonic-gate static int fdb_debug; 41*7c478bd9Sstevel@tonic-gate #define FDB_D_CREATE 001 42*7c478bd9Sstevel@tonic-gate #define FDB_D_ALLOC 002 43*7c478bd9Sstevel@tonic-gate #define FDB_D_IO 004 44*7c478bd9Sstevel@tonic-gate #define FDB_D_ASYNC 010 45*7c478bd9Sstevel@tonic-gate #define DEBUGF(lvl, args) { if ((lvl) & fdb_debug) cmn_err args; } 46*7c478bd9Sstevel@tonic-gate #else 47*7c478bd9Sstevel@tonic-gate #define DEBUGF(level, args) 48*7c478bd9Sstevel@tonic-gate #endif 49*7c478bd9Sstevel@tonic-gate static struct kmem_cache *fdb_cache; 50*7c478bd9Sstevel@tonic-gate static void fdb_zero_holes(fdbuffer_t *fdb); 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 53*7c478bd9Sstevel@tonic-gate static int 54*7c478bd9Sstevel@tonic-gate fdb_cache_constructor(void *buf, void *cdrarg, int kmflags) 55*7c478bd9Sstevel@tonic-gate { 56*7c478bd9Sstevel@tonic-gate fdbuffer_t *fdb = buf; 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate mutex_init(&fdb->fd_mutex, NULL, MUTEX_DEFAULT, NULL); 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate return (0); 61*7c478bd9Sstevel@tonic-gate } 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 64*7c478bd9Sstevel@tonic-gate static void 65*7c478bd9Sstevel@tonic-gate fdb_cache_destructor(void *buf, void *cdrarg) 66*7c478bd9Sstevel@tonic-gate { 67*7c478bd9Sstevel@tonic-gate fdbuffer_t *fdb = buf; 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate mutex_destroy(&fdb->fd_mutex); 70*7c478bd9Sstevel@tonic-gate } 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate void 73*7c478bd9Sstevel@tonic-gate fdb_init() 74*7c478bd9Sstevel@tonic-gate { 75*7c478bd9Sstevel@tonic-gate fdb_cache = kmem_cache_create("fdb_cache", sizeof (fdbuffer_t), 76*7c478bd9Sstevel@tonic-gate 0, fdb_cache_constructor, fdb_cache_destructor, 77*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 0); 78*7c478bd9Sstevel@tonic-gate } 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate static void 81*7c478bd9Sstevel@tonic-gate fdb_prepare(fdbuffer_t *fdb) 82*7c478bd9Sstevel@tonic-gate { 83*7c478bd9Sstevel@tonic-gate fdb->fd_holes = NULL; 84*7c478bd9Sstevel@tonic-gate fdb->fd_iofunc = NULL; 85*7c478bd9Sstevel@tonic-gate fdb->fd_iargp = NULL; 86*7c478bd9Sstevel@tonic-gate fdb->fd_parentbp = NULL; 87*7c478bd9Sstevel@tonic-gate fdb->fd_resid = 0; 88*7c478bd9Sstevel@tonic-gate fdb->fd_iocount = 0; 89*7c478bd9Sstevel@tonic-gate fdb->fd_iodispatch = 0; 90*7c478bd9Sstevel@tonic-gate fdb->fd_err = 0; 91*7c478bd9Sstevel@tonic-gate } 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate fdbuffer_t * 94*7c478bd9Sstevel@tonic-gate fdb_page_create(page_t *pp, size_t len, int flags) 95*7c478bd9Sstevel@tonic-gate { 96*7c478bd9Sstevel@tonic-gate fdbuffer_t *fdb; 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_CREATE, (CE_NOTE, 99*7c478bd9Sstevel@tonic-gate "?fdb_page_create: pp: %p len: %lux flags: %x", 100*7c478bd9Sstevel@tonic-gate (void *)pp, len, flags)); 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate ASSERT(flags & (FDB_READ|FDB_WRITE)); 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate fdb = kmem_cache_alloc(fdb_cache, KM_SLEEP); 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate fdb_prepare(fdb); 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate fdb->fd_type = FDB_PAGEIO; 109*7c478bd9Sstevel@tonic-gate fdb->fd_len = len; 110*7c478bd9Sstevel@tonic-gate fdb->fd_state = flags; 111*7c478bd9Sstevel@tonic-gate fdb->fd_pages = pp; 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate return (fdb); 114*7c478bd9Sstevel@tonic-gate } 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate fdbuffer_t * 117*7c478bd9Sstevel@tonic-gate fdb_addr_create( 118*7c478bd9Sstevel@tonic-gate caddr_t addr, 119*7c478bd9Sstevel@tonic-gate size_t len, 120*7c478bd9Sstevel@tonic-gate int flags, 121*7c478bd9Sstevel@tonic-gate page_t **pplist, 122*7c478bd9Sstevel@tonic-gate struct proc *procp) 123*7c478bd9Sstevel@tonic-gate { 124*7c478bd9Sstevel@tonic-gate fdbuffer_t *fdb; 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_CREATE, (CE_NOTE, 127*7c478bd9Sstevel@tonic-gate "?fdb_addr_create: addr: %p len: %lux flags: %x", 128*7c478bd9Sstevel@tonic-gate (void *)addr, len, flags)); 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate ASSERT(flags & (FDB_READ|FDB_WRITE)); 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate fdb = kmem_cache_alloc(fdb_cache, KM_SLEEP); 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate fdb_prepare(fdb); 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate fdb->fd_type = FDB_VADDR; 137*7c478bd9Sstevel@tonic-gate fdb->fd_len = len; 138*7c478bd9Sstevel@tonic-gate fdb->fd_state = flags; 139*7c478bd9Sstevel@tonic-gate fdb->fd_addr = addr; 140*7c478bd9Sstevel@tonic-gate fdb->fd_shadow = pplist; 141*7c478bd9Sstevel@tonic-gate fdb->fd_procp = procp; 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate return (fdb); 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate void 147*7c478bd9Sstevel@tonic-gate fdb_set_iofunc(fdbuffer_t *fdb, fdb_iodone_t iofunc, void *ioargp, int flag) 148*7c478bd9Sstevel@tonic-gate { 149*7c478bd9Sstevel@tonic-gate ASSERT(fdb); 150*7c478bd9Sstevel@tonic-gate ASSERT(iofunc); 151*7c478bd9Sstevel@tonic-gate ASSERT((flag & ~FDB_ICALLBACK) == 0); 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate fdb->fd_iofunc = iofunc; 154*7c478bd9Sstevel@tonic-gate fdb->fd_iargp = ioargp; 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex); 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate if (flag & FDB_ICALLBACK) 159*7c478bd9Sstevel@tonic-gate fdb->fd_state |= FDB_ICALLBACK; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate fdb->fd_state |= FDB_ASYNC; 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex); 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate int 167*7c478bd9Sstevel@tonic-gate fdb_get_error(fdbuffer_t *fdb) 168*7c478bd9Sstevel@tonic-gate { 169*7c478bd9Sstevel@tonic-gate return (fdb->fd_err); 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate void 173*7c478bd9Sstevel@tonic-gate fdb_free(fdbuffer_t *fdb) 174*7c478bd9Sstevel@tonic-gate { 175*7c478bd9Sstevel@tonic-gate fdb_holes_t *fdh, *fdhp; 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_CREATE, (CE_NOTE, "?fdb_free: addr: %p flags: %x", 178*7c478bd9Sstevel@tonic-gate (void *)fdb, fdb->fd_state)); 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate ASSERT(fdb); 181*7c478bd9Sstevel@tonic-gate ASSERT(fdb->fd_iodispatch == 0); 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate if (fdb->fd_state & FDB_ZEROHOLE) { 184*7c478bd9Sstevel@tonic-gate fdb_zero_holes(fdb); 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate for (fdh = fdb->fd_holes; fdh; ) { 188*7c478bd9Sstevel@tonic-gate fdhp = fdh; 189*7c478bd9Sstevel@tonic-gate fdh = fdh->next_hole; 190*7c478bd9Sstevel@tonic-gate kmem_free(fdhp, sizeof (fdb_holes_t)); 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate if (fdb->fd_parentbp != NULL) { 194*7c478bd9Sstevel@tonic-gate switch (fdb->fd_type) { 195*7c478bd9Sstevel@tonic-gate case FDB_PAGEIO: 196*7c478bd9Sstevel@tonic-gate pageio_done(fdb->fd_parentbp); 197*7c478bd9Sstevel@tonic-gate break; 198*7c478bd9Sstevel@tonic-gate case FDB_VADDR: 199*7c478bd9Sstevel@tonic-gate kmem_free(fdb->fd_parentbp, sizeof (struct buf)); 200*7c478bd9Sstevel@tonic-gate break; 201*7c478bd9Sstevel@tonic-gate default: 202*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?fdb_free: Unknown fdb type."); 203*7c478bd9Sstevel@tonic-gate break; 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate kmem_cache_free(fdb_cache, fdb); 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate /* 212*7c478bd9Sstevel@tonic-gate * The offset should be from the begining of the buffer 213*7c478bd9Sstevel@tonic-gate * it has nothing to do with file offset. This fact should be 214*7c478bd9Sstevel@tonic-gate * reflected in the caller of this routine. 215*7c478bd9Sstevel@tonic-gate */ 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate void 218*7c478bd9Sstevel@tonic-gate fdb_add_hole(fdbuffer_t *fdb, u_offset_t off, size_t len) 219*7c478bd9Sstevel@tonic-gate { 220*7c478bd9Sstevel@tonic-gate fdb_holes_t *this_hole; 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate ASSERT(fdb); 223*7c478bd9Sstevel@tonic-gate ASSERT(off < fdb->fd_len); 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_IO, (CE_NOTE, "?fdb_add_hole: off %llx len %lx", 226*7c478bd9Sstevel@tonic-gate off, len)); 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate this_hole = kmem_alloc(sizeof (fdb_holes_t), KM_SLEEP); 229*7c478bd9Sstevel@tonic-gate this_hole->off = off; 230*7c478bd9Sstevel@tonic-gate this_hole->len = len; 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate if (fdb->fd_holes == NULL || off < fdb->fd_holes->off) { 233*7c478bd9Sstevel@tonic-gate this_hole->next_hole = fdb->fd_holes; 234*7c478bd9Sstevel@tonic-gate fdb->fd_holes = this_hole; 235*7c478bd9Sstevel@tonic-gate } else { 236*7c478bd9Sstevel@tonic-gate fdb_holes_t *fdhp = fdb->fd_holes; 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate while (fdhp->next_hole && off > fdhp->next_hole->off) 239*7c478bd9Sstevel@tonic-gate fdhp = fdhp->next_hole; 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate this_hole->next_hole = fdhp->next_hole; 242*7c478bd9Sstevel@tonic-gate fdhp->next_hole = this_hole; 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex); 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate fdb->fd_iocount += len; 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex); 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate fdb_holes_t * 253*7c478bd9Sstevel@tonic-gate fdb_get_holes(fdbuffer_t *fdb) 254*7c478bd9Sstevel@tonic-gate { 255*7c478bd9Sstevel@tonic-gate ASSERT(fdb); 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate if (fdb->fd_state & FDB_ZEROHOLE) { 258*7c478bd9Sstevel@tonic-gate fdb_zero_holes(fdb); 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate return (fdb->fd_holes); 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate /* 265*7c478bd9Sstevel@tonic-gate * Note that offsets refer to offsets from the begining of the buffer 266*7c478bd9Sstevel@tonic-gate * and as such the memory should be cleared accordingly. 267*7c478bd9Sstevel@tonic-gate */ 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate static void 270*7c478bd9Sstevel@tonic-gate fdb_zero_holes(fdbuffer_t *fdb) 271*7c478bd9Sstevel@tonic-gate { 272*7c478bd9Sstevel@tonic-gate fdb_holes_t *fdh = fdb->fd_holes; 273*7c478bd9Sstevel@tonic-gate page_t *pp; 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate ASSERT(fdb); 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate if (!fdh) 278*7c478bd9Sstevel@tonic-gate return; 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate switch (fdb->fd_type) { 281*7c478bd9Sstevel@tonic-gate case FDB_PAGEIO: 282*7c478bd9Sstevel@tonic-gate pp = fdb->fd_pages; 283*7c478bd9Sstevel@tonic-gate while (fdh) { 284*7c478bd9Sstevel@tonic-gate fdb_holes_t *pfdh = fdh; 285*7c478bd9Sstevel@tonic-gate size_t l = fdh->len; 286*7c478bd9Sstevel@tonic-gate u_offset_t o = fdh->off; 287*7c478bd9Sstevel@tonic-gate ASSERT(pp); 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate do { 290*7c478bd9Sstevel@tonic-gate int zerolen; 291*7c478bd9Sstevel@tonic-gate ASSERT(o >= pp->p_offset); 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate /* 294*7c478bd9Sstevel@tonic-gate * This offset is wrong since 295*7c478bd9Sstevel@tonic-gate * the offset passed from the pages 296*7c478bd9Sstevel@tonic-gate * perspective starts at some virtual 297*7c478bd9Sstevel@tonic-gate * address but the hole is relative 298*7c478bd9Sstevel@tonic-gate * to the beginning of the fdbuffer. 299*7c478bd9Sstevel@tonic-gate */ 300*7c478bd9Sstevel@tonic-gate if (o >= pp->p_offset + PAGESIZE) 301*7c478bd9Sstevel@tonic-gate continue; 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate zerolen = min(PAGESIZE, l); 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate ASSERT(zerolen > 0); 306*7c478bd9Sstevel@tonic-gate ASSERT(zerolen <= PAGESIZE); 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate pagezero(pp, ((uintptr_t)o & PAGEOFFSET), 309*7c478bd9Sstevel@tonic-gate zerolen); 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate l -= zerolen; 312*7c478bd9Sstevel@tonic-gate o += zerolen; 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate if (l == 0) 315*7c478bd9Sstevel@tonic-gate break; 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate } while (pp = page_list_next(pp)); 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate if (!pp) 320*7c478bd9Sstevel@tonic-gate break; 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate fdh = fdh->next_hole; 323*7c478bd9Sstevel@tonic-gate kmem_free(pfdh, sizeof (fdb_holes_t)); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate break; 326*7c478bd9Sstevel@tonic-gate case FDB_VADDR: 327*7c478bd9Sstevel@tonic-gate while (fdh) { 328*7c478bd9Sstevel@tonic-gate fdb_holes_t *pfdh = fdh; 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate bzero(fdb->fd_addr + fdh->off, fdh->len); 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate fdh = fdh->next_hole; 333*7c478bd9Sstevel@tonic-gate kmem_free(pfdh, sizeof (fdb_holes_t)); 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate default: 336*7c478bd9Sstevel@tonic-gate panic("fdb_zero_holes: Unknown fdb type."); 337*7c478bd9Sstevel@tonic-gate break; 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate buf_t * 343*7c478bd9Sstevel@tonic-gate fdb_iosetup(fdbuffer_t *fdb, u_offset_t off, size_t len, struct vnode *vp, 344*7c478bd9Sstevel@tonic-gate int b_flags) 345*7c478bd9Sstevel@tonic-gate { 346*7c478bd9Sstevel@tonic-gate buf_t *bp; 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_IO, (CE_NOTE, 349*7c478bd9Sstevel@tonic-gate "?fdb_iosetup: off: %llx len: %lux fdb: len: %lux flags: %x", 350*7c478bd9Sstevel@tonic-gate off, len, fdb->fd_len, fdb->fd_state)); 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate ASSERT(fdb); 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex); 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate ASSERT(((b_flags & B_READ) && (fdb->fd_state & FDB_READ)) || 357*7c478bd9Sstevel@tonic-gate ((b_flags & B_WRITE) && (fdb->fd_state & FDB_WRITE))); 358*7c478bd9Sstevel@tonic-gate /* 359*7c478bd9Sstevel@tonic-gate * The fdb can be used either in sync or async mode, if the 360*7c478bd9Sstevel@tonic-gate * buffer has not been used it may be used in either mode, but 361*7c478bd9Sstevel@tonic-gate * once you have started to use the buf in either mode all 362*7c478bd9Sstevel@tonic-gate * subsequent i/o requests must take place the same way. 363*7c478bd9Sstevel@tonic-gate */ 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate ASSERT(((b_flags & B_ASYNC) && 366*7c478bd9Sstevel@tonic-gate ((fdb->fd_state & FDB_ASYNC) || !(fdb->fd_state & FDB_SYNC))) || 367*7c478bd9Sstevel@tonic-gate (!(b_flags & B_ASYNC) && 368*7c478bd9Sstevel@tonic-gate ((fdb->fd_state & FDB_SYNC) || !(fdb->fd_state & FDB_ASYNC)))); 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate fdb->fd_state |= b_flags & B_ASYNC ? FDB_ASYNC : FDB_SYNC; 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate fdb->fd_iodispatch++; 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate ASSERT((fdb->fd_state & FDB_ASYNC && fdb->fd_iofunc != NULL) || 376*7c478bd9Sstevel@tonic-gate fdb->fd_state & FDB_SYNC); 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex); 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate ASSERT((len & (DEV_BSIZE - 1)) == 0); 381*7c478bd9Sstevel@tonic-gate ASSERT(off+len <= fdb->fd_len); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate switch (fdb->fd_type) { 384*7c478bd9Sstevel@tonic-gate case FDB_PAGEIO: 385*7c478bd9Sstevel@tonic-gate if (fdb->fd_parentbp == NULL) { 386*7c478bd9Sstevel@tonic-gate bp = pageio_setup(fdb->fd_pages, len, vp, b_flags); 387*7c478bd9Sstevel@tonic-gate fdb->fd_parentbp = bp; 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate break; 390*7c478bd9Sstevel@tonic-gate case FDB_VADDR: 391*7c478bd9Sstevel@tonic-gate if (fdb->fd_parentbp == NULL) { 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate bp = kmem_alloc(sizeof (buf_t), KM_SLEEP); 394*7c478bd9Sstevel@tonic-gate bioinit(bp); 395*7c478bd9Sstevel@tonic-gate bp->b_error = 0; 396*7c478bd9Sstevel@tonic-gate bp->b_proc = fdb->fd_procp; 397*7c478bd9Sstevel@tonic-gate bp->b_flags = b_flags | B_BUSY | B_PHYS; 398*7c478bd9Sstevel@tonic-gate bp->b_bcount = len; 399*7c478bd9Sstevel@tonic-gate bp->b_un.b_addr = fdb->fd_addr; 400*7c478bd9Sstevel@tonic-gate bp->b_shadow = fdb->fd_shadow; 401*7c478bd9Sstevel@tonic-gate if (fdb->fd_shadow != NULL) 402*7c478bd9Sstevel@tonic-gate bp->b_flags |= B_SHADOW; 403*7c478bd9Sstevel@tonic-gate fdb->fd_parentbp = bp; 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate break; 406*7c478bd9Sstevel@tonic-gate default: 407*7c478bd9Sstevel@tonic-gate panic("fdb_iosetup: Unsupported fdb type."); 408*7c478bd9Sstevel@tonic-gate break; 409*7c478bd9Sstevel@tonic-gate }; 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate bp = bioclone(fdb->fd_parentbp, off, len, 0, 0, 412*7c478bd9Sstevel@tonic-gate (b_flags & B_ASYNC) ? (int (*)())fdb_iodone : NULL, 413*7c478bd9Sstevel@tonic-gate NULL, KM_SLEEP); 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate bp->b_forw = (struct buf *)fdb; 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate if (b_flags & B_ASYNC) 418*7c478bd9Sstevel@tonic-gate bp->b_flags |= B_ASYNC; 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate return (bp); 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate size_t 424*7c478bd9Sstevel@tonic-gate fdb_get_iolen(fdbuffer_t *fdb) 425*7c478bd9Sstevel@tonic-gate { 426*7c478bd9Sstevel@tonic-gate ASSERT(fdb); 427*7c478bd9Sstevel@tonic-gate ASSERT(fdb->fd_iodispatch == 0); 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate return (fdb->fd_iocount - fdb->fd_resid); 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate void 433*7c478bd9Sstevel@tonic-gate fdb_ioerrdone(fdbuffer_t *fdb, int error) 434*7c478bd9Sstevel@tonic-gate { 435*7c478bd9Sstevel@tonic-gate ASSERT(fdb); 436*7c478bd9Sstevel@tonic-gate ASSERT(fdb->fd_state & FDB_ASYNC); 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_IO, (CE_NOTE, 439*7c478bd9Sstevel@tonic-gate "?fdb_ioerrdone: fdb: len: %lux flags: %x error: %d", 440*7c478bd9Sstevel@tonic-gate fdb->fd_len, fdb->fd_state, error)); 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex); 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate fdb->fd_err = error; 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate if (error) 447*7c478bd9Sstevel@tonic-gate fdb->fd_state |= FDB_ERROR; 448*7c478bd9Sstevel@tonic-gate else 449*7c478bd9Sstevel@tonic-gate fdb->fd_state |= FDB_DONE; 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate /* 452*7c478bd9Sstevel@tonic-gate * If there is outstanding i/o return wainting for i/o's to complete. 453*7c478bd9Sstevel@tonic-gate */ 454*7c478bd9Sstevel@tonic-gate if (fdb->fd_iodispatch > 0) { 455*7c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex); 456*7c478bd9Sstevel@tonic-gate return; 457*7c478bd9Sstevel@tonic-gate } 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex); 460*7c478bd9Sstevel@tonic-gate fdb->fd_iofunc(fdb, fdb->fd_iargp, NULL); 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate void 464*7c478bd9Sstevel@tonic-gate fdb_iodone(buf_t *bp) 465*7c478bd9Sstevel@tonic-gate { 466*7c478bd9Sstevel@tonic-gate fdbuffer_t *fdb = (fdbuffer_t *)bp->b_forw; 467*7c478bd9Sstevel@tonic-gate int error, isasync; 468*7c478bd9Sstevel@tonic-gate int icallback; 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate ASSERT(fdb); 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_IO, (CE_NOTE, 473*7c478bd9Sstevel@tonic-gate "?fdb_iodone: fdb: len: %lux flags: %x error: %d", 474*7c478bd9Sstevel@tonic-gate fdb->fd_len, fdb->fd_state, geterror(bp))); 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate if (bp->b_flags & B_REMAPPED) 477*7c478bd9Sstevel@tonic-gate bp_mapout(bp); 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex); 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate icallback = fdb->fd_state & FDB_ICALLBACK; 482*7c478bd9Sstevel@tonic-gate isasync = fdb->fd_state & FDB_ASYNC; 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate ASSERT(fdb->fd_iodispatch > 0); 485*7c478bd9Sstevel@tonic-gate fdb->fd_iodispatch--; 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate if (error = geterror(bp)) { 488*7c478bd9Sstevel@tonic-gate fdb->fd_err = error; 489*7c478bd9Sstevel@tonic-gate if (bp->b_resid) 490*7c478bd9Sstevel@tonic-gate fdb->fd_resid += bp->b_resid; 491*7c478bd9Sstevel@tonic-gate else 492*7c478bd9Sstevel@tonic-gate fdb->fd_resid += bp->b_bcount; 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate fdb->fd_iocount += bp->b_bcount; 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate /* 498*7c478bd9Sstevel@tonic-gate * ioack collects the total amount of i/o accounted for 499*7c478bd9Sstevel@tonic-gate * this includes: 500*7c478bd9Sstevel@tonic-gate * 501*7c478bd9Sstevel@tonic-gate * - i/o completed 502*7c478bd9Sstevel@tonic-gate * - i/o attempted but not completed, 503*7c478bd9Sstevel@tonic-gate * - i/o not done due to holes. 504*7c478bd9Sstevel@tonic-gate * 505*7c478bd9Sstevel@tonic-gate * Once the entire i/o ranges has been accounted for we'll 506*7c478bd9Sstevel@tonic-gate * call the async function associated with the fdb. 507*7c478bd9Sstevel@tonic-gate * 508*7c478bd9Sstevel@tonic-gate */ 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate if ((fdb->fd_iodispatch == 0) && 511*7c478bd9Sstevel@tonic-gate (fdb->fd_state & (FDB_ERROR|FDB_DONE))) { 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex); 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate if (isasync || icallback) { 516*7c478bd9Sstevel@tonic-gate fdb->fd_iofunc(fdb, fdb->fd_iargp, bp); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate } else { 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex); 522*7c478bd9Sstevel@tonic-gate 523*7c478bd9Sstevel@tonic-gate if (icallback) { 524*7c478bd9Sstevel@tonic-gate fdb->fd_iofunc(fdb, fdb->fd_iargp, bp); 525*7c478bd9Sstevel@tonic-gate } 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate freerbuf(bp); 529*7c478bd9Sstevel@tonic-gate } 530